Only allow returning string types or bytea from json_serialize
authorAndrew Dunstan <andrew@dunslane.net>
Thu, 7 Jul 2022 21:40:02 +0000 (17:40 -0400)
committerAndrew Dunstan <andrew@dunslane.net>
Thu, 7 Jul 2022 21:40:02 +0000 (17:40 -0400)
These are documented to be the allowed types for the RETURNING clause,
but the restriction was not being enforced, which caused a segfault if
another type was specified. Add some testing for this.

Per report from a.kozhemyakin

Backpatch to release 15.

src/backend/parser/parse_expr.c
src/test/regress/expected/sqljson.out
src/test/regress/sql/sqljson.sql

index 0dc2fc472e58020821d9f521d555d6d585daf578..efcf1cd5abc0a31bc2ab04f3eee0b7ca6566c1a3 100644 (file)
@@ -4574,7 +4574,24 @@ transformJsonSerializeExpr(ParseState *pstate, JsonSerializeExpr *expr)
    JsonReturning *returning;
 
    if (expr->output)
+   {
        returning = transformJsonOutput(pstate, expr->output, true);
+
+       if (returning->typid != BYTEAOID)
+       {
+           char        typcategory;
+           bool        typispreferred;
+
+           get_type_category_preferred(returning->typid, &typcategory,
+                                       &typispreferred);
+           if (typcategory != TYPCATEGORY_STRING)
+               ereport(ERROR,
+                       (errcode(ERRCODE_DATATYPE_MISMATCH),
+                        errmsg("cannot use RETURNING type %s in JSON_SERIALIZE",
+                               format_type_be(returning->typid)),
+                        errhint("Try returning a string type or bytea")));
+       }
+   }
    else
    {
        /* RETURNING TEXT FORMAT JSON is by default */
index 0883261535d8697f171209e03d653a1c7edc9a4c..be27bce9d32032b9d1661e6bf0391904d1b5d610 100644 (file)
@@ -302,12 +302,22 @@ SELECT JSON_SERIALIZE('{ "a" : 1 } ' RETURNING bytea);
  \x7b20226122203a2031207d20
 (1 row)
 
+SELECT JSON_SERIALIZE('{ "a" : 1 } ' RETURNING varchar);
+ json_serialize 
+----------------
+ { "a" : 1 } 
+(1 row)
+
 SELECT pg_typeof(JSON_SERIALIZE(NULL));
  pg_typeof 
 -----------
  text
 (1 row)
 
+-- only string types or bytea allowed
+SELECT JSON_SERIALIZE('{ "a" : 1 } ' RETURNING jsonb);
+ERROR:  cannot use RETURNING type jsonb in JSON_SERIALIZE
+HINT:  Try returning a string type or bytea
 EXPLAIN (VERBOSE, COSTS OFF) SELECT JSON_SERIALIZE('{}');
                      QUERY PLAN                      
 -----------------------------------------------------
index 3db81a7ba861bd6fecb951325695aeacc69a08ef..c2742b40f1df0a07ed85dc04149a5ff60ebf0696 100644 (file)
@@ -60,8 +60,13 @@ SELECT JSON_SERIALIZE('{ "a" : 1 } ');
 SELECT JSON_SERIALIZE('1');
 SELECT JSON_SERIALIZE('1' FORMAT JSON);
 SELECT JSON_SERIALIZE('{ "a" : 1 } ' RETURNING bytea);
+SELECT JSON_SERIALIZE('{ "a" : 1 } ' RETURNING varchar);
 SELECT pg_typeof(JSON_SERIALIZE(NULL));
 
+-- only string types or bytea allowed
+SELECT JSON_SERIALIZE('{ "a" : 1 } ' RETURNING jsonb);
+
+
 EXPLAIN (VERBOSE, COSTS OFF) SELECT JSON_SERIALIZE('{}');
 EXPLAIN (VERBOSE, COSTS OFF) SELECT JSON_SERIALIZE('{}' RETURNING bytea);