diff options
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.patch | 131 |
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; + } + } + |