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

Commit68a8ea6

Browse files
committed
Fix memory leaks in record_out() and record_send().
record_out() leaks memory: it fails to free the strings returned by theper-column output functions, and also is careless about detoasted values.This results in a query-lifespan memory leakage when returning compositevalues to the client, because printtup() runs the output functions in thequery-lifespan memory context. Fix it to handle these issues the same wayprinttup() does. Also fix a similar leakage in record_send().(At some point we might want to try to run output functions inshorter-lived memory contexts, so that we don't need a zero-leakage policyfor them. But that would be a significantly more invasive patch, whichdoesn't seem like material for back-patching.)In passing, use appendStringInfoCharMacro instead of appendStringInfoCharin the innermost data-copying loop of record_out, to try to shave a fewcycles from this function's runtime.Per trouble report from Carlos Henrique Reimer. Back-patch to allsupported versions.
1 parentd0d58f7 commit68a8ea6

File tree

1 file changed

+40
-12
lines changed

1 file changed

+40
-12
lines changed

‎src/backend/utils/adt/rowtypes.c

Lines changed: 40 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ typedef struct ColumnIOData
3131
Oidcolumn_type;
3232
Oidtypiofunc;
3333
Oidtypioparam;
34+
booltypisvarlena;
3435
FmgrInfoproc;
3536
}ColumnIOData;
3637

@@ -363,6 +364,7 @@ record_out(PG_FUNCTION_ARGS)
363364
{
364365
ColumnIOData*column_info=&my_extra->columns[i];
365366
Oidcolumn_type=tupdesc->attrs[i]->atttypid;
367+
Datumattr;
366368
char*value;
367369
char*tmp;
368370
boolnq;
@@ -386,17 +388,24 @@ record_out(PG_FUNCTION_ARGS)
386388
*/
387389
if (column_info->column_type!=column_type)
388390
{
389-
booltypIsVarlena;
390-
391391
getTypeOutputInfo(column_type,
392392
&column_info->typiofunc,
393-
&typIsVarlena);
393+
&column_info->typisvarlena);
394394
fmgr_info_cxt(column_info->typiofunc,&column_info->proc,
395395
fcinfo->flinfo->fn_mcxt);
396396
column_info->column_type=column_type;
397397
}
398398

399-
value=OutputFunctionCall(&column_info->proc,values[i]);
399+
/*
400+
* If we have a toasted datum, forcibly detoast it here to avoid
401+
* memory leakage inside the type's output routine.
402+
*/
403+
if (column_info->typisvarlena)
404+
attr=PointerGetDatum(PG_DETOAST_DATUM(values[i]));
405+
else
406+
attr=values[i];
407+
408+
value=OutputFunctionCall(&column_info->proc,attr);
400409

401410
/* Detect whether we need double quotes for this value */
402411
nq= (value[0]=='\0');/* force quotes for empty string */
@@ -415,17 +424,23 @@ record_out(PG_FUNCTION_ARGS)
415424

416425
/* And emit the string */
417426
if (nq)
418-
appendStringInfoChar(&buf,'"');
427+
appendStringInfoCharMacro(&buf,'"');
419428
for (tmp=value;*tmp;tmp++)
420429
{
421430
charch=*tmp;
422431

423432
if (ch=='"'||ch=='\\')
424-
appendStringInfoChar(&buf,ch);
425-
appendStringInfoChar(&buf,ch);
433+
appendStringInfoCharMacro(&buf,ch);
434+
appendStringInfoCharMacro(&buf,ch);
426435
}
427436
if (nq)
428-
appendStringInfoChar(&buf,'"');
437+
appendStringInfoCharMacro(&buf,'"');
438+
439+
pfree(value);
440+
441+
/* Clean up detoasted copy, if any */
442+
if (DatumGetPointer(attr)!=DatumGetPointer(values[i]))
443+
pfree(DatumGetPointer(attr));
429444
}
430445

431446
appendStringInfoChar(&buf,')');
@@ -713,6 +728,7 @@ record_send(PG_FUNCTION_ARGS)
713728
{
714729
ColumnIOData*column_info=&my_extra->columns[i];
715730
Oidcolumn_type=tupdesc->attrs[i]->atttypid;
731+
Datumattr;
716732
bytea*outputbytes;
717733

718734
/* Ignore dropped columns in datatype */
@@ -733,23 +749,35 @@ record_send(PG_FUNCTION_ARGS)
733749
*/
734750
if (column_info->column_type!=column_type)
735751
{
736-
booltypIsVarlena;
737-
738752
getTypeBinaryOutputInfo(column_type,
739753
&column_info->typiofunc,
740-
&typIsVarlena);
754+
&column_info->typisvarlena);
741755
fmgr_info_cxt(column_info->typiofunc,&column_info->proc,
742756
fcinfo->flinfo->fn_mcxt);
743757
column_info->column_type=column_type;
744758
}
745759

746-
outputbytes=SendFunctionCall(&column_info->proc,values[i]);
760+
/*
761+
* If we have a toasted datum, forcibly detoast it here to avoid
762+
* memory leakage inside the type's output routine.
763+
*/
764+
if (column_info->typisvarlena)
765+
attr=PointerGetDatum(PG_DETOAST_DATUM(values[i]));
766+
else
767+
attr=values[i];
768+
769+
outputbytes=SendFunctionCall(&column_info->proc,attr);
747770

748771
/* We assume the result will not have been toasted */
749772
pq_sendint(&buf,VARSIZE(outputbytes)-VARHDRSZ,4);
750773
pq_sendbytes(&buf,VARDATA(outputbytes),
751774
VARSIZE(outputbytes)-VARHDRSZ);
775+
752776
pfree(outputbytes);
777+
778+
/* Clean up detoasted copy, if any */
779+
if (DatumGetPointer(attr)!=DatumGetPointer(values[i]))
780+
pfree(DatumGetPointer(attr));
753781
}
754782

755783
pfree(values);

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp