diff options
author | Nikias Bassen | 2021-12-24 02:49:56 +0100 |
---|---|---|
committer | Nikias Bassen | 2021-12-24 02:49:56 +0100 |
commit | a22f0f5dd020958c7a61282e067479add99a0a5a (patch) | |
tree | 7ea42064702a5826def5e3b584516922d168094e | |
parent | 914480a8771959bc2dc0f5e8e83365c15c05c36d (diff) | |
download | libplist-a22f0f5dd020958c7a61282e067479add99a0a5a.tar.gz libplist-a22f0f5dd020958c7a61282e067479add99a0a5a.tar.bz2 |
json: Update parser (jsmn) to verify the length of the input data
This way the string doesn't have to be 0-terminated.
-rw-r--r-- | src/jplist.c | 2 | ||||
-rw-r--r-- | src/jsmn.c | 19 | ||||
-rw-r--r-- | src/jsmn.h | 3 |
3 files changed, 17 insertions, 7 deletions
diff --git a/src/jplist.c b/src/jplist.c index fbc963e..889ce30 100644 --- a/src/jplist.c +++ b/src/jplist.c @@ -661,7 +661,7 @@ PLIST_API int plist_from_json(const char *json, uint32_t length, plist_t * plist } tokens = newtokens; - r = jsmn_parse(&parser, json, tokens, maxtoks); + r = jsmn_parse(&parser, json, length, tokens, maxtoks); if (r == JSMN_ERROR_NOMEM) { maxtoks+=16; continue; @@ -66,7 +66,7 @@ static jsmnerr_t jsmn_parse_primitive(jsmn_parser *parser, const char *js, start = parser->pos; - for (; js[parser->pos] != '\0'; parser->pos++) { + for (; (parser->end > 0 && parser->pos < parser->end) && js[parser->pos] != '\0'; parser->pos++) { switch (js[parser->pos]) { #ifndef JSMN_STRICT /* In strict mode primitive must be followed by "," or "}" or "]" */ @@ -75,6 +75,8 @@ static jsmnerr_t jsmn_parse_primitive(jsmn_parser *parser, const char *js, case '\t' : case '\r' : case '\n' : case ' ' : case ',' : case ']' : case '}' : goto found; + default: + break; } if (js[parser->pos] < 32 || js[parser->pos] >= 127) { parser->pos = start; @@ -102,7 +104,7 @@ found: } /** - * Filsl next token with JSON string. + * Fills next token with JSON string. */ static jsmnerr_t jsmn_parse_string(jsmn_parser *parser, const char *js, jsmntok_t *tokens, int num_tokens) { @@ -113,7 +115,7 @@ static jsmnerr_t jsmn_parse_string(jsmn_parser *parser, const char *js, parser->pos++; /* Skip starting quote */ - for (; js[parser->pos] != '\0'; parser->pos++) { + for (; (parser->end > 0 && parser->pos < parser->end) && js[parser->pos] != '\0'; parser->pos++) { char c = js[parser->pos]; /* Quote: end of string */ @@ -133,6 +135,10 @@ static jsmnerr_t jsmn_parse_string(jsmn_parser *parser, const char *js, /* Backslash: Quoted symbol expected */ if (c == '\\') { parser->pos++; + if (parser->end > 0 && parser->pos >= parser->end) { + parser->pos = start; + return JSMN_ERROR_INVAL; + } switch (js[parser->pos]) { /* Allowed escaped symbols */ case '\"': case '/' : case '\\' : case 'b' : @@ -156,13 +162,15 @@ static jsmnerr_t jsmn_parse_string(jsmn_parser *parser, const char *js, /** * Parse JSON string and fill tokens. */ -jsmnerr_t jsmn_parse(jsmn_parser *parser, const char *js, jsmntok_t *tokens, +jsmnerr_t jsmn_parse(jsmn_parser *parser, const char *js, unsigned int length, jsmntok_t *tokens, unsigned int num_tokens) { jsmnerr_t r; int i; jsmntok_t *token; - for (; js[parser->pos] != '\0'; parser->pos++) { + parser->end = length; + + for (; (parser->end > 0 && parser->pos < parser->end) && js[parser->pos] != '\0'; parser->pos++) { char c; jsmntype_t type; @@ -274,6 +282,7 @@ jsmnerr_t jsmn_parse(jsmn_parser *parser, const char *js, jsmntok_t *tokens, */ void jsmn_init(jsmn_parser *parser) { parser->pos = 0; + parser->end = 0; parser->toknext = 0; parser->toksuper = -1; } @@ -72,6 +72,7 @@ typedef struct { */ typedef struct { unsigned int pos; /* offset in the JSON string */ + unsigned int end; /* offset after last character of JSON string */ int toknext; /* next token to allocate */ int toksuper; /* superior token node, e.g parent object or array */ } jsmn_parser; @@ -85,7 +86,7 @@ void jsmn_init(jsmn_parser *parser); * Run JSON parser. It parses a JSON data string into and array of tokens, each describing * a single JSON object. */ -jsmnerr_t jsmn_parse(jsmn_parser *parser, const char *js, +jsmnerr_t jsmn_parse(jsmn_parser *parser, const char *js, unsigned int length, jsmntok_t *tokens, unsigned int num_tokens); #endif /* __JSMN_H_ */ |