[librsvg: 3/7] Make rsvg_css_parse_number_list() correspond to the Rust version



commit 78bb1392d3b45ca7ace11aa5de097e4c4d8dd446
Author: Federico Mena Quintero <federico gnome org>
Date:   Tue Jun 20 09:25:48 2017 -0500

    Make rsvg_css_parse_number_list() correspond to the Rust version
    
    And start turning the callers into using the new API.
    
    Also, this actually makes feConvolveMatrix be rendered.  Apparently they
    weren't working at all before?

 rsvg-css.c    |   25 +++++++++++++------
 rsvg-css.h    |   14 ++++++++++-
 rsvg-filter.c |   72 +++++++++++++++++++++++++++++++++++++++++++++------------
 3 files changed, 87 insertions(+), 24 deletions(-)
---
diff --git a/rsvg-css.c b/rsvg-css.c
index 199792a..a75bfa7 100644
--- a/rsvg-css.c
+++ b/rsvg-css.c
@@ -318,20 +318,28 @@ rsvg_css_parse_list (const char *in_str, guint * out_list_len)
     return string_array;
 }
 
-gdouble *
-rsvg_css_parse_number_list (const char *in_str, guint * out_list_len)
+gboolean
+rsvg_css_parse_number_list (const char       *in_str,
+                            NumberListLength nlength,
+                            gsize            size,
+                            gdouble          **out_list,
+                            gsize            *out_list_len)
 {
     gchar **string_array;
     gdouble *output;
     guint len, i;
 
-    if (out_list_len)
-        *out_list_len = 0;
+    *out_list = NULL;
+    *out_list_len = 0;
 
     string_array = rsvg_css_parse_list (in_str, &len);
 
     if (!(string_array && len))
-        return NULL;
+        return FALSE;
+
+    if ((nlength == NUMBER_LIST_LENGTH_EXACT && (gsize) len != size)
+        || (nlength == NUMBER_LIST_LENGTH_MAXIMUM && (gsize) len > size))
+        return FALSE;
 
     output = g_new0 (gdouble, len);
 
@@ -341,10 +349,11 @@ rsvg_css_parse_number_list (const char *in_str, guint * out_list_len)
 
     g_strfreev (string_array);
 
-    if (out_list_len != NULL)
-        *out_list_len = len;
+    *out_list_len = len;
+
+    *out_list = output;
 
-    return output;
+    return TRUE;
 }
 
 gboolean
