Due to some code reshuffling, xmlconcat(NULL) will crash in 8.3 and 8.4. The pfree(buf.data) in ExecEvalXml() frees a buffer that is actuall only initialized in the XMLFOREST case. So then the xmlconcat(NULL) falls through to the pfree() it crashes. I have attached a patch for 8.3 and 8.4 to clean this up.
diff -cr ../cvs-pgsql/src/backend/executor/execQual.c 
./src/backend/executor/execQual.c
*** ../cvs-pgsql/src/backend/executor/execQual.c        2008-11-03 
16:31:21.000000000 +0200
--- ./src/backend/executor/execQual.c   2008-11-14 16:31:52.000000000 +0200
***************
*** 3163,3175 ****
                        bool *isNull, ExprDoneCond *isDone)
  {
        XmlExpr    *xexpr = (XmlExpr *) xmlExpr->xprstate.expr;
-       text       *result;
-       StringInfoData buf;
        Datum           value;
        bool            isnull;
        ListCell   *arg;
        ListCell   *narg;
-       int                     i;
  
        if (isDone)
                *isDone = ExprSingleResult;
--- 3163,3172 ----
***************
*** 3195,3206 ****
                                        *isNull = false;
                                        return 
PointerGetDatum(xmlconcat(values));
                                }
                        }
                        break;
  
                case IS_XMLFOREST:
                        initStringInfo(&buf);
-                       i = 0;
                        forboth(arg, xmlExpr->named_args, narg, 
xexpr->arg_names)
                        {
                                ExprState  *e = (ExprState *) lfirst(arg);
--- 3192,3207 ----
                                        *isNull = false;
                                        return 
PointerGetDatum(xmlconcat(values));
                                }
+                               else
+                                       return (Datum) 0;
                        }
                        break;
  
                case IS_XMLFOREST:
+               {
+                       StringInfoData buf;
+ 
                        initStringInfo(&buf);
                        forboth(arg, xmlExpr->named_args, narg, 
xexpr->arg_names)
                        {
                                ExprState  *e = (ExprState *) lfirst(arg);
***************
*** 3215,3225 ****
                                                                         
argname);
                                        *isNull = false;
                                }
-                               i++;
                        }
                        break;
  
-                       /* The remaining cases don't need to set up buf */
                case IS_XMLELEMENT:
                        *isNull = false;
                        return PointerGetDatum(xmlelement(xmlExpr, econtext));
--- 3216,3240 ----
                                                                         
argname);
                                        *isNull = false;
                                }
                        }
+ 
+                       if (*isNull)
+                       {
+                               pfree(buf.data);
+                               return (Datum) 0;
+                       }
+                       else
+                       {
+                               text       *result;
+ 
+                               result = cstring_to_text_with_len(buf.data, 
buf.len);
+                               pfree(buf.data);
+ 
+                               return PointerGetDatum(result);
+                       }
+               }
                        break;
  
                case IS_XMLELEMENT:
                        *isNull = false;
                        return PointerGetDatum(xmlelement(xmlExpr, econtext));
***************
*** 3354,3366 ****
                        break;
        }
  
