From 903127e896428a76d2c93445fadd960b5c9f477b Mon Sep 17 00:00:00 2001 From: Georgios Kokolatos Date: Fri, 31 Jul 2020 08:17:02 +0000 Subject: [PATCH] Add and use a heap allocated string version of replace_string in pg_regress The exposed function replase_string() in pg_regress assumes that there exists enough space in the string it operates on. While this is documented and expected, the consequence can be subtle failures in the tests which might be hard to trace back to the root cause. Provide an alternative function that operates on a heap allocated string instead. The string regrows if needed and the new size can be used for subsequent reads. Co-authored-by: Asim R P --- src/test/regress/pg_regress.c | 58 ++++++++++++++++++++++++++++++----- 1 file changed, 51 insertions(+), 7 deletions(-) diff --git a/src/test/regress/pg_regress.c b/src/test/regress/pg_regress.c index d82e0189dc..5701c80e42 100644 --- a/src/test/regress/pg_regress.c +++ b/src/test/regress/pg_regress.c @@ -434,6 +434,40 @@ string_matches_pattern(const char *str, const char *pattern) return false; } +/* + * Replace all occurrences of a string in a string with a different string. + * + * The string grows if there is not enough space. + */ +static char * +replace_string_heap(char *string, size_t *stringlen, + const char *replace, const char *replacement) +{ + ssize_t overflowlen; + char *ptr; + + overflowlen = strlen(replacement) - strlen(replace); + while ((ptr = strstr(string, replace)) != NULL) + { + char *dup = pg_strdup(string); + + if (overflowlen > 0 && + ((ptr + strlen(ptr) + overflowlen) > (string + *stringlen - 1))) + { + *stringlen *= 2; + string = realloc(string, *stringlen); + ptr = strstr(string, replace); + } + + strlcpy(string, dup, ptr - string + 1); + strcat(string, replacement); + strcat(string, dup + (ptr - string) + strlen(replace)); + free(dup); + } + + return string; +} + /* * Replace all occurrences of a string in a string with a different string. * NOTE: Assumes there is enough room in the target buffer! @@ -521,7 +555,8 @@ convert_sourcefiles_in(const char *source_subdir, const char *dest_dir, const ch char prefix[MAXPGPATH]; FILE *infile, *outfile; - char line[1024]; + char *line; + size_t linelen; /* reject filenames not finishing in ".source" */ if (strlen(*name) < 8) @@ -551,15 +586,24 @@ convert_sourcefiles_in(const char *source_subdir, const char *dest_dir, const ch progname, destfile, strerror(errno)); exit(2); } - while (fgets(line, sizeof(line), infile)) + + linelen = 1024; + line = malloc(linelen); + while (fgets(line, linelen, infile)) { - replace_string(line, "@abs_srcdir@", inputdir); - replace_string(line, "@abs_builddir@", outputdir); - replace_string(line, "@testtablespace@", testtablespace); - replace_string(line, "@libdir@", dlpath); - replace_string(line, "@DLSUFFIX@", DLSUFFIX); + line = replace_string_heap(line, &linelen, + "@abs_srcdir@", inputdir); + line = replace_string_heap(line, &linelen, + "@abs_builddir@", outputdir); + line = replace_string_heap(line, &linelen, + "@testtablespace@", testtablespace); + line = replace_string_heap(line, &linelen, + "@libdir@", dlpath); + line = replace_string_heap(line, &linelen, + "@DLSUFFIX@", DLSUFFIX); fputs(line, outfile); } + free(line); fclose(infile); fclose(outfile); } -- 2.25.1