Skip to content

Commit b362872

Browse files
committed
patch 7.4.1445
Problem: Memory corruption when 'encoding' is not utf-8. Solution: Convert decoded string later.
1 parent 0f526f5 commit b362872

File tree

2 files changed

+27
-21
lines changed

2 files changed

+27
-21
lines changed

src/json.c

Lines changed: 25 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,8 @@ write_string(garray_T *gap, char_u *str)
8686

8787
if (!enc_utf8)
8888
{
89+
/* Convert the text from 'encoding' to utf-8, the JSON string is
90+
* always utf-8. */
8991
conv.vc_type = CONV_NONE;
9092
convert_setup(&conv, p_enc, (char_u*)"utf-8");
9193
if (conv.vc_type != CONV_NONE)
@@ -534,33 +536,23 @@ json_decode_string(js_read_T *reader, typval_T *res)
534536
int c;
535537
long nr;
536538
char_u buf[NUMBUFLEN];
537-
#if defined(FEAT_MBYTE) && defined(USE_ICONV)
538-
vimconv_T conv;
539-
char_u *converted = NULL;
540-
#endif
541539

542540
if (res != NULL)
543541
ga_init2(&ga, 1, 200);
544542

545543
p = reader->js_buf + reader->js_used + 1; /* skip over " */
546-
#if defined(FEAT_MBYTE) && defined(USE_ICONV)
547-
if (!enc_utf8)
548-
{
549-
conv.vc_type = CONV_NONE;
550-
convert_setup(&conv, (char_u*)"utf-8", p_enc);
551-
if (conv.vc_type != CONV_NONE)
552-
converted = p = string_convert(&conv, p, NULL);
553-
convert_setup(&conv, NULL, NULL);
554-
}
555-
#endif
556544
while (*p != '"')
557545
{
546+
/* The JSON is always expected to be utf-8, thus use utf functions
547+
* here. The string is converted below if needed. */
558548
if (*p == NUL || p[1] == NUL
559549
#ifdef FEAT_MBYTE
560550
|| utf_ptr2len(p) < utf_byte2len(*p)
561551
#endif
562552
)
563553
{
554+
/* Not enough bytes to make a character or end of the string. Get
555+
* more if possible. */
564556
if (reader->js_fill == NULL)
565557
break;
566558
len = (int)(reader->js_end - p);
@@ -652,9 +644,6 @@ json_decode_string(js_read_T *reader, typval_T *res)
652644
if (ga_grow(&ga, len) == FAIL)
653645
{
654646
ga_clear(&ga);
655-
#if defined(FEAT_MBYTE) && defined(USE_ICONV)
656-
vim_free(converted);
657-
#endif
658647
return FAIL;
659648
}
660649
mch_memmove((char *)ga.ga_data + ga.ga_len, p, (size_t)len);
@@ -663,9 +652,6 @@ json_decode_string(js_read_T *reader, typval_T *res)
663652
p += len;
664653
}
665654
}
666-
#if defined(FEAT_MBYTE) && defined(USE_ICONV)
667-
vim_free(converted);
668-
#endif
669655

670656
reader->js_used = (int)(p - reader->js_buf);
671657
if (*p == '"')
@@ -674,7 +660,25 @@ json_decode_string(js_read_T *reader, typval_T *res)
674660
if (res != NULL)
675661
{
676662
res->v_type = VAR_STRING;
677-
res->vval.v_string = ga.ga_data;
663+
#if defined(FEAT_MBYTE) && defined(USE_ICONV)
664+
if (!enc_utf8)
665+
{
666+
vimconv_T conv;
667+
668+
/* Convert the utf-8 string to 'encoding'. */
669+
conv.vc_type = CONV_NONE;
670+
convert_setup(&conv, (char_u*)"utf-8", p_enc);
671+
if (conv.vc_type != CONV_NONE)
672+
{
673+
res->vval.v_string =
674+
string_convert(&conv, ga.ga_data, NULL);
675+
vim_free(ga.ga_data);
676+
}
677+
convert_setup(&conv, NULL, NULL);
678+
}
679+
else
680+
#endif
681+
res->vval.v_string = ga.ga_data;
678682
}
679683
return OK;
680684
}

src/version.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -743,6 +743,8 @@ static char *(features[]) =
743743

744744
static int included_patches[] =
745745
{ /* Add new patch number below this line */
746+
/**/
747+
1445,
746748
/**/
747749
1444,
748750
/**/

0 commit comments

Comments
 (0)