Commit 435cddf43 for imagemagick.org
commit 435cddf43011ca48c328ccf7c6d9e492cc05d442
Author: Wei-Lun Li <b84330808@gmail.com>
Date: Thu Nov 5 01:46:20 2026 +0900
Parse SVG path arc flags as single digits (#9096)
The large-arc and sweep flags of an elliptical arc were read as numbers,
so compact path data such as "a4 4 0 010 8" (flags 0 and 1, then x=0)
was read as a single flag value of 10 and the rest of the path failed
to parse. The SVG grammar defines each flag as a single 0 or 1 that
does not need a separator, as written by many SVG minifiers.
Fixes #9092
diff --git a/MagickCore/draw.c b/MagickCore/draw.c
index ccb0fe295..70936545f 100644
--- a/MagickCore/draw.c
+++ b/MagickCore/draw.c
@@ -6764,6 +6764,29 @@ static MagickBooleanType TraceLine(PrimitiveInfo *primitive_info,
return(MagickTrue);
}
+static MagickBooleanType GetArcFlag(const char **path,MagickBooleanType *flag)
+{
+ const char
+ *p;
+
+ /*
+ An arc flag is a single 0 or 1 and need not be separated from the next
+ value, e.g. "a4 4 0 010 8".
+ */
+ p=(*path);
+ while (isspace((int) ((unsigned char) *p)) != 0)
+ p++;
+ if (*p == ',')
+ p++;
+ while (isspace((int) ((unsigned char) *p)) != 0)
+ p++;
+ if ((*p != '0') && (*p != '1'))
+ return(MagickFalse);
+ *flag=(*p == '1') ? MagickTrue : MagickFalse;
+ *path=p+1;
+ return(MagickTrue);
+}
+
static ssize_t TracePath(MVGInfo *mvg_info,const char *path,
ExceptionInfo *exception)
{
@@ -6872,22 +6895,10 @@ static ssize_t TracePath(MVGInfo *mvg_info,const char *path,
angle=GetDrawValue(token,&next_token);
if (token == next_token)
ThrowPointExpectedException(token,exception);
- (void) GetNextToken(p,&p,MagickPathExtent,token);
- if (IsValidListChar((int) ((unsigned char) *token)) == MagickFalse)
- ThrowPointExpectedException(token,exception);
- if (*token == ',')
- (void) GetNextToken(p,&p,MagickPathExtent,token);
- large_arc=StringToLong(token) != 0 ? MagickTrue : MagickFalse;
- (void) GetNextToken(p,&p,MagickPathExtent,token);
- if (IsValidListChar((int) ((unsigned char) *token)) == MagickFalse)
- ThrowPointExpectedException(token,exception);
- if (*token == ',')
- (void) GetNextToken(p,&p,MagickPathExtent,token);
- sweep=StringToLong(token) != 0 ? MagickTrue : MagickFalse;
- if (IsValidListChar((int) ((unsigned char) *token)) == MagickFalse)
- ThrowPointExpectedException(token,exception);
- if (*token == ',')
- (void) GetNextToken(p,&p,MagickPathExtent,token);
+ if (GetArcFlag(&p,&large_arc) == MagickFalse)
+ ThrowPointExpectedException(p,exception);
+ if (GetArcFlag(&p,&sweep) == MagickFalse)
+ ThrowPointExpectedException(p,exception);
(void) GetNextToken(p,&p,MagickPathExtent,token);
if (IsValidListChar((int) ((unsigned char) *token)) == MagickFalse)
ThrowPointExpectedException(token,exception);
diff --git a/tests/cli-svg.tap b/tests/cli-svg.tap
index 2baad8d4d..173f4f24a 100755
--- a/tests/cli-svg.tap
+++ b/tests/cli-svg.tap
@@ -18,7 +18,7 @@
#
. ./common.shi
. ${srcdir}/tests/common.shi
-echo "1..3"
+echo "1..4"
# gradientTransform should not cause a double-free / SIGABRT (#8582)
${MAGICK} ${SRCDIR}/input_svg_gradient_transform.svg null: && echo "ok" || echo "not ok"
@@ -41,4 +41,13 @@ case "$svg" in
*'<desc>x(<script>)</desc>'*) echo "ok" ;;
*) echo "not ok" ;;
esac
+
+# Arc flags are single digits and need not be followed by a separator (#9092).
+compact=`${MAGICK} -size 24x24 xc:white -fill none -stroke black \
+ -draw "path 'M6 12h9a4 4 0 010 8H7a1 1 0 01-1-1V5a1 1 0 011-1h7a4 4 0 010 8'" \
+ -format '%#' info:- 2>/dev/null`
+spaced=`${MAGICK} -size 24x24 xc:white -fill none -stroke black \
+ -draw "path 'M6 12 h9 a4 4 0 0 1 0 8 H7 a1 1 0 0 1 -1 -1 V5 a1 1 0 0 1 1 -1 h7 a4 4 0 0 1 0 8'" \
+ -format '%#' info:- 2>/dev/null`
+[ "X$compact" != "X" ] && [ "X$compact" = "X$spaced" ] && echo "ok" || echo "not ok"
: