[librsvg] (#497): Don't panic on paths with all-invalid commands



commit ac96f5abab12c3804c2adb1647e21d58d3a6c48f
Author: Federico Mena Quintero <federico gnome org>
Date:   Sat Aug 17 15:09:01 2019 -0500

    (#497): Don't panic on paths with all-invalid commands
    
    The path parser creates a PathBuilder with zero commands.
    
    In turn, builder.to_cairo() does nothing, as expected.
    
    But then we stroke_and_fill(), and the wrapper call to
    with_discrete_layer() doesn't like not having bounds.
    
    Fixes https://gitlab.gnome.org/GNOME/librsvg/issues/497

 rsvg_internals/src/path_builder.rs                 |  6 +++++
 rsvg_internals/src/shapes.rs                       | 28 ++++++++++++----------
 .../497-path-with-all-invalid-commands.svg         | 13 ++++++++++
 3 files changed, 34 insertions(+), 13 deletions(-)
---
diff --git a/rsvg_internals/src/path_builder.rs b/rsvg_internals/src/path_builder.rs
index 43316010..28ad9110 100644
--- a/rsvg_internals/src/path_builder.rs
+++ b/rsvg_internals/src/path_builder.rs
@@ -356,6 +356,8 @@ impl PathBuilder {
     }
 
     pub fn to_cairo(&self, cr: &cairo::Context) -> Result<(), cairo::Status> {
+        assert!(!self.empty());
+
         for s in &self.path_commands {
             s.to_cairo(cr);
         }
@@ -376,6 +378,10 @@ impl PathBuilder {
             Err(status)
         }
     }
+
+    pub fn empty(&self) -> bool {
+        self.path_commands.len() == 0
+    }
 }
 
 #[cfg(test)]
diff --git a/rsvg_internals/src/shapes.rs b/rsvg_internals/src/shapes.rs
index 5d03fb00..f91637fb 100644
--- a/rsvg_internals/src/shapes.rs
+++ b/rsvg_internals/src/shapes.rs
@@ -22,23 +22,25 @@ fn render_path_builder(
     render_markers: bool,
     clipping: bool,
 ) -> Result<(), RenderingError> {
-    draw_ctx.with_discrete_layer(node, values, clipping, &mut |dc| {
-        let cr = dc.get_cairo_context();
+    if !builder.empty() {
+        draw_ctx.with_discrete_layer(node, values, clipping, &mut |dc| {
+            let cr = dc.get_cairo_context();
 
-        builder.to_cairo(&cr)?;
+            builder.to_cairo(&cr)?;
 
-        if clipping {
-            cr.set_fill_rule(cairo::FillRule::from(values.clip_rule));
-        } else {
-            cr.set_fill_rule(cairo::FillRule::from(values.fill_rule));
-            dc.stroke_and_fill(&cr, values)?;
-        }
+            if clipping {
+                cr.set_fill_rule(cairo::FillRule::from(values.clip_rule));
+            } else {
+                cr.set_fill_rule(cairo::FillRule::from(values.fill_rule));
+                dc.stroke_and_fill(&cr, values)?;
+            }
 
-        Ok(())
-    })?;
+            Ok(())
+        })?;
 
-    if render_markers {
-        marker::render_markers_for_path_builder(builder, draw_ctx, values, clipping)?;
+        if render_markers {
+            marker::render_markers_for_path_builder(builder, draw_ctx, values, clipping)?;
+        }
     }
 
     Ok(())
diff --git a/tests/fixtures/render-crash/497-path-with-all-invalid-commands.svg 
b/tests/fixtures/render-crash/497-path-with-all-invalid-commands.svg
new file mode 100644
index 00000000..4aaf4c8f
--- /dev/null
+++ b/tests/fixtures/render-crash/497-path-with-all-invalid-commands.svg
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg xmlns="hg" width="100" height="100">
+  <defs>
+    <clipPath id="one" clipPathUnits="objectBoundingBox">
+  <path d="M 0P5 0.0 L 1.0 0.5 L 0.5 1.0 L 0.0 0.5 Z"/>
+</clipPath>
+  </defs>
+  <g clip-path="url(#one)">
+
+  <path d="M 0P5 " wiGth="40" height="40" fill="blue"/>
+    <rect x="50" y="50" width="40" heiKht="40" fill="#00ff00"/>
+  </g>
+</svg>


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