]> granicus.if.org Git - vim/commitdiff
patch 8.0.0166: JSON with a duplicate key gives an internal error v8.0.0166
authorBram Moolenaar <Bram@vim.org>
Tue, 10 Jan 2017 14:15:37 +0000 (15:15 +0100)
committerBram Moolenaar <Bram@vim.org>
Tue, 10 Jan 2017 14:15:37 +0000 (15:15 +0100)
Problem:    JSON with a duplicate key gives an internal error. (Lcd)
Solution:   Give a normal error.  Avoid an error when parsing JSON from a
            remote client fails.

src/channel.c
src/evalfunc.c
src/json.c
src/testdir/test_json.vim
src/version.c

index f409e1d2093ad181590b359450c2ed0872388a6b..f522e80c4ae323fb2ddd74a9aa922c969fde8acb 100644 (file)
@@ -1896,9 +1896,12 @@ channel_parse_json(channel_T *channel, ch_part_T part)
 
     /* When a message is incomplete we wait for a short while for more to
      * arrive.  After the delay drop the input, otherwise a truncated string
-     * or list will make us hang.  */
+     * or list will make us hang.
+     * Do not generate error messages, they will be written in a channel log. */
+    ++emsg_silent;
     status = json_decode(&reader, &listtv,
                                  chanpart->ch_mode == MODE_JS ? JSON_JS : 0);
+    --emsg_silent;
     if (status == OK)
     {
        /* Only accept the response when it is a list with at least two
index f66fa9a8e1b0070e10ea3c2143063d02924d8735..74676c2062ec7059a77d451a92403394426b89d1 100644 (file)
@@ -6818,8 +6818,7 @@ f_json_decode(typval_T *argvars, typval_T *rettv)
     reader.js_buf = get_tv_string(&argvars[0]);
     reader.js_fill = NULL;
     reader.js_used = 0;
-    if (json_decode_all(&reader, rettv, 0) != OK)
-       EMSG(_(e_invarg));
+    json_decode_all(&reader, rettv, 0);
 }
 
 /*
index 4ec4411fb233b572b3c63e8f52c9606481789495..2d0e706913a9861485d59bf09996494bbbff939a 100644 (file)
@@ -428,6 +428,7 @@ json_decode_array(js_read_T *reader, typval_T *res, int options)
        {
            if (*p == NUL)
                return MAYBE;
+           EMSG(_(e_invarg));
            return FAIL;
        }
     }
@@ -488,6 +489,7 @@ json_decode_object(js_read_T *reader, typval_T *res, int options)
                if (key == NULL || *key == NUL)
                {
                    clear_tv(&tvkey);
+                   EMSG(_(e_invarg));
                    return FAIL;
                }
            }
@@ -501,6 +503,7 @@ json_decode_object(js_read_T *reader, typval_T *res, int options)
                clear_tv(&tvkey);
            if (*p == NUL)
                return MAYBE;
+           EMSG(_(e_invarg));
            return FAIL;
        }
        ++reader->js_used;
@@ -514,6 +517,14 @@ json_decode_object(js_read_T *reader, typval_T *res, int options)
            return ret;
        }
 
+       if (res != NULL && dict_find(res->vval.v_dict, key, -1) != NULL)
+       {
+           EMSG2(_("E937: Duplicate key in JSON: \"%s\""), key);
+           clear_tv(&tvkey);
+           clear_tv(&item);
+           return FAIL;
+       }
+
        if (res != NULL)
        {
            di = dictitem_alloc(key);
@@ -540,6 +551,7 @@ json_decode_object(js_read_T *reader, typval_T *res, int options)
        {
            if (*p == NUL)
                return MAYBE;
+           EMSG(_(e_invarg));
            return FAIL;
        }
     }
@@ -715,7 +727,7 @@ json_decode_string(js_read_T *reader, typval_T *res)
  * Decode one item and put it in "res".  If "res" is NULL only advance.
  * Must already have skipped white space.
  *
- * Return FAIL for a decoding error.
+ * Return FAIL for a decoding error (and give an error).
  * Return MAYBE for an incomplete message.
  */
     static int
@@ -739,7 +751,10 @@ json_decode_item(js_read_T *reader, typval_T *res, int options)
 
        case ',': /* comma: empty item */
            if ((options & JSON_JS) == 0)
+           {
+               EMSG(_(e_invarg));
                return FAIL;
+           }
            /* FALLTHROUGH */
        case NUL: /* empty */
            if (res != NULL)
@@ -761,7 +776,10 @@ json_decode_item(js_read_T *reader, typval_T *res, int options)
                    if (*sp == NUL)
                        return MAYBE;
                    if (!VIM_ISDIGIT(*sp))
+                   {
+                       EMSG(_(e_invarg));
                        return FAIL;
+                   }
                }
                sp = skipdigits(sp);
                if (*sp == '.' || *sp == 'e' || *sp == 'E')
@@ -866,6 +884,7 @@ json_decode_item(js_read_T *reader, typval_T *res, int options)
        res->v_type = VAR_SPECIAL;
        res->vval.v_number = VVAL_NONE;
     }
+    EMSG(_(e_invarg));
     return FAIL;
 }
 
@@ -884,10 +903,17 @@ json_decode_all(js_read_T *reader, typval_T *res, int options)
     json_skip_white(reader);
     ret = json_decode_item(reader, res, options);
     if (ret != OK)
+    {
+       if (ret == MAYBE)
+           EMSG(_(e_invarg));
        return FAIL;
+    }
     json_skip_white(reader);
     if (reader->js_buf[reader->js_used] != NUL)
+    {
+       EMSG(_(e_trailing));
        return FAIL;
+    }
     return OK;
 }
 
index e1490364601472870b7b0e8c94fc846171aa421e..ecca0388ee52344142e781627f6f01ceb579223c 100644 (file)
@@ -148,8 +148,9 @@ func Test_json_decode()
 
   call assert_fails('call json_decode("\"")', "E474:")
   call assert_fails('call json_decode("blah")', "E474:")
-  call assert_fails('call json_decode("true blah")', "E474:")
+  call assert_fails('call json_decode("true blah")', "E488:")
   call assert_fails('call json_decode("<foobar>")', "E474:")
+  call assert_fails('call json_decode("{\"a\":1,\"a\":2}")', "E937:")
 
   call assert_fails('call json_decode("{")', "E474:")
   call assert_fails('call json_decode("{foobar}")', "E474:")
index b5039a01d8644ee4a9b873b50986cc7f6a318ea4..f5327cc34851e6be3d3239362bb368c51c8574ce 100644 (file)
@@ -764,6 +764,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    166,
 /**/
     165,
 /**/