1 From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
2 From: Daniel Veillard <veillard@redhat.com>
3 Date: Sun, 29 Oct 2017 01:04:54 +0200
4 Subject: [PATCH] Make generate-id deterministic
6 Origin: upstream, https://bugzilla.gnome.org/attachment.cgi?id=306475
7 Bug: https://bugzilla.gnome.org/show_bug.cgi?id=751621
8 Bug-Debian: https://bugs.debian.org/823857
10 libxslt/functions.c | 91 ++++++++++++++++++++++++++++++++++++++++-
11 libxslt/functions.h | 7 ++++
12 libxslt/transform.c | 8 ++++
13 libxslt/xsltInternals.h | 2 +
14 4 files changed, 107 insertions(+), 1 deletion(-)
16 diff --git a/libxslt/functions.c b/libxslt/functions.c
17 index 7887dda70f67..be0d897bd471 100644
18 --- a/libxslt/functions.c
19 +++ b/libxslt/functions.c
20 @@ -683,6 +683,63 @@ xsltFormatNumberFunction(xmlXPathParserContextPtr ctxt, int nargs)
21 xmlXPathFreeObject(decimalObj);
26 + * @ctxt: the transformation context
27 + * @root: the root of the resulting document
29 + * This clean up ids which may have been saved in Element contents
30 + * by xsltGenerateIdFunction() to provide stable IDs on elements.
32 + * Returns the number of items cleaned or -1 in case of error
35 +xsltCleanupIds(xsltTransformContextPtr ctxt, xmlNodePtr root) {
39 + if ((ctxt == NULL) || (root == NULL))
41 + if (root->type != XML_ELEMENT_NODE)
45 + while (cur != NULL) {
46 + if (cur->type == XML_ELEMENT_NODE) {
47 + if (cur->content != NULL) {
48 + cur->content = NULL;
51 + if (cur->children != NULL) {
52 + cur = cur->children;
56 + if (cur->next != NULL) {
64 + if (cur == (xmlNodePtr) root) {
68 + if (cur->next != NULL) {
72 + } while (cur != NULL);
75 +fprintf(stderr, "Attributed %d IDs for element, cleaned up %d\n",
76 + ctxt->nextid, count);
82 * xsltGenerateIdFunction:
83 * @ctxt: the XPath Parser context
84 @@ -734,7 +791,39 @@ xsltGenerateIdFunction(xmlXPathParserContextPtr ctxt, int nargs){
86 xmlXPathFreeObject(obj);
88 - val = (long)((char *)cur - (char *)&base_address);
90 + * Try to provide stable ID for generated document:
91 + * - usually ID are computed to be placed on elements via attributes
92 + * so using the element as the node for the ID
93 + * - the cur->content should be a correct placeholder for this, we use
94 + * it to hold element node numbers in xmlXPathOrderDocElems to
95 + * speed up XPath too
96 + * - xsltCleanupIds() clean them up before handing the XSLT output
97 + * to the API client.
98 + * - other nodes types use the node address method but that should
99 + * not end up in resulting document ID
100 + * - we can enable this by default without risk of performance issues
101 + * only the one pass xsltCleanupIds() is added
103 + if (cur->type == XML_ELEMENT_NODE) {
104 + if (cur->content == NULL) {
105 + xsltTransformContextPtr tctxt;
107 + tctxt = xsltXPathGetTransformContext(ctxt);
108 + if (tctxt == NULL) {
109 + val = (long)((char *)cur - (char *)&base_address);
112 + val = tctxt->nextid;
113 + cur->content = (void *) (val);
116 + val = (long) cur->content;
119 + val = (long)((char *)cur - (char *)&base_address);
123 snprintf((char *)str, sizeof(str), "idp%ld", val);
125 diff --git a/libxslt/functions.h b/libxslt/functions.h
126 index 5455b7f47802..31163613f6e9 100644
127 --- a/libxslt/functions.h
128 +++ b/libxslt/functions.h
129 @@ -63,6 +63,13 @@ XSLTPUBFUN void XSLTCALL
130 xsltFunctionAvailableFunction (xmlXPathParserContextPtr ctxt,
134 + * Cleanup for ID generation
136 +XSLTPUBFUN int XSLTCALL
137 + xsltCleanupIds (xsltTransformContextPtr ctxt,
141 * And the registration
143 diff --git a/libxslt/transform.c b/libxslt/transform.c
144 index 57f05bf71920..9368e17197bf 100644
145 --- a/libxslt/transform.c
146 +++ b/libxslt/transform.c
147 @@ -706,6 +706,7 @@ xsltNewTransformContext(xsltStylesheetPtr style, xmlDocPtr doc) {
148 cur->traceCode = (unsigned long*) &xsltDefaultTrace;
149 cur->xinclude = xsltGetXIncludeDefault();
150 cur->keyInitLevel = 0;
155 @@ -6038,6 +6039,13 @@ xsltApplyStylesheetInternal(xsltStylesheetPtr style, xmlDocPtr doc,
157 const xmlChar *doctype = NULL;
160 + * cleanup ids which may have been saved in Elements content ptrs
162 + if (ctxt->nextid != 0) {
163 + xsltCleanupIds(ctxt, root);
166 if ((root->ns != NULL) && (root->ns->prefix != NULL))
167 doctype = xmlDictQLookup(ctxt->dict, root->ns->prefix, root->name);
169 diff --git a/libxslt/xsltInternals.h b/libxslt/xsltInternals.h
170 index 14343d2751c8..9d3ff5fc0c06 100644
171 --- a/libxslt/xsltInternals.h
172 +++ b/libxslt/xsltInternals.h
173 @@ -1786,6 +1786,8 @@ struct _xsltTransformContext {
175 unsigned long opLimit;
176 unsigned long opCount;
178 + unsigned long nextid;/* for generating stable ids */