summaryrefslogtreecommitdiffstats
path: root/meta/recipes-core/expat/expat/CVE-2022-25313-regression.patch
diff options
context:
space:
mode:
Diffstat (limited to 'meta/recipes-core/expat/expat/CVE-2022-25313-regression.patch')
-rw-r--r--meta/recipes-core/expat/expat/CVE-2022-25313-regression.patch131
1 files changed, 131 insertions, 0 deletions
diff --git a/meta/recipes-core/expat/expat/CVE-2022-25313-regression.patch b/meta/recipes-core/expat/expat/CVE-2022-25313-regression.patch
new file mode 100644
index 0000000000..af255e8cb5
--- /dev/null
+++ b/meta/recipes-core/expat/expat/CVE-2022-25313-regression.patch
@@ -0,0 +1,131 @@
+From b12f34fe32821a69dc12ff9a021daca0856de238 Mon Sep 17 00:00:00 2001
+From: Samanta Navarro <ferivoz@riseup.net>
+Date: Sat, 19 Feb 2022 23:59:25 +0000
+Subject: [PATCH] Fix build_model regression.
+
+The iterative approach in build_model failed to fill children arrays
+correctly. A preorder traversal is not required and turned out to be the
+culprit. Use an easier algorithm:
+
+Add nodes from scaffold tree starting at index 0 (root) to the target
+array whenever children are encountered. This ensures that children
+are adjacent to each other. This complies with the recursive version.
+
+Store only the scaffold index in numchildren field to prevent a direct
+processing of these children, which would require a recursive solution.
+This allows the algorithm to iterate through the target array from start
+to end without jumping back and forth, converting on the fly.
+
+Co-authored-by: Sebastian Pipping <sebastian@pipping.org>
+---
+ lib/xmlparse.c | 79 ++++++++++++++++++++++++++------------------
+ 1 file changed, 47 insertions(+), 32 deletions(-)
+
+diff --git a/lib/xmlparse.c b/lib/xmlparse.c
+index c479a258..84885b5a 100644
+--- a/lib/xmlparse.c
++++ b/lib/xmlparse.c
+@@ -7373,39 +7373,58 @@ build_model(XML_Parser parser) {
+ *
+ * The iterative approach works as follows:
+ *
+- * - We use space in the target array for building a temporary stack structure
+- * while that space is still unused.
+- * The stack grows from the array's end downwards and the "actual data"
+- * grows from the start upwards, sequentially.
+- * (Because stack grows downwards, pushing onto the stack is a decrement
+- * while popping off the stack is an increment.)
++ * - We have two writing pointers, both walking up the result array; one does
++ * the work, the other creates "jobs" for its colleague to do, and leads
++ * the way:
+ *
+- * - A stack element appears as a regular XML_Content node on the outside,
+- * but only uses a single field -- numchildren -- to store the source
+- * tree node array index. These are the breadcrumbs leading the way back
+- * during pre-order (node first) depth-first traversal.
++ * - The faster one, pointer jobDest, always leads and writes "what job
++ * to do" by the other, once they reach that place in the
++ * array: leader "jobDest" stores the source node array index (relative
++ * to array dtd->scaffold) in field "numchildren".
+ *
+- * - The reason we know the stack will never grow into (or overlap with)
+- * the area with data of value at the start of the array is because
+- * the overall number of elements to process matches the size of the array,
+- * and the sum of fully processed nodes and yet-to-be processed nodes
+- * on the stack, cannot be more than the total number of nodes.
+- * It is possible for the top of the stack and the about-to-write node
+- * to meet, but that is safe because we get the source index out
+- * before doing any writes on that node.
++ * - The slower one, pointer dest, looks at the value stored in the
++ * "numchildren" field (which actually holds a source node array index
++ * at that time) and puts the real data from dtd->scaffold in.
++ *
++ * - Before the loop starts, jobDest writes source array index 0
++ * (where the root node is located) so that dest will have something to do
++ * when it starts operation.
++ *
++ * - Whenever nodes with children are encountered, jobDest appends
++ * them as new jobs, in order. As a result, tree node siblings are
++ * adjacent in the resulting array, for example:
++ *
++ * [0] root, has two children
++ * [1] first child of 0, has three children
++ * [3] first child of 1, does not have children
++ * [4] second child of 1, does not have children
++ * [5] third child of 1, does not have children
++ * [2] second child of 0, does not have children
++ *
++ * Or (the same data) presented in flat array view:
++ *
++ * [0] root, has two children
++ *
++ * [1] first child of 0, has three children
++ * [2] second child of 0, does not have children
++ *
++ * [3] first child of 1, does not have children
++ * [4] second child of 1, does not have children
++ * [5] third child of 1, does not have children
++ *
++ * - The algorithm repeats until all target array indices have been processed.
+ */
+ XML_Content *dest = ret; /* tree node writing location, moves upwards */
+ XML_Content *const destLimit = &ret[dtd->scaffCount];
+- XML_Content *const stackBottom = &ret[dtd->scaffCount];
+- XML_Content *stackTop = stackBottom; /* i.e. stack is initially empty */
++ XML_Content *jobDest = ret; /* next free writing location in target array */
+ str = (XML_Char *)&ret[dtd->scaffCount];
+
+- /* Push source tree root node index onto the stack */
+- (--stackTop)->numchildren = 0;
++ /* Add the starting job, the root node (index 0) of the source tree */
++ (jobDest++)->numchildren = 0;
+
+ for (; dest < destLimit; dest++) {
+- /* Pop source tree node index off the stack */
+- const int src_node = (int)(stackTop++)->numchildren;
++ /* Retrieve source tree array index from job storage */
++ const int src_node = (int)dest->numchildren;
+
+ /* Convert item */
+ dest->type = dtd->scaffold[src_node].type;
+@@ -7427,16 +7446,12 @@ build_model(XML_Parser parser) {
+ int cn;
+ dest->name = NULL;
+ dest->numchildren = dtd->scaffold[src_node].childcnt;
+- dest->children = &dest[1];
++ dest->children = jobDest;
+
+- /* Push children to the stack
+- * in a way where the first child ends up at the top of the
+- * (downwards growing) stack, in order to be processed first. */
+- stackTop -= dest->numchildren;
++ /* Append scaffold indices of children to array */
+ for (i = 0, cn = dtd->scaffold[src_node].firstchild;
+- i < dest->numchildren; i++, cn = dtd->scaffold[cn].nextsib) {
+- (stackTop + i)->numchildren = (unsigned int)cn;
+- }
++ i < dest->numchildren; i++, cn = dtd->scaffold[cn].nextsib)
++ (jobDest++)->numchildren = (unsigned int)cn;
+ }
+ }
+