Changeset: abba0742957f for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB/rev/abba0742957f
Modified Files:
        monetdb5/modules/atoms/json.c
        sql/test/SQLancer/Tests/sqlancer17.test
Branch: Jul2021
Log Message:

Fix buffer reallocation for JSONplaintext function


diffs (85 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
@@ -1288,7 +1288,8 @@ static str
 JSONplaintext(char **r, size_t *l, size_t *ilen, JSON *jt, int idx, str sep, 
size_t sep_len)
 {
        int i;
-       unsigned int j, u;
+       size_t j, next_len, next_concat_len;
+       unsigned int u;
        str msg = MAL_SUCCEED;
 
        switch (jt->elm[idx].kind) {
@@ -1309,17 +1310,23 @@ JSONplaintext(char **r, size_t *l, size_
                break;
        case JSON_STRING:
                // Make sure there is enough space for the value plus the 
separator plus the NULL byte
-               if (*l < jt->elm[idx].valuelen - 2 + sep_len + 1) {
-                       char *p = *r - *ilen + *l, *nr;
-                       *ilen *= 2;
+               next_len = jt->elm[idx].valuelen;
+               next_concat_len = next_len - 2 + sep_len + 1;
+               if (*l < next_concat_len) {
+                       size_t prev_ilen = *ilen, prev_l = *l;
+                       char *p = *r - (prev_ilen - prev_l), *nr;
+
+                       *ilen = (prev_ilen * 2) + next_concat_len; /* make sure 
sep_len + 1 is always included */
                        if (!(nr = GDKrealloc(p, *ilen))) {
                                *r = p;
                                throw(MAL,"JSONplaintext", SQLSTATE(HY013) 
MAL_MALLOC_FAIL);
                        }
-                       *r = nr + *l;
-                       *l = *ilen - *l;
+                       *r = nr + (prev_ilen - prev_l);
+                       *l = *ilen - prev_ilen + prev_l;
                }
-               for (j = 1; j < jt->elm[idx].valuelen - 1; j++) {
+               assert(next_len >= 2);
+               next_len--;
+               for (j = 1; j < next_len; j++) {
                        if (jt->elm[idx].value[j] == '\\') {
                                switch (jt->elm[idx].value[++j]) {
                                case '"':
@@ -1395,20 +1402,23 @@ JSONplaintext(char **r, size_t *l, size_
                *r += sep_len;
                break;
        default:
-               if (*l < jt->elm[idx].valuelen + sep_len + 1) {
-                       size_t offset = *ilen - *l;
-                       char *p = *r - offset, *nr;
-                       *ilen *= 2;
+               next_len = jt->elm[idx].valuelen;
+               next_concat_len = next_len + sep_len + 1;
+               if (*l < next_concat_len) {
+                       size_t prev_ilen = *ilen, prev_l = *l;
+                       char *p = *r - (prev_ilen - prev_l), *nr;
+
+                       *ilen = (prev_ilen * 2) + next_concat_len; /* make sure 
sep_len + 1 is always included */
                        if (!(nr = GDKrealloc(p, *ilen))) {
                                *r = p;
                                throw(MAL,"JSONplaintext", SQLSTATE(HY013) 
MAL_MALLOC_FAIL);
                        }
-                       *r = nr + offset;
-                       *l = *ilen - offset;
+                       *r = nr + (prev_ilen - prev_l);
+                       *l = *ilen - prev_ilen + prev_l;
                }
-               memcpy(*r, jt->elm[idx].value, jt->elm[idx].valuelen);
-               *l -= jt->elm[idx].valuelen;
-               *r += jt->elm[idx].valuelen;
+               memcpy(*r, jt->elm[idx].value, next_len);
+               *l -= next_len;
+               *r += next_len;
                memcpy(*r, sep, sep_len);
                *l -= sep_len;
                *r += sep_len;
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
@@ -161,4 +161,5 @@ DROP TABLE t1
 query T nosort
 SELECT json."text"(JSON '""', '344567')
 ----
+(empty)
 
_______________________________________________
checkin-list mailing list
checkin-list@monetdb.org
https://www.monetdb.org/mailman/listinfo/checkin-list

Reply via email to