From fa33bf317aa9b455e08b211252092dd9110c49fb Mon Sep 17 00:00:00 2001
From: Nick Wellnhofer <wellnhofer@aevum.de>
Date: Thu, 25 May 2017 00:45:10 +0200
Subject: [PATCH 08/13] Improve restoring of context size and position

Restore context size and position where it is modified, not in
seemingly random places.
---
 xpath.c | 133 ++++++++++++++++++++++----------------------------------
 1 file changed, 53 insertions(+), 80 deletions(-)

diff --git a/xpath.c b/xpath.c
index 4b9faaf6..9d223977 100644
--- a/xpath.c
+++ b/xpath.c
@@ -11661,6 +11661,7 @@ xmlXPathCompOpEvalPredicate(xmlXPathParserContextPtr ctxt,
 	xmlXPathContextPtr xpctxt = ctxt->context;
 	xmlNodePtr contextNode, oldContextNode;
 	xmlDocPtr oldContextDoc;
+        int oldcs, oldpp;
 	int i, res, contextPos = 0, newContextSize;
 	xmlXPathStepOpPtr exprOp;
 	xmlXPathObjectPtr contextObj = NULL, exprRes = NULL;
@@ -11697,6 +11698,8 @@ xmlXPathCompOpEvalPredicate(xmlXPathParserContextPtr ctxt,
 	*/
 	oldContextNode = xpctxt->node;
 	oldContextDoc = xpctxt->doc;
+        oldcs = xpctxt->contextSize;
+        oldpp = xpctxt->proximityPosition;
 	/*
 	* Get the expression of this predicate.
 	*/
@@ -11783,8 +11786,8 @@ evaluation_exit:
 	*/
 	xpctxt->node = oldContextNode;
 	xpctxt->doc = oldContextDoc;
-	xpctxt->contextSize = -1;
-	xpctxt->proximityPosition = -1;
+	xpctxt->contextSize = oldcs;
+	xpctxt->proximityPosition = oldpp;
 	return(newContextSize);
     }
     return(contextSize);
@@ -11827,6 +11830,7 @@ xmlXPathCompOpEvalPositionalPredicate(xmlXPathParserContextPtr ctxt,
 	return (contextSize);
     } else {
 	xmlDocPtr oldContextDoc;
+        int oldcs, oldpp;
 	int i, pos = 0, newContextSize = 0, contextPos = 0, res;
 	xmlXPathStepOpPtr exprOp;
 	xmlXPathObjectPtr contextObj = NULL, exprRes = NULL;
@@ -11847,6 +11851,8 @@ xmlXPathCompOpEvalPositionalPredicate(xmlXPathParserContextPtr ctxt,
 	*/
 	oldContextNode = xpctxt->node;
 	oldContextDoc = xpctxt->doc;
+        oldcs = xpctxt->contextSize;
+        oldpp = xpctxt->proximityPosition;
 	/*
 	* Get the expression of this predicate.
 	*/
@@ -11983,8 +11989,8 @@ evaluation_exit:
 	*/
 	xpctxt->node = oldContextNode;
 	xpctxt->doc = oldContextDoc;
-	xpctxt->contextSize = -1;
-	xpctxt->proximityPosition = -1;
+	xpctxt->contextSize = oldcs;
+	xpctxt->proximityPosition = oldpp;
 	return(newContextSize);
     }
     return(contextSize);
@@ -12829,8 +12835,6 @@ xmlXPathCompOpEvalLast(xmlXPathParserContextPtr ctxt, xmlXPathStepOpPtr op,
     int total = 0, cur;
     xmlXPathCompExprPtr comp;
     xmlXPathObjectPtr arg1, arg2;
-    int pp;
-    int cs;
 
     CHECK_ERROR0;
     comp = ctxt->comp;
@@ -12838,8 +12842,6 @@ xmlXPathCompOpEvalLast(xmlXPathParserContextPtr ctxt, xmlXPathStepOpPtr op,
         case XPATH_OP_END:
             return (0);
         case XPATH_OP_UNION:
-	    pp = ctxt->context->proximityPosition;
-	    cs = ctxt->context->contextSize;
             total =
                 xmlXPathCompOpEvalLast(ctxt, &comp->steps[op->ch1], last);
 	    CHECK_ERROR0;
@@ -12857,8 +12859,6 @@ xmlXPathCompOpEvalLast(xmlXPathParserContextPtr ctxt, xmlXPathStepOpPtr op,
                                                      nodesetval->nodeNr -
                                                      1];
             }
-	    ctxt->context->proximityPosition = pp;
-	    ctxt->context->contextSize = cs;
             cur =
                 xmlXPathCompOpEvalLast(ctxt, &comp->steps[op->ch2], last);
 	    CHECK_ERROR0;
@@ -12942,6 +12942,7 @@ xmlXPathCompOpEvalFilterFirst(xmlXPathParserContextPtr ctxt,
     xmlNodeSetPtr oldset;
     xmlNodePtr oldnode;
     xmlDocPtr oldDoc;
+    int oldcs, oldpp;
     int i;
 
     CHECK_ERROR0;
@@ -13015,6 +13016,8 @@ xmlXPathCompOpEvalFilterFirst(xmlXPathParserContextPtr ctxt,
 	obj = valuePop(ctxt);
 	oldlocset = obj->user;
         oldnode = ctxt->context->node;
+        oldcs = ctxt->context->contextSize;
+        oldpp = ctxt->context->proximityPosition;
 
 	newlocset = xmlXPtrLocationSetCreate(NULL);
 
@@ -13039,9 +13042,8 @@ xmlXPathCompOpEvalFilterFirst(xmlXPathParserContextPtr ctxt,
 	    if (op->ch2 != -1)
 		total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch2]);
 	    if (ctxt->error != XPATH_EXPRESSION_OK) {
-		xmlXPathFreeObject(obj);
-                ctxt->context->node = oldnode;
-		return(0);
+                xmlXPtrFreeLocationSet(newlocset);
+                goto xptr_error;
 	    }
 	    /*
 	    * The result of the evaluation need to be tested to
@@ -13083,11 +13085,12 @@ xmlXPathCompOpEvalFilterFirst(xmlXPathParserContextPtr ctxt,
 	/*
 	* The result is used as the new evaluation locset.
 	*/
-	xmlXPathReleaseObject(ctxt->context, obj);
-	ctxt->context->contextSize = -1;
-	ctxt->context->proximityPosition = -1;
 	valuePush(ctxt, xmlXPtrWrapLocationSet(newlocset));
+xptr_error:
+	xmlXPathReleaseObject(ctxt->context, obj);
 	ctxt->context->node = oldnode;
+	ctxt->context->contextSize = oldcs;
+	ctxt->context->proximityPosition = oldpp;
 	return (total);
     }
 #endif /* LIBXML_XPTR_ENABLED */
@@ -13108,6 +13111,8 @@ xmlXPathCompOpEvalFilterFirst(xmlXPathParserContextPtr ctxt,
         oldset = obj->nodesetval;
         oldnode = ctxt->context->node;
         oldDoc = ctxt->context->doc;
+        oldcs = ctxt->context->contextSize;
+        oldpp = ctxt->context->proximityPosition;
 
 	/*
 	* Initialize the new set.
@@ -13142,9 +13147,7 @@ xmlXPathCompOpEvalFilterFirst(xmlXPathParserContextPtr ctxt,
 		total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch2]);
 	    if (ctxt->error != XPATH_EXPRESSION_OK) {
 		xmlXPathFreeNodeSet(newset);
-		xmlXPathFreeObject(obj);
-	        ctxt->context->node = oldnode;
-		return(0);
+                goto error;
 	    }
 	    /*
 	    * The result of the evaluation needs to be tested to
@@ -13185,12 +13188,13 @@ xmlXPathCompOpEvalFilterFirst(xmlXPathParserContextPtr ctxt,
 	/*
 	* The result is used as the new evaluation set.
 	*/
+	valuePush(ctxt, xmlXPathCacheWrapNodeSet(ctxt->context, newset));
+error:
 	xmlXPathReleaseObject(ctxt->context, obj);
-	ctxt->context->contextSize = -1;
-	ctxt->context->proximityPosition = -1;
 	ctxt->context->node = oldnode;
 	ctxt->context->doc = oldDoc;
-	valuePush(ctxt, xmlXPathCacheWrapNodeSet(ctxt->context, newset));
+	ctxt->context->contextSize = oldcs;
+	ctxt->context->proximityPosition = oldpp;
     }
     return(total);
 }
@@ -13211,8 +13215,6 @@ xmlXPathCompOpEval(xmlXPathParserContextPtr ctxt, xmlXPathStepOpPtr op)
     int equal, ret;
     xmlXPathCompExprPtr comp;
     xmlXPathObjectPtr arg1, arg2;
-    int pp;
-    int cs;
 
     CHECK_ERROR0;
     comp = ctxt->comp;
@@ -13220,16 +13222,12 @@ xmlXPathCompOpEval(xmlXPathParserContextPtr ctxt, xmlXPathStepOpPtr op)
         case XPATH_OP_END:
             return (0);
         case XPATH_OP_AND:
-	    pp = ctxt->context->proximityPosition;
-	    cs = ctxt->context->contextSize;
             total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]);
 	    CHECK_ERROR0;
             xmlXPathBooleanFunction(ctxt, 1);
             if ((ctxt->value == NULL) || (ctxt->value->boolval == 0))
                 return (total);
             arg2 = valuePop(ctxt);
