[librsvg] bgo#776932: Don't render nodes whose "transform" attribute is invalid



commit 3b118396dded327e1b7bce43dfe37ed518a19e65
Author: Federico Mena Quintero <federico gnome org>
Date:   Thu Mar 16 08:39:42 2017 -0600

    bgo#776932: Don't render nodes whose "transform" attribute is invalid
    
    In the SVG 1.1 test suite, coords-trans-09-t.svg comes with this transform:
    
        <g transform="matrix(0 0 0 0 0 0)">
    
    which is invalid.  Now we detect whether transforms are in fact invalid,
    and propagate this info so that the corresponding nodes are not rendered.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=776932

 rsvg-styles.c                                      |   36 +++++--
 .../reftests/svg1.1/coords-trans-09-t-ref.png      |  Bin 0 -> 17268 bytes
 .../fixtures/reftests/svg1.1/coords-trans-09-t.svg |  102 ++++++++++++++++++++
 3 files changed, 127 insertions(+), 11 deletions(-)
---
diff --git a/rsvg-styles.c b/rsvg-styles.c
index 0f85f5a..b42c184 100644
--- a/rsvg-styles.c
+++ b/rsvg-styles.c
@@ -25,6 +25,7 @@
 */
 #include "config.h"
 
+#include <errno.h>
 #include <string.h>
 #include <math.h>
 
