Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Fix latent crash in do_text_output_multiline().
authorTom Lane <tgl@sss.pgh.pa.us>
Mon, 23 May 2016 18:16:41 +0000 (14:16 -0400)
committerTom Lane <tgl@sss.pgh.pa.us>
Mon, 23 May 2016 18:16:41 +0000 (14:16 -0400)
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>

src/backend/executor/execTuples.c
src/include/executor/executor.h

index c9a3de894d8cbfaa9cfe58b36e120a5f034b9c8b..41a947c3354d6e1e5079c100980cbf1500c46bbf 100644 (file)
@@ -1283,33 +1283,32 @@ do_tup_output(TupOutputState *tstate, Datum *values, bool *isnull)
  * Should only be used with a single-TEXT-attribute tupdesc.
  */
 void
-do_text_output_multiline(TupOutputState *tstate, char *text)
+do_text_output_multiline(TupOutputState *tstate, const char *txt)
 {
    Datum       values[1];
    bool        isnull[1] = {false};
 
-   while (*text)
+   while (*txt)
    {
-       char       *eol;
+       const char *eol;
        int         len;
 
-       eol = strchr(text, '\n');
+       eol = strchr(txt, '\n');
        if (eol)
        {
-           len = eol - text;
-
+           len = eol - txt;
            eol++;
        }
        else
        {
-           len = strlen(text);
-           eol += len;
+           len = strlen(txt);
+           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);
        pfree(DatumGetPointer(values[0]));
-       text = eol;
+       txt = eol;
    }
 }
 
index 2c69db773a66df40c98d4370d1306e78c594b235..61b4ba6410e4801e4d9336f7b7a4e312f66df31a 100644 (file)
@@ -276,7 +276,7 @@ typedef struct TupOutputState
 extern TupOutputState *begin_tup_output_tupdesc(DestReceiver *dest,
                         TupleDesc tupdesc);
 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);
 
 /*