diff options
Diffstat (limited to 'contrib/file/src/is_json.c')
-rw-r--r-- | contrib/file/src/is_json.c | 52 |
1 files changed, 36 insertions, 16 deletions
diff --git a/contrib/file/src/is_json.c b/contrib/file/src/is_json.c index c276b7be5984..eca2a49ee757 100644 --- a/contrib/file/src/is_json.c +++ b/contrib/file/src/is_json.c @@ -32,7 +32,7 @@ #include "file.h" #ifndef lint -FILE_RCSID("@(#)$File: is_json.c,v 1.20 2022/05/28 00:44:22 christos Exp $") +FILE_RCSID("@(#)$File: is_json.c,v 1.30 2022/09/27 19:12:40 christos Exp $") #endif #include "magic.h" @@ -122,6 +122,7 @@ json_skip_space(const unsigned char *uc, const unsigned char *ue) return uc; } +/*ARGSUSED*/ static int json_parse_string(const unsigned char **ucp, const unsigned char *ue, size_t lvl __file_debugused) @@ -183,6 +184,9 @@ json_parse_array(const unsigned char **ucp, const unsigned char *ue, DPRINTF("Parse array: ", uc, *ucp); while (uc < ue) { + uc = json_skip_space(uc, ue); + if (uc == ue) + goto out; if (*uc == ']') goto done; if (!json_parse(&uc, ue, st, lvl + 1)) @@ -265,6 +269,7 @@ out: return 0; } +/*ARGSUSED*/ static int json_parse_number(const unsigned char **ucp, const unsigned char *ue, size_t lvl __file_debugused) @@ -316,6 +321,7 @@ out: return got; } +/*ARGSUSED*/ static int json_parse_const(const unsigned char **ucp, const unsigned char *ue, const char *str, size_t len, size_t lvl __file_debugused) @@ -323,25 +329,28 @@ json_parse_const(const unsigned char **ucp, const unsigned char *ue, const unsigned char *uc = *ucp; DPRINTF("Parse const: ", uc, *ucp); - for (len--; uc < ue && --len;) { - if (*uc++ == *++str) - continue; + *ucp += --len - 1; + if (*ucp > ue) + *ucp = ue; + for (; uc < ue && --len;) { + if (*uc++ != *++str) { + DPRINTF("Bad const: ", uc, *ucp); + return 0; + } } - if (len) - DPRINTF("Bad const: ", uc, *ucp); - *ucp = uc; - return len == 0; + DPRINTF("Good const: ", uc, *ucp); + return 1; } static int json_parse(const unsigned char **ucp, const unsigned char *ue, size_t *st, size_t lvl) { - const unsigned char *uc; + const unsigned char *uc, *ouc; int rv = 0; int t; - uc = json_skip_space(*ucp, ue); + ouc = uc = json_skip_space(*ucp, ue); if (uc == ue) goto out; @@ -395,8 +404,16 @@ json_parse(const unsigned char **ucp, const unsigned char *ue, out: DPRINTF("End general: ", uc, *ucp); *ucp = uc; - if (lvl == 0) - return rv && uc == ue && (st[JSON_ARRAYN] || st[JSON_OBJECT]); + if (lvl == 0) { + if (!rv) + return 0; + if (uc == ue) + return (st[JSON_ARRAYN] || st[JSON_OBJECT]) ? 1 : 0; + if (*ouc == *uc && json_parse(&uc, ue, st, 1)) + return (st[JSON_ARRAYN] || st[JSON_OBJECT]) ? 2 : 0; + else + return 0; + } return rv; } @@ -408,6 +425,7 @@ file_is_json(struct magic_set *ms, const struct buffer *b) const unsigned char *ue = uc + b->flen; size_t st[JSON_MAX]; int mime = ms->flags & MAGIC_MIME; + int jt; if ((ms->flags & (MAGIC_APPLE|MAGIC_EXTENSION)) != 0) @@ -415,17 +433,19 @@ file_is_json(struct magic_set *ms, const struct buffer *b) memset(st, 0, sizeof(st)); - if (!json_parse(&uc, ue, st, 0)) + if ((jt = json_parse(&uc, ue, st, 0)) == 0) return 0; if (mime == MAGIC_MIME_ENCODING) return 1; if (mime) { - if (file_printf(ms, "application/json") == -1) + if (file_printf(ms, "application/%s", + jt == 1 ? "json" : "x-ndjson") == -1) return -1; return 1; } - if (file_printf(ms, "JSON text data") == -1) + if (file_printf(ms, "%sJSON text data", + jt == 1 ? "" : "New Line Delimited ") == -1) return -1; #if JSON_COUNT #define P(n) st[n], st[n] > 1 ? "s" : "" @@ -455,7 +475,7 @@ file_is_json(struct magic_set *ms, const struct buffer *b) int main(int argc, char *argv[]) { - int fd, rv; + int fd; struct stat st; unsigned char *p; size_t stats[JSON_MAX]; |