Source: libxslt Version: 1.1.28-2.1 Severity: wishlist Tags: patch upstream fixed-upstream User: [email protected] Usertags: toolchain randomness Forwarded: https://bugzilla.gnome.org/show_bug.cgi?id=751621
Dear maintainer,
in the context of reproducible builds we worked on a patch with upstream
to provide stable IDs to the generated documents. We've been using that
patch for the last 10 months and we're confident it does the job. Not
to say that it has been already incorporated upstream.
We would like to see the Debian package use this patch, instead of
having it on our experimental repository.
Please, find the patch attached.
Thanks in advance.
--
regards,
Mattia Rizzolo
GPG Key: 66AE 2B4A FCCF 3F52 DA18 4D18 4B04 3FCD B944 4540 .''`.
more about me: https://mapreri.org : :' :
Launchpad user: https://launchpad.net/~mapreri `. `'`
Debian QA page: https://qa.debian.org/developer.php?login=mattia `-
Description: Make generate-id() provide stable IDs Author: Daniel Veillard Origin: upstream, https://bugzilla.gnome.org/attachment.cgi?id=306475 Bug: https://bugzilla.gnome.org/show_bug.cgi?id=751621 Last-Update: 2015-07-01 diff --git a/libxslt/functions.c b/libxslt/functions.c index 6448bde..5b00a6d 100644 --- a/libxslt/functions.c +++ b/libxslt/functions.c @@ -651,6 +651,63 @@ xsltFormatNumberFunction(xmlXPathParserContextPtr ctxt, int nargs) } /** + * xsltCleanupIds: + * @ctxt: the transformation context + * @root: the root of the resulting document + * + * This clean up ids which may have been saved in Element contents + * by xsltGenerateIdFunction() to provide stable IDs on elements. + * + * Returns the number of items cleaned or -1 in case of error + */ +int +xsltCleanupIds(xsltTransformContextPtr ctxt, xmlNodePtr root) { + xmlNodePtr cur; + int count = 0; + + if ((ctxt == NULL) || (root == NULL)) + return(-1); + if (root->type != XML_ELEMENT_NODE) + return(-1); + + cur = root; + while (cur != NULL) { + if (cur->type == XML_ELEMENT_NODE) { + if (cur->content != NULL) { + cur->content = NULL; + count++; + } + if (cur->children != NULL) { + cur = cur->children; + continue; + } + } + if (cur->next != NULL) { + cur = cur->next; + continue; + } + do { + cur = cur->parent; + if (cur == NULL) + break; + if (cur == (xmlNodePtr) root) { + cur = NULL; + break; + } + if (cur->next != NULL) { + cur = cur->next; + break; + } + } while (cur != NULL); + } + +fprintf(stderr, "Attributed %d IDs for element, cleaned up %d\n", + ctxt->nextid, count); + + return(count); +} + +/** * xsltGenerateIdFunction: * @ctxt: the XPath Parser context * @nargs: the number of arguments @@ -701,7 +758,39 @@ xsltGenerateIdFunction(xmlXPathParserContextPtr ctxt, int nargs){ if (obj) xmlXPathFreeObject(obj); - val = (long)((char *)cur - (char *)&base_address); + /* + * Try to provide stable ID for generated document: + * - usually ID are computed to be placed on elements via attributes + * so using the element as the node for the ID + * - the cur->content should be a correct placeholder for this, we use + * it to hold element node numbers in xmlXPathOrderDocElems to + * speed up XPath too + * - xsltCleanupIds() clean them up before handing the XSLT output + * to the API client. + * - other nodes types use the node address method but that should + * not end up in resulting document ID + * - we can enable this by default without risk of performance issues + * only the one pass xsltCleanupIds() is added + */ + if (cur->type == XML_ELEMENT_NODE) { + if (cur->content == NULL) { + xsltTransformContextPtr tctxt; + + tctxt = xsltXPathGetTransformContext(ctxt); + if (tctxt == NULL) { + val = (long)((char *)cur - (char *)&base_address); + } else { + tctxt->nextid++; + val = tctxt->nextid; + cur->content = (void *) (val); + } + } else { + val = (long) cur->content; + } + } else { + val = (long)((char *)cur - (char *)&base_address); + } + if (val >= 0) { sprintf((char *)str, "idp%ld", val); } else { diff --git a/libxslt/functions.h b/libxslt/functions.h index e0e0bf9..4a1e163 100644 --- a/libxslt/functions.h +++ b/libxslt/functions.h @@ -64,6 +64,13 @@ XSLTPUBFUN void XSLTCALL int nargs); /* + * Cleanup for ID generation + */ +XSLTPUBFUN int XSLTCALL + xsltCleanupIds (xsltTransformContextPtr ctxt, + xmlNodePtr root); + +/* * And the registration */ diff --git a/libxslt/transform.c b/libxslt/transform.c index 24f9eb2..2bdf6bf 100644 --- a/libxslt/transform.c +++ b/libxslt/transform.c @@ -700,6 +700,7 @@ xsltNewTransformContext(xsltStylesheetPtr style, xmlDocPtr doc) { cur->traceCode = (unsigned long*) &xsltDefaultTrace; cur->xinclude = xsltGetXIncludeDefault(); cur->keyInitLevel = 0; + cur->nextid = 0; return(cur); @@ -6092,6 +6093,13 @@ xsltApplyStylesheetInternal(xsltStylesheetPtr style, xmlDocPtr doc, if (root != NULL) { const xmlChar *doctype = NULL; + /* + * cleanup ids which may have been saved in Elements content ptrs + */ + if (ctxt->nextid != 0) { + xsltCleanupIds(ctxt, root); + } + if ((root->ns != NULL) && (root->ns->prefix != NULL)) doctype = xmlDictQLookup(ctxt->dict, root->ns->prefix, root->name); if (doctype == NULL) diff --git a/libxslt/xsltInternals.h b/libxslt/xsltInternals.h index 95e8fe6..8eedae4 100644 --- a/libxslt/xsltInternals.h +++ b/libxslt/xsltInternals.h @@ -1786,6 +1786,8 @@ struct _xsltTransformContext { int funcLevel; /* Needed to catch recursive functions issues */ int maxTemplateDepth; int maxTemplateVars; + + unsigned long nextid;/* for generating stable ids */ }; /**
signature.asc
Description: PGP signature

