0006-Disallow-namespace-nodes-in-XPointer-ranges.patch 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249
  1. From c1d1f7121194036608bf555f08d3062a36fd344b Mon Sep 17 00:00:00 2001
  2. From: Nick Wellnhofer <wellnhofer@aevum.de>
  3. Date: Tue, 28 Jun 2016 18:34:52 +0200
  4. Subject: [PATCH] Disallow namespace nodes in XPointer ranges
  5. Namespace nodes must be copied to avoid use-after-free errors.
  6. But they don't necessarily have a physical representation in a
  7. document, so simply disallow them in XPointer ranges.
  8. Found with afl-fuzz.
  9. Fixes CVE-2016-4658.
  10. ---
  11. xpointer.c | 149 +++++++++++++++++++++++--------------------------------------
  12. 1 file changed, 56 insertions(+), 93 deletions(-)
  13. diff --git a/xpointer.c b/xpointer.c
  14. index a7b03fb..694d120 100644
  15. --- a/xpointer.c
  16. +++ b/xpointer.c
  17. @@ -320,6 +320,45 @@ xmlXPtrRangesEqual(xmlXPathObjectPtr range1, xmlXPathObjectPtr range2) {
  18. }
  19. /**
  20. + * xmlXPtrNewRangeInternal:
  21. + * @start: the starting node
  22. + * @startindex: the start index
  23. + * @end: the ending point
  24. + * @endindex: the ending index
  25. + *
  26. + * Internal function to create a new xmlXPathObjectPtr of type range
  27. + *
  28. + * Returns the newly created object.
  29. + */
  30. +static xmlXPathObjectPtr
  31. +xmlXPtrNewRangeInternal(xmlNodePtr start, int startindex,
  32. + xmlNodePtr end, int endindex) {
  33. + xmlXPathObjectPtr ret;
  34. +
  35. + /*
  36. + * Namespace nodes must be copied (see xmlXPathNodeSetDupNs).
  37. + * Disallow them for now.
  38. + */
  39. + if ((start != NULL) && (start->type == XML_NAMESPACE_DECL))
  40. + return(NULL);
  41. + if ((end != NULL) && (end->type == XML_NAMESPACE_DECL))
  42. + return(NULL);
  43. +
  44. + ret = (xmlXPathObjectPtr) xmlMalloc(sizeof(xmlXPathObject));
  45. + if (ret == NULL) {
  46. + xmlXPtrErrMemory("allocating range");
  47. + return(NULL);
  48. + }
  49. + memset(ret, 0, sizeof(xmlXPathObject));
  50. + ret->type = XPATH_RANGE;
  51. + ret->user = start;
  52. + ret->index = startindex;
  53. + ret->user2 = end;
  54. + ret->index2 = endindex;
  55. + return(ret);
  56. +}
  57. +
  58. +/**
  59. * xmlXPtrNewRange:
  60. * @start: the starting node
  61. * @startindex: the start index
  62. @@ -344,17 +383,7 @@ xmlXPtrNewRange(xmlNodePtr start, int startindex,
  63. if (endindex < 0)
  64. return(NULL);
  65. - ret = (xmlXPathObjectPtr) xmlMalloc(sizeof(xmlXPathObject));
  66. - if (ret == NULL) {
  67. - xmlXPtrErrMemory("allocating range");
  68. - return(NULL);
  69. - }
  70. - memset(ret, 0 , (size_t) sizeof(xmlXPathObject));
  71. - ret->type = XPATH_RANGE;
  72. - ret->user = start;
  73. - ret->index = startindex;
  74. - ret->user2 = end;
  75. - ret->index2 = endindex;
  76. + ret = xmlXPtrNewRangeInternal(start, startindex, end, endindex);
  77. xmlXPtrRangeCheckOrder(ret);
  78. return(ret);
  79. }
  80. @@ -381,17 +410,8 @@ xmlXPtrNewRangePoints(xmlXPathObjectPtr start, xmlXPathObjectPtr end) {
  81. if (end->type != XPATH_POINT)
  82. return(NULL);
  83. - ret = (xmlXPathObjectPtr) xmlMalloc(sizeof(xmlXPathObject));
  84. - if (ret == NULL) {
  85. - xmlXPtrErrMemory("allocating range");
  86. - return(NULL);
  87. - }
  88. - memset(ret, 0 , (size_t) sizeof(xmlXPathObject));
  89. - ret->type = XPATH_RANGE;
  90. - ret->user = start->user;
  91. - ret->index = start->index;
  92. - ret->user2 = end->user;
  93. - ret->index2 = end->index;
  94. + ret = xmlXPtrNewRangeInternal(start->user, start->index, end->user,
  95. + end->index);
  96. xmlXPtrRangeCheckOrder(ret);
  97. return(ret);
  98. }
  99. @@ -416,17 +436,7 @@ xmlXPtrNewRangePointNode(xmlXPathObjectPtr start, xmlNodePtr end) {
  100. if (start->type != XPATH_POINT)
  101. return(NULL);
  102. - ret = (xmlXPathObjectPtr) xmlMalloc(sizeof(xmlXPathObject));
  103. - if (ret == NULL) {
  104. - xmlXPtrErrMemory("allocating range");
  105. - return(NULL);
  106. - }
  107. - memset(ret, 0 , (size_t) sizeof(xmlXPathObject));
  108. - ret->type = XPATH_RANGE;
  109. - ret->user = start->user;
  110. - ret->index = start->index;
  111. - ret->user2 = end;
  112. - ret->index2 = -1;
  113. + ret = xmlXPtrNewRangeInternal(start->user, start->index, end, -1);
  114. xmlXPtrRangeCheckOrder(ret);
  115. return(ret);
  116. }
  117. @@ -453,17 +463,7 @@ xmlXPtrNewRangeNodePoint(xmlNodePtr start, xmlXPathObjectPtr end) {
  118. if (end->type != XPATH_POINT)
  119. return(NULL);
  120. - ret = (xmlXPathObjectPtr) xmlMalloc(sizeof(xmlXPathObject));
  121. - if (ret == NULL) {
  122. - xmlXPtrErrMemory("allocating range");
  123. - return(NULL);
  124. - }
  125. - memset(ret, 0 , (size_t) sizeof(xmlXPathObject));
  126. - ret->type = XPATH_RANGE;
  127. - ret->user = start;
  128. - ret->index = -1;
  129. - ret->user2 = end->user;
  130. - ret->index2 = end->index;
  131. + ret = xmlXPtrNewRangeInternal(start, -1, end->user, end->index);
  132. xmlXPtrRangeCheckOrder(ret);
  133. return(ret);
  134. }
  135. @@ -486,17 +486,7 @@ xmlXPtrNewRangeNodes(xmlNodePtr start, xmlNodePtr end) {
  136. if (end == NULL)
  137. return(NULL);
  138. - ret = (xmlXPathObjectPtr) xmlMalloc(sizeof(xmlXPathObject));
  139. - if (ret == NULL) {
  140. - xmlXPtrErrMemory("allocating range");
  141. - return(NULL);
  142. - }
  143. - memset(ret, 0 , (size_t) sizeof(xmlXPathObject));
  144. - ret->type = XPATH_RANGE;
  145. - ret->user = start;
  146. - ret->index = -1;
  147. - ret->user2 = end;
  148. - ret->index2 = -1;
  149. + ret = xmlXPtrNewRangeInternal(start, -1, end, -1);
  150. xmlXPtrRangeCheckOrder(ret);
  151. return(ret);
  152. }
  153. @@ -516,17 +506,7 @@ xmlXPtrNewCollapsedRange(xmlNodePtr start) {
  154. if (start == NULL)
  155. return(NULL);
  156. - ret = (xmlXPathObjectPtr) xmlMalloc(sizeof(xmlXPathObject));
  157. - if (ret == NULL) {
  158. - xmlXPtrErrMemory("allocating range");
  159. - return(NULL);
  160. - }
  161. - memset(ret, 0 , (size_t) sizeof(xmlXPathObject));
  162. - ret->type = XPATH_RANGE;
  163. - ret->user = start;
  164. - ret->index = -1;
  165. - ret->user2 = NULL;
  166. - ret->index2 = -1;
  167. + ret = xmlXPtrNewRangeInternal(start, -1, NULL, -1);
  168. return(ret);
  169. }
  170. @@ -541,6 +521,8 @@ xmlXPtrNewCollapsedRange(xmlNodePtr start) {
  171. */
  172. xmlXPathObjectPtr
  173. xmlXPtrNewRangeNodeObject(xmlNodePtr start, xmlXPathObjectPtr end) {
  174. + xmlNodePtr endNode;
  175. + int endIndex;
  176. xmlXPathObjectPtr ret;
  177. if (start == NULL)
  178. @@ -549,7 +531,12 @@ xmlXPtrNewRangeNodeObject(xmlNodePtr start, xmlXPathObjectPtr end) {
  179. return(NULL);
  180. switch (end->type) {
  181. case XPATH_POINT:
  182. + endNode = end->user;
  183. + endIndex = end->index;
  184. + break;
  185. case XPATH_RANGE:
  186. + endNode = end->user2;
  187. + endIndex = end->index2;
  188. break;
  189. case XPATH_NODESET:
  190. /*
  191. @@ -557,39 +544,15 @@ xmlXPtrNewRangeNodeObject(xmlNodePtr start, xmlXPathObjectPtr end) {
  192. */
  193. if (end->nodesetval->nodeNr <= 0)
  194. return(NULL);
  195. + endNode = end->nodesetval->nodeTab[end->nodesetval->nodeNr - 1];
  196. + endIndex = -1;
  197. break;
  198. default:
  199. /* TODO */
  200. return(NULL);
  201. }
  202. - ret = (xmlXPathObjectPtr) xmlMalloc(sizeof(xmlXPathObject));
  203. - if (ret == NULL) {
  204. - xmlXPtrErrMemory("allocating range");
  205. - return(NULL);
  206. - }
  207. - memset(ret, 0 , (size_t) sizeof(xmlXPathObject));
  208. - ret->type = XPATH_RANGE;
  209. - ret->user = start;
  210. - ret->index = -1;
  211. - switch (end->type) {
  212. - case XPATH_POINT:
  213. - ret->user2 = end->user;
  214. - ret->index2 = end->index;
  215. - break;
  216. - case XPATH_RANGE:
  217. - ret->user2 = end->user2;
  218. - ret->index2 = end->index2;
  219. - break;
  220. - case XPATH_NODESET: {
  221. - ret->user2 = end->nodesetval->nodeTab[end->nodesetval->nodeNr - 1];
  222. - ret->index2 = -1;
  223. - break;
  224. - }
  225. - default:
  226. - STRANGE
  227. - return(NULL);
  228. - }
  229. + ret = xmlXPtrNewRangeInternal(start, -1, endNode, endIndex);
  230. xmlXPtrRangeCheckOrder(ret);
  231. return(ret);
  232. }
  233. --
  234. 2.10.1