xmlconcat(NULL) crash

Поиск
Список
Период
Сортировка
От Peter Eisentraut
Тема xmlconcat(NULL) crash
Дата
Msg-id 491D9ACA.4000504@gmx.net
обсуждение исходный текст
Список pgsql-hackers
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,

В списке pgsql-hackers по дате отправления:

Предыдущее
От: "Jonah H. Harris"
Дата:
Сообщение: Re: Simple postgresql.conf wizard
Следующее
От: Tom Lane
Дата:
Сообщение: Re: gram.y => preproc.y