1
0
mirror of https://github.com/postgres/postgres.git synced 2025-11-19 13:42:17 +03:00

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
This commit is contained in:
Tom Lane
2022-12-12 16:17:49 -05:00
parent 101c37cd34
commit b0feda79fd
5 changed files with 90 additions and 18 deletions

View File

@@ -63,8 +63,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,
@@ -95,8 +96,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,