mirror of
https://github.com/postgres/postgres.git
synced 2025-07-30 11:03:19 +03:00
Be more careful about newline-chomping in pgbench.
process_backslash_command would drop the last character of the input command on the assumption that it was a newline. Given a non newline terminated input file, this could result in dropping the last character of the command. Fix that by doing an actual test that we're removing a newline. While at it, allow for Windows newlines (\r\n), and suppress multiple newlines if any. I do not think either of those cases really occur, since (a) we read script files in text mode and (b) the lexer stops when it hits a newline. But it's cheap enough and it provides a stronger guarantee about what the result string looks like. This is just cosmetic, I think, since the possibly-overly-chomped line was only used for display not for further processing. So it doesn't seem necessary to back-patch. Fabien Coelho, reviewed by Nikolay Shaplov, whacked around a bit by me Discussion: https://postgr.es/m/alpine.DEB.2.20.1704171422500.4025@lancre
This commit is contained in:
@ -197,7 +197,6 @@ expr_yyerror_more(yyscan_t yyscanner, const char *message, const char *more)
|
|||||||
int error_detection_offset = expr_scanner_offset(state) - 1;
|
int error_detection_offset = expr_scanner_offset(state) - 1;
|
||||||
YYSTYPE lval;
|
YYSTYPE lval;
|
||||||
char *full_line;
|
char *full_line;
|
||||||
size_t l;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* While parsing an expression, we may not have collected the whole line
|
* While parsing an expression, we may not have collected the whole line
|
||||||
@ -210,13 +209,11 @@ expr_yyerror_more(yyscan_t yyscanner, const char *message, const char *more)
|
|||||||
/* skip */ ;
|
/* skip */ ;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Extract the line, trimming trailing newline if any */
|
||||||
full_line = expr_scanner_get_substring(state,
|
full_line = expr_scanner_get_substring(state,
|
||||||
expr_start_offset,
|
expr_start_offset,
|
||||||
expr_scanner_offset(state));
|
expr_scanner_offset(state),
|
||||||
/* Trim trailing newline if any */
|
true);
|
||||||
l = strlen(full_line);
|
|
||||||
while (l > 0 && full_line[l - 1] == '\n')
|
|
||||||
full_line[--l] = '\0';
|
|
||||||
|
|
||||||
syntax_error(expr_source, expr_lineno, full_line, expr_command,
|
syntax_error(expr_source, expr_lineno, full_line, expr_command,
|
||||||
message, more, error_detection_offset - expr_start_offset);
|
message, more, error_detection_offset - expr_start_offset);
|
||||||
@ -341,19 +338,30 @@ expr_scanner_offset(PsqlScanState state)
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* Get a malloc'd copy of the lexer input string from start_offset
|
* Get a malloc'd copy of the lexer input string from start_offset
|
||||||
* to just before end_offset.
|
* to just before end_offset. If chomp is true, drop any trailing
|
||||||
|
* newline(s).
|
||||||
*/
|
*/
|
||||||
char *
|
char *
|
||||||
expr_scanner_get_substring(PsqlScanState state,
|
expr_scanner_get_substring(PsqlScanState state,
|
||||||
int start_offset, int end_offset)
|
int start_offset, int end_offset,
|
||||||
|
bool chomp)
|
||||||
{
|
{
|
||||||
char *result;
|
char *result;
|
||||||
|
const char *scanptr = state->scanbuf + start_offset;
|
||||||
int slen = end_offset - start_offset;
|
int slen = end_offset - start_offset;
|
||||||
|
|
||||||
Assert(slen >= 0);
|
Assert(slen >= 0);
|
||||||
Assert(end_offset <= strlen(state->scanbuf));
|
Assert(end_offset <= strlen(state->scanbuf));
|
||||||
|
|
||||||
|
if (chomp)
|
||||||
|
{
|
||||||
|
while (slen > 0 &&
|
||||||
|
(scanptr[slen - 1] == '\n' || scanptr[slen - 1] == '\r'))
|
||||||
|
slen--;
|
||||||
|
}
|
||||||
|
|
||||||
result = (char *) pg_malloc(slen + 1);
|
result = (char *) pg_malloc(slen + 1);
|
||||||
memcpy(result, state->scanbuf + start_offset, slen);
|
memcpy(result, scanptr, slen);
|
||||||
result[slen] = '\0';
|
result[slen] = '\0';
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
|
@ -3065,8 +3065,7 @@ process_backslash_command(PsqlScanState sstate, const char *source)
|
|||||||
PQExpBufferData word_buf;
|
PQExpBufferData word_buf;
|
||||||
int word_offset;
|
int word_offset;
|
||||||
int offsets[MAX_ARGS]; /* offsets of argument words */
|
int offsets[MAX_ARGS]; /* offsets of argument words */
|
||||||
int start_offset,
|
int start_offset;
|
||||||
end_offset;
|
|
||||||
int lineno;
|
int lineno;
|
||||||
int j;
|
int j;
|
||||||
|
|
||||||
@ -3120,13 +3119,11 @@ process_backslash_command(PsqlScanState sstate, const char *source)
|
|||||||
|
|
||||||
my_command->expr = expr_parse_result;
|
my_command->expr = expr_parse_result;
|
||||||
|
|
||||||
/* Get location of the ending newline */
|
/* Save line, trimming any trailing newline */
|
||||||
end_offset = expr_scanner_offset(sstate) - 1;
|
|
||||||
|
|
||||||
/* Save line */
|
|
||||||
my_command->line = expr_scanner_get_substring(sstate,
|
my_command->line = expr_scanner_get_substring(sstate,
|
||||||
start_offset,
|
start_offset,
|
||||||
end_offset);
|
expr_scanner_offset(sstate),
|
||||||
|
true);
|
||||||
|
|
||||||
expr_scanner_finish(yyscanner);
|
expr_scanner_finish(yyscanner);
|
||||||
|
|
||||||
@ -3147,13 +3144,11 @@ process_backslash_command(PsqlScanState sstate, const char *source)
|
|||||||
my_command->argc++;
|
my_command->argc++;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Get location of the ending newline */
|
/* Save line, trimming any trailing newline */
|
||||||
end_offset = expr_scanner_offset(sstate) - 1;
|
|
||||||
|
|
||||||
/* Save line */
|
|
||||||
my_command->line = expr_scanner_get_substring(sstate,
|
my_command->line = expr_scanner_get_substring(sstate,
|
||||||
start_offset,
|
start_offset,
|
||||||
end_offset);
|
expr_scanner_offset(sstate),
|
||||||
|
true);
|
||||||
|
|
||||||
if (pg_strcasecmp(my_command->argv[0], "sleep") == 0)
|
if (pg_strcasecmp(my_command->argv[0], "sleep") == 0)
|
||||||
{
|
{
|
||||||
|
@ -128,7 +128,8 @@ extern yyscan_t expr_scanner_init(PsqlScanState state,
|
|||||||
extern void expr_scanner_finish(yyscan_t yyscanner);
|
extern void expr_scanner_finish(yyscan_t yyscanner);
|
||||||
extern int expr_scanner_offset(PsqlScanState state);
|
extern int expr_scanner_offset(PsqlScanState state);
|
||||||
extern char *expr_scanner_get_substring(PsqlScanState state,
|
extern char *expr_scanner_get_substring(PsqlScanState state,
|
||||||
int start_offset, int end_offset);
|
int start_offset, int end_offset,
|
||||||
|
bool chomp);
|
||||||
extern int expr_scanner_get_lineno(PsqlScanState state, int offset);
|
extern int expr_scanner_get_lineno(PsqlScanState state, int offset);
|
||||||
|
|
||||||
extern void syntax_error(const char *source, int lineno, const char *line,
|
extern void syntax_error(const char *source, int lineno, const char *line,
|
||||||
|
Reference in New Issue
Block a user