xmlparser

XML parser
git clone git://git.codemadness.org/xmlparser
Log | Files | Refs | README | LICENSE

commit 22dd4a4f48ad39da91869d56348538e063f3c790
parent 0acf4adc915dae0ca25cee374189a602f905cdce
Author: Hiltjo Posthuma <hiltjo@codemadness.org>
Date:   Thu, 11 Dec 2025 20:48:19 +0100

stricter numeric entity validation before parsing

Diffstat:
Mxml.c | 35+++++++++++++++++++++++++++--------
1 file changed, 27 insertions(+), 8 deletions(-)

diff --git a/xml.c b/xml.c @@ -6,7 +6,9 @@ #include "xml.h" #define ISALPHA(c) ((((unsigned)c) | 32) - 'a' < 26) +#define ISDIGIT(c) (((unsigned)c) - '0' < 10) #define ISSPACE(c) ((c) == ' ' || ((((unsigned)c) - '\t') < 5)) +#define ISXDIGIT(c) ((((unsigned)c) - '0' < 10) || (((unsigned)c) | 32) - 'a' < 6) static void xml_parseattrs(XMLParser *x) @@ -275,22 +277,39 @@ static int numericentitytostr(const char *e, char *buf, size_t bufsiz) { long l; - int len; + int base, len; + const char *s; char *end; /* buffer is too small */ if (bufsiz < 5) return -1; + /* hex (base 16) or decimal (base 10) */ + if (*e == 'x') { + e++; + for (s = e; *s && *s != ';'; s++) { + if (!ISXDIGIT((unsigned char)*s)) + return -1; /* invalid: no hex */ + } + base = 16; + + } else { + for (s = e; *s && *s != ';'; s++) { + if (!ISDIGIT((unsigned char)*s)) + return -1; /* invalid: no digits */ + } + base = 10; + } + if (*s != ';' || *(s + 1) != '\0') + return -1; /* must end with ';' NUL */ + errno = 0; - /* hex (16) or decimal (10) */ - if (*e == 'x') - l = strtol(++e, &end, 16); - else - l = strtol(e, &end, 10); + l = strtol(e, &end, base); + /* invalid value or not a well-formed entity or invalid code point */ if (errno || e == end || *end != ';' || l < 0 || l > 0x10ffff || - (l >= 0xd800 && l <= 0xdfff)) + (l >= 0xd800 && l <= 0xdfff)) /* surrogate range */ return -1; len = codepointtoutf8(l, buf); buf[len] = '\0'; @@ -401,7 +420,7 @@ xml_parse(XMLParser *x) if (x->xmldatastart) x->xmldatastart(x); while ((c = GETNEXT()) != EOF) { - if (c == '&') { + if (c == '&') { /* entities */ if (datalen) { x->data[datalen] = '\0'; if (x->xmldata)