-	    ctxt->context->proximityPosition = pp;
-	    ctxt->context->contextSize = cs;
             total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch2]);
 	    if (ctxt->error) {
 		xmlXPathFreeObject(arg2);
@@ -13242,16 +13240,12 @@ xmlXPathCompOpEval(xmlXPathParserContextPtr ctxt, xmlXPathStepOpPtr op)
 	    xmlXPathReleaseObject(ctxt->context, arg2);
             return (total);
         case XPATH_OP_OR:
-	    pp = ctxt->context->proximityPosition;
-	    cs = ctxt->context->contextSize;
             total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]);
 	    CHECK_ERROR0;
             xmlXPathBooleanFunction(ctxt, 1);
             if ((ctxt->value == NULL) || (ctxt->value->boolval == 1))
                 return (total);
             arg2 = valuePop(ctxt);
-	    ctxt->context->proximityPosition = pp;
-	    ctxt->context->contextSize = cs;
             total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch2]);
 	    if (ctxt->error) {
 		xmlXPathFreeObject(arg2);
@@ -13264,12 +13258,8 @@ xmlXPathCompOpEval(xmlXPathParserContextPtr ctxt, xmlXPathStepOpPtr op)
 	    xmlXPathReleaseObject(ctxt->context, arg2);
             return (total);
         case XPATH_OP_EQUAL:
-	    pp = ctxt->context->proximityPosition;
-	    cs = ctxt->context->contextSize;
             total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]);
 	    CHECK_ERROR0;
