meerk40t / svgelements

SVG Parsing for Elements, Paths, and other SVG Objects.
MIT License
133 stars 29 forks source link

Crash on parsing 0 width SVG #68

Closed abey79 closed 3 years ago

abey79 commented 3 years ago

The following SVG crashes upon parsing:

<?xml version="1.0" encoding="utf-8" ?>
<svg width="0.0cm" height="3.0cm" version="1.2" viewBox="0 0 0.0 113.38582677165354" xmlns="http://www.w3.org/2000/svg" xmlns:cc="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:ev="http://www.w3.org/2001/xml-events" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" xmlns:xlink="http://www.w3.org/1999/xlink" baseProfile="tiny" >
  <metadata>
    <rdf:RDF>
      <cc:Work>
        <dc:format>image/svg+xml</dc:format>
        <dc:source>vpype line 0 0 0 3cm write test.svg
</dc:source>
        <dc:date>2020-11-24T16:55:21.962795</dc:date>
      </cc:Work>
    </rdf:RDF>
  </metadata>
  <defs/>
  <g fill="none" id="layer1" inkscape:groupmode="layer" inkscape:label="1" stroke="#00f" style="display:inline">
    <line x1="0.0" x2="0.0" y1="0.0" y2="113.3858"/>
  </g>
</svg>

Backtrace:

  File "/Users/hhip/src/vpype/vpype/io.py", line 263, in read_multilayer_svg
    svg = svgelements.SVG.parse(filename)
  File "/Users/hhip/src/svgelements/svgelements/svgelements.py", line 7128, in parse
    viewport_transform = s.viewbox.transform()
  File "/Users/hhip/src/svgelements/svgelements/svgelements.py", line 6803, in transform
    return Viewbox.viewbox_transform(
  File "/Users/hhip/src/svgelements/svgelements/svgelements.py", line 6845, in viewbox_transform
    scale_x = e_width / vb_width
ZeroDivisionError: float division by zero
tatarize commented 3 years ago

https://www.w3.org/TR/SVG11/struct.html#SVGElementWidthAttribute

A negative value is an error (see Error processing). A value of zero disables rendering of the element.

Disabled rendering of elements happens elsewhere and those elements are not parsed. If width or height is zero for the SVG the correct action is to stop parsing and pretend the entire document is basically blank. Elements with visibility='hidden' just get the fact that their .values['visibility'] == 'hidden' here we're disabling rendering so zero there means there is no there there.

I'll correct it shortly, soon SVGs that would display nothing and lead to an error, will display nothing without error.

tatarize commented 3 years ago

https://github.com/meerk40t/svgelements/commit/b5031104b1e0190c8c373f1703e89172ed07a6ee

Fixed the Bug.

abey79 commented 3 years ago

Thanks!

As it turns out, this test SVG was generated with vpype ( gives it away). According to the spec, the fact that my svg writer generates 0 width is a bug, as the intent is that this line is indeed visible. I guess a max(width, 1) is in order somewhere in my code.

tatarize commented 3 years ago

Yeah, point to point without any consideration of the linewidth gets you a 0 width svg. But, the spec is clear, I don't render anything if the width is zero. It does mean checking it on your side when I could do it on mine, but my side says to just stop trying so that the solution. Though it doesn't help you any since checking it on your side would have the exact same result, and zero still isn't a useful width. Just less crashy.

1.3.2 is up on pypi. (had neglected to upload it til now)