Changeset: 2f01d888e997 for MonetDB URL: http://dev.monetdb.org/hg/MonetDB?cmd=changeset;node=2f01d888e997 Modified Files: monetdb5/modules/atoms/json.c Branch: Jun2016 Log Message:
Properly check for errors. diffs (truncated from 1173 to 300 lines): diff --git a/monetdb5/modules/atoms/json.c b/monetdb5/modules/atoms/json.c --- a/monetdb5/modules/atoms/json.c +++ b/monetdb5/modules/atoms/json.c @@ -69,7 +69,7 @@ JSONnewtree(int size) if (js == NULL) return NULL; js->elm = (JSONterm *) GDKzalloc(sizeof(JSONterm) * size); - if( js->elm == NULL){ + if (js->elm == NULL) { GDKfree(js); return NULL; } @@ -89,7 +89,7 @@ JSONnew(JSON *js) return js->free - 1; } js->elm = term; - memset(((char *) term) + sizeof(JSONterm) * js->size, 0, 8 * sizeof(JSONterm)); + memset(term + js->size, 0, 8 * sizeof(JSONterm)); js->size += 8; if (jsonhint < js->size) jsonhint = js->size; @@ -124,9 +124,10 @@ JSONfromString(str src, int *len, json * } JSONfree(jt); + *len = (int) slen; *j = GDKstrdup(src); - *len = (int) slen; - if (GDKstrFromStr((unsigned char *) *j, (const unsigned char *) src, slen) < 0) { + if (*j == NULL || + GDKstrFromStr((unsigned char *) *j, (const unsigned char *) src, slen) < 0) { GDKfree(*j); *j = GDKstrdup(str_nil); *len = 2; @@ -168,7 +169,7 @@ JSONtoString(str *s, int *len, json src) if (cnt > (size_t) *len) { GDKfree(*s); - *s = (str) GDKmalloc(cnt); + *s = GDKmalloc(cnt); if (*s == NULL) return -1; *len = (int) cnt; @@ -196,7 +197,12 @@ JSONtoString(str *s, int *len, json src) return (int) (cnt - 1); /* length without \0 */ } -#define tab(D) { int kk; for(kk=0; kk< D * 4; kk++) mnstr_printf(fd," ");} +#define tab(D) \ + do { \ + int kk; \ + for (kk = 0; kk < (D) * 4; kk++) \ + mnstr_printf(fd, " "); \ + } while (0) static void JSONdumpInternal(JSON *jt, int depth) @@ -339,6 +345,8 @@ JSONappend(JSON *jt, int idx, int nxt) if (jt->elm[nxt].kind == JSON_OBJECT || jt->elm[nxt].kind == JSON_ARRAY) { chld = JSONnew(jt); + if (jt->error) + return; jt->elm[chld].kind = jt->elm[nxt].kind; jt->elm[chld].name = jt->elm[nxt].name; jt->elm[chld].namelen = jt->elm[nxt].namelen; @@ -497,8 +505,11 @@ JSONglue(str res, str r, char sep) return r; l = strlen(res); n = GDKzalloc(l + len + 3); - if( n == NULL) - throw(MAL, "json.glue.", MAL_MALLOC_FAIL); + if( n == NULL) { + GDKfree(res); + GDKfree(r); + return NULL; + } strcpy(n, res); GDKfree(res); if (sep) { @@ -513,24 +524,32 @@ JSONglue(str res, str r, char sep) return n; } +/* return NULL on no match, return (str) -1 on (malloc) failure */ static str JSONmatch(JSON *jt, int ji, pattern * terms, int ti) { str r = NULL, res = NULL; - int i, match; + int i; int cnt; if (terms[ti].token == ROOT_STEP) { - if (terms[ti + 1].token == END_STEP) - return JSONgetValue(jt, 0); + if (terms[ti + 1].token == END_STEP) { + res = JSONgetValue(jt, 0); + if (res == NULL) + res = (str) -1; + return res; + } ti++; } switch (jt->elm[ji].kind) { case JSON_ARRAY: if (terms[ti].name != 0 && terms[ti].token != ANY_STEP) { - if (terms[ti].token == END_STEP) + if (terms[ti].token == END_STEP) { res = JSONgetValue(jt, ji); + if (res == NULL) + res = (str) -1; + } return res; } cnt = 0; @@ -546,8 +565,14 @@ JSONmatch(JSON *jt, int ji, pattern * te r = JSONgetValue(jt, jt->elm[i].child); else r = JSONgetValue(jt, i); + if (r == NULL) + r = (str) -1; } else r = JSONmatch(jt, jt->elm[i].child, terms, ti + 1); + if (r == (str) -1) { + GDKfree(res); + return r; + } res = JSONglue(res, r, ','); } } @@ -556,18 +581,32 @@ JSONmatch(JSON *jt, int ji, pattern * te cnt = 0; for (i = jt->elm[ji].next; i && cnt >= 0; i = jt->elm[i].next) { // check the element label - match = (terms[ti].name && jt->elm[i].valuelen == terms[ti].namelen && strncmp(terms[ti].name, jt->elm[i].value, terms[ti].namelen) == 0) ||terms[ti].name == 0 || terms[ti].name[0] == '*'; - if (match) { - if (terms[ti].index == INT_MAX || (cnt >= terms[ti].first && cnt <= terms[ti].last)) { - if (terms[ti + 1].token == END_STEP) + if ((terms[ti].name && + jt->elm[i].valuelen == terms[ti].namelen && + strncmp(terms[ti].name, jt->elm[i].value, terms[ti].namelen) == 0) || + terms[ti].name == 0 || + terms[ti].name[0] == '*') { + if (terms[ti].index == INT_MAX || + (cnt >= terms[ti].first && cnt <= terms[ti].last)) { + if (terms[ti + 1].token == END_STEP) { r = JSONgetValue(jt, jt->elm[i].child); - else + if (r == NULL) + r = (str) -1; + } else r = JSONmatch(jt, jt->elm[i].child, terms, ti + 1); + if (r == (str) -1) { + GDKfree(res); + return r; + } res = JSONglue(res, r, ','); } cnt++; } else if (terms[ti].token == ANY_STEP && jt->elm[i].child) { r = JSONmatch(jt, jt->elm[i].child, terms, ti); + if (r == (str) -1) { + GDKfree(res); + return r; + } res = JSONglue(res, r, ','); cnt++; } @@ -589,6 +628,8 @@ JSONfilterInternal(json *ret, json *js, (void) other; if (strNil(j)) { *ret = GDKstrdup(j); + if (*ret == NULL) + throw(MAL,"JSONfilterInternal",MAL_MALLOC_FAIL); return MAL_SUCCEED; } jt = JSONparse(j, FALSE); @@ -599,10 +640,18 @@ JSONfilterInternal(json *ret, json *js, goto bailout; result = s = JSONmatch(jt, 0, terms, tidx); + if (s == (char *) -1) { + msg = createException(MAL,"JSONfilterInternal",MAL_MALLOC_FAIL); + goto bailout; + } // process all other PATH expression for (tidx++; tidx < MAXTERMS && terms[tidx].token; tidx++) if (terms[tidx].token == END_STEP && tidx + 1 < MAXTERMS && terms[tidx + 1].token) { s = JSONmatch(jt, 0, terms, ++tidx); + if (s == (char *) -1) { + msg = createException(MAL,"JSONfilterInternal",MAL_MALLOC_FAIL); + goto bailout; + } result = JSONglue(result, s, ','); } if (result) { @@ -612,8 +661,10 @@ JSONfilterInternal(json *ret, json *js, } else l = 3; s = GDKzalloc(l + 3); - if( s == NULL) + if (s == NULL) { + GDKfree(result); throw(MAL,"JSONfilterInternal",MAL_MALLOC_FAIL); + } snprintf(s, l + 3, "[%s]", (result ? result : "")); GDKfree(result); *ret = s; @@ -725,6 +776,8 @@ JSONtoken(JSON *jt, char *j, char **next int nxt, idx = JSONnew(jt); assert(silent==0); + if (jt->error) + return idx; skipblancs(j); switch (*j) { case '{': @@ -736,7 +789,7 @@ JSONtoken(JSON *jt, char *j, char **next if (*j == '}') break; nxt = JSONtoken(jt, j, next, silent); - if (jt->error) + if (jt->error) return idx; if (jt->elm[nxt].kind != JSON_ELEMENT) { if (!silent) @@ -744,6 +797,8 @@ JSONtoken(JSON *jt, char *j, char **next return idx; } JSONappend(jt, idx, nxt); + if (jt->error) + return idx; j = *next; skipblancs(j); if (*j == '}') @@ -773,11 +828,13 @@ JSONtoken(JSON *jt, char *j, char **next if (*j == ']') break; nxt = JSONtoken(jt, j, next, silent); - if (jt->error) + if (jt->error) return idx; switch (jt->elm[nxt].kind) { case JSON_ELEMENT:{ int k = JSONnew(jt); + if (jt->error) + return idx; jt->elm[k].kind = JSON_OBJECT; jt->elm[k].child = nxt; nxt = k; @@ -787,13 +844,19 @@ JSONtoken(JSON *jt, char *j, char **next case JSON_ARRAY: if (jt->elm[nxt].kind == JSON_OBJECT || jt->elm[nxt].kind == JSON_ARRAY) { int k = JSONnew(jt); + if (jt->error) + return idx; JSONappend(jt, idx, k); + if (jt->error) + return idx; jt->elm[k].kind = JSON_VALUE; jt->elm[k].child = nxt; } break; default: JSONappend(jt, idx, nxt); + if (jt->error) + return idx; } j = *next; skipblancs(j); @@ -826,6 +889,8 @@ JSONtoken(JSON *jt, char *j, char **next jt->error = msg; return idx; } + if (msg != MAL_SUCCEED && msg != M5OutOfMemory) + GDKfree(msg); jt->elm[idx].kind = JSON_STRING; jt->elm[idx].value = j; jt->elm[idx].valuelen = *next - j; @@ -836,7 +901,7 @@ JSONtoken(JSON *jt, char *j, char **next skipblancs(j); jt->elm[idx].kind = JSON_ELEMENT; nxt = JSONtoken(jt, j, next, silent); - if (jt->error) + if (jt->error) return idx; jt->elm[idx].child = nxt; jt->elm[idx].value++; @@ -882,6 +947,8 @@ JSONtoken(JSON *jt, char *j, char **next msg = JSONnumberParser(j, next, silent); if (!silent && msg) jt->error = msg; + else if (msg != MAL_SUCCEED && msg != M5OutOfMemory) + GDKfree(msg); jt->elm[idx].kind = JSON_NUMBER; jt->elm[idx].valuelen = *next - jt->elm[idx].value; return idx; @@ -1075,8 +1142,10 @@ JSONjson2text(str *ret, json *js) _______________________________________________ checkin-list mailing list checkin-list@monetdb.org https://www.monetdb.org/mailman/listinfo/checkin-list