Changeset: 7c22c59d7c79 for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB/rev/7c22c59d7c79
Modified Files:
monetdb5/modules/atoms/json.c
sql/test/SQLancer/Tests/sqlancer17.test
Branch: Jul2021
Log Message:
Missing NULL values and stack overflow checks in the JSON module
diffs (213 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
@@ -645,7 +645,7 @@ JSONglue(str res, str r, char sep)
return n;
}
-/* return NULL on no match, return (str) -1 on (malloc) failure */
+/* return NULL on no match, return (str) -1 on (malloc) failure, (str) -2 on
stack overflow */
static str
JSONmatch(JSON *jt, int ji, pattern * terms, int ti)
{
@@ -653,6 +653,8 @@ JSONmatch(JSON *jt, int ji, pattern * te
int i;
int cnt;
+ if (THRhighwater())
+ return (str) -2;
if (ti >= MAXTERMS)
return res;
@@ -697,7 +699,7 @@ JSONmatch(JSON *jt, int ji, pattern * te
r = (str) -1;
} else
r = JSONmatch(jt, jt->elm[i].child,
terms, ti + 1);
- if (r == (str) -1) {
+ if (r == (str) -1 || r == (str) -2) {
GDKfree(res);
return r;
}
@@ -724,7 +726,7 @@ JSONmatch(JSON *jt, int ji, pattern * te
r = (str) -1;
} else
r = JSONmatch(jt,
jt->elm[i].child, terms, ti + 1);
- if (r == (str) -1) {
+ if (r == (str) -1 || r == (str) -2) {
GDKfree(res);
return r;
}
@@ -733,7 +735,7 @@ JSONmatch(JSON *jt, int ji, pattern * te
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) {
+ if (r == (str) -1 || r == (str) -2) {
GDKfree(res);
return r;
}
@@ -777,6 +779,10 @@ JSONfilterInternal(json *ret, json *js,
msg = createException(MAL,"JSONfilterInternal", SQLSTATE(HY013)
MAL_MALLOC_FAIL);
goto bailout;
}
+ if (s == (char *) -2) {
+ msg = createException(MAL, "JSONfilterInternal",
SQLSTATE(42000) "Expression too complex to parse");
+ 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) {
@@ -785,6 +791,10 @@ JSONfilterInternal(json *ret, json *js,
msg = createException(MAL,"JSONfilterInternal",
SQLSTATE(HY013) MAL_MALLOC_FAIL);
goto bailout;
}
+ if (s == (char *) -2) {
+ msg = createException(MAL,
"JSONfilterInternal", SQLSTATE(42000) "Expression too complex to parse");
+ goto bailout;
+ }
result = JSONglue(result, s, ',');
}
if (result) {
@@ -991,7 +1001,7 @@ JSONtoken(JSON *jt, const char *j, const
if (jt->error)
return idx;
if (THRhighwater()) {
- jt->error = createException(MAL, "json.parser", "expression too
complex to parse");
+ jt->error = createException(MAL, "json.parser", SQLSTATE(42000)
"Expression too complex to parse");
return idx;
}
skipblancs(j);
@@ -1191,8 +1201,14 @@ static str
JSONlength(int *ret, json *j)
{
int i, cnt = 0;
- JSON *jt = JSONparse(*j);
+ JSON *jt;
+ if (strNil(*j)) {
+ *ret = int_nil;
+ return MAL_SUCCEED;
+ }
+
+ jt = JSONparse(*j);
CHECK_JSON(jt);
for (i = jt->elm[0].next; i; i = jt->elm[i].next)
cnt++;
@@ -1292,6 +1308,11 @@ JSONplaintext(char **r, size_t *l, size_
unsigned int u;
str msg = MAL_SUCCEED;
+ if (THRhighwater()) {
+ *r = *r - (*ilen - *l);
+ throw(MAL,"JSONplaintext", SQLSTATE(42000) "Expression too
complex to parse");
+ }
+
switch (jt->elm[idx].kind) {
case JSON_OBJECT:
for (i = jt->elm[idx].next; i; i = jt->elm[i].next)
@@ -1433,8 +1454,15 @@ JSONjson2textSeparator(str *ret, json *j
{
size_t l, ilen, sep_len;
str s, msg;
- JSON *jt = JSONparse(*js);
+ JSON *jt;
+ if (strNil(*js) || strNil(*sep)) {
+ if (!(*ret = GDKstrdup(str_nil)))
+ throw(MAL,"json2txt", SQLSTATE(HY013) MAL_MALLOC_FAIL);
+ return MAL_SUCCEED;
+ }
+
+ jt = JSONparse(*js);
CHECK_JSON(jt);
sep_len = strlen(*sep);
ilen = l = strlen(*js) + 1;
@@ -1531,14 +1559,17 @@ JSONjson2number(dbl *ret, json *js)
dbl val = 0;
dbl *val_ptr = &val;
str tmp;
- rethrow(__func__, tmp, JSONjson2numberInternal((void **)&val_ptr, js,
strtod_wrapper));
- if (val_ptr == NULL) {
+ if (strNil(*js)) {
*ret = dbl_nil;
+ return MAL_SUCCEED;
}
- else {
+
+ rethrow(__func__, tmp, JSONjson2numberInternal((void **)&val_ptr, js,
strtod_wrapper));
+ if (val_ptr == NULL)
+ *ret = dbl_nil;
+ else
*ret = val;
- }
return MAL_SUCCEED;
}
@@ -1550,13 +1581,16 @@ JSONjson2integer(lng *ret, json *js)
lng *val_ptr = &val;
str tmp;
- rethrow(__func__, tmp, JSONjson2numberInternal((void **)&val_ptr, js,
strtol_wrapper));
- if (val_ptr == NULL) {
+ if (strNil(*js)) {
*ret = lng_nil;
+ return MAL_SUCCEED;
}
- else {
+
+ rethrow(__func__, tmp, JSONjson2numberInternal((void **)&val_ptr, js,
strtol_wrapper));
+ if (val_ptr == NULL)
+ *ret = lng_nil;
+ else
*ret = val;
- }
return MAL_SUCCEED;
}
@@ -1729,6 +1763,12 @@ JSONkeyArray(json *ret, json *js)
int i;
JSON *jt;
+ if (strNil(*js)) {
+ if (!(*ret = GDKstrdup(str_nil)))
+ throw(MAL,"json.keyarray", SQLSTATE(HY013)
MAL_MALLOC_FAIL);
+ return MAL_SUCCEED;
+ }
+
jt = JSONparse(*js); // already validated
CHECK_JSON(jt);
@@ -1826,6 +1866,12 @@ JSONvalueArray(json *ret, json *js)
int i;
JSON *jt;
+ if (strNil(*js)) {
+ if (!(*ret = GDKstrdup(str_nil)))
+ throw(MAL,"json.valuearray", SQLSTATE(HY013)
MAL_MALLOC_FAIL);
+ return MAL_SUCCEED;
+ }
+
jt = JSONparse(*js); // already validated
CHECK_JSON(jt);
diff --git a/sql/test/SQLancer/Tests/sqlancer17.test
b/sql/test/SQLancer/Tests/sqlancer17.test
--- a/sql/test/SQLancer/Tests/sqlancer17.test
+++ b/sql/test/SQLancer/Tests/sqlancer17.test
@@ -163,6 +163,16 @@ SELECT json."text"(JSON '""', '344567')
----
(empty)
+query T nosort
+select json.text(json '[1,2,3,4]', null)
+----
+NULL
+
+query T nosort
+select json.text(null, '23131')
+----
+NULL
+
statement ok
START TRANSACTION
_______________________________________________
checkin-list mailing list
[email protected]
https://www.monetdb.org/mailman/listinfo/checkin-list