@@ -99,6 +99,7 @@ static ArchiveHandle *_allocAH(const char *FileSpec, const ArchiveFormat fmt,
9999static void _getObjectDescription (PQExpBuffer buf , TocEntry * te ,
100100 ArchiveHandle * AH );
101101static void _printTocEntry (ArchiveHandle * AH , TocEntry * te , RestoreOptions * ropt , bool isData , bool acl_pass );
102+ static char * replace_line_endings (const char * str );
102103
103104
104105static void _doSetFixedOutputState (ArchiveHandle * AH );
@@ -2932,6 +2933,9 @@ _printTocEntry(ArchiveHandle *AH, TocEntry *te, RestoreOptions *ropt, bool isDat
29322933 if (!AH -> noTocComments )
29332934 {
29342935 const char * pfx ;
2936+ char * sanitized_name ;
2937+ char * sanitized_schema ;
2938+ char * sanitized_owner ;
29352939
29362940 if (isData )
29372941 pfx = "Data for " ;
@@ -2953,12 +2957,39 @@ _printTocEntry(ArchiveHandle *AH, TocEntry *te, RestoreOptions *ropt, bool isDat
29532957 ahprintf (AH , "\n" );
29542958 }
29552959 }
2960+
2961+ /*
2962+ * Zap any line endings embedded in user-supplied fields, to prevent
2963+ * corruption of the dump (which could, in the worst case, present an
2964+ * SQL injection vulnerability if someone were to incautiously load a
2965+ * dump containing objects with maliciously crafted names).
2966+ */
2967+ sanitized_name = replace_line_endings (te -> tag );
2968+ if (te -> namespace )
2969+ sanitized_schema = replace_line_endings (te -> namespace );
2970+ else
2971+ sanitized_schema = pg_strdup ("-" );
2972+ if (!ropt -> noOwner )
2973+ sanitized_owner = replace_line_endings (te -> owner );
2974+ else
2975+ sanitized_owner = pg_strdup ("-" );
2976+
29562977 ahprintf (AH , "-- %sName: %s; Type: %s; Schema: %s; Owner: %s" ,
2957- pfx , te -> tag , te -> desc ,
2958- te -> namespace ? te -> namespace : "-" ,
2959- ropt -> noOwner ? "-" : te -> owner );
2978+ pfx , sanitized_name , te -> desc , sanitized_schema ,
2979+ sanitized_owner );
2980+
2981+ free (sanitized_name );
2982+ free (sanitized_schema );
2983+ free (sanitized_owner );
2984+
29602985 if (te -> tablespace && !ropt -> noTablespace )
2961- ahprintf (AH , "; Tablespace: %s" , te -> tablespace );
2986+ {
2987+ char * sanitized_tablespace ;
2988+
2989+ sanitized_tablespace = replace_line_endings (te -> tablespace );
2990+ ahprintf (AH , "; Tablespace: %s" , sanitized_tablespace );
2991+ free (sanitized_tablespace );
2992+ }
29622993 ahprintf (AH , "\n" );
29632994
29642995 if (AH -> PrintExtraTocPtr != NULL )
@@ -3053,6 +3084,27 @@ _printTocEntry(ArchiveHandle *AH, TocEntry *te, RestoreOptions *ropt, bool isDat
30533084 }
30543085}
30553086
3087+ /*
3088+ * Sanitize a string to be included in an SQL comment, by replacing any
3089+ * newlines with spaces.
3090+ */
3091+ static char *
3092+ replace_line_endings (const char * str )
3093+ {
3094+ char * result ;
3095+ char * s ;
3096+
3097+ result = pg_strdup (str );
3098+
3099+ for (s = result ; * s != '\0' ; s ++ )
3100+ {
3101+ if (* s == '\n' || * s == '\r' )
3102+ * s = ' ' ;
3103+ }
3104+
3105+ return result ;
3106+ }
3107+
30563108void
30573109WriteHead (ArchiveHandle * AH )
30583110{
0 commit comments