Change-Id: I7348878ca91c3d001dbf073780edff9eaa6af9b4
Reviewed-on: http://photon-jenkins.eng.vmware.com:8082/1596
Tested-by: gerrit-photon <photon-checkins@vmware.com>
Reviewed-by: suezzelur <anishs@vmware.com>
1 | 1 |
new file mode 100644 |
... | ... |
@@ -0,0 +1,171 @@ |
0 |
+From 9ab01a277d71f54d3143c2cf333c5c2e9aaedd9e Mon Sep 17 00:00:00 2001 |
|
1 |
+From: Nick Wellnhofer <wellnhofer@aevum.de> |
|
2 |
+Date: Tue, 28 Jun 2016 14:22:23 +0200 |
|
3 |
+Subject: Fix XPointer paths beginning with range-to |
|
4 |
+ |
|
5 |
+The old code would invoke the broken xmlXPtrRangeToFunction. range-to |
|
6 |
+isn't really a function but a special kind of location step. Remove |
|
7 |
+this function and always handle range-to in the XPath code. |
|
8 |
+ |
|
9 |
+The old xmlXPtrRangeToFunction could also be abused to trigger a |
|
10 |
+use-after-free error with the potential for remote code execution. |
|
11 |
+ |
|
12 |
+Found with afl-fuzz. |
|
13 |
+ |
|
14 |
+Fixes CVE-2016-5131. |
|
15 |
+--- |
|
16 |
+ result/XPath/xptr/vidbase | 13 ++++++++ |
|
17 |
+ test/XPath/xptr/vidbase | 1 + |
|
18 |
+ xpath.c | 7 ++++- |
|
19 |
+ xpointer.c | 76 ++++------------------------------------------- |
|
20 |
+ 4 files changed, 26 insertions(+), 71 deletions(-) |
|
21 |
+ |
|
22 |
+diff --git a/result/XPath/xptr/vidbase b/result/XPath/xptr/vidbase |
|
23 |
+index 8b9e92d..f19193e 100644 |
|
24 |
+--- a/result/XPath/xptr/vidbase |
|
25 |
+@@ -17,3 +17,16 @@ Object is a Location Set: |
|
26 |
+ To node |
|
27 |
+ ELEMENT p |
|
28 |
+ |
|
29 |
++ |
|
30 |
++======================== |
|
31 |
++Expression: xpointer(range-to(id('chapter2'))) |
|
32 |
++Object is a Location Set: |
|
33 |
++1 : Object is a range : |
|
34 |
++ From node |
|
35 |
++ / |
|
36 |
++ To node |
|
37 |
++ ELEMENT chapter |
|
38 |
++ ATTRIBUTE id |
|
39 |
++ TEXT |
|
40 |
++ content=chapter2 |
|
41 |
++ |
|
42 |
+diff --git a/test/XPath/xptr/vidbase b/test/XPath/xptr/vidbase |
|
43 |
+index b146383..884b106 100644 |
|
44 |
+--- a/test/XPath/xptr/vidbase |
|
45 |
+@@ -1,2 +1,3 @@ |
|
46 |
+ xpointer(id('chapter1')/p) |
|
47 |
+ xpointer(id('chapter1')/p[1]/range-to(following-sibling::p[2])) |
|
48 |
++xpointer(range-to(id('chapter2'))) |
|
49 |
+diff --git a/xpath.c b/xpath.c |
|
50 |
+index d992841..5a01b1b 100644 |
|
51 |
+--- a/xpath.c |
|
52 |
+@@ -10691,13 +10691,18 @@ xmlXPathCompPathExpr(xmlXPathParserContextPtr ctxt) { |
|
53 |
+ lc = 1; |
|
54 |
+ break; |
|
55 |
+ } else if ((NXT(len) == '(')) { |
|
56 |
+- /* Note Type or Function */ |
|
57 |
++ /* Node Type or Function */ |
|
58 |
+ if (xmlXPathIsNodeType(name)) { |
|
59 |
+ #ifdef DEBUG_STEP |
|
60 |
+ xmlGenericError(xmlGenericErrorContext, |
|
61 |
+ "PathExpr: Type search\n"); |
|
62 |
+ #endif |
|
63 |
+ lc = 1; |
|
64 |
++#ifdef LIBXML_XPTR_ENABLED |
|
65 |
++ } else if (ctxt->xptr && |
|
66 |
++ xmlStrEqual(name, BAD_CAST "range-to")) { |
|
67 |
++ lc = 1; |
|
68 |
++#endif |
|
69 |
+ } else { |
|
70 |
+ #ifdef DEBUG_STEP |
|
71 |
+ xmlGenericError(xmlGenericErrorContext, |
|
72 |
+diff --git a/xpointer.c b/xpointer.c |
|
73 |
+index 676c510..d74174a 100644 |
|
74 |
+--- a/xpointer.c |
|
75 |
+@@ -1332,8 +1332,6 @@ xmlXPtrNewContext(xmlDocPtr doc, xmlNodePtr here, xmlNodePtr origin) { |
|
76 |
+ ret->here = here; |
|
77 |
+ ret->origin = origin; |
|
78 |
+ |
|
79 |
+- xmlXPathRegisterFunc(ret, (xmlChar *)"range-to", |
|
80 |
+- xmlXPtrRangeToFunction); |
|
81 |
+ xmlXPathRegisterFunc(ret, (xmlChar *)"range", |
|
82 |
+ xmlXPtrRangeFunction); |
|
83 |
+ xmlXPathRegisterFunc(ret, (xmlChar *)"range-inside", |
|
84 |
+@@ -2243,76 +2241,14 @@ xmlXPtrRangeInsideFunction(xmlXPathParserContextPtr ctxt, int nargs) { |
|
85 |
+ * @nargs: the number of args |
|
86 |
+ * |
|
87 |
+ * Implement the range-to() XPointer function |
|
88 |
++ * |
|
89 |
++ * Obsolete. range-to is not a real function but a special type of location |
|
90 |
++ * step which is handled in xpath.c. |
|
91 |
+ */ |
|
92 |
+ void |
|
93 |
+-xmlXPtrRangeToFunction(xmlXPathParserContextPtr ctxt, int nargs) { |
|
94 |
+- xmlXPathObjectPtr range; |
|
95 |
+- const xmlChar *cur; |
|
96 |
+- xmlXPathObjectPtr res, obj; |
|
97 |
+- xmlXPathObjectPtr tmp; |
|
98 |
+- xmlLocationSetPtr newset = NULL; |
|
99 |
+- xmlNodeSetPtr oldset; |
|
100 |
+- int i; |
|
101 |
+- |
|
102 |
+- if (ctxt == NULL) return; |
|
103 |
+- CHECK_ARITY(1); |
|
104 |
+- /* |
|
105 |
+- * Save the expression pointer since we will have to evaluate |
|
106 |
+- * it multiple times. Initialize the new set. |
|
107 |
+- */ |
|
108 |
+- CHECK_TYPE(XPATH_NODESET); |
|
109 |
+- obj = valuePop(ctxt); |
|
110 |
+- oldset = obj->nodesetval; |
|
111 |
+- ctxt->context->node = NULL; |
|
112 |
+- |
|
113 |
+- cur = ctxt->cur; |
|
114 |
+- newset = xmlXPtrLocationSetCreate(NULL); |
|
115 |
+- |
|
116 |
+- for (i = 0; i < oldset->nodeNr; i++) { |
|
117 |
+- ctxt->cur = cur; |
|
118 |
+- |
|
119 |
+- /* |
|
120 |
+- * Run the evaluation with a node list made of a single item |
|
121 |
+- * in the nodeset. |
|
122 |
+- */ |
|
123 |
+- ctxt->context->node = oldset->nodeTab[i]; |
|
124 |
+- tmp = xmlXPathNewNodeSet(ctxt->context->node); |
|
125 |
+- valuePush(ctxt, tmp); |
|
126 |
+- |
|
127 |
+- xmlXPathEvalExpr(ctxt); |
|
128 |
+- CHECK_ERROR; |
|
129 |
+- |
|
130 |
+- /* |
|
131 |
+- * The result of the evaluation need to be tested to |
|
132 |
+- * decided whether the filter succeeded or not |
|
133 |
+- */ |
|
134 |
+- res = valuePop(ctxt); |
|
135 |
+- range = xmlXPtrNewRangeNodeObject(oldset->nodeTab[i], res); |
|
136 |
+- if (range != NULL) { |
|
137 |
+- xmlXPtrLocationSetAdd(newset, range); |
|
138 |
+- } |
|
139 |
+- |
|
140 |
+- /* |
|
141 |
+- * Cleanup |
|
142 |
+- */ |
|
143 |
+- if (res != NULL) |
|
144 |
+- xmlXPathFreeObject(res); |
|
145 |
+- if (ctxt->value == tmp) { |
|
146 |
+- res = valuePop(ctxt); |
|
147 |
+- xmlXPathFreeObject(res); |
|
148 |
+- } |
|
149 |
+- |
|
150 |
+- ctxt->context->node = NULL; |
|
151 |
+- } |
|
152 |
+- |
|
153 |
+- /* |
|
154 |
+- * The result is used as the new evaluation set. |
|
155 |
+- */ |
|
156 |
+- xmlXPathFreeObject(obj); |
|
157 |
+- ctxt->context->node = NULL; |
|
158 |
+- ctxt->context->contextSize = -1; |
|
159 |
+- ctxt->context->proximityPosition = -1; |
|
160 |
+- valuePush(ctxt, xmlXPtrWrapLocationSet(newset)); |
|
161 |
++xmlXPtrRangeToFunction(xmlXPathParserContextPtr ctxt, |
|
162 |
++ int nargs ATTRIBUTE_UNUSED) { |
|
163 |
++ XP_ERROR(XPATH_EXPR_ERROR); |
|
164 |
+ } |
|
165 |
+ |
|
166 |
+ /** |
0 | 167 |
new file mode 100644 |
... | ... |
@@ -0,0 +1,172 @@ |
0 |
+From d77e5fc4bcdb7da748c9cca116a601ae4df60d21 |
|
1 |
+To a005199330b86dada19d162cae15ef9bdcb6baa8 |
|
2 |
+Bring upstream patches to support CVE-2016-5131 fix |
|
3 |
+as one of the tests failed with just applying the CVE fix. |
|
4 |
+ |
|
5 |
+diff --git a/relaxng.c b/relaxng.c |
|
6 |
+index 56a3344..3d3e69c 100644 |
|
7 |
+--- a/relaxng.c |
|
8 |
+@@ -2088,6 +2088,7 @@ xmlRelaxNGGetErrorString(xmlRelaxNGValidErr err, const xmlChar * arg1, |
|
9 |
+ const xmlChar * arg2) |
|
10 |
+ { |
|
11 |
+ char msg[1000]; |
|
12 |
++ xmlChar *result; |
|
13 |
+ |
|
14 |
+ if (arg1 == NULL) |
|
15 |
+ arg1 = BAD_CAST ""; |
|
16 |
+@@ -2215,7 +2216,7 @@ xmlRelaxNGGetErrorString(xmlRelaxNGValidErr err, const xmlChar * arg1, |
|
17 |
+ snprintf(msg, 1000, "Unknown error code %d\n", err); |
|
18 |
+ } |
|
19 |
+ msg[1000 - 1] = 0; |
|
20 |
+- xmlChar *result = xmlCharStrdup(msg); |
|
21 |
++ result = xmlCharStrdup(msg); |
|
22 |
+ return (xmlEscapeFormatString(&result)); |
|
23 |
+ } |
|
24 |
+ |
|
25 |
+diff --git a/result/XPath/xptr/viderror b/result/XPath/xptr/viderror |
|
26 |
+new file mode 100644 |
|
27 |
+index 0000000..d589882 |
|
28 |
+--- /dev/null |
|
29 |
+@@ -0,0 +1,4 @@ |
|
30 |
++ |
|
31 |
++======================== |
|
32 |
++Expression: xpointer(non-existing-fn()/range-to(id('chapter2'))) |
|
33 |
++Object is empty (NULL) |
|
34 |
+diff --git a/runtest.c b/runtest.c |
|
35 |
+index bb74d2a..1861577 100644 |
|
36 |
+--- a/runtest.c |
|
37 |
+@@ -2317,10 +2317,19 @@ static FILE *xpathOutput; |
|
38 |
+ static xmlDocPtr xpathDocument; |
|
39 |
+ |
|
40 |
+ static void |
|
41 |
++ignoreGenericError(void *ctx ATTRIBUTE_UNUSED, |
|
42 |
++ const char *msg ATTRIBUTE_UNUSED, ...) { |
|
43 |
++} |
|
44 |
++ |
|
45 |
++static void |
|
46 |
+ testXPath(const char *str, int xptr, int expr) { |
|
47 |
++ xmlGenericErrorFunc handler = ignoreGenericError; |
|
48 |
+ xmlXPathObjectPtr res; |
|
49 |
+ xmlXPathContextPtr ctxt; |
|
50 |
+ |
|
51 |
++ /* Don't print generic errors to stderr. */ |
|
52 |
++ initGenericErrorDefaultFunc(&handler); |
|
53 |
++ |
|
54 |
+ nb_tests++; |
|
55 |
+ #if defined(LIBXML_XPTR_ENABLED) |
|
56 |
+ if (xptr) { |
|
57 |
+@@ -2349,6 +2358,9 @@ testXPath(const char *str, int xptr, int expr) { |
|
58 |
+ xmlXPathDebugDumpObject(xpathOutput, res, 0); |
|
59 |
+ xmlXPathFreeObject(res); |
|
60 |
+ xmlXPathFreeContext(ctxt); |
|
61 |
++ |
|
62 |
++ /* Reset generic error handler. */ |
|
63 |
++ initGenericErrorDefaultFunc(NULL); |
|
64 |
+ } |
|
65 |
+ |
|
66 |
+ /** |
|
67 |
+diff --git a/test/XPath/xptr/viderror b/test/XPath/xptr/viderror |
|
68 |
+new file mode 100644 |
|
69 |
+index 0000000..da8c53b |
|
70 |
+--- /dev/null |
|
71 |
+@@ -0,0 +1 @@ |
|
72 |
++xpointer(non-existing-fn()/range-to(id('chapter2'))) |
|
73 |
+diff --git a/xmlschemas.c b/xmlschemas.c |
|
74 |
+index e1b3a4f..d42afb7 100644 |
|
75 |
+--- a/xmlschemas.c |
|
76 |
+@@ -3168,8 +3168,8 @@ xmlSchemaPSimpleTypeErr(xmlSchemaParserCtxtPtr ctxt, |
|
77 |
+ "valid."); |
|
78 |
+ } |
|
79 |
+ if (expected) { |
|
80 |
+- msg = xmlStrcat(msg, BAD_CAST " Expected is '"); |
|
81 |
+ xmlChar *expectedEscaped = xmlCharStrdup(expected); |
|
82 |
++ msg = xmlStrcat(msg, BAD_CAST " Expected is '"); |
|
83 |
+ msg = xmlStrcat(msg, xmlEscapeFormatString(&expectedEscaped)); |
|
84 |
+ FREE_AND_NULL(expectedEscaped); |
|
85 |
+ msg = xmlStrcat(msg, BAD_CAST "'.\n"); |
|
86 |
+@@ -27391,6 +27391,7 @@ xmlSchemaSAXHandleStartElementNs(void *ctx, |
|
87 |
+ * attributes yet. |
|
88 |
+ */ |
|
89 |
+ if (nb_attributes != 0) { |
|
90 |
++ int valueLen, k, l; |
|
91 |
+ xmlChar *value; |
|
92 |
+ |
|
93 |
+ for (j = 0, i = 0; i < nb_attributes; i++, j += 5) { |
|
94 |
+@@ -27400,12 +27401,31 @@ xmlSchemaSAXHandleStartElementNs(void *ctx, |
|
95 |
+ * libxml2 differs from normal SAX here in that it escapes all ampersands |
|
96 |
+ * as & instead of delivering the raw converted string. Changing the |
|
97 |
+ * behavior at this point would break applications that use this API, so |
|
98 |
+- * we are forced to work around it. There is no danger of accidentally |
|
99 |
+- * decoding some entity other than & in this step because without |
|
100 |
+- * unescaped ampersands there can be no other entities in the string. |
|
101 |
++ * we are forced to work around it. |
|
102 |
+ */ |
|
103 |
+- value = xmlStringLenDecodeEntities(vctxt->parserCtxt, attributes[j+3], |
|
104 |
+- attributes[j+4] - attributes[j+3], XML_SUBSTITUTE_REF, 0, 0, 0); |
|
105 |
++ valueLen = attributes[j+4] - attributes[j+3]; |
|
106 |
++ value = xmlMallocAtomic(valueLen + 1); |
|
107 |
++ if (value == NULL) { |
|
108 |
++ xmlSchemaVErrMemory(vctxt, |
|
109 |
++ "allocating string for decoded attribute", |
|
110 |
++ NULL); |
|
111 |
++ goto internal_error; |
|
112 |
++ } |
|
113 |
++ for (k = 0, l = 0; k < valueLen; l++) { |
|
114 |
++ if (k < valueLen - 4 && |
|
115 |
++ attributes[j+3][k+0] == '&' && |
|
116 |
++ attributes[j+3][k+1] == '#' && |
|
117 |
++ attributes[j+3][k+2] == '3' && |
|
118 |
++ attributes[j+3][k+3] == '8' && |
|
119 |
++ attributes[j+3][k+4] == ';') { |
|
120 |
++ value[l] = '&'; |
|
121 |
++ k += 5; |
|
122 |
++ } else { |
|
123 |
++ value[l] = attributes[j+3][k]; |
|
124 |
++ k++; |
|
125 |
++ } |
|
126 |
++ } |
|
127 |
++ value[l] = '\0'; |
|
128 |
+ /* |
|
129 |
+ * TODO: Set the node line. |
|
130 |
+ */ |
|
131 |
+diff --git a/xpath.c b/xpath.c |
|
132 |
+index 113bce6..d992841 100644 |
|
133 |
+--- a/xpath.c |
|
134 |
+@@ -3342,13 +3342,13 @@ xmlXPathCmpNodes(xmlNodePtr node1, xmlNodePtr node2) { |
|
135 |
+ * compute depth to root |
|
136 |
+ */ |
|
137 |
+ for (depth2 = 0, cur = node2;cur->parent != NULL;cur = cur->parent) { |
|
138 |
+- if (cur == node1) |
|
139 |
++ if (cur->parent == node1) |
|
140 |
+ return(1); |
|
141 |
+ depth2++; |
|
142 |
+ } |
|
143 |
+ root = cur; |
|
144 |
+ for (depth1 = 0, cur = node1;cur->parent != NULL;cur = cur->parent) { |
|
145 |
+- if (cur == node2) |
|
146 |
++ if (cur->parent == node2) |
|
147 |
+ return(-1); |
|
148 |
+ depth1++; |
|
149 |
+ } |
|
150 |
+@@ -14005,9 +14005,14 @@ xmlXPathCompOpEval(xmlXPathParserContextPtr ctxt, xmlXPathStepOpPtr op) |
|
151 |
+ xmlNodeSetPtr oldset; |
|
152 |
+ int i, j; |
|
153 |
+ |
|
154 |
+- if (op->ch1 != -1) |
|
155 |
++ if (op->ch1 != -1) { |
|
156 |
+ total += |
|
157 |
+ xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]); |
|
158 |
++ CHECK_ERROR0; |
|
159 |
++ } |
|
160 |
++ if (ctxt->value == NULL) { |
|
161 |
++ XP_ERROR0(XPATH_INVALID_OPERAND); |
|
162 |
++ } |
|
163 |
+ if (op->ch2 == -1) |
|
164 |
+ return (total); |
|
165 |
+ |
... | ... |
@@ -1,13 +1,15 @@ |
1 | 1 |
Summary: Libxml2 |
2 | 2 |
Name: libxml2 |
3 | 3 |
Version: 2.9.4 |
4 |
-Release: 2%{?dist} |
|
4 |
+Release: 3%{?dist} |
|
5 | 5 |
License: MIT |
6 | 6 |
URL: http://xmlsoft.org/ |
7 | 7 |
Group: System Environment/General Libraries |
8 | 8 |
Vendor: VMware, Inc. |
9 | 9 |
Distribution: Photon |
10 | 10 |
Source0: ftp://xmlsoft.org/libxml2/%{name}-%{version}.tar.gz |
11 |
+Patch0: libxml2-2.9.4-support-cve-2016-5131.patch |
|
12 |
+Patch1: libxml2-2.9.4-cve-2016-5131.patch |
|
11 | 13 |
%define sha1 libxml2=958ae70baf186263a4bd801a81dd5d682aedd1db |
12 | 14 |
Requires: python2 |
13 | 15 |
BuildRequires: python2-devel |
... | ... |
@@ -37,6 +39,8 @@ Static libraries and header files for the support library for libxml |
37 | 37 |
|
38 | 38 |
%prep |
39 | 39 |
%setup -q |
40 |
+%patch0 -p1 |
|
41 |
+%patch1 -p1 |
|
40 | 42 |
sed \ |
41 | 43 |
-e /xmlInitializeCatalog/d \ |
42 | 44 |
-e 's/((ent->checked =.*&&/(((ent->checked == 0) ||\ |
... | ... |
@@ -86,6 +90,8 @@ rm -rf %{buildroot}/* |
86 | 86 |
|
87 | 87 |
|
88 | 88 |
%changelog |
89 |
+* Thu Oct 20 2016 Priyesh Padmavilasom <ppadmavilasom@vmware.com> 2.9.4-3 |
|
90 |
+- Apply patch for CVE-2016-5131 |
|
89 | 91 |
* Mon Oct 03 2016 Chang Lee <changlee@vmware.com> 2.9.4-2 |
90 | 92 |
- Modified check |
91 | 93 |
* Wed Jun 01 2016 Anish Swaminathan <anishs@vmware.com> 2.9.4-1 |