[libxslt] Rework xsltAttrVT allocation



commit a1457d84da5e837e79cecda1c5fd4d3a8c9f9548
Author: Nick Wellnhofer <wellnhofer aevum de>
Date:   Tue Apr 16 12:58:27 2019 +0200

    Rework xsltAttrVT allocation
    
    - Suppress false positives under UBSan.
    - Fix memory leak in error case.

 libxslt/attrvt.c | 21 +++++++++++++++------
 1 file changed, 15 insertions(+), 6 deletions(-)
---
diff --git a/libxslt/attrvt.c b/libxslt/attrvt.c
index 125159ce..9744dfb3 100644
--- a/libxslt/attrvt.c
+++ b/libxslt/attrvt.c
@@ -48,7 +48,12 @@ struct _xsltAttrVT {
     /*
      * the content is an alternate of string and xmlXPathCompExprPtr
      */
-    void *segments[MAX_AVT_SEG];
+#if __STDC_VERSION__ >= 199901L
+    /* Using a C99 flexible array member avoids false positives under UBSan */
+    void *segments[];
+#else
+    void *segments[1];
+#endif
 };
 
 /**
@@ -62,15 +67,16 @@ struct _xsltAttrVT {
 static xsltAttrVTPtr
 xsltNewAttrVT(xsltStylesheetPtr style) {
     xsltAttrVTPtr cur;
+    size_t size = sizeof(xsltAttrVT) + MAX_AVT_SEG * sizeof(void*);
 
-    cur = (xsltAttrVTPtr) xmlMalloc(sizeof(xsltAttrVT));
+    cur = (xsltAttrVTPtr) xmlMalloc(size);
     if (cur == NULL) {
        xsltTransformError(NULL, style, NULL,
                "xsltNewAttrVTPtr : malloc failed\n");
        if (style != NULL) style->errors++;
        return(NULL);
     }
-    memset(cur, 0, sizeof(xsltAttrVT));
+    memset(cur, 0, size);
 
     cur->nb_seg = 0;
     cur->max_seg = MAX_AVT_SEG;
@@ -146,11 +152,14 @@ xsltFreeAVTList(void *avt) {
 static xsltAttrVTPtr
 xsltSetAttrVTsegment(xsltAttrVTPtr avt, void *val) {
     if (avt->nb_seg >= avt->max_seg) {
-       avt = (xsltAttrVTPtr) xmlRealloc(avt, sizeof(xsltAttrVT) +
-                       avt->max_seg * sizeof(void *));
-       if (avt == NULL) {
+        size_t size = sizeof(xsltAttrVT) +
+                      (avt->max_seg + MAX_AVT_SEG) * sizeof(void *);
+       xsltAttrVTPtr tmp = (xsltAttrVTPtr) xmlRealloc(avt, size);
+       if (tmp == NULL) {
+            xsltFreeAttrVT(avt);
            return NULL;
        }
+        avt = tmp;
        memset(&avt->segments[avt->nb_seg], 0, MAX_AVT_SEG*sizeof(void *));
        avt->max_seg += MAX_AVT_SEG;
     }


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]