Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit0c5783f

Browse files
committed
Avoid integer overflow in hstore_to_json().
The length of the output buffer was calculated based on the size of theargument hstore. On a sizeof(int) == 4 platform and a huge argument, itcould overflow, causing a too small buffer to be allocated.Refactor the function to use a StringInfo instead of pre-allocating thebuffer. Makes it shorter and more readable, too.
1 parent8c059df commit0c5783f

File tree

1 file changed

+41
-109
lines changed

1 file changed

+41
-109
lines changed

‎contrib/hstore/hstore_io.c

Lines changed: 41 additions & 109 deletions
Original file line numberDiff line numberDiff line change
@@ -1245,77 +1245,49 @@ Datum
12451245
hstore_to_json_loose(PG_FUNCTION_ARGS)
12461246
{
12471247
HStore*in=PG_GETARG_HS(0);
1248-
intbuflen,
1249-
i;
1248+
inti;
12501249
intcount=HS_COUNT(in);
1251-
char*out,
1252-
*ptr;
12531250
char*base=STRPTR(in);
12541251
HEntry*entries=ARRPTR(in);
12551252
boolis_number;
1256-
StringInfosrc,
1253+
StringInfoDatatmp,
12571254
dst;
12581255

12591256
if (count==0)
12601257
PG_RETURN_TEXT_P(cstring_to_text_with_len("{}",2));
12611258

1262-
buflen=3;
1259+
initStringInfo(&tmp);
1260+
initStringInfo(&dst);
12631261

1264-
/*
1265-
* Formula adjusted slightly from the logic in hstore_out. We have to take
1266-
* account of out treatment of booleans to be a bit more pessimistic about
1267-
* the length of values.
1268-
*/
1262+
appendStringInfoChar(&dst,'{');
12691263

12701264
for (i=0;i<count;i++)
12711265
{
1272-
/* include "" and colon-space and comma-space */
1273-
buflen+=6+2*HS_KEYLEN(entries,i);
1274-
/* include "" only if nonnull */
1275-
buflen+=3+ (HS_VALISNULL(entries,i)
1276-
?1
1277-
:2*HS_VALLEN(entries,i));
1278-
}
1279-
1280-
out=ptr=palloc(buflen);
1281-
1282-
src=makeStringInfo();
1283-
dst=makeStringInfo();
1284-
1285-
*ptr++='{';
1286-
1287-
for (i=0;i<count;i++)
1288-
{
1289-
resetStringInfo(src);
1290-
resetStringInfo(dst);
1291-
appendBinaryStringInfo(src,HS_KEY(entries,base,i),HS_KEYLEN(entries,i));
1292-
escape_json(dst,src->data);
1293-
strncpy(ptr,dst->data,dst->len);
1294-
ptr+=dst->len;
1295-
*ptr++=':';
1296-
*ptr++=' ';
1297-
resetStringInfo(dst);
1266+
resetStringInfo(&tmp);
1267+
appendBinaryStringInfo(&tmp,HS_KEY(entries,base,i),HS_KEYLEN(entries,i));
1268+
escape_json(&dst,tmp.data);
1269+
appendStringInfoString(&dst,": ");
12981270
if (HS_VALISNULL(entries,i))
1299-
appendStringInfoString(dst,"null");
1271+
appendStringInfoString(&dst,"null");
13001272
/* guess that values of 't' or 'f' are booleans */
13011273
elseif (HS_VALLEN(entries,i)==1&&*(HS_VAL(entries,base,i))=='t')
1302-
appendStringInfoString(dst,"true");
1274+
appendStringInfoString(&dst,"true");
13031275
elseif (HS_VALLEN(entries,i)==1&&*(HS_VAL(entries,base,i))=='f')
1304-
appendStringInfoString(dst,"false");
1276+
appendStringInfoString(&dst,"false");
13051277
else
13061278
{
13071279
is_number= false;
1308-
resetStringInfo(src);
1309-
appendBinaryStringInfo(src,HS_VAL(entries,base,i),HS_VALLEN(entries,i));
1280+
resetStringInfo(&tmp);
1281+
appendBinaryStringInfo(&tmp,HS_VAL(entries,base,i),HS_VALLEN(entries,i));
13101282

13111283
/*
13121284
* don't treat something with a leading zero followed by another
13131285
* digit as numeric - could be a zip code or similar
13141286
*/
1315-
if (src->len>0&&
1316-
!(src->data[0]=='0'&&
1317-
isdigit((unsignedchar)src->data[1]))&&
1318-
strspn(src->data,"+-0123456789Ee.")==src->len)
1287+
if (tmp.len>0&&
1288+
!(tmp.data[0]=='0'&&
1289+
isdigit((unsignedchar)tmp.data[1]))&&
1290+
strspn(tmp.data,"+-0123456789Ee.")==tmp.len)
13191291
{
13201292
/*
13211293
* might be a number. See if we can input it as a numeric
@@ -1324,7 +1296,7 @@ hstore_to_json_loose(PG_FUNCTION_ARGS)
13241296
char*endptr="junk";
13251297
longlval;
13261298

1327-
lval=strtol(src->data,&endptr,10);
1299+
lval=strtol(tmp.data,&endptr,10);
13281300
(void)lval;
13291301
if (*endptr=='\0')
13301302
{
@@ -1339,30 +1311,24 @@ hstore_to_json_loose(PG_FUNCTION_ARGS)
13391311
/* not an int - try a double */
13401312
doubledval;
13411313

1342-
dval=strtod(src->data,&endptr);
1314+
dval=strtod(tmp.data,&endptr);
13431315
(void)dval;
13441316
if (*endptr=='\0')
13451317
is_number= true;
13461318
}
13471319
}
13481320
if (is_number)
1349-
appendBinaryStringInfo(dst,src->data,src->len);
1321+
appendBinaryStringInfo(&dst,tmp.data,tmp.len);
13501322
else
1351-
escape_json(dst,src->data);
1323+
escape_json(&dst,tmp.data);
13521324
}
1353-
strncpy(ptr,dst->data,dst->len);
1354-
ptr+=dst->len;
13551325

13561326
if (i+1!=count)
1357-
{
1358-
*ptr++=',';
1359-
*ptr++=' ';
1360-
}
1327+
appendStringInfoString(&dst,", ");
13611328
}
1362-
*ptr++='}';
1363-
*ptr='\0';
1329+
appendStringInfoChar(&dst,'}');
13641330

