- make sure nsvg__addPath() hands only valid number of pointts (1+N*3)
- require moveTo path command before handling other commands
- require (sign+)digit for a valid path command coordinate
- allow to add bezier segment only after there’s at leat one point (now
also consistent with nsvg__lineTo)
This commit is contained in:
Mikko Mononen 2020-09-28 10:35:41 +03:00
parent 07a5e2a33c
commit e7f5981b1e

View File

@ -225,11 +225,6 @@ static int nsvg__isdigit(char c)
return c >= '0' && c <= '9'; return c >= '0' && c <= '9';
} }
static int nsvg__isnum(char c)
{
return strchr("0123456789+-.eE", c) != 0;
}
static NSVG_INLINE float nsvg__minf(float a, float b) { return a < b ? a : b; } static NSVG_INLINE float nsvg__minf(float a, float b) { return a < b ? a : b; }
static NSVG_INLINE float nsvg__maxf(float a, float b) { return a > b ? a : b; } static NSVG_INLINE float nsvg__maxf(float a, float b) { return a > b ? a : b; }
@ -736,10 +731,12 @@ static void nsvg__lineTo(NSVGparser* p, float x, float y)
static void nsvg__cubicBezTo(NSVGparser* p, float cpx1, float cpy1, float cpx2, float cpy2, float x, float y) static void nsvg__cubicBezTo(NSVGparser* p, float cpx1, float cpy1, float cpx2, float cpy2, float x, float y)
{ {
if (p->npts > 0) {
nsvg__addPoint(p, cpx1, cpy1); nsvg__addPoint(p, cpx1, cpy1);
nsvg__addPoint(p, cpx2, cpy2); nsvg__addPoint(p, cpx2, cpy2);
nsvg__addPoint(p, x, y); nsvg__addPoint(p, x, y);
} }
}
static NSVGattrib* nsvg__getAttr(NSVGparser* p) static NSVGattrib* nsvg__getAttr(NSVGparser* p)
{ {
@ -1040,6 +1037,10 @@ static void nsvg__addPath(NSVGparser* p, char closed)
if (closed) if (closed)
nsvg__lineTo(p, p->pts[0], p->pts[1]); nsvg__lineTo(p, p->pts[0], p->pts[1]);
// Expect 1 + N*3 points (N = number of cubic bezier segments).
if ((p->npts % 3) != 1)
return;
path = (NSVGpath*)malloc(sizeof(NSVGpath)); path = (NSVGpath*)malloc(sizeof(NSVGpath));
if (path == NULL) goto error; if (path == NULL) goto error;
memset(path, 0, sizeof(NSVGpath)); memset(path, 0, sizeof(NSVGpath));
@ -1458,6 +1459,15 @@ static int nsvg__parseUnits(const char* units)
return NSVG_UNITS_USER; return NSVG_UNITS_USER;
} }
static int nsvg__isCoordinate(const char* s)
{
// optional sign
if (*s == '-' || *s == '+')
s++;
// must have at least one digit
return nsvg__isdigit(*s);
}
static NSVGcoordinate nsvg__parseCoordinateRaw(const char* str) static NSVGcoordinate nsvg__parseCoordinateRaw(const char* str)
{ {
NSVGcoordinate coord = {0, NSVG_UNITS_USER}; NSVGcoordinate coord = {0, NSVG_UNITS_USER};
@ -1883,9 +1893,12 @@ static int nsvg__getArgsPerElement(char cmd)
case 'a': case 'a':
case 'A': case 'A':
return 7; return 7;
} case 'z':
case 'Z':
return 0; return 0;
} }
return -1;
}
static void nsvg__pathMoveTo(NSVGparser* p, float* cpx, float* cpy, float* args, int rel) static void nsvg__pathMoveTo(NSVGparser* p, float* cpx, float* cpy, float* args, int rel)
{ {
@ -2194,6 +2207,7 @@ static void nsvg__parsePath(NSVGparser* p, const char** attr)
float args[10]; float args[10];
int nargs; int nargs;
int rargs = 0; int rargs = 0;
char initPoint;
float cpx, cpy, cpx2, cpy2; float cpx, cpy, cpx2, cpy2;
const char* tmp[4]; const char* tmp[4];
char closedFlag; char closedFlag;
@ -2216,13 +2230,14 @@ static void nsvg__parsePath(NSVGparser* p, const char** attr)
nsvg__resetPath(p); nsvg__resetPath(p);
cpx = 0; cpy = 0; cpx = 0; cpy = 0;
cpx2 = 0; cpy2 = 0; cpx2 = 0; cpy2 = 0;
initPoint = 0;
closedFlag = 0; closedFlag = 0;
nargs = 0; nargs = 0;
while (*s) { while (*s) {
s = nsvg__getNextPathItem(s, item); s = nsvg__getNextPathItem(s, item);
if (!*item) break; if (!*item) break;
if (nsvg__isnum(item[0])) { if (cmd != '\0' && nsvg__isCoordinate(item)) {
if (nargs < 10) if (nargs < 10)
args[nargs++] = (float)nsvg__atof(item); args[nargs++] = (float)nsvg__atof(item);
if (nargs >= rargs) { if (nargs >= rargs) {
@ -2235,6 +2250,7 @@ static void nsvg__parsePath(NSVGparser* p, const char** attr)
cmd = (cmd == 'm') ? 'l' : 'L'; cmd = (cmd == 'm') ? 'l' : 'L';
rargs = nsvg__getArgsPerElement(cmd); rargs = nsvg__getArgsPerElement(cmd);
cpx2 = cpx; cpy2 = cpy; cpx2 = cpx; cpy2 = cpy;
initPoint = 1;
break; break;
case 'l': case 'l':
case 'L': case 'L':
@ -2284,7 +2300,6 @@ static void nsvg__parsePath(NSVGparser* p, const char** attr)
} }
} else { } else {
cmd = item[0]; cmd = item[0];
rargs = nsvg__getArgsPerElement(cmd);
if (cmd == 'M' || cmd == 'm') { if (cmd == 'M' || cmd == 'm') {
// Commit path. // Commit path.
if (p->npts > 0) if (p->npts > 0)
@ -2293,7 +2308,11 @@ static void nsvg__parsePath(NSVGparser* p, const char** attr)
nsvg__resetPath(p); nsvg__resetPath(p);
closedFlag = 0; closedFlag = 0;
nargs = 0; nargs = 0;
} else if (cmd == 'Z' || cmd == 'z') { } else if (initPoint == 0) {
// Do not allow other commands until initial point has been set (moveTo called once).
cmd = '\0';
}
if (cmd == 'Z' || cmd == 'z') {
closedFlag = 1; closedFlag = 1;
// Commit path. // Commit path.
if (p->npts > 0) { if (p->npts > 0) {
@ -2309,6 +2328,12 @@ static void nsvg__parsePath(NSVGparser* p, const char** attr)
closedFlag = 0; closedFlag = 0;
nargs = 0; nargs = 0;
} }
rargs = nsvg__getArgsPerElement(cmd);
if (rargs == -1) {
// Command not recognized
cmd = '\0';
rargs = 0;
}
} }
} }
// Commit path. // Commit path.