diff mbox series

[kirkstone] libxslt: fix CVE-2023-40403

Message ID 20250811070335.65789-1-hprajapati@mvista.com
State New
Headers show
Series [kirkstone] libxslt: fix CVE-2023-40403 | expand

Commit Message

Hitendra Prajapati Aug. 11, 2025, 7:03 a.m. UTC
Upstream-Status: Backport from  https://gitlab.gnome.org/GNOME/libxslt/-/commit/adebe45f6ef9f9d036acacd8aec7411d4ea84e25 && https://gitlab.gnome.org/GNOME/libxslt/-/commit/1d9820635c271b35f88431f33ea78dc8be349e5b && https://gitlab.gnome.org/GNOME/libxslt/-/commit/ccec6fa31d11ab0a5299f15ea184c7a457e92940 && https://gitlab.gnome.org/GNOME/libxslt/-/commit/82f6cbf8ca61b1f9e00dc04aa3b15d563e7bbc6d && https://gitlab.gnome.org/GNOME/libxslt/-/commit/452fb4ca9b9803448826008b9573987c615912a1

Signed-off-by: Hitendra Prajapati <hprajapati@mvista.com>
---
 .../libxslt/libxslt/CVE-2023-40403-001.patch  | 257 +++++++++++++
 .../libxslt/libxslt/CVE-2023-40403-002.patch  | 147 ++++++++
 .../libxslt/libxslt/CVE-2023-40403-003.patch  | 231 ++++++++++++
 .../libxslt/libxslt/CVE-2023-40403-004.patch  | 349 ++++++++++++++++++
 .../libxslt/libxslt/CVE-2023-40403-005.patch  |  55 +++
 .../recipes-support/libxslt/libxslt_1.1.35.bb |   5 +
 6 files changed, 1044 insertions(+)
 create mode 100644 meta/recipes-support/libxslt/libxslt/CVE-2023-40403-001.patch
 create mode 100644 meta/recipes-support/libxslt/libxslt/CVE-2023-40403-002.patch
 create mode 100644 meta/recipes-support/libxslt/libxslt/CVE-2023-40403-003.patch
 create mode 100644 meta/recipes-support/libxslt/libxslt/CVE-2023-40403-004.patch
 create mode 100644 meta/recipes-support/libxslt/libxslt/CVE-2023-40403-005.patch
diff mbox series

Patch

