Skip to content

Commit 97de12e

Browse files
authored
Fix history file parsing. (#995)
The previous coding used a statically allocated array of pointers to newlines in that file, limiting our parsing abilities to files of 1024 lines maximum. Apparently that's not a good limit, so use dynamically allocated memory instead. Fixes #991.
1 parent 10c62c2 commit 97de12e

File tree

3 files changed

+49
-6
lines changed

3 files changed

+49
-6
lines changed

src/bin/pg_autoctl/pgsql.c

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3094,18 +3094,18 @@ bool
30943094
parseTimeLineHistory(const char *filename, const char *content,
30953095
IdentifySystem *system)
30963096
{
3097-
char *historyLines[BUFSIZE] = { 0 };
3098-
int lineCount = splitLines((char *) content, historyLines, BUFSIZE);
3097+
int lineCount = countLines((char *) content);
3098+
char **historyLines = (char **) calloc(lineCount, sizeof(char *));
30993099
int lineNumber = 0;
31003100

3101-
if (lineCount >= PG_AUTOCTL_MAX_TIMELINES)
3101+
if (historyLines == NULL)
31023102
{
3103-
log_error("history file \"%s\" contains %d lines, "
3104-
"pg_autoctl only supports up to %d lines",
3105-
filename, lineCount, PG_AUTOCTL_MAX_TIMELINES - 1);
3103+
log_error(ALLOCATION_FAILED_ERROR);
31063104
return false;
31073105
}
31083106

3107+
splitLines((char *) content, historyLines, lineCount);
3108+
31093109
uint64_t prevend = InvalidXLogRecPtr;
31103110

31113111
system->timelines.count = 0;
@@ -3141,6 +3141,7 @@ parseTimeLineHistory(const char *filename, const char *content,
31413141
{
31423142
log_error("Failed to parse history file line %d: \"%s\"",
31433143
lineNumber, ptr);
3144+
free(historyLines);
31443145
return false;
31453146
}
31463147

@@ -3149,6 +3150,7 @@ parseTimeLineHistory(const char *filename, const char *content,
31493150
if (!stringToUInt(historyLines[lineNumber], &(entry->tli)))
31503151
{
31513152
log_error("Failed to parse history timeline \"%s\"", tabptr);
3153+
free(historyLines);
31523154
return false;
31533155
}
31543156

@@ -3167,6 +3169,7 @@ parseTimeLineHistory(const char *filename, const char *content,
31673169
{
31683170
log_error("Failed to parse history timeline %d LSN \"%s\"",
31693171
entry->tli, lsn);
3172+
free(historyLines);
31703173
return false;
31713174
}
31723175

@@ -3184,6 +3187,8 @@ parseTimeLineHistory(const char *filename, const char *content,
31843187
entry = &(system->timelines.history[++system->timelines.count]);
31853188
}
31863189

3190+
free(historyLines);
3191+
31873192
/*
31883193
* Create one more entry for the "tip" of the timeline, which has no entry
31893194
* in the history file.

src/bin/pg_autoctl/string_utils.c

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -495,6 +495,43 @@ IntervalToString(double seconds, char *buffer, size_t size)
495495
}
496496

497497

498+
/*
499+
* countLines returns how many line separators (\n) are found in the given
500+
* string.
501+
*/
502+
int
503+
countLines(char *buffer)
504+
{
505+
int lineNumber = 0;
506+
char *currentLine = buffer;
507+
508+
if (buffer == NULL)
509+
{
510+
return 0;
511+
}
512+
513+
do {
514+
char *newLinePtr = strchr(currentLine, '\n');
515+
516+
if (newLinePtr == NULL)
517+
{
518+
if (strlen(currentLine) > 0)
519+
{
520+
++lineNumber;
521+
}
522+
currentLine = NULL;
523+
}
524+
else
525+
{
526+
++lineNumber;
527+
currentLine = ++newLinePtr;
528+
}
529+
} while (currentLine != NULL && *currentLine != '\0');
530+
531+
return lineNumber;
532+
}
533+
534+
498535
/*
499536
* splitLines prepares a multi-line error message in a way that calling code
500537
* can loop around one line at a time and call log_error() or log_warn() on

src/bin/pg_autoctl/string_utils.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ bool stringToUInt32(const char *str, uint32_t *number);
3737
bool stringToDouble(const char *str, double *number);
3838
bool IntervalToString(double seconds, char *buffer, size_t size);
3939

40+
int countLines(char *buffer);
4041
int splitLines(char *errorMessage, char **linesArray, int size);
4142
void processBufferCallback(const char *buffer, bool error);
4243

0 commit comments

Comments
 (0)