!       if (*isNull)
!               result = NULL;
!       else
!               result = cstring_to_text_with_len(buf.data, buf.len);
! 
!       pfree(buf.data);
!       return PointerGetDatum(result);
  }
  
  /* ----------------------------------------------------------------
--- 3369,3376 ----
                        break;
        }
  
!       elog(ERROR, "unrecognized XML operation");
!       return (Datum) 0;
  }
  
  /* ----------------------------------------------------------------
diff -cr ../cvs-pgsql/src/test/regress/expected/xml.out 
./src/test/regress/expected/xml.out
*** ../cvs-pgsql/src/test/regress/expected/xml.out      2008-09-02 
15:11:11.000000000 +0300
--- ./src/test/regress/expected/xml.out 2008-11-14 16:50:02.000000000 +0200
***************
*** 77,82 ****
--- 77,94 ----
   <?xml version="1.1"?><foo/><bar/>
  (1 row)
  
+ SELECT xmlconcat(NULL);
+  xmlconcat 
+ -----------
+  
+ (1 row)
+ 
+ SELECT xmlconcat(NULL, NULL);
+  xmlconcat 
+ -----------
+  
+ (1 row)
+ 
  SELECT xmlelement(name element,
                    xmlattributes (1 as one, 'deuce' as two),
                    'content');
diff -cr ../cvs-pgsql/src/test/regress/expected/xml_1.out 
./src/test/regress/expected/xml_1.out
*** ../cvs-pgsql/src/test/regress/expected/xml_1.out    2008-09-02 
15:11:11.000000000 +0300
--- ./src/test/regress/expected/xml_1.out       2008-11-14 16:50:16.000000000 
+0200
***************
*** 79,84 ****
--- 79,96 ----
                           ^
  DETAIL:  This functionality requires the server to be built with libxml 
support.
  HINT:  You need to rebuild PostgreSQL using --with-libxml.
+ SELECT xmlconcat(NULL);
+  xmlconcat 
+ -----------
+  
+ (1 row)
+ 
+ SELECT xmlconcat(NULL, NULL);
+  xmlconcat 
+ -----------
+  
+ (1 row)
+ 
  SELECT xmlelement(name element,
                    xmlattributes (1 as one, 'deuce' as two),
                    'content');
diff -cr ../cvs-pgsql/src/test/regress/sql/xml.sql 
./src/test/regress/sql/xml.sql
*** ../cvs-pgsql/src/test/regress/sql/xml.sql   2007-11-09 17:52:51.000000000 
+0200
--- ./src/test/regress/sql/xml.sql      2008-11-14 16:49:41.000000000 +0200
***************
*** 26,31 ****
--- 26,33 ----
  SELECT xmlconcat('bad', '<syntax');
  SELECT xmlconcat('<foo/>', NULL, '<?xml version="1.1" 
standalone="no"?><bar/>');
  SELECT xmlconcat('<?xml version="1.1"?><foo/>', NULL, '<?xml version="1.1" 
standalone="no"?><bar/>');
+ SELECT xmlconcat(NULL);
+ SELECT xmlconcat(NULL, NULL);
  
  
  SELECT xmlelement(name element,
diff -cr ../cvs-pgsql/src/backend/executor/execQual.c 
./src/backend/executor/execQual.c
*** ../cvs-pgsql/src/backend/executor/execQual.c        2008-09-04 
15:15:17.000000000 +0300
--- ./src/backend/executor/execQual.c   2008-11-14 15:57:59.000000000 +0200
***************
*** 2848,2860 ****
                        bool *isNull, ExprDoneCond *isDone)
  {
        XmlExpr    *xexpr = (XmlExpr *) xmlExpr->xprstate.expr;
-       text       *result;
-       StringInfoData buf;
        Datum           value;
        bool            isnull;
        ListCell   *arg;
        ListCell   *narg;
-       int                     i;
  
        if (isDone)
                *isDone = ExprSingleResult;
--- 2848,2857 ----
***************
*** 2880,2891 ****
                                        *isNull = false;
                                        return 
PointerGetDatum(xmlconcat(values));
                                }
                        }
                        break;
  
                case IS_XMLFOREST:
                        initStringInfo(&buf);
-                       i = 0;
                        forboth(arg, xmlExpr->named_args, narg, 
xexpr->arg_names)
                        {
                                ExprState  *e = (ExprState *) lfirst(arg);
--- 2877,2892 ----
                                        *isNull = false;
                                        return 
PointerGetDatum(xmlconcat(values));
                                }
+                               else
+                                       return (Datum) 0;
                        }
                        break;
  
                case IS_XMLFOREST:
+               {
+                       StringInfoData buf;
+ 
                        initStringInfo(&buf);
                        forboth(arg, xmlExpr->named_args, narg, 
xexpr->arg_names)
                        {
                                ExprState  *e = (ExprState *) lfirst(arg);
***************
*** 2900,2910 ****
                                                                         
argname);
                                        *isNull = false;
                                }
-                               i++;
                        }
                        break;
  
-                       /* The remaining cases don't need to set up buf */
                case IS_XMLELEMENT:
                        *isNull = false;
                        return PointerGetDatum(xmlelement(xmlExpr, econtext));
--- 2901,2930 ----
                                                                         
