Commit 8a4930e3 authored by Tom Lane's avatar Tom Lane

Fix latent crash in do_text_output_multiline().

do_text_output_multiline() would fail (typically with a null pointer
dereference crash) if its input string did not end with a newline.  Such
cases do not arise in our current sources; but it certainly could happen
in future, or in extension code's usage of the function, so we should fix
it.  To fix, replace "eol += len" with "eol = text + len".

While at it, make two cosmetic improvements: mark the input string const,
and rename the argument from "text" to "txt" to dodge pgindent strangeness
(since "text" is a typedef name).

Even though this problem is only latent at present, it seems like a good
idea to back-patch the fix, since it's a very simple/safe patch and it's
not out of the realm of possibility that we might in future back-patch
something that expects sane behavior from do_text_output_multiline().

Per report from Hao Lee.

Report: <CAGoxFiFPAGyPAJLcFxTB5cGhTW2yOVBDYeqDugYwV4dEd1L_Ag@mail.gmail.com>
parent a50b605a
...@@ -1325,33 +1325,32 @@ do_tup_output(TupOutputState *tstate, Datum *values, bool *isnull) ...@@ -1325,33 +1325,32 @@ do_tup_output(TupOutputState *tstate, Datum *values, bool *isnull)
* Should only be used with a single-TEXT-attribute tupdesc. * Should only be used with a single-TEXT-attribute tupdesc.
*/ */
void void
do_text_output_multiline(TupOutputState *tstate, char *text) do_text_output_multiline(TupOutputState *tstate, const char *txt)
{ {
Datum values[1]; Datum values[1];
bool isnull[1] = {false}; bool isnull[1] = {false};
while (*text) while (*txt)
{ {
char *eol; const char *eol;
int len; int len;
eol = strchr(text, '\n'); eol = strchr(txt, '\n');
if (eol) if (eol)
{ {
len = eol - text; len = eol - txt;
eol++; eol++;
} }
else else
{ {
len = strlen(text); len = strlen(txt);
eol += len; eol = txt + len;
} }
values[0] = PointerGetDatum(cstring_to_text_with_len(text, len)); values[0] = PointerGetDatum(cstring_to_text_with_len(txt, len));
do_tup_output(tstate, values, isnull); do_tup_output(tstate, values, isnull);
pfree(DatumGetPointer(values[0])); pfree(DatumGetPointer(values[0]));
text = eol; txt = eol;
} }
} }
......
...@@ -284,7 +284,7 @@ typedef struct TupOutputState ...@@ -284,7 +284,7 @@ typedef struct TupOutputState
extern TupOutputState *begin_tup_output_tupdesc(DestReceiver *dest, extern TupOutputState *begin_tup_output_tupdesc(DestReceiver *dest,
TupleDesc tupdesc); TupleDesc tupdesc);
extern void do_tup_output(TupOutputState *tstate, Datum *values, bool *isnull); extern void do_tup_output(TupOutputState *tstate, Datum *values, bool *isnull);
extern void do_text_output_multiline(TupOutputState *tstate, char *text); extern void do_text_output_multiline(TupOutputState *tstate, const char *txt);
extern void end_tup_output(TupOutputState *tstate); extern void end_tup_output(TupOutputState *tstate);
/* /*
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment