]> git.ipfire.org Git - thirdparty/postgresql.git/commitdiff
Further tightening of the array literal parser. Prevent junk
authorJoe Conway <mail@joeconway.com>
Sat, 28 Aug 2004 19:31:29 +0000 (19:31 +0000)
committerJoe Conway <mail@joeconway.com>
Sat, 28 Aug 2004 19:31:29 +0000 (19:31 +0000)
from being accepted after the outer right brace. Per report from
Markus Bertheau.

Also add regression test cases for this change, and for previous
recent array literal parser changes.

src/backend/utils/adt/arrayfuncs.c
src/test/regress/expected/arrays.out
src/test/regress/sql/arrays.sql

index 8e46c2fde105ba7b356941aa654886531f56e2eb..6f9b5bfaa956b647ac85b8ce90c9bb78d6744d57 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/utils/adt/arrayfuncs.c,v 1.107 2004/08/08 05:01:55 joe Exp $
+ *       $PostgreSQL: pgsql/src/backend/utils/adt/arrayfuncs.c,v 1.108 2004/08/28 19:31:28 joe Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -183,9 +183,7 @@ array_in(PG_FUNCTION_ARGS)
        typioparam = my_extra->typioparam;
 
        /* Make a modifiable copy of the input */
-       /* XXX why are we allocating an extra 2 bytes here? */
-       string_save = (char *) palloc(strlen(string) + 3);
-       strcpy(string_save, string);
+       string_save = pstrdup(string);
 
        /*
         * If the input string starts with dimension info, read and use that.
@@ -375,6 +373,7 @@ ArrayCount(char *str, int *dim, char typdelim)
                                        nelems_last[MAXDIM];
        bool                    scanning_string = false;
        bool                    eoArray = false;
+       bool                    empty_array = true;
        char               *ptr;
        ArrayParseState parse_state = ARRAY_NO_LEVEL;
 
@@ -385,7 +384,7 @@ ArrayCount(char *str, int *dim, char typdelim)
        }
 
        /* special case for an empty array */
-       if (strncmp(str, "{}", 2) == 0)
+       if (strcmp(str, "{}") == 0)
                return 0;
 
        ptr = str;
@@ -395,6 +394,10 @@ ArrayCount(char *str, int *dim, char typdelim)
 
                while (!itemdone)
                {
+                       if (parse_state == ARRAY_ELEM_STARTED ||
+                               parse_state == ARRAY_QUOTED_ELEM_STARTED)
+                               empty_array = false;
+                       
                        switch (*ptr)
                        {
                                case '\0':
@@ -481,7 +484,8 @@ ArrayCount(char *str, int *dim, char typdelim)
                                                if (parse_state != ARRAY_ELEM_STARTED &&
                                                        parse_state != ARRAY_ELEM_COMPLETED &&
                                                        parse_state != ARRAY_QUOTED_ELEM_COMPLETED &&
-                                                       parse_state != ARRAY_LEVEL_COMPLETED)
+                                                       parse_state != ARRAY_LEVEL_COMPLETED &&
+                                                       !(nest_level == 1 &&  parse_state == ARRAY_LEVEL_STARTED))
                                                        ereport(ERROR,
                                                                (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
                                                                errmsg("malformed array literal: \"%s\"", str)));
@@ -562,6 +566,20 @@ ArrayCount(char *str, int *dim, char typdelim)
                temp[ndim - 1]++;
                ptr++;
        }
+       
+       /* only whitespace is allowed after the closing brace */
+       while (*ptr)
+       {
+               if (!isspace(*ptr++))
+                       ereport(ERROR,
+                               (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
+                               errmsg("malformed array literal: \"%s\"", str)));
+       }
+       
+       /* special case for an empty array */
+       if (empty_array)
+               return 0;
+               
        for (i = 0; i < ndim; ++i)
                dim[i] = temp[i];
 
index ea8e2b6e8f9b38bd2006d0959d1f4a7469e2e085..083693ffa947bfa29ce6388c68e7ab60db3c7a80 100644 (file)
@@ -425,3 +425,61 @@ select 'foo' ilike all (array['F%', '%O']); -- t
  t
 (1 row)
 
+--
+-- General array parser tests
+--
+-- none of the following should be accepted
+select '{{1,{2}},{2,3}}'::text[];
+ERROR:  malformed array literal: "{{1,{2}},{2,3}}"
+select '{{},{}}'::text[];
+ERROR:  malformed array literal: "{{},{}}"
+select '{{1,2},\\{2,3}}'::text[];
+ERROR:  malformed array literal: "{{1,2},\{2,3}}"
+select '{{"1 2" x},{3}}'::text[];
+ERROR:  malformed array literal: "{{"1 2" x},{3}}"
+select '{}}'::text[];
+ERROR:  malformed array literal: "{}}"
+select '{ }}'::text[];
+ERROR:  malformed array literal: "{ }}"
+-- none of the above should be accepted
+-- all of the following should be accepted
+select '{}'::text[];
+ text 
+------
+ {}
+(1 row)
+
+select '{{{1,2,3,4},{2,3,4,5}},{{3,4,5,6},{4,5,6,7}}}'::text[];
+                     text                      
+-----------------------------------------------
+ {{{1,2,3,4},{2,3,4,5}},{{3,4,5,6},{4,5,6,7}}}
+(1 row)
+
+select '{0 second  ,0 second}'::interval[];
+   interval    
+---------------
+ {"@ 0","@ 0"}
+(1 row)
+
+select '{ { "," } , { 3 } }'::text[];
+    text     
+-------------
+ {{","},{3}}
+(1 row)
+
+select '  {   {  "  0 second  "   ,  0 second  }   }'::text[];
+             text              
+-------------------------------
+ {{"  0 second  ","0 second"}}
+(1 row)
+
+select '{
+           0 second,
+           @ 1 hour @ 42 minutes @ 20 seconds
+         }'::interval[];
+              interval              
+------------------------------------
+ {"@ 0","@ 1 hour 42 mins 20 secs"}
+(1 row)
+
+-- all of the above should be accepted
index 97cb5bbc075f455ec597ed8d966643d6ee9a8a8a..d9a3252d316025af1df7248a1d735131f092721b 100644 (file)
@@ -192,3 +192,28 @@ select 'foo' not like any (array['%a', '%b']); -- t
 select 'foo' not like all (array['%a', '%o']); -- f
 select 'foo' ilike any (array['%A', '%O']); -- t
 select 'foo' ilike all (array['F%', '%O']); -- t
+
+--
+-- General array parser tests
+--
+
+-- none of the following should be accepted
+select '{{1,{2}},{2,3}}'::text[];
+select '{{},{}}'::text[];
+select '{{1,2},\\{2,3}}'::text[];
+select '{{"1 2" x},{3}}'::text[];
+select '{}}'::text[];
+select '{ }}'::text[];
+-- none of the above should be accepted
+
+-- all of the following should be accepted
+select '{}'::text[];
+select '{{{1,2,3,4},{2,3,4,5}},{{3,4,5,6},{4,5,6,7}}}'::text[];
+select '{0 second  ,0 second}'::interval[];
+select '{ { "," } , { 3 } }'::text[];
+select '  {   {  "  0 second  "   ,  0 second  }   }'::text[];
+select '{
+           0 second,
+           @ 1 hour @ 42 minutes @ 20 seconds
+         }'::interval[];
+-- all of the above should be accepted