]> granicus.if.org Git - postgresql/commitdiff
Be more careful about newline-chomping in pgbench.
authorTom Lane <tgl@sss.pgh.pa.us>
Mon, 4 Sep 2017 21:25:31 +0000 (17:25 -0400)
committerTom Lane <tgl@sss.pgh.pa.us>
Mon, 4 Sep 2017 21:25:31 +0000 (17:25 -0400)
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

src/bin/pgbench/exprscan.l
src/bin/pgbench/pgbench.c
src/bin/pgbench/pgbench.h

index 1862fe40302b25cba5cd6e13c7e0a34a00748bae..9bf6d237f570c3dcf0078ee22f827a0a9b6adac0 100644 (file)
@@ -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;
        YYSTYPE         lval;
        char       *full_line;
-       size_t          l;
 
        /*
         * 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 */ ;
        }
 
+       /* Extract the line, trimming trailing newline if any */
        full_line = expr_scanner_get_substring(state,
                                                                                   expr_start_offset,
-                                                                                  expr_scanner_offset(state));
-       /* Trim trailing newline if any */
-       l = strlen(full_line);
-       while (l > 0 && full_line[l - 1] == '\n')
-               full_line[--l] = '\0';
+                                                                                  expr_scanner_offset(state),
+                                                                                  true);
 
        syntax_error(expr_source, expr_lineno, full_line, expr_command,
                                 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
- * to just before end_offset.
+ * to just before end_offset.  If chomp is true, drop any trailing
+ * newline(s).
  */
 char *
 expr_scanner_get_substring(PsqlScanState state,
-                                                  int start_offset, int end_offset)
+                                                  int start_offset, int end_offset,
+                                                  bool chomp)
 {
        char       *result;
+       const char *scanptr = state->scanbuf + start_offset;
        int                     slen = end_offset - start_offset;
 
        Assert(slen >= 0);
        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);
-       memcpy(result, state->scanbuf + start_offset, slen);
+       memcpy(result, scanptr, slen);
        result[slen] = '\0';
 
        return result;
index 364e25447e431330aab526e989eb28ffe6366ab6..e37496c971459f07ecae968a8d48bf3cd038b7ad 100644 (file)
@@ -3065,8 +3065,7 @@ process_backslash_command(PsqlScanState sstate, const char *source)
        PQExpBufferData word_buf;
        int                     word_offset;
        int                     offsets[MAX_ARGS];      /* offsets of argument words */
-       int                     start_offset,
-                               end_offset;
+       int                     start_offset;
        int                     lineno;
        int                     j;
 
@@ -3120,13 +3119,11 @@ process_backslash_command(PsqlScanState sstate, const char *source)
 
                my_command->expr = expr_parse_result;
 
-               /* Get location of the ending newline */
-               end_offset = expr_scanner_offset(sstate) - 1;
-
-               /* Save line */
+               /* Save line, trimming any trailing newline */
                my_command->line = expr_scanner_get_substring(sstate,
                                                                                                          start_offset,
-                                                                                                         end_offset);
+                                                                                                         expr_scanner_offset(sstate),
+                                                                                                         true);
 
                expr_scanner_finish(yyscanner);
 
@@ -3147,13 +3144,11 @@ process_backslash_command(PsqlScanState sstate, const char *source)
                my_command->argc++;
        }
 
-       /* Get location of the ending newline */
-       end_offset = expr_scanner_offset(sstate) - 1;
-
-       /* Save line */
+       /* Save line, trimming any trailing newline */
        my_command->line = expr_scanner_get_substring(sstate,
                                                                                                  start_offset,
-                                                                                                 end_offset);
+                                                                                                 expr_scanner_offset(sstate),
+                                                                                                 true);
 
        if (pg_strcasecmp(my_command->argv[0], "sleep") == 0)
        {
index abc13e9463423714ac70968a4fd8e243b4d995e5..fd428af274f26e98e611b4f5e7fdcce6c2a76b5b 100644 (file)
@@ -128,7 +128,8 @@ extern yyscan_t expr_scanner_init(PsqlScanState state,
 extern void expr_scanner_finish(yyscan_t yyscanner);
 extern int     expr_scanner_offset(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 void syntax_error(const char *source, int lineno, const char *line,