argname);
                                        *isNull = false;
                                }
                        }
+ 
+                       if (*isNull)
+                       {
+                               pfree(buf.data);
+                               return (Datum) 0;
+                       }
+                       else
+                       {
+                               int                     len;
+                               text       *result;
+ 
+                               len = buf.len + VARHDRSZ;
+ 
+                               result = palloc(len);
+                               SET_VARSIZE(result, len);
+                               memcpy(VARDATA(result), buf.data, buf.len);
+                               pfree(buf.data);
+ 
+                               return PointerGetDatum(result);
+                       }
+               }
                        break;
  
                case IS_XMLELEMENT:
                        *isNull = false;
                        return PointerGetDatum(xmlelement(xmlExpr, econtext));
***************
*** 3039,3057 ****
                        break;
        }
  
!       if (*isNull)
!               result = NULL;
!       else
!       {
!               int                     len = buf.len + VARHDRSZ;
! 
!               result = palloc(len);
!               SET_VARSIZE(result, len);
!               memcpy(VARDATA(result), buf.data, buf.len);
!       }
! 
!       pfree(buf.data);
!       return PointerGetDatum(result);
  }
  
  /* ----------------------------------------------------------------
--- 3059,3066 ----
                        break;
        }
  
!       elog(ERROR, "unrecognized XML operation");
!       return (Datum) 0;
  }
  
  /* ----------------------------------------------------------------
diff -cr ../cvs-pgsql/src/test/regress/expected/xml.out 
./src/test/regress/expected/xml.out
*** ../cvs-pgsql/src/test/regress/expected/xml.out      2008-09-04 
15:15:55.000000000 +0300
--- ./src/test/regress/expected/xml.out 2008-11-14 16:48:59.000000000 +0200
***************
*** 71,76 ****
--- 71,88 ----
   <?xml version="1.1"?><foo/><bar/>
  (1 row)
  
+ SELECT xmlconcat(NULL);
+  xmlconcat 
+ -----------
+  
+ (1 row)
+ 
+ SELECT xmlconcat(NULL, NULL);
+  xmlconcat 
+ -----------
+  
+ (1 row)
+ 
  SELECT xmlelement(name element,
                    xmlattributes (1 as one, 'deuce' as two),
                    'content');
diff -cr ../cvs-pgsql/src/test/regress/expected/xml_1.out 
./src/test/regress/expected/xml_1.out
*** ../cvs-pgsql/src/test/regress/expected/xml_1.out    2008-09-04 
15:15:55.000000000 +0300
--- ./src/test/regress/expected/xml_1.out       2008-11-14 16:49:19.000000000 
+0200
***************
*** 63,68 ****
--- 63,80 ----
  ERROR:  unsupported XML feature
  DETAIL:  This functionality requires the server to be built with libxml 
support.
  HINT:  You need to rebuild PostgreSQL using --with-libxml.
+ SELECT xmlconcat(NULL);
+  xmlconcat 
+ -----------
+  
+ (1 row)
+ 
+ SELECT xmlconcat(NULL, NULL);
+  xmlconcat 
+ -----------
+  
+ (1 row)
+ 
  SELECT xmlelement(name element,
                    xmlattributes (1 as one, 'deuce' as two),
                    'content');
diff -cr ../cvs-pgsql/src/test/regress/sql/xml.sql 
./src/test/regress/sql/xml.sql
*** ../cvs-pgsql/src/test/regress/sql/xml.sql   2007-11-09 17:52:51.000000000 
+0200
--- ./src/test/regress/sql/xml.sql      2008-11-14 16:48:31.000000000 +0200
***************
*** 26,31 ****
--- 26,33 ----
  SELECT xmlconcat('bad', '<syntax');
  SELECT xmlconcat('<foo/>', NULL, '<?xml version="1.1" 
standalone="no"?><bar/>');
  SELECT xmlconcat('<?xml version="1.1"?><foo/>', NULL, '<?xml version="1.1" 
standalone="no"?><bar/>');
+ SELECT xmlconcat(NULL);
+ SELECT xmlconcat(NULL, NULL);
  
  
  SELECT xmlelement(name element,
-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

Reply via email to