Skip to content

Commit 0b707d6

Browse files
committed
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
1 parent c23bb6b commit 0b707d6

File tree

3 files changed

+26
-22
lines changed

3 files changed

+26
-22
lines changed

src/bin/pgbench/exprscan.l

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -197,7 +197,6 @@ expr_yyerror_more(yyscan_t yyscanner, const char *message, const char *more)
197197
int error_detection_offset = expr_scanner_offset(state) - 1;
198198
YYSTYPE lval;
199199
char *full_line;
200-
size_t l;
201200

202201
/*
203202
* 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)
210209
/* skip */ ;
211210
}
212211

212+
/* Extract the line, trimming trailing newline if any */
213213
full_line = expr_scanner_get_substring(state,
214214
expr_start_offset,
215-
expr_scanner_offset(state));
216-
/* Trim trailing newline if any */
217-
l = strlen(full_line);
218-
while (l > 0 && full_line[l - 1] == '\n')
219-
full_line[--l] = '\0';
215+
expr_scanner_offset(state),
216+
true);
220217

221218
syntax_error(expr_source, expr_lineno, full_line, expr_command,
222219
message, more, error_detection_offset - expr_start_offset);
@@ -341,19 +338,30 @@ expr_scanner_offset(PsqlScanState state)
341338

342339
/*
343340
* Get a malloc'd copy of the lexer input string from start_offset
344-
* to just before end_offset.
341+
* to just before end_offset. If chomp is true, drop any trailing
342+
* newline(s).
345343
*/
346344
char *
347345
expr_scanner_get_substring(PsqlScanState state,
348-
int start_offset, int end_offset)
346+
int start_offset, int end_offset,
347+
bool chomp)
349348
{
350349
char *result;
350+
const char *scanptr = state->scanbuf + start_offset;
351351
int slen = end_offset - start_offset;
352352

353353
Assert(slen >= 0);
354354
Assert(end_offset <= strlen(state->scanbuf));
355+
356+
if (chomp)
357+
{
358+
while (slen > 0 &&
359+
(scanptr[slen - 1] == '\n' || scanptr[slen - 1] == '\r'))
360+
slen--;
361+
}
362+
355363
result = (char *) pg_malloc(slen + 1);
356-
memcpy(result, state->scanbuf + start_offset, slen);
364+
memcpy(result, scanptr, slen);
357365
result[slen] = '\0';
358366

359367
return result;

src/bin/pgbench/pgbench.c

Lines changed: 7 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3065,8 +3065,7 @@ process_backslash_command(PsqlScanState sstate, const char *source)
30653065
PQExpBufferData word_buf;
30663066
int word_offset;
30673067
int offsets[MAX_ARGS]; /* offsets of argument words */
3068-
int start_offset,
3069-
end_offset;
3068+
int start_offset;
30703069
int lineno;
30713070
int j;
30723071

@@ -3120,13 +3119,11 @@ process_backslash_command(PsqlScanState sstate, const char *source)
31203119

31213120
my_command->expr = expr_parse_result;
31223121

3123-
/* Get location of the ending newline */
3124-
end_offset = expr_scanner_offset(sstate) - 1;
3125-
3126-
/* Save line */
3122+
/* Save line, trimming any trailing newline */
31273123
my_command->line = expr_scanner_get_substring(sstate,
31283124
start_offset,
3129-
end_offset);
3125+
expr_scanner_offset(sstate),
3126+
true);
31303127

31313128
expr_scanner_finish(yyscanner);
31323129

@@ -3147,13 +3144,11 @@ process_backslash_command(PsqlScanState sstate, const char *source)
31473144
my_command->argc++;
31483145
}
31493146

3150-
/* Get location of the ending newline */
3151-
end_offset = expr_scanner_offset(sstate) - 1;
3152-
3153-
/* Save line */
3147+
/* Save line, trimming any trailing newline */
31543148
my_command->line = expr_scanner_get_substring(sstate,
31553149
start_offset,
3156-
end_offset);
3150+
expr_scanner_offset(sstate),
3151+
true);
31573152

31583153
if (pg_strcasecmp(my_command->argv[0], "sleep") == 0)
31593154
{

src/bin/pgbench/pgbench.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,8 @@ extern yyscan_t expr_scanner_init(PsqlScanState state,
128128
extern void expr_scanner_finish(yyscan_t yyscanner);
129129
extern int expr_scanner_offset(PsqlScanState state);
130130
extern char *expr_scanner_get_substring(PsqlScanState state,
131-
int start_offset, int end_offset);
131+
int start_offset, int end_offset,
132+
bool chomp);
132133
extern int expr_scanner_get_lineno(PsqlScanState state, int offset);
133134

134135
extern void syntax_error(const char *source, int lineno, const char *line,

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy