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);