@@ -1305,16 +1306,18 @@ ccss_import_style (CRDocHandler * a_this,
    working draft dated 1999-07-06, section 8.5. Return TRUE on
    success. */
 gboolean
-rsvg_parse_transform (cairo_matrix_t *dst, const char *src)
+rsvg_parse_transform (cairo_matrix_t *out_matrix, const char *src)
 {
+    cairo_matrix_t dst;
     int idx;
     char keyword[32];
     double args[6];
     int n_args;
     guint key_len;
     cairo_matrix_t affine;
+    cairo_matrix_t inverse;
 
-    cairo_matrix_init_identity (dst);
+    cairo_matrix_init_identity (&dst);
 
     idx = 0;
     while (src[idx]) {
@@ -1358,7 +1361,11 @@ rsvg_parse_transform (cairo_matrix_t *dst, const char *src)
             if (g_ascii_isdigit (c) || c == '+' || c == '-' || c == '.') {
                 if (n_args == sizeof (args) / sizeof (args[0]))
                     return FALSE;       /* too many args */
+
                 args[n_args] = g_ascii_strtod (src + idx, &end_ptr);
+                if (errno == ERANGE)
+                    return FALSE; /* overflow / underflow */
+
                 idx = end_ptr - src;
 
                 while (g_ascii_isspace (src[idx]))
@@ -1380,42 +1387,42 @@ rsvg_parse_transform (cairo_matrix_t *dst, const char *src)
                 return FALSE;
 
             cairo_matrix_init (&affine, args[0], args[1], args[2], args[3], args[4], args[5]);
-            cairo_matrix_multiply (dst, &affine, dst);
+            cairo_matrix_multiply (&dst, &affine, &dst);
         } else if (!strcmp (keyword, "translate")) {
             if (n_args == 1)
                 args[1] = 0;
             else if (n_args != 2)
                 return FALSE;
             cairo_matrix_init_translate (&affine, args[0], args[1]);
-            cairo_matrix_multiply (dst, &affine, dst);
+            cairo_matrix_multiply (&dst, &affine, &dst);
         } else if (!strcmp (keyword, "scale")) {
             if (n_args == 1)
                 args[1] = args[0];
             else if (n_args != 2)
                 return FALSE;
             cairo_matrix_init_scale (&affine, args[0], args[1]);
-            cairo_matrix_multiply (dst, &affine, dst);
+            cairo_matrix_multiply (&dst, &affine, &dst);
         } else if (!strcmp (keyword, "rotate")) {
             if (n_args == 1) {
 
                 cairo_matrix_init_rotate (&affine, args[0] * M_PI / 180.);
-                cairo_matrix_multiply (dst, &affine, dst);
+                cairo_matrix_multiply (&dst, &affine, &dst);
             } else if (n_args == 3) {
                 cairo_matrix_init_translate (&affine, args[1], args[2]);
-                cairo_matrix_multiply (dst, &affine, dst);
+                cairo_matrix_multiply (&dst, &affine, &dst);
 
                 cairo_matrix_init_rotate (&affine, args[0] * M_PI / 180.);
-                cairo_matrix_multiply (dst, &affine, dst);
+                cairo_matrix_multiply (&dst, &affine, &dst);
 
                 cairo_matrix_init_translate (&affine, -args[1], -args[2]);
-                cairo_matrix_multiply (dst, &affine, dst);
+                cairo_matrix_multiply (&dst, &affine, &dst);
             } else
                 return FALSE;
         } else if (!strcmp (keyword, "skewX")) {
             if (n_args != 1)
                 return FALSE;
             _rsvg_cairo_matrix_init_shear (&affine, args[0]);
-            cairo_matrix_multiply (dst, &affine, dst);
+            cairo_matrix_multiply (&dst, &affine, &dst);
         } else if (!strcmp (keyword, "skewY")) {
             if (n_args != 1)
                 return FALSE;
@@ -1423,10 +1430,17 @@ rsvg_parse_transform (cairo_matrix_t *dst, const char *src)
             /* transpose the affine, given that we know [1] is zero */
             affine.yx = affine.xy;
             affine.xy = 0.;
-            cairo_matrix_multiply (dst, &affine, dst);
+            cairo_matrix_multiply (&dst, &affine, &dst);
         } else
             return FALSE;       /* unknown keyword */
     }
+
+    inverse = dst;
+    if (cairo_matrix_invert (&inverse) != CAIRO_STATUS_SUCCESS) {
+        return FALSE; /* we got passed an invalid matrix */
+    }
+
+    *out_matrix = dst;
     return TRUE;
 }
 
diff --git a/tests/fixtures/reftests/svg1.1/coords-trans-09-t-ref.png 
b/tests/fixtures/reftests/svg1.1/coords-trans-09-t-ref.png
new file mode 100644
index 0000000..c8b8ccf
Binary files /dev/null and b/tests/fixtures/reftests/svg1.1/coords-trans-09-t-ref.png differ
diff --git a/tests/fixtures/reftests/svg1.1/coords-trans-09-t.svg 
b/tests/fixtures/reftests/svg1.1/coords-trans-09-t.svg
new file mode 100644
index 0000000..d37ef9c
--- /dev/null
+++ b/tests/fixtures/reftests/svg1.1/coords-trans-09-t.svg
@@ -0,0 +1,102 @@
+<svg version="1.1" baseProfile="tiny" id="svg-root"
+  width="100%" height="100%" viewBox="0 0 480 360"
+  xmlns="http://www.w3.org/2000/svg"; xmlns:xlink="http://www.w3.org/1999/xlink";>
+  <!--======================================================================-->
+  <!--=  SVG 1.1 2nd Edition Test Case                                     =-->
+  <!--======================================================================-->
+  <!--=  Copyright 2009 World Wide Web Consortium, (Massachusetts          =-->
+  <!--=  Institute of Technology, European Research Consortium for         =-->
+  <!--=  Informatics and Mathematics (ERCIM), Keio University).            =-->
+  <!--=  All Rights Reserved.                                              =-->
+  <!--=  See http://www.w3.org/Consortium/Legal/.                          =-->
+  <!--======================================================================-->
+  <d:SVGTestCase xmlns:d="http://www.w3.org/2000/02/svg/testsuite/description/";
+    template-version="1.4" reviewer="OA" author="CN" status="accepted"
+    version="$Revision: 1.6 $" testname="$RCSfile: coords-trans-09-t.svg,v $">
+    <d:testDescription xmlns="http://www.w3.org/1999/xhtml"; 
href="http://www.w3.org/TR/SVG11/coords.html#EstablishingANewUserSpace";>
+      <p>
+        This test verifies the implementation of transforms. It tests elementary transforms
+        and transform nesting.
+        Note that for layout purposes, this test uses nesting of translation with the elementary  transforms.
+      </p>
+      <p>
+        This test will check if the various matrix operations work
+      </p>
+    </d:testDescription>
+    <d:operatorScript xmlns="http://www.w3.org/1999/xhtml";>
+      <p>
+        Run the test. No interaction required.
+      </p>
+    </d:operatorScript>
+    <d:passCriteria xmlns="http://www.w3.org/1999/xhtml";>
+      <p>
+        The rendered picture should match the reference image exactly except for variations in the labeling 
text.
+      </p>
+    </d:passCriteria>
+  </d:SVGTestCase>
+  <title id="test-title">$RCSfile: coords-trans-09-t.svg,v $</title>
+  <defs>
+    <font-face font-family="SVGFreeSansASCII" unicode-range="U+0-7F">
+      <font-face-src>
+        <font-face-uri xlink:href="../resources/SVGFreeSans.svg#ascii"/>
+      </font-face-src>
+    </font-face>
+  </defs>
+  <g id="test-body-content" font-family="SVGFreeSansASCII,sans-serif" font-size="18">
+    <g id="elementary-transforms-test">
+
+      <g transform="matrix(0 0 0 0 0 0)">
+        <rect x="0" y="0" width="150" height="5" fill="blue"/>
+        <rect x="0" y="0" width="5" height="50" fill="red"/>
+      </g>
+      <text x="6" y="20" font-size="20">matrix(0 0 0 0 0 0)</text>
+
+      <g transform="matrix(1 0 0 1 100 100)">
+        <rect x="0" y="0" width="150" height="5" fill="blue"/>
+        <rect x="0" y="0" width="5" height="50" fill="red"/>
+      </g>
+      <text x="100" y="100" font-size="20">matrix(1 0 0 1 100 100)</text>
+
+      <g transform="matrix(1.5 0 0 1.5 70 60)">
+        <rect x="0" y="0" width="150" height="5" fill="blue"/>
+        <rect x="0" y="0" width="5" height="50" fill="red"/>
+      </g>
+      <text x="70" y="60" font-size="20">matrix(1.5 0 0 1.5 70 60)</text>
+
+      <g transform="matrix(1 0 0.5 1 30 170)">
+        <rect x="0" y="0" width="150" height="5" fill="blue"/>
+        <rect x="0" y="0" width="5" height="50" fill="red"/>
+      </g>
+      <text x="30" y="170" font-size="20">matrix(1 0 0.5 1 30 170)</text>
+
+      <g transform="matrix(1 0.5 0 1 100 200)">
+        <rect x="0" y="0" width="150" height="5" fill="blue"/>
+        <rect x="0" y="0" width="5" height="50" fill="red"/>
+      </g>
+      <text x="100" y="200" font-size="20">matrix(1 0.5 0 1 100 200)</text>
+
+      <g transform="matrix(0 1 -1 0 450 0)">
+        <rect x="0" y="0" width="150" height="5" fill="blue"/>
+        <rect x="0" y="0" width="5" height="50" fill="red"/>
+      </g>
+      <text x="275" y="30" font-size="20">matrix(0 1 -1 0 450 0)</text>
+
+      <g transform="matrix(1 0.8 0.8 1 300 220)">
+        <rect x="0" y="0" width="150" height="5" fill="blue"/>
+        <rect x="0" y="0" width="5" height="50" fill="red"/>
+      </g>
+      <text x="230" y="220" font-size="20">matrix(1 0.8 0.8 1 300 220)</text>
+
+    </g>
+  </g>
+  <g font-family="SVGFreeSansASCII,sans-serif" font-size="32">
+    <text id="revision" x="10" y="340" stroke="none" fill="black">$Revision: 1.6 $</text>
+  </g>
+  <rect id="test-frame" x="1" y="1" width="478" height="358" fill="none" stroke="#000000"/>
+  <!-- comment out this watermark once the test is approved -->
+  <!--<g id="draft-watermark">
+    <rect x="1" y="1" width="478" height="20" fill="red" stroke="black" stroke-width="1"/>
+    <text font-family="SVGFreeSansASCII,sans-serif" font-weight="bold" font-size="20" x="240"
+      text-anchor="middle" y="18" stroke-width="0.5" stroke="black" fill="white">DRAFT</text>
+  </g>-->
+</svg>


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