-	    ctxt->context->proximityPosition = pp;
-	    ctxt->context->contextSize = cs;
             total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch2]);
 	    CHECK_ERROR0;
 	    if (op->value)
@@ -13279,25 +13269,17 @@ xmlXPathCompOpEval(xmlXPathParserContextPtr ctxt, xmlXPathStepOpPtr op)
 	    valuePush(ctxt, xmlXPathCacheNewBoolean(ctxt->context, equal));
             return (total);
         case XPATH_OP_CMP:
-	    pp = ctxt->context->proximityPosition;
-	    cs = ctxt->context->contextSize;
             total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]);
 	    CHECK_ERROR0;
-	    ctxt->context->proximityPosition = pp;
-	    ctxt->context->contextSize = cs;
             total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch2]);
 	    CHECK_ERROR0;
             ret = xmlXPathCompareValues(ctxt, op->value, op->value2);
 	    valuePush(ctxt, xmlXPathCacheNewBoolean(ctxt->context, ret));
             return (total);
         case XPATH_OP_PLUS:
-	    pp = ctxt->context->proximityPosition;
-	    cs = ctxt->context->contextSize;
             total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]);
 	    CHECK_ERROR0;
             if (op->ch2 != -1) {
-		ctxt->context->proximityPosition = pp;
-		ctxt->context->contextSize = cs;
                 total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch2]);
 	    }
 	    CHECK_ERROR0;
@@ -13313,12 +13295,8 @@ xmlXPathCompOpEval(xmlXPathParserContextPtr ctxt, xmlXPathStepOpPtr op)
             }
             return (total);
         case XPATH_OP_MULT:
-	    pp = ctxt->context->proximityPosition;
-	    cs = ctxt->context->contextSize;
             total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]);
 	    CHECK_ERROR0;
-	    ctxt->context->proximityPosition = pp;
-	    ctxt->context->contextSize = cs;
             total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch2]);
 	    CHECK_ERROR0;
             if (op->value == 0)
@@ -13329,12 +13307,8 @@ xmlXPathCompOpEval(xmlXPathParserContextPtr ctxt, xmlXPathStepOpPtr op)
                 xmlXPathModValues(ctxt);
             return (total);
         case XPATH_OP_UNION:
-	    pp = ctxt->context->proximityPosition;
-	    cs = ctxt->context->contextSize;
             total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]);
 	    CHECK_ERROR0;
-	    ctxt->context->proximityPosition = pp;
-	    ctxt->context->contextSize = cs;
             total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch2]);
 	    CHECK_ERROR0;
 
@@ -13489,18 +13463,12 @@ xmlXPathCompOpEval(xmlXPathParserContextPtr ctxt, xmlXPathStepOpPtr op)
                 return (total);
             }
         case XPATH_OP_ARG:
-	    pp = ctxt->context->proximityPosition;
-	    cs = ctxt->context->contextSize;
             if (op->ch1 != -1) {
                 total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]);
-                ctxt->context->contextSize = cs;
-                ctxt->context->proximityPosition = pp;
 	        CHECK_ERROR0;
             }
             if (op->ch2 != -1) {
                 total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch2]);
-                ctxt->context->contextSize = cs;
-                ctxt->context->proximityPosition = pp;
 	        CHECK_ERROR0;
 	    }
             return (total);
@@ -13512,6 +13480,7 @@ xmlXPathCompOpEval(xmlXPathParserContextPtr ctxt, xmlXPathStepOpPtr op)
                 xmlNodeSetPtr oldset;
                 xmlNodePtr oldnode;
 		xmlDocPtr oldDoc;
+                int oldcs, oldpp;
                 int i;
 
                 /*
@@ -13636,6 +13605,8 @@ xmlXPathCompOpEval(xmlXPathParserContextPtr ctxt, xmlXPathStepOpPtr op)
                     obj = valuePop(ctxt);
                     oldlocset = obj->user;
                     oldnode = ctxt->context->node;
+                    oldcs = ctxt->context->contextSize;
+                    oldpp = ctxt->context->proximityPosition;
 
                     newlocset = xmlXPtrLocationSetCreate(NULL);
 
@@ -13656,9 +13627,8 @@ xmlXPathCompOpEval(xmlXPathParserContextPtr ctxt, xmlXPathStepOpPtr op)
                                 xmlXPathCompOpEval(ctxt,
                                                    &comp->steps[op->ch2]);
 			if (ctxt->error != XPATH_EXPRESSION_OK) {
-			    xmlXPathFreeObject(obj);
-                            ctxt->context->node = oldnode;
-			    return(0);
+                            xmlXPtrFreeLocationSet(newlocset);
+                            goto filter_xptr_error;
 			}
 
                         /*
@@ -13687,11 +13657,12 @@ xmlXPathCompOpEval(xmlXPathParserContextPtr ctxt, xmlXPathStepOpPtr op)
                     /*
                      * The result is used as the new evaluation locset.
                      */
-		    xmlXPathReleaseObject(ctxt->context, obj);
-                    ctxt->context->contextSize = -1;
-                    ctxt->context->proximityPosition = -1;
                     valuePush(ctxt, xmlXPtrWrapLocationSet(newlocset));
+filter_xptr_error:
+		    xmlXPathReleaseObject(ctxt->context, obj);
                     ctxt->context->node = oldnode;
+                    ctxt->context->contextSize = oldcs;
+                    ctxt->context->proximityPosition = oldpp;
                     return (total);
                 }
 #endif /* LIBXML_XPTR_ENABLED */
@@ -13709,6 +13680,8 @@ xmlXPathCompOpEval(xmlXPathParserContextPtr ctxt, xmlXPathStepOpPtr op)
                     oldset = obj->nodesetval;
                     oldnode = ctxt->context->node;
                     oldDoc = ctxt->context->doc;
