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
