1062 lines
32 KiB
Diff
1062 lines
32 KiB
Diff
From e494220e4a57e87e8561e6798f57f4dcf91762b3 Mon Sep 17 00:00:00 2001
|
|
From: Nick Wellnhofer <wellnhofer@aevum.de>
|
|
Date: Wed, 31 Aug 2022 15:29:57 +0200
|
|
Subject: [PATCH 1/5] 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.
|
|
---
|
|
libxslt/transform.c | 34 ++++++++++
|
|
libxslt/xsltInternals.h | 3 +
|
|
libxslt/xsltutils.c | 135 ++++++++++++++++++++++++++++++++++++++++
|
|
libxslt/xsltutils.h | 15 ++++-
|
|
4 files changed, 186 insertions(+), 1 deletion(-)
|
|
|
|
diff --git a/libxslt/transform.c b/libxslt/transform.c
|
|
index f748f2df..8634b09e 100644
|
|
--- a/libxslt/transform.c
|
|
+++ b/libxslt/transform.c
|
|
@@ -5824,6 +5824,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
|
|
@@ -6210,6 +6241,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 47125b36..39b488c0 100644
|
|
--- a/libxslt/xsltInternals.h
|
|
+++ b/libxslt/xsltInternals.h
|
|
@@ -1789,6 +1789,9 @@ struct _xsltTransformContext {
|
|
int depth; /* Needed to catch recursions */
|
|
int maxTemplateDepth;
|
|
int maxTemplateVars;
|
|
+ unsigned long opLimit;
|
|
+ unsigned long opCount;
|
|
+ int sourceDocDirty;
|
|
};
|
|
|
|
/**
|
|
diff --git a/libxslt/xsltutils.c b/libxslt/xsltutils.c
|
|
index 2154b238..a0d9d331 100644
|
|
--- a/libxslt/xsltutils.c
|
|
+++ b/libxslt/xsltutils.c
|
|
@@ -1788,6 +1788,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;
|
|
+ }
|
|
+}
|
|
+
|
|
/************************************************************************
|
|
* *
|
|
* Generating profiling informations *
|
|
diff --git a/libxslt/xsltutils.h b/libxslt/xsltutils.h
|
|
index 789865a6..df89aeb1 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.
|
|
*/
|
|
@@ -267,6 +280,7 @@ XSLTPUBFUN void XSLTCALL
|
|
* Sampling precision for profiling
|
|
*/
|
|
#define XSLT_TIMESTAMP_TICS_PER_SEC 100000l
|
|
+#endif
|
|
|
|
/*
|
|
* Hooks for the debugger.
|
|
@@ -306,7 +320,6 @@ XSLTPUBFUN void XSLTCALL
|
|
|
|
#ifdef __cplusplus
|
|
}
|
|
-#endif
|
|
|
|
#endif /* __XML_XSLTUTILS_H__ */
|
|
|
|
--
|
|
2.49.0
|
|
|
|
|
|
From 5895aaae58025fa35a540f6f922f9137505f1e27 Mon Sep 17 00:00:00 2001
|
|
From: Nick Wellnhofer <wellnhofer@aevum.de>
|
|
Date: Wed, 31 Aug 2022 15:34:47 +0200
|
|
Subject: [PATCH 2/5] Store key status of source nodes as bit flag
|
|
|
|
This frees up the psvi member.
|
|
---
|
|
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 85902b0d..6675903d 100644
|
|
--- a/libxslt/keys.c
|
|
+++ b/libxslt/keys.c
|
|
@@ -826,24 +826,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 c094e974..11d8c3e5 100644
|
|
--- a/libxslt/pattern.c
|
|
+++ b/libxslt/pattern.c
|
|
@@ -2328,7 +2328,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);
|
|
@@ -2405,37 +2404,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:
|
|
@@ -2496,7 +2483,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) || (list->priority > priority))) {
|
|
@@ -2521,27 +2508,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 df89aeb1..80194891 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
|
|
--
|
|
2.49.0
|
|
|
|
|
|
From 5bdb3e5c9a0a4bc42dd14fe07cf594298a79edce Mon Sep 17 00:00:00 2001
|
|
From: Nick Wellnhofer <wellnhofer@aevum.de>
|
|
Date: Wed, 31 Aug 2022 15:35:37 +0200
|
|
Subject: [PATCH 3/5] 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.
|
|
---
|
|
libexslt/functions.c | 2 +-
|
|
libxslt/transform.c | 20 +++++++++----------
|
|
libxslt/variables.c | 44 ++++++++++++++++++++---------------------
|
|
libxslt/variables.h | 6 +++---
|
|
libxslt/xsltInternals.h | 2 +-
|
|
5 files changed, 37 insertions(+), 37 deletions(-)
|
|
|
|
diff --git a/libexslt/functions.c b/libexslt/functions.c
|
|
index aeb7aaf9..079acde6 100644
|
|
--- a/libexslt/functions.c
|
|
+++ b/libexslt/functions.c
|
|
@@ -758,7 +758,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 8634b09e..a631529c 100644
|
|
--- a/libxslt/transform.c
|
|
+++ b/libxslt/transform.c
|
|
@@ -2307,21 +2307,21 @@ 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) {
|
|
- if (prev == NULL)
|
|
- ctxt->localRVT = tmp;
|
|
- else
|
|
- prev->next = (xmlNodePtr) tmp;
|
|
- tmp->prev = (xmlNodePtr) prev;
|
|
- prev = tmp;
|
|
+ } 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->compression = XSLT_RVT_FUNC_RESULT;
|
|
} else {
|
|
xmlGenericError(xmlGenericErrorContext,
|
|
"xsltReleaseLocalRVTs: Unexpected RVT flag %p\n",
|
|
- tmp->psvi);
|
|
+ tmp->compression);
|
|
}
|
|
} while (cur != base);
|
|
|
|
diff --git a/libxslt/variables.c b/libxslt/variables.c
|
|
index 5fdbee0f..0f4b72f3 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
|
|
@@ -253,7 +253,7 @@ xsltExtensionInstructionResultRegister(xsltTransformContextPtr ctxt,
|
|
* 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;
|
|
@@ -300,34 +300,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;
|
|
}
|
|
}
|
|
}
|
|
@@ -380,7 +380,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;
|
|
@@ -419,7 +419,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)
|
|
@@ -578,15 +578,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);
|
|
}
|
|
}
|
|
}
|
|
@@ -981,7 +981,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 039288fb..e2adee0f 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 39b488c0..e7a058cc 100644
|
|
--- a/libxslt/xsltInternals.h
|
|
+++ b/libxslt/xsltInternals.h
|
|
@@ -1918,7 +1918,7 @@ XSLTPUBFUN int XSLTCALL
|
|
xsltFlagRVTs(
|
|
xsltTransformContextPtr ctxt,
|
|
xmlXPathObjectPtr obj,
|
|
- void *val);
|
|
+ int val);
|
|
XSLTPUBFUN void XSLTCALL
|
|
xsltFreeRVTs (xsltTransformContextPtr ctxt);
|
|
XSLTPUBFUN void XSLTCALL
|
|
--
|
|
2.49.0
|
|
|
|
|
|
From 957e111edb935259e777c15e809b1d4de8ee2f3f Mon Sep 17 00:00:00 2001
|
|
From: Nick Wellnhofer <wellnhofer@aevum.de>
|
|
Date: Wed, 31 Aug 2022 13:35:23 +0200
|
|
Subject: [PATCH 4/5] 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.
|
|
---
|
|
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 43d82f6d..cd759d4e 100644
|
|
--- a/libxslt/functions.c
|
|
+++ b/libxslt/functions.c
|
|
@@ -680,11 +680,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;
|
|
@@ -694,16 +699,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++) {
|
|
@@ -712,22 +716,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 e7a058cc..ae9b76af 100644
|
|
--- a/libxslt/xsltInternals.h
|
|
+++ b/libxslt/xsltInternals.h
|
|
@@ -1792,6 +1792,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 80194891..bae9ad75 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 00000000..237a9f27
|
|
--- /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 00000000..84484f66
|
|
--- /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 00000000..5cf5dd33
|
|
--- /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 00000000..1b7b7bad
|
|
--- /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 00000000..69d62f2c
|
|
--- /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 00000000..8478f6af
|
|
--- /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>
|
|
--
|
|
2.49.0
|
|
|
|
|
|
From 7eff64281f0bcd4c6a452dc04f3250037d28786e Mon Sep 17 00:00:00 2001
|
|
From: Nick Wellnhofer <wellnhofer@aevum.de>
|
|
Date: Wed, 31 Aug 2022 21:37:44 +0200
|
|
Subject: [PATCH 5/5] Clean up attributes in source doc
|
|
|
|
Also make bit flag constants unsigned to avoid implicit-conversion
|
|
warnings.
|
|
---
|
|
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 a631529c..8a424773 100644
|
|
--- a/libxslt/transform.c
|
|
+++ b/libxslt/transform.c
|
|
@@ -5841,6 +5841,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 bae9ad75..98ca83a1 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
|
|
--
|
|
2.49.0
|
|
|