diff --git a/meta/recipes-support/libxslt/libxslt/CVE-2023-40403-001.patch b/meta/recipes-support/libxslt/libxslt/CVE-2023-40403-001.patch
new file mode 100644
index 0000000000..044e100373
--- /dev/null
+++ b/meta/recipes-support/libxslt/libxslt/CVE-2023-40403-001.patch
@@ -0,0 +1,257 @@ 
+From 4f26166f9e253aa62f8c121a6a25c76df5aa8142 Mon Sep 17 00:00:00 2001
+From: Nick Wellnhofer <wellnhofer@aevum.de>
+Date: Wed, 31 Aug 2022 15:29:57 +0200
+Subject: [PATCH] Infrastructure to store extra data in source nodes
+
+Provide a mechanism to store bit flags in nodes from the source
+document. This will later be used to store key and id status.
+
+Provide a function to find the psvi member of a node.
+
+Revert any changes to the source document after the transformation.
+
+Upstream-Status: Backport [https://gitlab.gnome.org/GNOME/libxslt/-/commit/adebe45f6ef9f9d036acacd8aec7411d4ea84e25]
+CVE: CVE-2023-40403
+Signed-off-by: Hitendra Prajapati <hprajapati@mvista.com>
+
+---
+ libxslt/transform.c     |  34 ++++++++++
+ libxslt/xsltInternals.h |   1 +
+ libxslt/xsltutils.c     | 135 ++++++++++++++++++++++++++++++++++++++++
+ libxslt/xsltutils.h     |  13 ++++
+ 4 files changed, 183 insertions(+)
+
+diff --git a/libxslt/transform.c b/libxslt/transform.c
+index 57f05bf..40ab810 100644
+--- a/libxslt/transform.c
++++ b/libxslt/transform.c
+@@ -5747,6 +5747,37 @@ xsltCountKeys(xsltTransformContextPtr ctxt)
+     return(ctxt->nbKeys);
+ }
+ 
++/**
++ * xsltCleanupSourceDoc:
++ * @doc:  Document
++ *
++ * Resets source node flags and ids stored in 'psvi' member.
++ */
++static void
++xsltCleanupSourceDoc(xmlDocPtr doc) {
++    xmlNodePtr cur = (xmlNodePtr) doc;
++    void **psviPtr;
++
++    while (1) {
++        xsltClearSourceNodeFlags(cur, XSLT_SOURCE_NODE_MASK);
++        psviPtr = xsltGetPSVIPtr(cur);
++        if (psviPtr)
++            *psviPtr = NULL;
++
++        if (cur->children != NULL && cur->type != XML_ENTITY_REF_NODE) {
++            cur = cur->children;
++        } else {
++            while (cur->next == NULL) {
++                cur = cur->parent;
++                if (cur == (xmlNodePtr) doc)
++                    return;
++            }
++
++            cur = cur->next;
++        }
++    }
++}
++
+ /**
+  * xsltApplyStylesheetInternal:
+  * @style:  a parsed XSLT stylesheet
+@@ -6145,6 +6176,9 @@ xsltApplyStylesheetInternal(xsltStylesheetPtr style, xmlDocPtr doc,
+     printf("# Reused variables     : %d\n", ctxt->cache->dbgReusedVars);
+ #endif
+ 
++    if (ctxt->sourceDocDirty)
++        xsltCleanupSourceDoc(doc);
++
+     if ((ctxt != NULL) && (userCtxt == NULL))
+ 	xsltFreeTransformContext(ctxt);
+ 
+diff --git a/libxslt/xsltInternals.h b/libxslt/xsltInternals.h
+index 14343d2..b0125c2 100644
+--- a/libxslt/xsltInternals.h
++++ b/libxslt/xsltInternals.h
+@@ -1786,6 +1786,7 @@ struct _xsltTransformContext {
+     int maxTemplateVars;
+     unsigned long opLimit;
+     unsigned long opCount;
++    int sourceDocDirty;
+ };
+ 
+ /**
+diff --git a/libxslt/xsltutils.c b/libxslt/xsltutils.c
+index 9faa6b2..a879aa8 100644
+--- a/libxslt/xsltutils.c
++++ b/libxslt/xsltutils.c
+@@ -1835,6 +1835,141 @@ xsltSaveResultToString(xmlChar **doc_txt_ptr, int * doc_txt_len,
+     return 0;
+ }
+ 
++/**
++ * xsltGetSourceNodeFlags:
++ * @node:  Node from source document
++ *
++ * Returns the flags for a source node.
++ */
++int
++xsltGetSourceNodeFlags(xmlNodePtr node) {
++    /*
++     * Squeeze the bit flags into the upper bits of
++     *
++     * - 'int properties' member in struct _xmlDoc
++     * - 'xmlAttributeType atype' member in struct _xmlAttr
++     * - 'unsigned short extra' member in struct _xmlNode
++     */
++    switch (node->type) {
++        case XML_DOCUMENT_NODE:
++        case XML_HTML_DOCUMENT_NODE:
++            return ((xmlDocPtr) node)->properties >> 27;
++
++        case XML_ATTRIBUTE_NODE:
++            return ((xmlAttrPtr) node)->atype >> 27;
++
++        case XML_ELEMENT_NODE:
++        case XML_TEXT_NODE:
++        case XML_CDATA_SECTION_NODE:
++        case XML_PI_NODE:
++        case XML_COMMENT_NODE:
++            return node->extra >> 12;
++
++        default:
++            return 0;
++    }
++}
++
++/**
++ * xsltSetSourceNodeFlags:
++ * @node:  Node from source document
++ * @flags:  Flags
++ *
++ * Sets the specified flags to 1.
++ *
++ * Returns 0 on success, -1 on error.
++ */
++int
++xsltSetSourceNodeFlags(xsltTransformContextPtr ctxt, xmlNodePtr node,
++                       int flags) {
++    if (node->doc == ctxt->initialContextDoc)
++        ctxt->sourceDocDirty = 1;
++
++    switch (node->type) {
++        case XML_DOCUMENT_NODE:
++        case XML_HTML_DOCUMENT_NODE:
++            ((xmlDocPtr) node)->properties |= flags << 27;
++            return 0;
++
++        case XML_ATTRIBUTE_NODE:
++            ((xmlAttrPtr) node)->atype |= flags << 27;
++            return 0;
++
++        case XML_ELEMENT_NODE:
++        case XML_TEXT_NODE:
++        case XML_CDATA_SECTION_NODE:
++        case XML_PI_NODE:
++        case XML_COMMENT_NODE:
++            node->extra |= flags << 12;
++            return 0;
++
++        default:
++            return -1;
++    }
++}
++
++/**
++ * xsltClearSourceNodeFlags:
++ * @node:  Node from source document
++ * @flags:  Flags
++ *
++ * Sets the specified flags to 0.
++ *
++ * Returns 0 on success, -1 on error.
++ */
++int
++xsltClearSourceNodeFlags(xmlNodePtr node, int flags) {
++    switch (node->type) {
++        case XML_DOCUMENT_NODE:
++        case XML_HTML_DOCUMENT_NODE:
++            ((xmlDocPtr) node)->properties &= ~(flags << 27);
++            return 0;
++
++        case XML_ATTRIBUTE_NODE:
++            ((xmlAttrPtr) node)->atype &= ~(flags << 27);
++            return 0;
++
++        case XML_ELEMENT_NODE:
++        case XML_TEXT_NODE:
++        case XML_CDATA_SECTION_NODE:
++        case XML_PI_NODE:
++        case XML_COMMENT_NODE:
++            node->extra &= ~(flags << 12);
++            return 0;
++
++        default:
++            return -1;
++    }
++}
++
++/**
++ * xsltGetPSVIPtr:
++ * @cur:  Node
++ *
++ * Returns a pointer to the psvi member of a node or NULL on error.
++ */
++void **
++xsltGetPSVIPtr(xmlNodePtr cur) {
++    switch (cur->type) {
++        case XML_DOCUMENT_NODE:
++        case XML_HTML_DOCUMENT_NODE:
++            return &((xmlDocPtr) cur)->psvi;
++
++        case XML_ATTRIBUTE_NODE:
++            return &((xmlAttrPtr) cur)->psvi;
++
++        case XML_ELEMENT_NODE:
++        case XML_TEXT_NODE:
++        case XML_CDATA_SECTION_NODE:
++        case XML_PI_NODE:
++        case XML_COMMENT_NODE:
++            return &cur->psvi;
++
++        default:
++            return NULL;
++    }
++}
++
+ #ifdef WITH_PROFILER
+ 
+ /************************************************************************
+diff --git a/libxslt/xsltutils.h b/libxslt/xsltutils.h
+index ea6c374..202694f 100644
+--- a/libxslt/xsltutils.h
++++ b/libxslt/xsltutils.h
+@@ -247,6 +247,19 @@ XSLTPUBFUN xmlXPathCompExprPtr XSLTCALL
+ 						 const xmlChar *str,
+ 						 int flags);
+ 
++#ifdef IN_LIBXSLT
++#define XSLT_SOURCE_NODE_MASK       15
++int
++xsltGetSourceNodeFlags(xmlNodePtr node);
++int
++xsltSetSourceNodeFlags(xsltTransformContextPtr ctxt, xmlNodePtr node,
++                       int flags);
++int
++xsltClearSourceNodeFlags(xmlNodePtr node, int flags);
++void **
++xsltGetPSVIPtr(xmlNodePtr cur);
++#endif
++
+ /*
+  * Profiling.
+  */
diff --git a/meta/recipes-support/libxslt/libxslt/CVE-2023-40403-002.patch b/meta/recipes-support/libxslt/libxslt/CVE-2023-40403-002.patch
new file mode 100644
index 0000000000..0d815c1090
--- /dev/null
+++ b/meta/recipes-support/libxslt/libxslt/CVE-2023-40403-002.patch
@@ -0,0 +1,147 @@ 
+From b392a3d0265f190d86cc122d86769a23ddb1fe66 Mon Sep 17 00:00:00 2001
+From: Nick Wellnhofer <wellnhofer@aevum.de>
+Date: Wed, 31 Aug 2022 15:34:47 +0200
+Subject: [PATCH] Store key status of source nodes as bit flag
+
+This frees up the psvi member.
+
+CVE: CVE-2023-40403
+Upstream-Status: Backport [https://gitlab.gnome.org/GNOME/libxslt/-/commit/1d9820635c271b35f88431f33ea78dc8be349e5b]
+Signed-off-by: Hitendra Prajapati <hprajapati@mvista.com>
+
+---
+ libxslt/keys.c      | 19 +------------------
+ libxslt/pattern.c   | 37 ++-----------------------------------
+ libxslt/xsltutils.h |  1 +
+ 3 files changed, 4 insertions(+), 53 deletions(-)
+
+diff --git a/libxslt/keys.c b/libxslt/keys.c
+index ecef538..3a134ab 100644
+--- a/libxslt/keys.c
++++ b/libxslt/keys.c
+@@ -834,24 +834,7 @@ fprintf(stderr, "xsltInitCtxtKey %s : %d\n", keyDef->name, ctxt->keyInitLevel);
+ 		*/
+ 		xmlXPathNodeSetAdd(keylist, cur);
+ 	    }
+-	    switch (cur->type) {
+-		case XML_ELEMENT_NODE:
+-		case XML_TEXT_NODE:
+-		case XML_CDATA_SECTION_NODE:
+-		case XML_PI_NODE:
+-		case XML_COMMENT_NODE:
+-		    cur->psvi = keyDef;
+-		    break;
+-		case XML_ATTRIBUTE_NODE:
+-		    ((xmlAttrPtr) cur)->psvi = keyDef;
+-		    break;
+-		case XML_DOCUMENT_NODE:
+-		case XML_HTML_DOCUMENT_NODE:
+-		    ((xmlDocPtr) cur)->psvi = keyDef;
+-		    break;
+-		default:
+-		    break;
+-	    }
++            xsltSetSourceNodeFlags(ctxt, cur, XSLT_SOURCE_NODE_HAS_KEY);
+ 	    xmlFree(str);
+ 	    str = NULL;
+ 
+diff --git a/libxslt/pattern.c b/libxslt/pattern.c
+index 1944661..9372bc3 100644
+--- a/libxslt/pattern.c
++++ b/libxslt/pattern.c
+@@ -2283,7 +2283,6 @@ xsltGetTemplate(xsltTransformContextPtr ctxt, xmlNodePtr node,
+     const xmlChar *name = NULL;
+     xsltCompMatchPtr list = NULL;
+     float priority;
+-    int keyed = 0;
+ 
+     if ((ctxt == NULL) || (node == NULL))
+ 	return(NULL);
+@@ -2361,37 +2360,25 @@ xsltGetTemplate(xsltTransformContextPtr ctxt, xmlNodePtr node,
+ 		    list = curstyle->rootMatch;
+ 		else
+ 		    list = curstyle->elemMatch;
+-		if (node->psvi != NULL) keyed = 1;
+ 		break;
+ 	    case XML_ATTRIBUTE_NODE: {
+-	        xmlAttrPtr attr;
+-
+ 		list = curstyle->attrMatch;
+-		attr = (xmlAttrPtr) node;
+-		if (attr->psvi != NULL) keyed = 1;
+ 		break;
+ 	    }
+ 	    case XML_PI_NODE:
+ 		list = curstyle->piMatch;
+-		if (node->psvi != NULL) keyed = 1;
+ 		break;
+ 	    case XML_DOCUMENT_NODE:
+ 	    case XML_HTML_DOCUMENT_NODE: {
+-	        xmlDocPtr doc;
+-
+ 		list = curstyle->rootMatch;
+-		doc = (xmlDocPtr) node;
+-		if (doc->psvi != NULL) keyed = 1;
+ 		break;
+ 	    }
+ 	    case XML_TEXT_NODE:
+ 	    case XML_CDATA_SECTION_NODE:
+ 		list = curstyle->textMatch;
+-		if (node->psvi != NULL) keyed = 1;
+ 		break;
+ 	    case XML_COMMENT_NODE:
+ 		list = curstyle->commentMatch;
+-		if (node->psvi != NULL) keyed = 1;
+ 		break;
+ 	    case XML_ENTITY_REF_NODE:
+ 	    case XML_ENTITY_NODE:
+@@ -2461,7 +2448,7 @@ xsltGetTemplate(xsltTransformContextPtr ctxt, xmlNodePtr node,
+ 	}
+ 
+ keyed_match:
+-	if (keyed) {
++        if (xsltGetSourceNodeFlags(node) & XSLT_SOURCE_NODE_HAS_KEY) {
+ 	    list = curstyle->keyMatch;
+ 	    while ((list != NULL) &&
+                    ((ret == NULL) ||
+@@ -2489,27 +2476,7 @@ keyed_match:
+ 	    if (xsltComputeAllKeys(ctxt, node) == -1)
+ 		goto error;
+ 
+-	    switch (node->type) {
+-		case XML_ELEMENT_NODE:
+-		    if (node->psvi != NULL) keyed = 1;
+-		    break;
+-		case XML_ATTRIBUTE_NODE:
+-		    if (((xmlAttrPtr) node)->psvi != NULL) keyed = 1;
+-		    break;
+-		case XML_TEXT_NODE:
+-		case XML_CDATA_SECTION_NODE:
+-		case XML_COMMENT_NODE:
+-		case XML_PI_NODE:
+-		    if (node->psvi != NULL) keyed = 1;
+-		    break;
+-		case XML_DOCUMENT_NODE:
+-		case XML_HTML_DOCUMENT_NODE:
+-		    if (((xmlDocPtr) node)->psvi != NULL) keyed = 1;
+-		    break;
+-		default:
+-		    break;
+-	    }
+-	    if (keyed)
++            if (xsltGetSourceNodeFlags(node) & XSLT_SOURCE_NODE_HAS_KEY)
+ 		goto keyed_match;
+ 	}
+ 	if (ret != NULL)
+diff --git a/libxslt/xsltutils.h b/libxslt/xsltutils.h
+index 202694f..dcfd139 100644
+--- a/libxslt/xsltutils.h
++++ b/libxslt/xsltutils.h
+@@ -249,6 +249,7 @@ XSLTPUBFUN xmlXPathCompExprPtr XSLTCALL
+ 
+ #ifdef IN_LIBXSLT
+ #define XSLT_SOURCE_NODE_MASK       15
++#define XSLT_SOURCE_NODE_HAS_KEY    1
+ int
+ xsltGetSourceNodeFlags(xmlNodePtr node);
+ int
diff --git a/meta/recipes-support/libxslt/libxslt/CVE-2023-40403-003.patch b/meta/recipes-support/libxslt/libxslt/CVE-2023-40403-003.patch
new file mode 100644
index 0000000000..0b9ab5829e
--- /dev/null
+++ b/meta/recipes-support/libxslt/libxslt/CVE-2023-40403-003.patch
@@ -0,0 +1,231 @@ 
+From 8986995b07126852762e8a59eaee83be0b8de9a3 Mon Sep 17 00:00:00 2001
+From: Nick Wellnhofer <wellnhofer@aevum.de>
+Date: Wed, 31 Aug 2022 15:35:37 +0200
+Subject: [PATCH] Store RVT ownership in 'compression' member
+
+'compression' is another unused member in struct _xmlDoc which is even
+better suited to store ownership status. More importantly, this frees up
+the 'psvi' member.
+
+This changes the public API but this feature is only required to
+implement EXSLT functions.
+
+CVE: CVE-2023-40403
+Upstream-Status: Backport [https://gitlab.gnome.org/GNOME/libxslt/-/commit/ccec6fa31d11ab0a5299f15ea184c7a457e92940]
+Signed-off-by: Hitendra Prajapati <hprajapati@mvista.com>
+
+---
+ libexslt/functions.c    |  2 +-
+ libxslt/transform.c     |  8 ++++----
+ libxslt/variables.c     | 44 ++++++++++++++++++++---------------------
+ libxslt/variables.h     |  6 +++---
+ libxslt/xsltInternals.h |  2 +-
+ 5 files changed, 31 insertions(+), 31 deletions(-)
+
+diff --git a/libexslt/functions.c b/libexslt/functions.c
+index 958bf60..859a992 100644
+--- a/libexslt/functions.c
++++ b/libexslt/functions.c
+@@ -775,7 +775,7 @@ exsltFuncResultElem (xsltTransformContextPtr ctxt,
+ 	}
+         /* Mark as function result. */
+         xsltRegisterLocalRVT(ctxt, container);
+-        container->psvi = XSLT_RVT_FUNC_RESULT;
++        container->compression = XSLT_RVT_FUNC_RESULT;
+ 
+ 	oldInsert = ctxt->insert;
+ 	ctxt->insert = (xmlNodePtr) container;
+diff --git a/libxslt/transform.c b/libxslt/transform.c
+index 40ab810..19d7326 100644
+--- a/libxslt/transform.c
++++ b/libxslt/transform.c
+@@ -2276,17 +2276,17 @@ xsltReleaseLocalRVTs(xsltTransformContextPtr ctxt, xmlDocPtr base)
+     do {
+         tmp = cur;
+         cur = (xmlDocPtr) cur->next;
+-        if (tmp->psvi == XSLT_RVT_LOCAL) {
++        if (tmp->compression == XSLT_RVT_LOCAL) {
+             xsltReleaseRVT(ctxt, tmp);
+-        } else if (tmp->psvi == XSLT_RVT_GLOBAL) {
++        } else if (tmp->compression == XSLT_RVT_GLOBAL) {
+             xsltRegisterPersistRVT(ctxt, tmp);
+-        } else if (tmp->psvi == XSLT_RVT_FUNC_RESULT) {
++        } else if (tmp->compression == XSLT_RVT_FUNC_RESULT) {
+             /*
+              * This will either register the RVT again or move it to the
+              * context variable.
+              */
+             xsltRegisterLocalRVT(ctxt, tmp);
+-            tmp->psvi = XSLT_RVT_FUNC_RESULT;
++            tmp->compression = XSLT_RVT_FUNC_RESULT;
+         } else {
+             xmlGenericError(xmlGenericErrorContext,
+                     "xsltReleaseLocalRVTs: Unexpected RVT flag %p\n",
+diff --git a/libxslt/variables.c b/libxslt/variables.c
+index 4c972a4..dab0bab 100644
+--- a/libxslt/variables.c
++++ b/libxslt/variables.c
+@@ -123,7 +123,7 @@ xsltRegisterTmpRVT(xsltTransformContextPtr ctxt, xmlDocPtr RVT)
+ 	return(-1);
+ 
+     RVT->prev = NULL;
+-    RVT->psvi = XSLT_RVT_LOCAL;
++    RVT->compression = XSLT_RVT_LOCAL;
+ 
+     /*
+     * We'll restrict the lifetime of user-created fragments
+@@ -163,7 +163,7 @@ xsltRegisterLocalRVT(xsltTransformContextPtr ctxt,
+ 	return(-1);
+ 
+     RVT->prev = NULL;
+-    RVT->psvi = XSLT_RVT_LOCAL;
++    RVT->compression = XSLT_RVT_LOCAL;
+ 
+     /*
+     * When evaluating "select" expressions of xsl:variable
+@@ -255,7 +255,7 @@ xsltExtensionInstructionResultRegister(
+  * Returns 0 in case of success and -1 in case of error.
+  */
+ int
+-xsltFlagRVTs(xsltTransformContextPtr ctxt, xmlXPathObjectPtr obj, void *val) {
++xsltFlagRVTs(xsltTransformContextPtr ctxt, xmlXPathObjectPtr obj, int val) {
+     int i;
+     xmlNodePtr cur;
+     xmlDocPtr doc;
+@@ -302,34 +302,34 @@ xsltFlagRVTs(xsltTransformContextPtr ctxt, xmlXPathObjectPtr obj, void *val) {
+ 	    return(-1);
+ 	}
+ 	if (doc->name && (doc->name[0] == ' ') &&
+-            doc->psvi != XSLT_RVT_GLOBAL) {
++            doc->compression != XSLT_RVT_GLOBAL) {
+ 	    /*
+ 	    * This is a result tree fragment.
+-	    * We store ownership information in the @psvi field.
++	    * We store ownership information in the @compression field.
+ 	    * TODO: How do we know if this is a doc acquired via the
+ 	    *  document() function?
+ 	    */
+ #ifdef WITH_XSLT_DEBUG_VARIABLE
+             XSLT_TRACE(ctxt,XSLT_TRACE_VARIABLES,xsltGenericDebug(xsltGenericDebugContext,
+-                "Flagging RVT %p: %p -> %p\n", doc, doc->psvi, val));
++                "Flagging RVT %p: %d -> %d\n", doc, doc->compression, val));
+ #endif
+ 
+             if (val == XSLT_RVT_LOCAL) {
+-                if (doc->psvi == XSLT_RVT_FUNC_RESULT)
+-                    doc->psvi = XSLT_RVT_LOCAL;
++                if (doc->compression == XSLT_RVT_FUNC_RESULT)
++                    doc->compression = XSLT_RVT_LOCAL;
+             } else if (val == XSLT_RVT_GLOBAL) {
+-                if (doc->psvi != XSLT_RVT_LOCAL) {
++                if (doc->compression != XSLT_RVT_LOCAL) {
+ 		    xmlGenericError(xmlGenericErrorContext,
+-                            "xsltFlagRVTs: Invalid transition %p => GLOBAL\n",
+-                            doc->psvi);
+-                    doc->psvi = XSLT_RVT_GLOBAL;
++                            "xsltFlagRVTs: Invalid transition %d => GLOBAL\n",
++                            doc->compression);
++                    doc->compression = XSLT_RVT_GLOBAL;
+                     return(-1);
+                 }
+ 
+                 /* Will be registered as persistant in xsltReleaseLocalRVTs. */
+-                doc->psvi = XSLT_RVT_GLOBAL;
++                doc->compression = XSLT_RVT_GLOBAL;
+             } else if (val == XSLT_RVT_FUNC_RESULT) {
+-	        doc->psvi = val;
++	        doc->compression = val;
+             }
+ 	}
+     }
+@@ -382,7 +382,7 @@ xsltReleaseRVT(xsltTransformContextPtr ctxt, xmlDocPtr RVT)
+ 	/*
+ 	* Reset the ownership information.
+ 	*/
+-	RVT->psvi = NULL;
++	RVT->compression = 0;
+ 
+ 	RVT->next = (xmlNodePtr) ctxt->cache->RVT;
+ 	ctxt->cache->RVT = RVT;
+@@ -421,7 +421,7 @@ xsltRegisterPersistRVT(xsltTransformContextPtr ctxt, xmlDocPtr RVT)
+ {
+     if ((ctxt == NULL) || (RVT == NULL)) return(-1);
+ 
+-    RVT->psvi = XSLT_RVT_GLOBAL;
++    RVT->compression = XSLT_RVT_GLOBAL;
+     RVT->prev = NULL;
+     RVT->next = (xmlNodePtr) ctxt->persistRVT;
+     if (ctxt->persistRVT != NULL)
+@@ -580,15 +580,15 @@ xsltFreeStackElem(xsltStackElemPtr elem) {
+ 	    cur = elem->fragment;
+ 	    elem->fragment = (xmlDocPtr) cur->next;
+ 
+-            if (cur->psvi == XSLT_RVT_LOCAL) {
++            if (cur->compression == XSLT_RVT_LOCAL) {
+ 		xsltReleaseRVT(elem->context, cur);
+-            } else if (cur->psvi == XSLT_RVT_FUNC_RESULT) {
++            } else if (cur->compression == XSLT_RVT_FUNC_RESULT) {
+                 xsltRegisterLocalRVT(elem->context, cur);
+-                cur->psvi = XSLT_RVT_FUNC_RESULT;
++                cur->compression = XSLT_RVT_FUNC_RESULT;
+             } else {
+                 xmlGenericError(xmlGenericErrorContext,
+-                        "xsltFreeStackElem: Unexpected RVT flag %p\n",
+-                        cur->psvi);
++                        "xsltFreeStackElem: Unexpected RVT flag %d\n",
++                        cur->compression);
+             }
+ 	}
+     }
+@@ -989,7 +989,7 @@ xsltEvalVariable(xsltTransformContextPtr ctxt, xsltStackElemPtr variable,
+ 		* the Result Tree Fragment.
+ 		*/
+ 		variable->fragment = container;
+-                container->psvi = XSLT_RVT_LOCAL;
++                container->compression = XSLT_RVT_LOCAL;
+ 
+ 		oldOutput = ctxt->output;
+ 		oldInsert = ctxt->insert;
+diff --git a/libxslt/variables.h b/libxslt/variables.h
+index 039288f..e2adee0 100644
+--- a/libxslt/variables.h
++++ b/libxslt/variables.h
+@@ -43,7 +43,7 @@ extern "C" {
+  *
+  * RVT is destroyed after the current instructions ends.
+  */
+-#define XSLT_RVT_LOCAL       ((void *)1)
++#define XSLT_RVT_LOCAL       1
+ 
+ /**
+  * XSLT_RVT_FUNC_RESULT:
+@@ -52,14 +52,14 @@ extern "C" {
+  * destroyed after exiting a template and will be reset to XSLT_RVT_LOCAL or
+  * XSLT_RVT_VARIABLE in the template that receives the return value.
+  */
+-#define XSLT_RVT_FUNC_RESULT ((void *)2)
++#define XSLT_RVT_FUNC_RESULT 2
+ 
+ /**
+  * XSLT_RVT_GLOBAL:
+  *
+  * RVT is part of a global variable.
+  */
+-#define XSLT_RVT_GLOBAL      ((void *)3)
++#define XSLT_RVT_GLOBAL      3
+ 
+ /*
+  * Interfaces for the variable module.
+diff --git a/libxslt/xsltInternals.h b/libxslt/xsltInternals.h
+index b0125c2..74a2b64 100644
+--- a/libxslt/xsltInternals.h
++++ b/libxslt/xsltInternals.h
+@@ -1916,7 +1916,7 @@ XSLTPUBFUN int XSLTCALL
+ 			xsltFlagRVTs(
+ 						 xsltTransformContextPtr ctxt,
+ 						 xmlXPathObjectPtr obj,
+-						 void *val);
++						 int val);
+ XSLTPUBFUN void XSLTCALL
+ 			xsltFreeRVTs		(xsltTransformContextPtr ctxt);
+ XSLTPUBFUN void XSLTCALL
diff --git a/meta/recipes-support/libxslt/libxslt/CVE-2023-40403-004.patch b/meta/recipes-support/libxslt/libxslt/CVE-2023-40403-004.patch
new file mode 100644
index 0000000000..59e7c1bad3
--- /dev/null
+++ b/meta/recipes-support/libxslt/libxslt/CVE-2023-40403-004.patch
@@ -0,0 +1,349 @@ 
+From 91c9c56dcca01bfe3f9dae74fb75dcf792ebe58b Mon Sep 17 00:00:00 2001
+From: Nick Wellnhofer <wellnhofer@aevum.de>
+Date: Wed, 31 Aug 2022 13:35:23 +0200
+Subject: [PATCH] Make generate-id() deterministic
+
+Rework the generate-id() function to return deterministic values. We use
+a simple incrementing counter and store ids in the 'psvi' member of
+nodes which was freed up by previous commits. The presence of an id is
+indicated by a new "source node" flag.
+
+This fixes long-standing problems with reproducible builds, see
+https://bugzilla.gnome.org/show_bug.cgi?id=751621
+
+This also hardens security, as the old implementation leaked the
+difference between a heap and a global pointer, see
+https://bugs.chromium.org/p/chromium/issues/detail?id=1356211
+
+The old implementation could also generate the same id for dynamically
+created nodes which happened to reuse the same memory. Ids for namespace
+nodes were completely broken. They now use the id of the parent element
+together with the hex-encoded namespace prefix.
+
+CVE: CVE-2023-40403
+Upstream-Status: Backport [https://gitlab.gnome.org/GNOME/libxslt/-/commit/82f6cbf8ca61b1f9e00dc04aa3b15d563e7bbc6d]
+Signed-off-by: Hitendra Prajapati <hprajapati@mvista.com>
+
+---
+ libxslt/functions.c               | 107 +++++++++++++++++++++++++-----
+ libxslt/xsltInternals.h           |   1 +
+ libxslt/xsltutils.h               |   1 +
+ tests/REC/test-12.4-1.out         |  11 +++
+ tests/REC/test-12.4-1.xml         |   6 ++
+ tests/REC/test-12.4-1.xsl         |  38 +++++++++++
+ tests/exslt/common/dynamic-id.out |  13 ++++
+ tests/exslt/common/dynamic-id.xml |   1 +
+ tests/exslt/common/dynamic-id.xsl |  29 ++++++++
+ 9 files changed, 191 insertions(+), 16 deletions(-)
+ create mode 100644 tests/REC/test-12.4-1.out
+ create mode 100644 tests/REC/test-12.4-1.xml
+ create mode 100644 tests/REC/test-12.4-1.xsl
+ create mode 100644 tests/exslt/common/dynamic-id.out
+ create mode 100644 tests/exslt/common/dynamic-id.xml
+ create mode 100644 tests/exslt/common/dynamic-id.xsl
+
+diff --git a/libxslt/functions.c b/libxslt/functions.c
+index 7887dda..da25c24 100644
+--- a/libxslt/functions.c
++++ b/libxslt/functions.c
+@@ -693,11 +693,16 @@ xsltFormatNumberFunction(xmlXPathParserContextPtr ctxt, int nargs)
+  */
+ void
+ xsltGenerateIdFunction(xmlXPathParserContextPtr ctxt, int nargs){
+-    static char base_address;
++    xsltTransformContextPtr tctxt;
+     xmlNodePtr cur = NULL;
+     xmlXPathObjectPtr obj = NULL;
+-    long val;
+-    xmlChar str[30];
++    char *str;
++    const xmlChar *nsPrefix = NULL;
++    void **psviPtr;
++    unsigned long id;
++    size_t size, nsPrefixSize;
++
++    tctxt = xsltXPathGetTransformContext(ctxt);
+ 
+     if (nargs == 0) {
+ 	cur = ctxt->context->node;
+@@ -707,16 +712,15 @@ xsltGenerateIdFunction(xmlXPathParserContextPtr ctxt, int nargs){
+ 
+ 	if ((ctxt->value == NULL) || (ctxt->value->type != XPATH_NODESET)) {
+ 	    ctxt->error = XPATH_INVALID_TYPE;
+-	    xsltTransformError(xsltXPathGetTransformContext(ctxt), NULL, NULL,
++	    xsltTransformError(tctxt, NULL, NULL,
+ 		"generate-id() : invalid arg expecting a node-set\n");
+-	    return;
++            goto out;
+ 	}
+ 	obj = valuePop(ctxt);
+ 	nodelist = obj->nodesetval;
+ 	if ((nodelist == NULL) || (nodelist->nodeNr <= 0)) {
+-	    xmlXPathFreeObject(obj);
+ 	    valuePush(ctxt, xmlXPathNewCString(""));
+-	    return;
++	    goto out;
+ 	}
+ 	cur = nodelist->nodeTab[0];
+ 	for (i = 1;i < nodelist->nodeNr;i++) {
+@@ -725,22 +729,93 @@ xsltGenerateIdFunction(xmlXPathParserContextPtr ctxt, int nargs){
+ 	        cur = nodelist->nodeTab[i];
+ 	}
+     } else {
+-	xsltTransformError(xsltXPathGetTransformContext(ctxt), NULL, NULL,
++	xsltTransformError(tctxt, NULL, NULL,
+ 		"generate-id() : invalid number of args %d\n", nargs);
+ 	ctxt->error = XPATH_INVALID_ARITY;
+-	return;
++	goto out;
++    }
++
++    size = 30; /* for "id%lu" */
++
++    if (cur->type == XML_NAMESPACE_DECL) {
++        xmlNsPtr ns = (xmlNsPtr) cur;
++
++        nsPrefix = ns->prefix;
++        if (nsPrefix == NULL)
++            nsPrefix = BAD_CAST "";
++        nsPrefixSize = xmlStrlen(nsPrefix);
++        /* For "ns" and hex-encoded string */
++        size += nsPrefixSize * 2 + 2;
++
++        /* Parent is stored in 'next'. */
++        cur = (xmlNodePtr) ns->next;
++    }
++
++    psviPtr = xsltGetPSVIPtr(cur);
++    if (psviPtr == NULL) {
++        xsltTransformError(tctxt, NULL, NULL,
++                "generate-id(): invalid node type %d\n", cur->type);
++        ctxt->error = XPATH_INVALID_TYPE;
++        goto out;
+     }
+ 
+-    if (obj)
+-        xmlXPathFreeObject(obj);
++    if (xsltGetSourceNodeFlags(cur) & XSLT_SOURCE_NODE_HAS_ID) {
++        id = (unsigned long) *psviPtr;
++    } else {
++        if (cur->type == XML_TEXT_NODE && cur->line == USHRT_MAX) {
++            /* Text nodes store big line numbers in psvi. */
++            cur->line = 0;
++        } else if (*psviPtr != NULL) {
++            xsltTransformError(tctxt, NULL, NULL,
++                    "generate-id(): psvi already set\n");
++            ctxt->error = XPATH_MEMORY_ERROR;
++            goto out;
++        }
++
++        if (tctxt->currentId == ULONG_MAX) {
++            xsltTransformError(tctxt, NULL, NULL,
++                    "generate-id(): id overflow\n");
++            ctxt->error = XPATH_MEMORY_ERROR;
++            goto out;
++        }
++
++        id = ++tctxt->currentId;
++        *psviPtr = (void *) id;
++        xsltSetSourceNodeFlags(tctxt, cur, XSLT_SOURCE_NODE_HAS_ID);
++    }
+ 
+-    val = (long)((char *)cur - (char *)&base_address);
+-    if (val >= 0) {
+-      snprintf((char *)str, sizeof(str), "idp%ld", val);
++    str = xmlMalloc(size);
++    if (str == NULL) {
++        xsltTransformError(tctxt, NULL, NULL,
++                "generate-id(): out of memory\n");
++        ctxt->error = XPATH_MEMORY_ERROR;
++        goto out;
++    }
++    if (nsPrefix == NULL) {
++        snprintf(str, size, "id%lu", id);
+     } else {
+-      snprintf((char *)str, sizeof(str), "idm%ld", -val);
++        size_t i, j;
++
++        snprintf(str, size, "id%luns", id);
++
++        /*
++         * Only ASCII alphanumerics are allowed, so we hex-encode the prefix.
++         */
++        j = strlen(str);
++        for (i = 0; i < nsPrefixSize; i++) {
++            int v;
++
++            v = nsPrefix[i] >> 4;
++            str[j++] = v < 10 ? '0' + v : 'A' + (v - 10);
++            v = nsPrefix[i] & 15;
++            str[j++] = v < 10 ? '0' + v : 'A' + (v - 10);
++        }
++        str[j] = '\0';
+     }
+-    valuePush(ctxt, xmlXPathNewString(str));
++    valuePush(ctxt, xmlXPathWrapString(BAD_CAST str));
++
++out:
++    xmlXPathFreeObject(obj);
+ }
+ 
+ /**
+diff --git a/libxslt/xsltInternals.h b/libxslt/xsltInternals.h
+index 74a2b64..2fd1f68 100644
+--- a/libxslt/xsltInternals.h
++++ b/libxslt/xsltInternals.h
+@@ -1787,6 +1787,7 @@ struct _xsltTransformContext {
+     unsigned long opLimit;
+     unsigned long opCount;
+     int sourceDocDirty;
++    unsigned long currentId; /* For generate-id() */
+ };
+ 
+ /**
+diff --git a/libxslt/xsltutils.h b/libxslt/xsltutils.h
+index dcfd139..6c14ecf 100644
+--- a/libxslt/xsltutils.h
++++ b/libxslt/xsltutils.h
+@@ -250,6 +250,7 @@ XSLTPUBFUN xmlXPathCompExprPtr XSLTCALL
+ #ifdef IN_LIBXSLT
+ #define XSLT_SOURCE_NODE_MASK       15
+ #define XSLT_SOURCE_NODE_HAS_KEY    1
++#define XSLT_SOURCE_NODE_HAS_ID     2
+ int
+ xsltGetSourceNodeFlags(xmlNodePtr node);
+ int
+diff --git a/tests/REC/test-12.4-1.out b/tests/REC/test-12.4-1.out
+new file mode 100644
+index 0000000..237a9f2
+--- /dev/null
++++ b/tests/REC/test-12.4-1.out
+@@ -0,0 +1,11 @@
++<?xml version="1.0"?>
++<result>
++  <document>id1</document>
++  <element>id2</element>
++  <attribute>id3</attribute>
++  <namespace>id2ns</namespace>
++  <namespace>id2nsC3A4C3B6C3BC</namespace>
++  <text>id4</text>
++  <comment>id5</comment>
++  <processing-instruction>id6</processing-instruction>
++</result>
+diff --git a/tests/REC/test-12.4-1.xml b/tests/REC/test-12.4-1.xml
+new file mode 100644
+index 0000000..84484f6
+--- /dev/null
++++ b/tests/REC/test-12.4-1.xml
+@@ -0,0 +1,6 @@
++<doc xmlns="s:def">
++    <elem attr="value" xmlns:äöü="uri"/>
++    <text>text</text>
++    <!-- comment -->
++    <?pi content?>
++</doc>
+diff --git a/tests/REC/test-12.4-1.xsl b/tests/REC/test-12.4-1.xsl
+new file mode 100644
+index 0000000..5cf5dd3
+--- /dev/null
++++ b/tests/REC/test-12.4-1.xsl
+@@ -0,0 +1,38 @@
++<xsl:stylesheet
++    version="1.0"
++    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
++    xmlns:d="s:def"
++    exclude-result-prefixes="d">
++
++<xsl:output indent="yes"/>
++
++<xsl:template match="/">
++    <result>
++        <document>
++            <xsl:value-of select="generate-id(/)"/>
++        </document>
++        <element>
++            <xsl:value-of select="generate-id(/d:doc/d:elem)"/>
++        </element>
++        <attribute>
++            <xsl:value-of select="generate-id(d:doc/d:elem/@attr)"/>
++        </attribute>
++        <namespace>
++            <xsl:value-of select="generate-id(d:doc/d:elem/namespace::*[local-name()=''])"/>
++        </namespace>
++        <namespace>
++            <xsl:value-of select="generate-id(d:doc/d:elem/namespace::äöü)"/>
++        </namespace>
++        <text>
++            <xsl:value-of select="generate-id(d:doc/d:text/text())"/>
++        </text>
++        <comment>
++            <xsl:value-of select="generate-id(d:doc/comment())"/>
++        </comment>
++        <processing-instruction>
++            <xsl:value-of select="generate-id(d:doc/processing-instruction())"/>
++        </processing-instruction>
++    </result>
++</xsl:template>
++
++</xsl:stylesheet>
+diff --git a/tests/exslt/common/dynamic-id.out b/tests/exslt/common/dynamic-id.out
+new file mode 100644
+index 0000000..1b7b7ba
+--- /dev/null
++++ b/tests/exslt/common/dynamic-id.out
+@@ -0,0 +1,13 @@
++<?xml version="1.0"?>
++<result xmlns:exsl="http://exslt.org/common">
++  <id>id1</id>
++  <id>id2</id>
++  <id>id3</id>
++  <id>id4</id>
++  <id>id5</id>
++  <id>id6</id>
++  <id>id7</id>
++  <id>id8</id>
++  <id>id9</id>
++  <id>id10</id>
++</result>
+diff --git a/tests/exslt/common/dynamic-id.xml b/tests/exslt/common/dynamic-id.xml
+new file mode 100644
+index 0000000..69d62f2
+--- /dev/null
++++ b/tests/exslt/common/dynamic-id.xml
+@@ -0,0 +1 @@
++<doc/>
+diff --git a/tests/exslt/common/dynamic-id.xsl b/tests/exslt/common/dynamic-id.xsl
+new file mode 100644
+index 0000000..8478f6a
+--- /dev/null
++++ b/tests/exslt/common/dynamic-id.xsl
+@@ -0,0 +1,29 @@
++<xsl:stylesheet
++    version="1.0"
++    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
++    xmlns:exsl="http://exslt.org/common">
++
++<xsl:output indent="yes"/>
++
++<xsl:template name="dynamic-id">
++    <id>
++        <xsl:value-of select="generate-id(exsl:node-set('string'))"/>
++    </id>
++</xsl:template>
++
++<xsl:template match="/">
++    <result>
++        <xsl:call-template name="dynamic-id"/>
++        <xsl:call-template name="dynamic-id"/>
++        <xsl:call-template name="dynamic-id"/>
++        <xsl:call-template name="dynamic-id"/>
++        <xsl:call-template name="dynamic-id"/>
++        <xsl:call-template name="dynamic-id"/>
++        <xsl:call-template name="dynamic-id"/>
++        <xsl:call-template name="dynamic-id"/>
++        <xsl:call-template name="dynamic-id"/>
++        <xsl:call-template name="dynamic-id"/>
++    </result>
++</xsl:template>
++
++</xsl:stylesheet>
diff --git a/meta/recipes-support/libxslt/libxslt/CVE-2023-40403-005.patch b/meta/recipes-support/libxslt/libxslt/CVE-2023-40403-005.patch
new file mode 100644
index 0000000000..e27034a0ec
--- /dev/null
+++ b/meta/recipes-support/libxslt/libxslt/CVE-2023-40403-005.patch
@@ -0,0 +1,55 @@ 
+From 3014af50b22f1be89b5514faea284de7b63fa5dc Mon Sep 17 00:00:00 2001
+From: Nick Wellnhofer <wellnhofer@aevum.de>
+Date: Wed, 31 Aug 2022 21:37:44 +0200
+Subject: [PATCH] Clean up attributes in source doc
+
+Also make bit flag constants unsigned to avoid implicit-conversion
+warnings.
+
+CVE: CVE-2023-40403
+Upstream-Status: Backport [https://gitlab.gnome.org/GNOME/libxslt/-/commit/452fb4ca9b9803448826008b9573987c615912a1]
+Signed-off-by: Hitendra Prajapati <hprajapati@mvista.com>
+
+---
+ libxslt/transform.c | 10 ++++++++++
+ libxslt/xsltutils.h |  6 +++---
+ 2 files changed, 13 insertions(+), 3 deletions(-)
+
+diff --git a/libxslt/transform.c b/libxslt/transform.c
+index 19d7326..7299eb5 100644
+--- a/libxslt/transform.c
++++ b/libxslt/transform.c
+@@ -5764,6 +5764,16 @@ xsltCleanupSourceDoc(xmlDocPtr doc) {
+         if (psviPtr)
+             *psviPtr = NULL;
+ 
++        if (cur->type == XML_ELEMENT_NODE) {
++            xmlAttrPtr prop = cur->properties;
++
++            while (prop) {
++                prop->atype &= ~(XSLT_SOURCE_NODE_MASK << 27);
++                prop->psvi = NULL;
++                prop = prop->next;
++            }
++        }
++
+         if (cur->children != NULL && cur->type != XML_ENTITY_REF_NODE) {
+             cur = cur->children;
+         } else {
+diff --git a/libxslt/xsltutils.h b/libxslt/xsltutils.h
+index 6c14ecf..2af4282 100644
+--- a/libxslt/xsltutils.h
++++ b/libxslt/xsltutils.h
+@@ -248,9 +248,9 @@ XSLTPUBFUN xmlXPathCompExprPtr XSLTCALL
+ 						 int flags);
+ 
+ #ifdef IN_LIBXSLT
+-#define XSLT_SOURCE_NODE_MASK       15
+-#define XSLT_SOURCE_NODE_HAS_KEY    1
+-#define XSLT_SOURCE_NODE_HAS_ID     2
++#define XSLT_SOURCE_NODE_MASK       15u
++#define XSLT_SOURCE_NODE_HAS_KEY    1u
++#define XSLT_SOURCE_NODE_HAS_ID     2u
+ int
+ xsltGetSourceNodeFlags(xmlNodePtr node);
+ int
diff --git a/meta/recipes-support/libxslt/libxslt_1.1.35.bb b/meta/recipes-support/libxslt/libxslt_1.1.35.bb
index 3df372b267..2291ed2cad 100644
--- a/meta/recipes-support/libxslt/libxslt_1.1.35.bb
+++ b/meta/recipes-support/libxslt/libxslt_1.1.35.bb
@@ -16,6 +16,11 @@  DEPENDS = "libxml2"
 SRC_URI = "https://download.gnome.org/sources/libxslt/1.1/libxslt-${PV}.tar.xz \
            file://CVE-2024-55549.patch \
            file://CVE-2025-24855.patch \
+           file://CVE-2023-40403-001.patch \
+           file://CVE-2023-40403-002.patch \
+           file://CVE-2023-40403-003.patch \
+           file://CVE-2023-40403-004.patch \
+           file://CVE-2023-40403-005.patch \
           "
 
 SRC_URI[sha256sum] = "8247f33e9a872c6ac859aa45018bc4c4d00b97e2feac9eebc10c93ce1f34dd79"