diff --git a/src/backend/utils/adt/arrayfuncs.c b/src/backend/utils/adt/arrayfuncs.c
index 8e46c2fde105ba7b356941aa654886531f56e2eb..6f9b5bfaa956b647ac85b8ce90c9bb78d6744d57 100644
--- a/src/backend/utils/adt/arrayfuncs.c
+++ b/src/backend/utils/adt/arrayfuncs.c
@@ -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];
 
diff --git a/src/test/regress/expected/arrays.out b/src/test/regress/expected/arrays.out
index ea8e2b6e8f9b38bd2006d0959d1f4a7469e2e085..083693ffa947bfa29ce6388c68e7ab60db3c7a80 100644
--- a/src/test/regress/expected/arrays.out
+++ b/src/test/regress/expected/arrays.out
@@ -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
diff --git a/src/test/regress/sql/arrays.sql b/src/test/regress/sql/arrays.sql
index 97cb5bbc075f455ec597ed8d966643d6ee9a8a8a..d9a3252d316025af1df7248a1d735131f092721b 100644
--- a/src/test/regress/sql/arrays.sql
+++ b/src/test/regress/sql/arrays.sql
@@ -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