summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBram Moolenaar <Bram@vim.org>2017-01-10 15:15:37 +0100
committerBram Moolenaar <Bram@vim.org>2017-01-10 15:15:37 +0100
commit03c60c1573cdbebbb662863cfc1780d19d511db5 (patch)
tree15d54d07bbb9de9a678b8f5beabc9ed042c5d680
parentf446b48ff0bffae2b453cd4f9e3c25dfe363d29d (diff)
downloadvim-git-03c60c1573cdbebbb662863cfc1780d19d511db5.tar.gz
patch 8.0.0166: JSON with a duplicate key gives an internal errorv8.0.0166
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.
-rw-r--r--src/channel.c5
-rw-r--r--src/evalfunc.c3
-rw-r--r--src/json.c28
-rw-r--r--src/testdir/test_json.vim3
-rw-r--r--src/version.c2
5 files changed, 36 insertions, 5 deletions
diff --git a/src/channel.c b/src/channel.c
index f409e1d20..f522e80c4 100644
--- a/src/channel.c
+++ b/src/channel.c
@@ -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
diff --git a/src/evalfunc.c b/src/evalfunc.c
index f66fa9a8e..74676c206 100644
--- a/src/evalfunc.c
+++ b/src/evalfunc.c
@@ -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);
}
/*
diff --git a/src/json.c b/src/json.c
index 4ec4411fb..2d0e70691 100644
--- a/src/json.c
+++ b/src/json.c
@@ -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;
}
diff --git a/src/testdir/test_json.vim b/src/testdir/test_json.vim
index e14903646..ecca0388e 100644
--- a/src/testdir/test_json.vim
+++ b/src/testdir/test_json.vim
@@ -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:")
diff --git a/src/version.c b/src/version.c
index b5039a01d..f5327cc34 100644
--- a/src/version.c
+++ b/src/version.c
@@ -765,6 +765,8 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
+ 166,
+/**/
165,
/**/
164,