width or height written in scientific notation (e.g. 1e3) crashes rasterization with an uncaught DivisionByZeroError. Exponent notation is valid in SVG attribute syntax, and real exporters emit it — I hit this on a production file.
Reproduction
<?php
require __DIR__ . '/vendor/autoload.php';
use SVG\SVG;
$svg = '<svg xmlns="http://www.w3.org/2000/svg" width="1e3" height="328.56">'
. '<rect x="0" y="0" width="100" height="100" fill="#000000"/>'
. '</svg>';
var_dump(SVG::fromString($svg)->getDocument()->getWidth());
SVG::fromString($svg)->toRasterImage(200, 200);
Output (php-svg v0.14.7, PHP 8.4):
string(3) "1e3"
Fatal error: Uncaught DivisionByZeroError: Division by zero in
.../src/Rasterization/SVGRasterizer.php:83
Stack trace:
#0 .../src/SVG.php(62): SVG\Rasterization\SVGRasterizer->__construct('1e3', '328.56', NULL, 200, 200, NULL)
#1 repro.php(11): SVG\SVG->toRasterImage(200, 200)
Replacing width="1e3" with width="1000" renders correctly. Also reproduces with 1E3, and with an exponent in height (3.2856e2).
Cause
Length.php:24 has no exponent in its number pattern:
$regex = '/^([+-]?\d*\.?\d*)(px|pt|pc|cm|mm|in|%)?$/';
So convert() returns null, and SVGRasterizer.php:83 turns that into a zero denominator:
$scaleX = $width / (!empty($viewBox) ? $viewBox[2] : $this->docWidth ?? 0);
Suggested fix
Allow an optional exponent, requiring at least one digit in the mantissa:
$regex = '/^([+-]?(?:\d+\.?\d*|\.\d+)(?:[eE][+-]?\d+)?)(px|pt|pc|cm|mm|in|%)?$/';
Parsing results, current vs proposed:
INPUT CURRENT PROPOSED
'1e3' null 1000 <- fixed
'1E3' null 1000 <- fixed
'3.2856e2' null 328.56 <- fixed
'1e-3' null 0.001 <- fixed
'+1.5e+2' null 150 <- fixed
'1000' 1000 1000
'3.28' 3.28 3.28
'50%' 50 50
'12pt' 12 12
'.5' 0.5 0.5
'-2.5cm' -2.5 -2.5
'abc' null null
'1e' null null
'e3' null null
'.' 0 null <- behaviour change
'-' 0 null <- behaviour change
Note the last two: '.' and '-' currently parse as 0 and would become null. Neither is a valid length, so returning null matches the documented contract ("null is returned if the string does not denote a valid length unit"), but it is a change beyond the exponent fix and you may want it handled separately.
Separately, ?? 0 at SVGRasterizer.php:83-84 converts any unparseable dimension into a division by zero. Guarding that would turn this class of bug into a graceful failure rather than a fatal, independent of the regex.
I have not run this against the test suite — the table above is from testing the patterns in isolation. Happy to open a PR with tests if the approach looks right to you.
widthorheightwritten in scientific notation (e.g.1e3) crashes rasterization with an uncaughtDivisionByZeroError. Exponent notation is valid in SVG attribute syntax, and real exporters emit it — I hit this on a production file.Reproduction
Output (php-svg v0.14.7, PHP 8.4):
Replacing
width="1e3"withwidth="1000"renders correctly. Also reproduces with1E3, and with an exponent inheight(3.2856e2).Cause
Length.php:24has no exponent in its number pattern:So
convert()returnsnull, andSVGRasterizer.php:83turns that into a zero denominator:Suggested fix
Allow an optional exponent, requiring at least one digit in the mantissa:
Parsing results, current vs proposed:
Note the last two:
'.'and'-'currently parse as0and would becomenull. Neither is a valid length, so returningnullmatches the documented contract ("null is returned if the string does not denote a valid length unit"), but it is a change beyond the exponent fix and you may want it handled separately.Separately,
?? 0atSVGRasterizer.php:83-84converts any unparseable dimension into a division by zero. Guarding that would turn this class of bug into a graceful failure rather than a fatal, independent of the regex.I have not run this against the test suite — the table above is from testing the patterns in isolation. Happy to open a PR with tests if the approach looks right to you.