+                    oldcs = ctxt->context->contextSize;
+                    oldpp = ctxt->context->proximityPosition;
 		    tmp = NULL;
                     /*
                      * Initialize the new set.
@@ -13774,9 +13747,7 @@ xmlXPathCompOpEval(xmlXPathParserContextPtr ctxt, xmlXPathStepOpPtr op)
                                                    &comp->steps[op->ch2]);
 			if (ctxt->error != XPATH_EXPRESSION_OK) {
 			    xmlXPathFreeNodeSet(newset);
-			    xmlXPathFreeObject(obj);
-                            ctxt->context->node = oldnode;
-			    return(0);
+                            goto filter_error;
 			}
 
                         /*
@@ -13816,13 +13787,14 @@ xmlXPathCompOpEval(xmlXPathParserContextPtr ctxt, xmlXPathStepOpPtr op)
                     /*
                      * The result is used as the new evaluation set.
                      */
+		    valuePush(ctxt,
+			xmlXPathCacheWrapNodeSet(ctxt->context, newset));
+filter_error:
 		    xmlXPathReleaseObject(ctxt->context, obj);
-                    ctxt->context->contextSize = -1;
-                    ctxt->context->proximityPosition = -1;
 		    ctxt->context->node = oldnode;
 		    ctxt->context->doc = oldDoc;
-		    valuePush(ctxt,
-			xmlXPathCacheWrapNodeSet(ctxt->context, newset));
+                    ctxt->context->contextSize = oldcs;
+                    ctxt->context->proximityPosition = oldpp;
                 }
                 return (total);
             }
@@ -13847,6 +13819,8 @@ xmlXPathCompOpEval(xmlXPathParserContextPtr ctxt, xmlXPathStepOpPtr op)
 		    xmlLocationSetPtr oldlocset;
                 xmlNodeSetPtr oldset;
                 xmlNodePtr oldnode = ctxt->context->node;
+                int oldcs = ctxt->context->contextSize;
+                int oldpp = ctxt->context->proximityPosition;
                 int i, j;
 
                 if (op->ch1 != -1) {
@@ -13894,9 +13868,8 @@ xmlXPathCompOpEval(xmlXPathParserContextPtr ctxt, xmlXPathStepOpPtr op)
                                 xmlXPathCompOpEval(ctxt,
                                                    &comp->steps[op->ch2]);
 			if (ctxt->error != XPATH_EXPRESSION_OK) {
-			    xmlXPathFreeObject(obj);
-                            ctxt->context->node = oldnode;
-			    return(0);
+                            xmlXPtrFreeLocationSet(newlocset);
+                            goto rangeto_error;
 			}
 
                         res = valuePop(ctxt);
@@ -13958,9 +13931,8 @@ xmlXPathCompOpEval(xmlXPathParserContextPtr ctxt, xmlXPathStepOpPtr op)
                                     xmlXPathCompOpEval(ctxt,
                                                    &comp->steps[op->ch2]);
 			    if (ctxt->error != XPATH_EXPRESSION_OK) {
-				xmlXPathFreeObject(obj);
-                                ctxt->context->node = oldnode;
-				return(0);
+                                xmlXPtrFreeLocationSet(newlocset);
+                                goto rangeto_error;
 			    }
 
                             res = valuePop(ctxt);
@@ -13988,11 +13960,12 @@ xmlXPathCompOpEval(xmlXPathParserContextPtr ctxt, xmlXPathStepOpPtr op)
                 /*
                  * The result is used as the new evaluation set.
                  */
+                valuePush(ctxt, xmlXPtrWrapLocationSet(newlocset));
+rangeto_error:
 		xmlXPathReleaseObject(ctxt->context, obj);
                 ctxt->context->node = oldnode;
-                ctxt->context->contextSize = -1;
-                ctxt->context->proximityPosition = -1;
-                valuePush(ctxt, xmlXPtrWrapLocationSet(newlocset));
+                ctxt->context->contextSize = oldcs;
+                ctxt->context->proximityPosition = oldpp;
                 return (total);
             }
 #endif /* LIBXML_XPTR_ENABLED */
-- 
2.18.0

