diff --git a/include/libxml/xpath.h b/include/libxml/xpath.h
index 1a9e30e..64939f6 100644
--- a/include/libxml/xpath.h
+++ b/include/libxml/xpath.h
@@ -20,6 +20,7 @@
 #define __XML_XPATH_H__
 
 #include <libxml/xmlversion.h>
+#include <sys/time.h>
 
 #ifdef LIBXML_XPATH_ENABLED
 
@@ -350,6 +351,10 @@ struct _xmlXPathContext {
 
     /* Cache for reusal of XPath objects */
     void *cache;
+
+	/* Deadline for evaluating xpaths */
+	time_t deadline;
+	int aborted;
 };
 
 /*
@@ -493,6 +498,8 @@ XMLPUBFUN xmlXPathObjectPtr XMLCALL
 XMLPUBFUN xmlXPathContextPtr XMLCALL 
 		    xmlXPathNewContext		(xmlDocPtr doc);
 XMLPUBFUN void XMLCALL
+		    xmlXPathContextSetDeadline	(xmlXPathContextPtr ctxt, time_t deadline);
+XMLPUBFUN void XMLCALL
 		    xmlXPathFreeContext		(xmlXPathContextPtr ctxt);
 XMLPUBFUN int XMLCALL
 		    xmlXPathContextSetCache(xmlXPathContextPtr ctxt,
diff --git a/xpath.c b/xpath.c
index 8b56189..6bd8ffd 100644
--- a/xpath.c
+++ b/xpath.c
@@ -17,6 +17,7 @@
 #define IN_LIBXML
 #include "libxml.h"
 
+#include <sys/time.h>
 #include <string.h>
 
 #ifdef HAVE_SYS_TYPES_H
@@ -3836,8 +3837,11 @@ xmlXPathNodeSetMergeUnique(xmlNodeSetPtr val1, xmlNodeSetPtr val2) {
  */
 static xmlNodeSetPtr
 xmlXPathNodeSetMergeAndClear(xmlNodeSetPtr set1, xmlNodeSetPtr set2,
-			     int hasNullEntries)
+			     int hasNullEntries, xmlXPathContextPtr ctxt)
 {
+	if (ctxt->aborted) {
+		return set1;
+	}
     if ((set1 == NULL) && (hasNullEntries == 0)) {
 	/*
 	* Note that doing a memcpy of the list, namespace nodes are
@@ -3853,6 +3857,9 @@ xmlXPathNodeSetMergeAndClear(xmlNodeSetPtr set1, xmlNodeSetPtr set2,
 	}
     } else {
 	int i, j, initNbSet1;
+	struct timeval now;
+	long count = 0;
+	
 	xmlNodePtr n1, n2;
 
 	if (set1 == NULL)
@@ -3872,6 +3879,18 @@ xmlXPathNodeSetMergeAndClear(xmlNodeSetPtr set1, xmlNodeSetPtr set2,
 	    * Skip duplicates.
 	    */
 	    for (j = 0; j < initNbSet1; j++) {
+		if (ctxt->deadline > 0) {
+			count ++;
+			if (count >= 1000000L) {
+				count = 0;
+				gettimeofday(&now, NULL);
+				if (now.tv_sec >= ctxt->deadline) {
+					printf("\n\naborted merge\n\n");
+					ctxt->aborted = 1;
+					return set1;
+				}
+			}	
+		}
 		n1 = set1->nodeTab[j];
 		if (n1 == n2) {
 		    goto skip_node;
@@ -3945,8 +3964,11 @@ skip_node:
  */
 static xmlNodeSetPtr
 xmlXPathNodeSetMergeAndClearNoDupls(xmlNodeSetPtr set1, xmlNodeSetPtr set2,
-				    int hasNullEntries)
+				    int hasNullEntries, xmlXPathContextPtr ctxt)
 {
+	if (ctxt->aborted) {
+		return set1;
+	}
     if (set2 == NULL)
 	return(set1);
     if ((set1 == NULL) && (hasNullEntries == 0)) {
@@ -5991,6 +6013,7 @@ xmlXPathConvertBoolean(xmlXPathObjectPtr val) {
 xmlXPathContextPtr
 xmlXPathNewContext(xmlDocPtr doc) {
     xmlXPathContextPtr ret;
+	struct timeval now;
 
     ret = (xmlXPathContextPtr) xmlMalloc(sizeof(xmlXPathContext));
     if (ret == NULL) {
@@ -6019,6 +6042,9 @@ xmlXPathNewContext(xmlDocPtr doc) {
     ret->contextSize = -1;
     ret->proximityPosition = -1;
 
+	ret->deadline = 0;
+	ret->aborted = 0;
+
 #ifdef XP_DEFAULT_CACHE_ON
     if (xmlXPathContextSetCache(ret, 1, -1, 0) == -1) {
 	xmlXPathFreeContext(ret);
@@ -6032,6 +6058,19 @@ xmlXPathNewContext(xmlDocPtr doc) {
 }
 
 /**
+ * xmlXPathContextSetDeadline:
+ * @ctxt:  the context to set a deadline for xpath evaluation
+ * @deadline: a deadline in seconds (from epoch)
+ *
+ * set a deadline for xpath evaluation
+ */
+void
+xmlXPathContextSetDeadline(xmlXPathContextPtr ctxt, time_t deadline) {
+    if (ctxt == NULL) return;
+	ctxt->deadline = deadline;
+}
+
+/**
  * xmlXPathFreeContext:
  * @ctxt:  the context to free
  *
@@ -7509,7 +7548,7 @@ typedef xmlNodePtr (*xmlXPathTraversalFunctionExt)
  * Used for merging node sets in xmlXPathCollectAndTest().
  */
 typedef xmlNodeSetPtr (*xmlXPathNodeSetMergeFunction)
-		    (xmlNodeSetPtr, xmlNodeSetPtr, int);
+		    (xmlNodeSetPtr, xmlNodeSetPtr, int, xmlXPathContextPtr);
 
 
 /**
@@ -12402,8 +12441,16 @@ axis_range_end: /* ----------------------------------------------------- */
 	if (outSeq == NULL) {
 	    outSeq = seq;
 	    seq = NULL;
-	} else
-	    outSeq = mergeAndClear(outSeq, seq, 0);
+	} else {
+	    outSeq = mergeAndClear(outSeq, seq, 0, ctxt->context);
+		if (ctxt->context->aborted == 1) {
+			xmlXPathCompExprPtr xpathComp = ctxt->comp;
+			xmlGenericError(xmlGenericErrorContext,
+			"\nResult Set Too Large to Evaluate: %s\n", xpathComp->expr);
+			ctxt->context->aborted = 2;
+			goto error;
+		}
+	}
 	/*
 	* Break if only a true/false result was requested.
 	*/
@@ -12419,8 +12466,16 @@ first_hit: /* ---------------------------------------------------------- */
 	if (outSeq == NULL) {
 	    outSeq = seq;
 	    seq = NULL;
-	} else
-	    outSeq = mergeAndClear(outSeq, seq, 0);
+	} else {
+	    outSeq = mergeAndClear(outSeq, seq, 0, ctxt->context);
+		if (ctxt->context->aborted == 1) {
+			xmlXPathCompExprPtr xpathComp = ctxt->comp;
+			xmlGenericError(xmlGenericErrorContext,
+			"\nResult Set Too Large to Evaluate: %s\n", xpathComp->expr);
+			ctxt->context->aborted = 2;
+			goto error;
+		}
+	}
 	break;
 
 #ifdef DEBUG_STEP
@@ -12491,14 +12546,29 @@ apply_predicates: /* --------------------------------------------------- */
 			* We need to merge and clear here, since
 			* the sequence will contained NULLed entries.
 			*/
-			outSeq = mergeAndClear(NULL, seq, 1);
+			outSeq = mergeAndClear(NULL, seq, 1, ctxt->context);
+			if (ctxt->context->aborted == 1) {
+				xmlXPathCompExprPtr xpathComp = ctxt->comp;
+				xmlGenericError(xmlGenericErrorContext,
+				"\nResult Set Too Large to Evaluate: %s\n", xpathComp->expr);
+				ctxt->context->aborted = 2;
+				goto error;
+			}
 		    } else {
 			outSeq = seq;
 			seq = NULL;
 		    }
-		} else
+		} else {
 		    outSeq = mergeAndClear(outSeq, seq,
-			(size != newSize) ? 1: 0);
+			(size != newSize) ? 1: 0, ctxt->context);
+			if (ctxt->context->aborted == 1) {
+				xmlXPathCompExprPtr xpathComp = ctxt->comp;
+				xmlGenericError(xmlGenericErrorContext,
+				"\nResult Set Too Large to Evaluate: %s\n", xpathComp->expr);
+				ctxt->context->aborted = 2;
+				goto error;
+			}
+		}
 		/*
 		* Break if only a true/false result was requested.
 		*/
@@ -12513,7 +12583,14 @@ apply_predicates: /* --------------------------------------------------- */
 		outSeq = seq;
 		seq = NULL;
 	    } else {
-		outSeq = mergeAndClear(outSeq, seq, 0);
+			outSeq = mergeAndClear(outSeq, seq, 0, ctxt->context);
+			if (ctxt->context->aborted == 1) {
+				xmlXPathCompExprPtr xpathComp = ctxt->comp;
+				xmlGenericError(xmlGenericErrorContext,
+				"\nResult Set Too Large to Evaluate: %s\n", xpathComp->expr);
+				ctxt->context->aborted = 2;
+				goto error;
+			}
 	    }
 	}
     }
