Handle one more valid real number format in svgLib parse_path()

Using svg.draw(pen) and parse_path() from svgLib threw exception
     ValueError: could not convert string to float: 'a'
on a SVG <path> string generated by Inkscape. Altering the path
string might object to other string bits like 'Z' or 'v', or
give even stranger exceptions.

Finally tracked it down to the path containing particular valid
numbers like "-4e-5" or "1e-4". Changing these to "-4.0e-5" or
"1.0e-4" would stop the exceptions. The parse_path() was not
accepting valid SVG real numbers.

The specification for real number formats is a bit of a mess in
CSS land right now, but the reassuringly concrete spec is:
    https://www.w3.org/TR/css-syntax-3/#number-token-diagram
which allows a real number having an exponent but without having
a fractional part, such as the number "1e3".

This change updates an RE to make fractional parts optional,
and adds a test for this valid SVG number format.
This commit is contained in:
Thomas Shinnick 2022-05-03 17:48:14 -05:00
parent 41bd3a143d
commit 5abfef15e1
2 changed files with 13 additions and 1 deletions

View File

@ -16,10 +16,13 @@ ARC_COMMANDS = set("Aa")
UPPERCASE = set('MZLHVCSQTA')
COMMAND_RE = re.compile("([MmZzLlHhVvCcSsQqTtAa])")
# https://www.w3.org/TR/css-syntax-3/#number-token-diagram
# but -6.e-5 will be tokenized as "-6" then "-5" and confuse parsing
FLOAT_RE = re.compile(
r"[-+]?" # optional sign
r"(?:"
r"(?:0|[1-9][0-9]*)(?:\.[0-9]+(?:[eE][-+]?[0-9]+)?)?" # int/float
r"(?:0|[1-9][0-9]*)(?:\.[0-9]+)?(?:[eE][-+]?[0-9]+)?" # int/float
r"|"
r"(?:\.[0-9]+(?:[eE][-+]?[0-9]+)?)" # float with leading dot (e.g. '.42')
r")"

View File

@ -280,6 +280,15 @@ def test_exponents():
assert pen.value == expected
pen = RecordingPen()
parse_path("M-3e38 3E+38L-3E-38,3e-38", pen)
expected = [
("moveTo", ((-3e+38, 3e+38),)),
("lineTo", ((-3e-38, 3e-38),)),
("endPath", ()),
]
assert pen.value == expected
def test_invalid_implicit_command():
with pytest.raises(ValueError) as exc_info: