libxml2-6-hardening-xpath.patch 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224
  1. From f5048b3e71fc30ad096970b8df6e7af073bae4cb Mon Sep 17 00:00:00 2001
  2. From: Daniel Veillard <veillard@redhat.com>
  3. Date: Thu, 18 Aug 2011 09:10:13 +0000
  4. Subject: Hardening of XPath evaluation
  5. Add a mechanism of frame for XPath evaluation when entering a function
  6. or a scoped evaluation, also fix a potential problem in predicate
  7. evaluation.
  8. ---
  9. diff --git a/include/libxml/xpath.h b/include/libxml/xpath.h
  10. index 1a9e30e..ddd9dd8 100644
  11. --- a/include/libxml/xpath.h
  12. +++ b/include/libxml/xpath.h
  13. @@ -68,7 +68,8 @@ typedef enum {
  14. XPATH_UNDEF_PREFIX_ERROR,
  15. XPATH_ENCODING_ERROR,
  16. XPATH_INVALID_CHAR_ERROR,
  17. - XPATH_INVALID_CTXT
  18. + XPATH_INVALID_CTXT,
  19. + XPATH_STACK_ERROR
  20. } xmlXPathError;
  21. /*
  22. @@ -380,6 +381,8 @@ struct _xmlXPathParserContext {
  23. xmlXPathCompExprPtr comp; /* the precompiled expression */
  24. int xptr; /* it this an XPointer expression */
  25. xmlNodePtr ancestor; /* used for walking preceding axis */
  26. +
  27. + int valueFrame; /* used to limit Pop on the stack */
  28. };
  29. /************************************************************************
  30. diff --git a/xpath.c b/xpath.c
  31. index b59ac5a..bcee2ea 100644
  32. --- a/xpath.c
  33. +++ b/xpath.c
  34. @@ -252,6 +252,7 @@ static const char *xmlXPathErrorMessages[] = {
  35. "Encoding error\n",
  36. "Char out of XML range\n",
  37. "Invalid or incomplete context\n",
  38. + "Stack usage errror\n",
  39. "?? Unknown error ??\n" /* Must be last in the list! */
  40. };
  41. #define MAXERRNO ((int)(sizeof(xmlXPathErrorMessages) / \
  42. @@ -2398,6 +2399,42 @@ xmlXPathCacheConvertNumber(xmlXPathContextPtr ctxt, xmlXPathObjectPtr val) {
  43. ************************************************************************/
  44. /**
  45. + * xmlXPathSetFrame:
  46. + * @ctxt: an XPath parser context
  47. + *
  48. + * Set the callee evaluation frame
  49. + *
  50. + * Returns the previous frame value to be restored once done
  51. + */
  52. +static int
  53. +xmlXPathSetFrame(xmlXPathParserContextPtr ctxt) {
  54. + int ret;
  55. +
  56. + if (ctxt == NULL)
  57. + return(0);
  58. + ret = ctxt->valueFrame;
  59. + ctxt->valueFrame = ctxt->valueNr;
  60. + return(ret);
  61. +}
  62. +
  63. +/**
  64. + * xmlXPathPopFrame:
  65. + * @ctxt: an XPath parser context
  66. + * @frame: the previous frame value
  67. + *
  68. + * Remove the callee evaluation frame
  69. + */
  70. +static void
  71. +xmlXPathPopFrame(xmlXPathParserContextPtr ctxt, int frame) {
  72. + if (ctxt == NULL)
  73. + return;
  74. + if (ctxt->valueNr < ctxt->valueFrame) {
  75. + xmlXPatherror(ctxt, __FILE__, __LINE__, XPATH_STACK_ERROR);
  76. + }
  77. + ctxt->valueFrame = frame;
  78. +}
  79. +
  80. +/**
  81. * valuePop:
  82. * @ctxt: an XPath evaluation context
  83. *
  84. @@ -2412,6 +2449,12 @@ valuePop(xmlXPathParserContextPtr ctxt)
  85. if ((ctxt == NULL) || (ctxt->valueNr <= 0))
  86. return (NULL);
  87. +
  88. + if (ctxt->valueNr <= ctxt->valueFrame) {
  89. + xmlXPatherror(ctxt, __FILE__, __LINE__, XPATH_STACK_ERROR);
  90. + return (NULL);
  91. + }
  92. +
  93. ctxt->valueNr--;
  94. if (ctxt->valueNr > 0)
  95. ctxt->value = ctxt->valueTab[ctxt->valueNr - 1];
  96. @@ -6154,6 +6197,7 @@ xmlXPathCompParserContext(xmlXPathCompExprPtr comp, xmlXPathContextPtr ctxt) {
  97. ret->valueNr = 0;
  98. ret->valueMax = 10;
  99. ret->value = NULL;
  100. + ret->valueFrame = 0;
  101. ret->context = ctxt;
  102. ret->comp = comp;
  103. @@ -11711,6 +11755,7 @@ xmlXPathCompOpEvalPositionalPredicate(xmlXPathParserContextPtr ctxt,
  104. xmlXPathObjectPtr contextObj = NULL, exprRes = NULL;
  105. xmlNodePtr oldContextNode, contextNode = NULL;
  106. xmlXPathContextPtr xpctxt = ctxt->context;
  107. + int frame;
  108. #ifdef LIBXML_XPTR_ENABLED
  109. /*
  110. @@ -11730,6 +11775,8 @@ xmlXPathCompOpEvalPositionalPredicate(xmlXPathParserContextPtr ctxt,
  111. */
  112. exprOp = &ctxt->comp->steps[op->ch2];
  113. for (i = 0; i < set->nodeNr; i++) {
  114. + xmlXPathObjectPtr tmp;
  115. +
  116. if (set->nodeTab[i] == NULL)
  117. continue;
  118. @@ -11757,23 +11804,25 @@ xmlXPathCompOpEvalPositionalPredicate(xmlXPathParserContextPtr ctxt,
  119. xmlXPathNodeSetAddUnique(contextObj->nodesetval,
  120. contextNode);
  121. + frame = xmlXPathSetFrame(ctxt);
  122. valuePush(ctxt, contextObj);
  123. res = xmlXPathCompOpEvalToBoolean(ctxt, exprOp, 1);
  124. + tmp = valuePop(ctxt);
  125. + xmlXPathPopFrame(ctxt, frame);
  126. if ((ctxt->error != XPATH_EXPRESSION_OK) || (res == -1)) {
  127. - xmlXPathObjectPtr tmp;
  128. - /* pop the result if any */
  129. - tmp = valuePop(ctxt);
  130. - if (tmp != contextObj) {
  131. + while (tmp != contextObj) {
  132. /*
  133. * Free up the result
  134. * then pop off contextObj, which will be freed later
  135. */
  136. xmlXPathReleaseObject(xpctxt, tmp);
  137. - valuePop(ctxt);
  138. + tmp = valuePop(ctxt);
  139. }
  140. goto evaluation_error;
  141. }
  142. + /* push the result back onto the stack */
  143. + valuePush(ctxt, tmp);
  144. if (res)
  145. pos++;
  146. @@ -13377,7 +13426,9 @@ xmlXPathCompOpEval(xmlXPathParserContextPtr ctxt, xmlXPathStepOpPtr op)
  147. xmlXPathFunction func;
  148. const xmlChar *oldFunc, *oldFuncURI;
  149. int i;
  150. + int frame;
  151. + frame = xmlXPathSetFrame(ctxt);
  152. if (op->ch1 != -1)
  153. total +=
  154. xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]);
  155. @@ -13385,15 +13436,18 @@ xmlXPathCompOpEval(xmlXPathParserContextPtr ctxt, xmlXPathStepOpPtr op)
  156. xmlGenericError(xmlGenericErrorContext,
  157. "xmlXPathCompOpEval: parameter error\n");
  158. ctxt->error = XPATH_INVALID_OPERAND;
  159. + xmlXPathPopFrame(ctxt, frame);
  160. return (total);
  161. }
  162. - for (i = 0; i < op->value; i++)
  163. + for (i = 0; i < op->value; i++) {
  164. if (ctxt->valueTab[(ctxt->valueNr - 1) - i] == NULL) {
  165. xmlGenericError(xmlGenericErrorContext,
  166. "xmlXPathCompOpEval: parameter error\n");
  167. ctxt->error = XPATH_INVALID_OPERAND;
  168. + xmlXPathPopFrame(ctxt, frame);
  169. return (total);
  170. }
  171. + }
  172. if (op->cache != NULL)
  173. XML_CAST_FPTR(func) = op->cache;
  174. else {
  175. @@ -13409,6 +13463,7 @@ xmlXPathCompOpEval(xmlXPathParserContextPtr ctxt, xmlXPathStepOpPtr op)
  176. xmlGenericError(xmlGenericErrorContext,
  177. "xmlXPathCompOpEval: function %s bound to undefined prefix %s\n",
  178. (char *)op->value4, (char *)op->value5);
  179. + xmlXPathPopFrame(ctxt, frame);
  180. return (total);
  181. }
  182. func = xmlXPathFunctionLookupNS(ctxt->context,
  183. @@ -13430,6 +13485,7 @@ xmlXPathCompOpEval(xmlXPathParserContextPtr ctxt, xmlXPathStepOpPtr op)
  184. func(ctxt, op->value);
  185. ctxt->context->function = oldFunc;
  186. ctxt->context->functionURI = oldFuncURI;
  187. + xmlXPathPopFrame(ctxt, frame);
  188. return (total);
  189. }
  190. case XPATH_OP_ARG:
  191. @@ -14333,6 +14389,7 @@ xmlXPathRunEval(xmlXPathParserContextPtr ctxt, int toBool)
  192. ctxt->valueNr = 0;
  193. ctxt->valueMax = 10;
  194. ctxt->value = NULL;
  195. + ctxt->valueFrame = 0;
  196. }
  197. #ifdef XPATH_STREAMING
  198. if (ctxt->comp->stream) {
  199. diff --git a/xpointer.c b/xpointer.c
  200. index 7a42d02..37afa3a 100644
  201. --- a/xpointer.c
  202. +++ b/xpointer.c
  203. @@ -1269,6 +1269,7 @@ xmlXPtrEvalXPointer(xmlXPathParserContextPtr ctxt) {
  204. ctxt->valueNr = 0;
  205. ctxt->valueMax = 10;
  206. ctxt->value = NULL;
  207. + ctxt->valueFrame = 0;
  208. }
  209. SKIP_BLANKS;
  210. if (CUR == '/') {
  211. --
  212. cgit v0.9.0.2