@@ -99,6 +99,7 @@ static ArchiveHandle *_allocAH(const char *FileSpec, const ArchiveFormat fmt,
99
99
static void _getObjectDescription (PQExpBuffer buf , TocEntry * te ,
100
100
ArchiveHandle * AH );
101
101
static void _printTocEntry (ArchiveHandle * AH , TocEntry * te , RestoreOptions * ropt , bool isData , bool acl_pass );
102
+ static char * replace_line_endings (const char * str );
102
103
103
104
104
105
static void _doSetFixedOutputState (ArchiveHandle * AH );
@@ -2932,6 +2933,9 @@ _printTocEntry(ArchiveHandle *AH, TocEntry *te, RestoreOptions *ropt, bool isDat
2932
2933
if (!AH -> noTocComments )
2933
2934
{
2934
2935
const char * pfx ;
2936
+ char * sanitized_name ;
2937
+ char * sanitized_schema ;
2938
+ char * sanitized_owner ;
2935
2939
2936
2940
if (isData )
2937
2941
pfx = "Data for " ;
@@ -2953,12 +2957,39 @@ _printTocEntry(ArchiveHandle *AH, TocEntry *te, RestoreOptions *ropt, bool isDat
2953
2957
ahprintf (AH , "\n" );
2954
2958
}
2955
2959
}
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
+
2956
2977
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
+
2960
2985
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
+ }
2962
2993
ahprintf (AH , "\n" );
2963
2994
2964
2995
if (AH -> PrintExtraTocPtr != NULL )
@@ -3053,6 +3084,27 @@ _printTocEntry(ArchiveHandle *AH, TocEntry *te, RestoreOptions *ropt, bool isDat
3053
3084
}
3054
3085
}
3055
3086
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
+
3056
3108
void
3057
3109
WriteHead (ArchiveHandle * AH )
3058
3110
{
0 commit comments