diff options
| author | 2021-12-24 02:49:56 +0100 | |
|---|---|---|
| committer | 2021-12-24 02:49:56 +0100 | |
| commit | a22f0f5dd020958c7a61282e067479add99a0a5a (patch) | |
| tree | 7ea42064702a5826def5e3b584516922d168094e /src | |
| 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.
Diffstat (limited to 'src')
| -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 | |||
| 661 | } | 661 | } |
| 662 | tokens = newtokens; | 662 | tokens = newtokens; |
| 663 | 663 | ||
| 664 | r = jsmn_parse(&parser, json, tokens, maxtoks); | 664 | r = jsmn_parse(&parser, json, length, tokens, maxtoks); |
| 665 | if (r == JSMN_ERROR_NOMEM) { | 665 | if (r == JSMN_ERROR_NOMEM) { |
| 666 | maxtoks+=16; | 666 | maxtoks+=16; |
| 667 | continue; | 667 | continue; |
| @@ -66,7 +66,7 @@ static jsmnerr_t jsmn_parse_primitive(jsmn_parser *parser, const char *js, | |||
| 66 | 66 | ||
| 67 | start = parser->pos; | 67 | start = parser->pos; |
| 68 | 68 | ||
| 69 | for (; js[parser->pos] != '\0'; parser->pos++) { | 69 | for (; (parser->end > 0 && parser->pos < parser->end) && js[parser->pos] != '\0'; parser->pos++) { |
| 70 | switch (js[parser->pos]) { | 70 | switch (js[parser->pos]) { |
| 71 | #ifndef JSMN_STRICT | 71 | #ifndef JSMN_STRICT |
| 72 | /* In strict mode primitive must be followed by "," or "}" or "]" */ | 72 | /* 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, | |||
| 75 | case '\t' : case '\r' : case '\n' : case ' ' : | 75 | case '\t' : case '\r' : case '\n' : case ' ' : |
| 76 | case ',' : case ']' : case '}' : | 76 | case ',' : case ']' : case '}' : |
| 77 | goto found; | 77 | goto found; |
| 78 | default: | ||
| 79 | break; | ||
| 78 | } | 80 | } |
| 79 | if (js[parser->pos] < 32 || js[parser->pos] >= 127) { | 81 | if (js[parser->pos] < 32 || js[parser->pos] >= 127) { |
| 80 | parser->pos = start; | 82 | parser->pos = start; |
| @@ -102,7 +104,7 @@ found: | |||
| 102 | } | 104 | } |
| 103 | 105 | ||
| 104 | /** | 106 | /** |
| 105 | * Filsl next token with JSON string. | 107 | * Fills next token with JSON string. |
| 106 | */ | 108 | */ |
| 107 | static jsmnerr_t jsmn_parse_string(jsmn_parser *parser, const char *js, | 109 | static jsmnerr_t jsmn_parse_string(jsmn_parser *parser, const char *js, |
| 108 | jsmntok_t *tokens, int num_tokens) { | 110 | jsmntok_t *tokens, int num_tokens) { |
| @@ -113,7 +115,7 @@ static jsmnerr_t jsmn_parse_string(jsmn_parser *parser, const char *js, | |||
| 113 | parser->pos++; | 115 | parser->pos++; |
| 114 | 116 | ||
| 115 | /* Skip starting quote */ | 117 | /* Skip starting quote */ |
| 116 | for (; js[parser->pos] != '\0'; parser->pos++) { | 118 | for (; (parser->end > 0 && parser->pos < parser->end) && js[parser->pos] != '\0'; parser->pos++) { |
| 117 | char c = js[parser->pos]; | 119 | char c = js[parser->pos]; |
| 118 | 120 | ||
| 119 | /* Quote: end of string */ | 121 | /* Quote: end of string */ |
| @@ -133,6 +135,10 @@ static jsmnerr_t jsmn_parse_string(jsmn_parser *parser, const char *js, | |||
| 133 | /* Backslash: Quoted symbol expected */ | 135 | /* Backslash: Quoted symbol expected */ |
| 134 | if (c == '\\') { | 136 | if (c == '\\') { |
| 135 | parser->pos++; | 137 | parser->pos++; |
| 138 | if (parser->end > 0 && parser->pos >= parser->end) { | ||
| 139 | parser->pos = start; | ||
| 140 | return JSMN_ERROR_INVAL; | ||
| 141 | } | ||
| 136 | switch (js[parser->pos]) { | 142 | switch (js[parser->pos]) { |
| 137 | /* Allowed escaped symbols */ | 143 | /* Allowed escaped symbols */ |
| 138 | case '\"': case '/' : case '\\' : case 'b' : | 144 | case '\"': case '/' : case '\\' : case 'b' : |
| @@ -156,13 +162,15 @@ static jsmnerr_t jsmn_parse_string(jsmn_parser *parser, const char *js, | |||
| 156 | /** | 162 | /** |
| 157 | * Parse JSON string and fill tokens. | 163 | * Parse JSON string and fill tokens. |
| 158 | */ | 164 | */ |
| 159 | jsmnerr_t jsmn_parse(jsmn_parser *parser, const char *js, jsmntok_t *tokens, | 165 | jsmnerr_t jsmn_parse(jsmn_parser *parser, const char *js, unsigned int length, jsmntok_t *tokens, |
| 160 | unsigned int num_tokens) { | 166 | unsigned int num_tokens) { |
| 161 | jsmnerr_t r; | 167 | jsmnerr_t r; |
| 162 | int i; | 168 | int i; |
| 163 | jsmntok_t *token; | 169 | jsmntok_t *token; |
| 164 | 170 | ||
| 165 | for (; js[parser->pos] != '\0'; parser->pos++) { | 171 | parser->end = length; |
| 172 | |||
| 173 | for (; (parser->end > 0 && parser->pos < parser->end) && js[parser->pos] != '\0'; parser->pos++) { | ||
| 166 | char c; | 174 | char c; |
| 167 | jsmntype_t type; | 175 | jsmntype_t type; |
| 168 | 176 | ||
| @@ -274,6 +282,7 @@ jsmnerr_t jsmn_parse(jsmn_parser *parser, const char *js, jsmntok_t *tokens, | |||
| 274 | */ | 282 | */ |
| 275 | void jsmn_init(jsmn_parser *parser) { | 283 | void jsmn_init(jsmn_parser *parser) { |
| 276 | parser->pos = 0; | 284 | parser->pos = 0; |
| 285 | parser->end = 0; | ||
| 277 | parser->toknext = 0; | 286 | parser->toknext = 0; |
| 278 | parser->toksuper = -1; | 287 | parser->toksuper = -1; |
| 279 | } | 288 | } |
| @@ -72,6 +72,7 @@ typedef struct { | |||
| 72 | */ | 72 | */ |
| 73 | typedef struct { | 73 | typedef struct { |
| 74 | unsigned int pos; /* offset in the JSON string */ | 74 | unsigned int pos; /* offset in the JSON string */ |
| 75 | unsigned int end; /* offset after last character of JSON string */ | ||
| 75 | int toknext; /* next token to allocate */ | 76 | int toknext; /* next token to allocate */ |
| 76 | int toksuper; /* superior token node, e.g parent object or array */ | 77 | int toksuper; /* superior token node, e.g parent object or array */ |
| 77 | } jsmn_parser; | 78 | } jsmn_parser; |
| @@ -85,7 +86,7 @@ void jsmn_init(jsmn_parser *parser); | |||
| 85 | * Run JSON parser. It parses a JSON data string into and array of tokens, each describing | 86 | * Run JSON parser. It parses a JSON data string into and array of tokens, each describing |
| 86 | * a single JSON object. | 87 | * a single JSON object. |
| 87 | */ | 88 | */ |
| 88 | jsmnerr_t jsmn_parse(jsmn_parser *parser, const char *js, | 89 | jsmnerr_t jsmn_parse(jsmn_parser *parser, const char *js, unsigned int length, |
| 89 | jsmntok_t *tokens, unsigned int num_tokens); | 90 | jsmntok_t *tokens, unsigned int num_tokens); |
| 90 | 91 | ||
| 91 | #endif /* __JSMN_H_ */ | 92 | #endif /* __JSMN_H_ */ |