diff --git a/rsvg-css.h b/rsvg-css.h
index 353bc11..4efbde6 100644
--- a/rsvg-css.h
+++ b/rsvg-css.h
@@ -133,8 +133,20 @@ gboolean rsvg_css_parse_number_optional_number (const char *str, double *out_x,
 
 G_GNUC_INTERNAL
 gchar       **rsvg_css_parse_list           (const char *in_str, guint * out_list_len);
+
+/* Keep in sync with rust/src/parsers.rs:NumberListLength */
+typedef enum {
+    NUMBER_LIST_LENGTH_EXACT,
+    NUMBER_LIST_LENGTH_MAXIMUM
+} NumberListLength;
+
 G_GNUC_INTERNAL
-gdouble             *rsvg_css_parse_number_list    (const char *in_str, guint * out_list_len);
+gboolean rsvg_css_parse_number_list (const char      *in_str,
+                                     NumberListLength nlength,
+                                     gsize            size,
+                                     gdouble         **out_list,
+                                     gsize           *out_list_len);
+
 G_GNUC_INTERNAL
 gboolean      rsvg_css_parse_overflow       (const char *str, gboolean * inherit);
 G_GNUC_INTERNAL
diff --git a/rsvg-filter.c b/rsvg-filter.c
index aea801f..1729eca 100644
--- a/rsvg-filter.c
+++ b/rsvg-filter.c
@@ -1247,7 +1247,6 @@ rsvg_filter_primitive_convolve_matrix_set_atts (RsvgNode *node, gpointer impl, R
 {
     RsvgFilterPrimitiveConvolveMatrix *filter = impl;
     gint i, j;
-    guint listlen = 0;
     const char *value;
     gboolean has_target_x, has_target_y;
 
@@ -1279,16 +1278,29 @@ rsvg_filter_primitive_convolve_matrix_set_atts (RsvgNode *node, gpointer impl, R
     }
     if ((value = rsvg_property_bag_lookup (atts, "divisor")))
         filter->divisor = atof (value);
+
     if ((value = rsvg_property_bag_lookup (atts, "order"))) {
         double tempx, tempy;
-        if (rsvg_css_parse_number_optional_number (value, &tempx, &tempy)) {
-            filter->orderx = MAX (tempx, G_MAXINT);
-            filter->ordery = MAX (tempy, G_MAXINT);
+        if (rsvg_css_parse_number_optional_number (value, &tempx, &tempy)
+            && tempx >= 1.0 && tempy <= 100.0
+            && tempy >= 1.0 && tempy <= 100.0) {
+            filter->orderx = (int) tempx;
+            filter->ordery = (int) tempy;
+            g_assert (filter->orderx >= 1);
+            g_assert (filter->ordery >= 1);
+
+#define SIZE_OVERFLOWS(a,b) (G_UNLIKELY ((b) > 0 && (a) > G_MAXSIZE / (b)))
+
+            if (SIZE_OVERFLOWS (filter->orderx, filter->ordery)) {
+                rsvg_node_set_attribute_parse_error (node, "order", "number of kernelMatrix elements would 
be too big");
+                return;
+            }
         } else {
-            rsvg_node_set_attribute_parse_error (node, "order", "expected number-optional-number");
+            rsvg_node_set_attribute_parse_error (node, "order", "invalid size for convolve matrix");
             return;
         }
     }
+
     if ((value = rsvg_property_bag_lookup (atts, "kernelUnitLength"))) {
         if (!rsvg_css_parse_number_optional_number (value, &filter->dx, &filter->dy)) {
             rsvg_node_set_attribute_parse_error (node, "kernelUnitLength", "expected 
number-optional-number");
@@ -1296,8 +1308,23 @@ rsvg_filter_primitive_convolve_matrix_set_atts (RsvgNode *node, gpointer impl, R
         }
     }
 
-    if ((value = rsvg_property_bag_lookup (atts, "kernelMatrix")))
-        filter->KernelMatrix = rsvg_css_parse_number_list (value, &listlen);
+    if ((value = rsvg_property_bag_lookup (atts, "kernelMatrix"))) {
+        gsize num_elems;
+        gsize got_num_elems;
+
+        num_elems = filter->orderx * filter->ordery;
+
+        if (!rsvg_css_parse_number_list (value,
+                                         NUMBER_LIST_LENGTH_EXACT,
+                                         num_elems,
+                                         &filter->KernelMatrix,
+                                         &got_num_elems)) {
+            rsvg_node_set_attribute_parse_error (node, "kernelMatrix", "expected a matrix of numbers");
+            return;
+        }
+
+        g_assert (num_elems == got_num_elems);
+    }
 
     if ((value = rsvg_property_bag_lookup (atts, "edgeMode"))) {
         if (!strcmp (value, "wrap"))
@@ -1308,9 +1335,6 @@ rsvg_filter_primitive_convolve_matrix_set_atts (RsvgNode *node, gpointer impl, R
             filter->edgemode = 0;
     }
 
-    if ((gint64) listlen != (gint64) filter->orderx * filter->ordery)
-        filter->orderx = filter->ordery = 0;
-
     if (filter->divisor == 0) {
         for (j = 0; j < filter->orderx; j++)
             for (i = 0; i < filter->ordery; i++)
@@ -2374,7 +2398,7 @@ rsvg_filter_primitive_color_matrix_set_atts (RsvgNode *node, gpointer impl, Rsvg
 {
     RsvgFilterPrimitiveColorMatrix *filter = impl;
     gint type;
-    guint listlen = 0;
+    gsize listlen = 0;
     const char *value;
 
     type = 0;
@@ -2388,7 +2412,16 @@ rsvg_filter_primitive_color_matrix_set_atts (RsvgNode *node, gpointer impl, Rsvg
 
     if ((value = rsvg_property_bag_lookup (atts, "values"))) {
         unsigned int i;
-        double *temp = rsvg_css_parse_number_list (value, &listlen);
+        double *temp;
+        if (!rsvg_css_parse_number_list (value,
+                                         NUMBER_LIST_LENGTH_MAXIMUM,
+                                         20,
+                                         &temp,
+                                         &listlen)) {
+            rsvg_node_set_attribute_parse_error (node, "values", "invalid number list");
+            return;
+        }
+
         filter->KernelMatrix = g_new0 (int, listlen);
         for (i = 0; i < listlen; i++)
             filter->KernelMatrix[i] = temp[i] * 255.;
@@ -2504,7 +2537,7 @@ typedef struct _RsvgFilterPrimitiveComponentTransfer
 struct _RsvgNodeComponentTransferFunc {
     ComponentTransferFunc function;
     gint *tableValues;
-    guint nbTableValues;
+    gsize nbTableValues;
     gint slope;
     gint intercept;
     gint amplitude;
@@ -2747,10 +2780,19 @@ rsvg_node_component_transfer_function_set_atts (RsvgNode *node, gpointer impl, R
         else if (!strcmp (value, "gamma"))
             data->function = gamma_component_transfer_func;
     }
+
     if ((value = rsvg_property_bag_lookup (atts, "tableValues"))) {
         unsigned int i;
-        double *temp = rsvg_css_parse_number_list (value,
-                                                   &data->nbTableValues);
+        double *temp;
+        if (!rsvg_css_parse_number_list (value,
+                                         NUMBER_LIST_LENGTH_MAXIMUM,
+                                         256,
+                                         &temp,
+                                         &data->nbTableValues)) {
+            rsvg_node_set_attribute_parse_error (node, "tableValues", "invalid number list");
+            return;
+        }
+
         data->tableValues = g_new0 (gint, data->nbTableValues);
         for (i = 0; i < data->nbTableValues; i++)
             data->tableValues[i] = temp[i] * 255.;


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