>From aa709979cad4ac7d8b4ea8b34815e5ea7f4dde1d Mon Sep 17 00:00:00 2001 From: Mathieu Lirzin Date: Mon, 18 Apr 2016 23:21:42 +0200 Subject: [PATCH 1/2] gnu: libxslt: Make generated documentation reproducible. * gnu/packages/patches/libxslt-generated-ids.patch: New file. * gnu/packages/patches/libxslt-remove-date-timestamps.patch: Likewise. * gnu/packages/xml.scm (libxslt)[source]: Use them. * gnu-system.am (dist_patch_DATA): Add them. --- gnu-system.am | 2 + gnu/packages/patches/libxslt-generated-ids.patch | 173 +++++++++++++++++++++ .../patches/libxslt-remove-date-timestamps.patch | 66 ++++++++ gnu/packages/xml.scm | 5 +- 4 files changed, 245 insertions(+), 1 deletion(-) create mode 100644 gnu/packages/patches/libxslt-generated-ids.patch create mode 100644 gnu/packages/patches/libxslt-remove-date-timestamps.patch diff --git a/gnu-system.am b/gnu-system.am index d58155a..8a0ad82 100644 --- a/gnu-system.am +++ b/gnu-system.am @@ -594,6 +594,8 @@ dist_patch_DATA = \ gnu/packages/patches/libwmf-CVE-2015-4695.patch \ gnu/packages/patches/libwmf-CVE-2015-4696.patch \ gnu/packages/patches/libxslt-CVE-2015-7995.patch \ + gnu/packages/patches/libxslt-generated-ids.patch \ + gnu/packages/patches/libxslt-remove-date-timestamps.patch \ gnu/packages/patches/lirc-localstatedir.patch \ gnu/packages/patches/libpthread-glibc-preparation.patch \ gnu/packages/patches/lm-sensors-hwmon-attrs.patch \ diff --git a/gnu/packages/patches/libxslt-generated-ids.patch b/gnu/packages/patches/libxslt-generated-ids.patch new file mode 100644 index 0000000..4273875 --- /dev/null +++ b/gnu/packages/patches/libxslt-generated-ids.patch @@ -0,0 +1,173 @@ +This makes generated IDs deterministic. + +Written by Daniel Veillard. + +This should be fixed in next release (2.29). +See https://bugzilla.gnome.org/show_bug.cgi?id=751621. + +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 */ + }; + + /** diff --git a/gnu/packages/patches/libxslt-remove-date-timestamps.patch b/gnu/packages/patches/libxslt-remove-date-timestamps.patch new file mode 100644 index 0000000..51470d0 --- /dev/null +++ b/gnu/packages/patches/libxslt-remove-date-timestamps.patch @@ -0,0 +1,66 @@ +Use deterministic SOURCE_DATE_EPOCH for embedded timestamps in generated documentation. + +Written by Eduard Sanou. + +https://bugzilla.gnome.org/show_bug.cgi?id=758148 + +--- libxslt-1.1.28.orig/libexslt/date.c ++++ libxslt-1.1.28/libexslt/date.c +@@ -46,6 +46,7 @@ + #include "exslt.h" + + #include ++#include + + #ifdef HAVE_MATH_H + #include +@@ -747,21 +748,46 @@ static exsltDateValPtr + exsltDateCurrent (void) + { + struct tm localTm, gmTm; ++ struct tm *tb = NULL; + time_t secs; + int local_s, gm_s; + exsltDateValPtr ret; ++ char *source_date_epoch; + + ret = exsltDateCreateDate(XS_DATETIME); + if (ret == NULL) + return NULL; + +- /* get current time */ + secs = time(NULL); ++ /* ++ * Allow the date and time to be set externally by an exported ++ * environment variable to enable reproducible builds. ++ */ ++ source_date_epoch = getenv("SOURCE_DATE_EPOCH"); ++ if (source_date_epoch) { ++ errno = 0; ++ secs = (time_t) strtol (source_date_epoch, NULL, 10); ++ if (errno == 0) { ++ tb = gmtime(&secs); ++ if (tb == NULL) { ++ /* SOURCE_DATE_EPOCH is not a valid date */ ++ return NULL; ++ } else { ++ localTm = *tb; ++ } ++ } else { ++ /* SOURCE_DATE_EPOCH is not a valid number */ ++ return NULL; ++ } ++ } else { ++ /* get current time */ + #if HAVE_LOCALTIME_R +- localtime_r(&secs, &localTm); ++ localtime_r(&secs, &localTm); + #else +- localTm = *localtime(&secs); ++ localTm = *localtime(&secs); + #endif ++ } ++ + + /* get real year, not years since 1900 */ + ret->value.date.year = localTm.tm_year + 1900; diff --git a/gnu/packages/xml.scm b/gnu/packages/xml.scm index e1f111e..33ce970 100644 --- a/gnu/packages/xml.scm +++ b/gnu/packages/xml.scm @@ -7,6 +7,7 @@ ;;; Copyright © 2015 Mark H Weaver ;;; Copyright © 2015 Efraim Flashner ;;; Copyright © 2015 Raimon Grau +;;; Copyright © 2016 Mathieu Lirzin ;;; ;;; This file is part of GNU Guix. ;;; @@ -132,7 +133,9 @@ project (but it is usable outside of the Gnome platform).") (sha256 (base32 "13029baw9kkyjgr7q3jccw2mz38amq7mmpr5p3bh775qawd1bisz")) - (patches (search-patches "libxslt-CVE-2015-7995.patch")))) + (patches (search-patches "libxslt-generated-ids.patch" + "libxslt-remove-date-timestamps.patch" + "libxslt-CVE-2015-7995.patch")))) (build-system gnu-build-system) (home-page "http://xmlsoft.org/XSLT/index.html") (synopsis "C library for applying XSLT stylesheets to XML documents") -- 2.8.0.rc3