1365-
PG_RETURN_TEXT_P(cstring_to_text(out));
1331+
PG_RETURN_TEXT_P(cstring_to_text(dst.data));
13661332
}
13671333

13681334
PG_FUNCTION_INFO_V1(hstore_to_json);
@@ -1371,74 +1337,40 @@ Datum
13711337
hstore_to_json(PG_FUNCTION_ARGS)
13721338
{
13731339
HStore*in=PG_GETARG_HS(0);
1374-
intbuflen,
1375-
i;
1340+
inti;
13761341
intcount=HS_COUNT(in);
1377-
char*out,
1378-
*ptr;
13791342
char*base=STRPTR(in);
13801343
HEntry*entries=ARRPTR(in);
1381-
StringInfosrc,
1344+
StringInfoDatatmp,
13821345
dst;
13831346

13841347
if (count==0)
13851348
PG_RETURN_TEXT_P(cstring_to_text_with_len("{}",2));
13861349

1387-
buflen=3;
1350+
initStringInfo(&tmp);
1351+
initStringInfo(&dst);
13881352

1389-
/*
1390-
* Formula adjusted slightly from the logic in hstore_out. We have to take
1391-
* account of out treatment of booleans to be a bit more pessimistic about
1392-
* the length of values.
1393-
*/
1353+
appendStringInfoChar(&dst,'{');
13941354

13951355
for (i=0;i<count;i++)
13961356
{
1397-
/* include "" and colon-space and comma-space */
1398-
buflen+=6+2*HS_KEYLEN(entries,i);
1399-
/* include "" only if nonnull */
1400-
buflen+=3+ (HS_VALISNULL(entries,i)
1401-
?1
1402-
:2*HS_VALLEN(entries,i));
1403-
}
1404-
1405-
out=ptr=palloc(buflen);
1406-
1407-
src=makeStringInfo();
1408-
dst=makeStringInfo();
1409-
1410-
*ptr++='{';
1411-
1412-
for (i=0;i<count;i++)
1413-
{
1414-
resetStringInfo(src);
1415-
resetStringInfo(dst);
1416-
appendBinaryStringInfo(src,HS_KEY(entries,base,i),HS_KEYLEN(entries,i));
1417-
escape_json(dst,src->data);
1418-
strncpy(ptr,dst->data,dst->len);
1419-
ptr+=dst->len;
1420-
*ptr++=':';
1421-
*ptr++=' ';
1422-
resetStringInfo(dst);
1357+
resetStringInfo(&tmp);
1358+
appendBinaryStringInfo(&tmp,HS_KEY(entries,base,i),HS_KEYLEN(entries,i));
1359+
escape_json(&dst,tmp.data);
1360+
appendStringInfoString(&dst,": ");
14231361
if (HS_VALISNULL(entries,i))
1424-
appendStringInfoString(dst,"null");
1362+
appendStringInfoString(&dst,"null");
14251363
else
14261364
{
1427-
resetStringInfo(src);
1428-
appendBinaryStringInfo(src,HS_VAL(entries,base,i),HS_VALLEN(entries,i));
1429-
escape_json(dst,src->data);
1365+
resetStringInfo(&tmp);
1366+
appendBinaryStringInfo(&tmp,HS_VAL(entries,base,i),HS_VALLEN(entries,i));
1367+
escape_json(&dst,tmp.data);
14301368
}
1431-
strncpy(ptr,dst->data,dst->len);
1432-
ptr+=dst->len;
14331369

14341370
if (i+1!=count)
1435-
{
1436-
*ptr++=',';
1437-
*ptr++=' ';
1438-
}
1371+
appendStringInfoString(&dst,", ");
14391372
}
1440-
*ptr++='}';
1441-
*ptr='\0';
1373+
appendStringInfoChar(&dst,'}');
14421374

1443-
PG_RETURN_TEXT_P(cstring_to_text(out));
1375+
PG_RETURN_TEXT_P(cstring_to_text(dst.data));
14441376
}

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp