aboutsummaryrefslogtreecommitdiff
path: root/src/backend/utils/adt/jsonb_op.c
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2022-12-12 16:17:49 -0500
committerTom Lane <tgl@sss.pgh.pa.us>2022-12-12 16:17:49 -0500
commita18328bb3395188befc2785dbbe47f0d84baf6d1 (patch)
treeb3a4cb360d7867bbbef0f81caa1f69da76f70e20 /src/backend/utils/adt/jsonb_op.c
parentd43a97ef493a7edc9e03b5dd15870e04a0c38f75 (diff)
downloadpostgresql-a18328bb3395188befc2785dbbe47f0d84baf6d1.tar.gz
postgresql-a18328bb3395188befc2785dbbe47f0d84baf6d1.zip
Fix jsonb subscripting to cope with toasted subscript values.
jsonb_get_element() was incautious enough to use VARDATA() and VARSIZE() directly on an arbitrary text Datum. That of course fails if the Datum is short-header, compressed, or out-of-line. The typical result would be failing to match any element of a jsonb object, though matching the wrong one seems possible as well. setPathObject() was slightly brighter, in that it used VARDATA_ANY and VARSIZE_ANY_EXHDR, but that only kept it out of trouble for short-header Datums. push_path() had the same issue. This could result in faulty subscripted insertions, though keys long enough to cause a problem are likely rare in the wild. Having seen these, I looked around for unsafe usages in the rest of the adt/json* files. There are a couple of places where it's not immediately obvious that the Datum can't be compressed or out-of-line, so I added pg_detoast_datum_packed() to cope if it is. Also, remove some other usages of VARDATA/VARSIZE on Datums we just extracted from a text array. Those aren't actively broken, but they will become so if we ever start allowing short-header array elements, which does not seem like a terribly unreasonable thing to do. In any case they are not great coding examples, and they could also do with comments pointing out that we're assuming we don't need pg_detoast_datum_packed. Per report from exe-dealer@yandex.ru. Patch by me, but thanks to David Johnston for initial investigation. Back-patch to v14 where jsonb subscripting was introduced. Discussion: https://postgr.es/m/205321670615953@mail.yandex.ru
Diffstat (limited to 'src/backend/utils/adt/jsonb_op.c')
-rw-r--r--src/backend/utils/adt/jsonb_op.c10
1 files changed, 6 insertions, 4 deletions
diff --git a/src/backend/utils/adt/jsonb_op.c b/src/backend/utils/adt/jsonb_op.c
index 6e85e5c36b3..758fd7beaae 100644
--- a/src/backend/utils/adt/jsonb_op.c
+++ b/src/backend/utils/adt/jsonb_op.c
@@ -64,8 +64,9 @@ jsonb_exists_any(PG_FUNCTION_ARGS)
continue;
strVal.type = jbvString;
- strVal.val.string.val = VARDATA(key_datums[i]);
- strVal.val.string.len = VARSIZE(key_datums[i]) - VARHDRSZ;
+ /* We rely on the array elements not being toasted */
+ strVal.val.string.val = VARDATA_ANY(key_datums[i]);
+ strVal.val.string.len = VARSIZE_ANY_EXHDR(key_datums[i]);
if (findJsonbValueFromContainer(&jb->root,
JB_FOBJECT | JB_FARRAY,
@@ -97,8 +98,9 @@ jsonb_exists_all(PG_FUNCTION_ARGS)
continue;
strVal.type = jbvString;
- strVal.val.string.val = VARDATA(key_datums[i]);
- strVal.val.string.len = VARSIZE(key_datums[i]) - VARHDRSZ;
+ /* We rely on the array elements not being toasted */
+ strVal.val.string.val = VARDATA_ANY(key_datums[i]);
+ strVal.val.string.len = VARSIZE_ANY_EXHDR(key_datums[i]);
if (findJsonbValueFromContainer(&jb->root,
JB_FOBJECT | JB_FARRAY,