Proposed patch for psql backtick safety - Mailing list pgsql-patches

From Tom Lane
Subject Proposed patch for psql backtick safety
Date
Msg-id 4256.1103398275@sss.pgh.pa.us
Whole thread Raw
List pgsql-patches
Attached is a proposed patch for 8.0 to address the concerns raised
in this thread:
http://archives.postgresql.org/pgsql-bugs/2004-12/msg00189.php

The patch extends the psql lexer to have an additional argument mode
OT_VERBATIM, which is like OT_NORMAL except that backtick and variable
substitutions don't happen.  (Variable substitution is not dangerous
AFAICS, but I thought that this definition might have other uses later.)

Then, it makes two changes in post-backslash-command cleanup:

1. Following a successful command, any "extra" arguments are eaten in
OT_VERBATIM instead of OT_NORMAL mode.  For example, since \t takes
no arguments:

regression=# \t `echo bozo`
Showing only tuples.
\t: extra argument "`echo" ignored
\t: extra argument "bozo`" ignored
regression=#

whereas formerly the backtick command would be evaluated:

regression=# \t `echo bozo`
Showing only tuples.
\t: extra argument "bozo" ignored
regression=#

2. Following an unrecognized or unsuccessful command, the rest of the
line is eaten (in OT_WHOLE_LINE mode, which doesn't do backticks or
variables either).  For example,

regression=# \N `touch bozo`
Invalid command \N. Try \? for help.
regression=# \q
$ ls bozo
bozo not found
$

whereas formerly the backtick command would be evaluated.

Comments, objections?

            regards, tom lane


Index: command.c
===================================================================
RCS file: /cvsroot/pgsql/src/bin/psql/command.c,v
retrieving revision 1.137
diff -c -r1.137 command.c
*** command.c    30 Nov 2004 20:00:34 -0000    1.137
--- command.c    18 Dec 2004 19:18:38 -0000
***************
*** 127,139 ****
          status = CMD_ERROR;
      }

!     /* eat the rest of the options, if any */
!     while ((arg = psql_scan_slash_option(scan_state,
!                                          OT_NORMAL, NULL, false)))
      {
!         if (status != CMD_ERROR)
              psql_error("\\%s: extra argument \"%s\" ignored\n", cmd, arg);
!         free(arg);
      }

      /* if there is a trailing \\, swallow it */
--- 127,149 ----
          status = CMD_ERROR;
      }

!     if (status != CMD_ERROR)
      {
!         /* eat any remaining arguments after a valid command */
!         /* note we suppress evaluation of backticks here */
!         while ((arg = psql_scan_slash_option(scan_state,
!                                              OT_VERBATIM, NULL, false)))
!         {
              psql_error("\\%s: extra argument \"%s\" ignored\n", cmd, arg);
!             free(arg);
!         }
!     }
!     else
!     {
!         /* silently throw away rest of line after an erroneous command */
!         while ((arg = psql_scan_slash_option(scan_state,
!                                              OT_WHOLE_LINE, NULL, false)))
!             free(arg);
      }

      /* if there is a trailing \\, swallow it */
Index: psqlscan.h
===================================================================
RCS file: /cvsroot/pgsql/src/bin/psql/psqlscan.h,v
retrieving revision 1.3
diff -c -r1.3 psqlscan.h
*** psqlscan.h    29 Aug 2004 05:06:54 -0000    1.3
--- psqlscan.h    18 Dec 2004 19:18:38 -0000
***************
*** 32,38 ****
      OT_SQLID,                    /* treat as SQL identifier */
      OT_SQLIDHACK,                /* SQL identifier, but don't downcase */
      OT_FILEPIPE,                /* it's a filename or pipe */
!     OT_WHOLE_LINE                /* just snarf the rest of the line */
  };


--- 32,39 ----
      OT_SQLID,                    /* treat as SQL identifier */
      OT_SQLIDHACK,                /* SQL identifier, but don't downcase */
      OT_FILEPIPE,                /* it's a filename or pipe */
!     OT_WHOLE_LINE,                /* just snarf the rest of the line */
!     OT_VERBATIM                    /* literal (no backticks or variables) */
  };


Index: psqlscan.l
===================================================================
RCS file: /cvsroot/pgsql/src/bin/psql/psqlscan.l,v
retrieving revision 1.7
diff -c -r1.7 psqlscan.l
*** psqlscan.l    29 Aug 2004 04:13:02 -0000    1.7
--- psqlscan.l    18 Dec 2004 19:18:38 -0000
***************
*** 723,746 ****
                  }

  "`"                {
!                     *option_quote = '`';
!                     BEGIN(xslashbackquote);
                  }

  :[A-Za-z0-9_]*    {
                      /* Possible psql variable substitution */
!                     const char *value;

!                     value = GetVariable(pset.vars, yytext + 1);

!                     /*
!                      * The variable value is just emitted without any
!                      * further examination.  This is consistent with the
!                      * pre-8.0 code behavior, if not with the way that
!                      * variables are handled outside backslash commands.
!                      */
!                     if (value)
!                         appendPQExpBufferStr(output_buf, value);

                      *option_quote = ':';

--- 723,760 ----
                  }

  "`"                {
!                     if (option_type == OT_VERBATIM)
!                     {
!                         /* in verbatim mode, backquote is not special */
!                         ECHO;
!                         BEGIN(xslashdefaultarg);
!                     }
!                     else
!                     {
!                         *option_quote = '`';
!                         BEGIN(xslashbackquote);
!                     }
                  }

  :[A-Za-z0-9_]*    {
                      /* Possible psql variable substitution */
!                     if (option_type == OT_VERBATIM)
!                         ECHO;
!                     else
!                     {
!                         const char *value;

!                         value = GetVariable(pset.vars, yytext + 1);

!                         /*
!                          * The variable value is just emitted without any
!                          * further examination.  This is consistent with the
!                          * pre-8.0 code behavior, if not with the way that
!                          * variables are handled outside backslash commands.
!                          */
!                         if (value)
!                             appendPQExpBufferStr(output_buf, value);
!                     }

                      *option_quote = ':';


pgsql-patches by date:

Previous
From: "Ioseph Kim"
Date:
Subject: update korean po messages
Next
From: Bruce Momjian
Date:
Subject: Re: [pgsql-hackers-win32] Patch to add version numbers to