summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGravatar Nikias Bassen2021-12-24 02:49:56 +0100
committerGravatar Nikias Bassen2021-12-24 02:49:56 +0100
commita22f0f5dd020958c7a61282e067479add99a0a5a (patch)
tree7ea42064702a5826def5e3b584516922d168094e
parent914480a8771959bc2dc0f5e8e83365c15c05c36d (diff)
downloadlibplist-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.c2
-rw-r--r--src/jsmn.c19
-rw-r--r--src/jsmn.h3
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;
diff --git a/src/jsmn.c b/src/jsmn.c
index ff7c818..f190312 100644
--- a/src/jsmn.c
+++ b/src/jsmn.c
@@ -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;
}
diff --git a/src/jsmn.h b/src/jsmn.h
index f12dc5a..380744d 100644
--- a/src/jsmn.h
+++ b/src/jsmn.h
@@ -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_ */