mirror of
https://github.com/vim/vim.git
synced 2025-07-26 11:04:33 -04:00
patch 8.0.0166: JSON with a duplicate key gives an internal error
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.
This commit is contained in:
parent
f446b48ff0
commit
03c60c1573
@ -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
|
/* 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
|
* 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,
|
status = json_decode(&reader, &listtv,
|
||||||
chanpart->ch_mode == MODE_JS ? JSON_JS : 0);
|
chanpart->ch_mode == MODE_JS ? JSON_JS : 0);
|
||||||
|
--emsg_silent;
|
||||||
if (status == OK)
|
if (status == OK)
|
||||||
{
|
{
|
||||||
/* Only accept the response when it is a list with at least two
|
/* Only accept the response when it is a list with at least two
|
||||||
|
@ -6818,8 +6818,7 @@ f_json_decode(typval_T *argvars, typval_T *rettv)
|
|||||||
reader.js_buf = get_tv_string(&argvars[0]);
|
reader.js_buf = get_tv_string(&argvars[0]);
|
||||||
reader.js_fill = NULL;
|
reader.js_fill = NULL;
|
||||||
reader.js_used = 0;
|
reader.js_used = 0;
|
||||||
if (json_decode_all(&reader, rettv, 0) != OK)
|
json_decode_all(&reader, rettv, 0);
|
||||||
EMSG(_(e_invarg));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
28
src/json.c
28
src/json.c
@ -428,6 +428,7 @@ json_decode_array(js_read_T *reader, typval_T *res, int options)
|
|||||||
{
|
{
|
||||||
if (*p == NUL)
|
if (*p == NUL)
|
||||||
return MAYBE;
|
return MAYBE;
|
||||||
|
EMSG(_(e_invarg));
|
||||||
return FAIL;
|
return FAIL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -488,6 +489,7 @@ json_decode_object(js_read_T *reader, typval_T *res, int options)
|
|||||||
if (key == NULL || *key == NUL)
|
if (key == NULL || *key == NUL)
|
||||||
{
|
{
|
||||||
clear_tv(&tvkey);
|
clear_tv(&tvkey);
|
||||||
|
EMSG(_(e_invarg));
|
||||||
return FAIL;
|
return FAIL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -501,6 +503,7 @@ json_decode_object(js_read_T *reader, typval_T *res, int options)
|
|||||||
clear_tv(&tvkey);
|
clear_tv(&tvkey);
|
||||||
if (*p == NUL)
|
if (*p == NUL)
|
||||||
return MAYBE;
|
return MAYBE;
|
||||||
|
EMSG(_(e_invarg));
|
||||||
return FAIL;
|
return FAIL;
|
||||||
}
|
}
|
||||||
++reader->js_used;
|
++reader->js_used;
|
||||||
@ -514,6 +517,14 @@ json_decode_object(js_read_T *reader, typval_T *res, int options)
|
|||||||
return ret;
|
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)
|
if (res != NULL)
|
||||||
{
|
{
|
||||||
di = dictitem_alloc(key);
|
di = dictitem_alloc(key);
|
||||||
@ -540,6 +551,7 @@ json_decode_object(js_read_T *reader, typval_T *res, int options)
|
|||||||
{
|
{
|
||||||
if (*p == NUL)
|
if (*p == NUL)
|
||||||
return MAYBE;
|
return MAYBE;
|
||||||
|
EMSG(_(e_invarg));
|
||||||
return FAIL;
|
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.
|
* Decode one item and put it in "res". If "res" is NULL only advance.
|
||||||
* Must already have skipped white space.
|
* 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.
|
* Return MAYBE for an incomplete message.
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
@ -739,7 +751,10 @@ json_decode_item(js_read_T *reader, typval_T *res, int options)
|
|||||||
|
|
||||||
case ',': /* comma: empty item */
|
case ',': /* comma: empty item */
|
||||||
if ((options & JSON_JS) == 0)
|
if ((options & JSON_JS) == 0)
|
||||||
|
{
|
||||||
|
EMSG(_(e_invarg));
|
||||||
return FAIL;
|
return FAIL;
|
||||||
|
}
|
||||||
/* FALLTHROUGH */
|
/* FALLTHROUGH */
|
||||||
case NUL: /* empty */
|
case NUL: /* empty */
|
||||||
if (res != NULL)
|
if (res != NULL)
|
||||||
@ -761,8 +776,11 @@ json_decode_item(js_read_T *reader, typval_T *res, int options)
|
|||||||
if (*sp == NUL)
|
if (*sp == NUL)
|
||||||
return MAYBE;
|
return MAYBE;
|
||||||
if (!VIM_ISDIGIT(*sp))
|
if (!VIM_ISDIGIT(*sp))
|
||||||
|
{
|
||||||
|
EMSG(_(e_invarg));
|
||||||
return FAIL;
|
return FAIL;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
sp = skipdigits(sp);
|
sp = skipdigits(sp);
|
||||||
if (*sp == '.' || *sp == 'e' || *sp == 'E')
|
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->v_type = VAR_SPECIAL;
|
||||||
res->vval.v_number = VVAL_NONE;
|
res->vval.v_number = VVAL_NONE;
|
||||||
}
|
}
|
||||||
|
EMSG(_(e_invarg));
|
||||||
return FAIL;
|
return FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -884,10 +903,17 @@ json_decode_all(js_read_T *reader, typval_T *res, int options)
|
|||||||
json_skip_white(reader);
|
json_skip_white(reader);
|
||||||
ret = json_decode_item(reader, res, options);
|
ret = json_decode_item(reader, res, options);
|
||||||
if (ret != OK)
|
if (ret != OK)
|
||||||
|
{
|
||||||
|
if (ret == MAYBE)
|
||||||
|
EMSG(_(e_invarg));
|
||||||
return FAIL;
|
return FAIL;
|
||||||
|
}
|
||||||
json_skip_white(reader);
|
json_skip_white(reader);
|
||||||
if (reader->js_buf[reader->js_used] != NUL)
|
if (reader->js_buf[reader->js_used] != NUL)
|
||||||
|
{
|
||||||
|
EMSG(_(e_trailing));
|
||||||
return FAIL;
|
return FAIL;
|
||||||
|
}
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -148,8 +148,9 @@ func Test_json_decode()
|
|||||||
|
|
||||||
call assert_fails('call json_decode("\"")', "E474:")
|
call assert_fails('call json_decode("\"")', "E474:")
|
||||||
call assert_fails('call json_decode("blah")', "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("<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("{")', "E474:")
|
||||||
call assert_fails('call json_decode("{foobar}")', "E474:")
|
call assert_fails('call json_decode("{foobar}")', "E474:")
|
||||||
|
@ -764,6 +764,8 @@ static char *(features[]) =
|
|||||||
|
|
||||||
static int included_patches[] =
|
static int included_patches[] =
|
||||||
{ /* Add new patch number below this line */
|
{ /* Add new patch number below this line */
|
||||||
|
/**/
|
||||||
|
166,
|
||||||
/**/
|
/**/
|
||||||
165,
|
165,
|
||||||
/**/
|
/**/
|
||||||
|
Loading…
x
Reference in New Issue
Block a user