0
0
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:
Bram Moolenaar 2017-01-10 15:15:37 +01:00
parent f446b48ff0
commit 03c60c1573
5 changed files with 36 additions and 5 deletions

View 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 /* 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

View File

@ -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));
} }
/* /*

View File

@ -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;
} }

View File

@ -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:")

View File

@ -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,
/**/ /**/