Skip to content

Commit 5302760

Browse files
committed
Unpack jbvBinary objects passed to pushJsonbValue
pushJsonbValue was accepting jbvBinary objects passed as WJB_ELEM or WJB_VALUE data. While this succeeded, when those objects were later encountered in attempting to convert the result to Jsonb, errors occurred. With this change we ghuarantee that a JSonbValue constructed from calls to pushJsonbValue does not contain any jbvBinary objects. This cures a problem observed with jsonb_delete. This means callers of pushJsonbValue no longer need to perform this unpacking themselves. A subsequent patch will perform some cleanup in that area. The error was not triggered by any 9.4 code, but this is a publicly visible routine, and so the error could be exercised by third party code, therefore backpatch to 9.4. Bug report from Peter Geoghegan, fix by me.
1 parent 6d1733f commit 5302760

File tree

2 files changed

+40
-6
lines changed

2 files changed

+40
-6
lines changed

src/backend/utils/adt/jsonb_util.c

Lines changed: 39 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,9 @@ static void appendElement(JsonbParseState *pstate, JsonbValue *scalarVal);
5757
static int lengthCompareJsonbStringValue(const void *a, const void *b);
5858
static int lengthCompareJsonbPair(const void *a, const void *b, void *arg);
5959
static void uniqueifyJsonbObject(JsonbValue *object);
60+
static JsonbValue *pushJsonbValueScalar(JsonbParseState **pstate,
61+
JsonbIteratorToken seq,
62+
JsonbValue *scalarVal);
6063

6164
/*
6265
* Turn an in-memory JsonbValue into a Jsonb for on-disk storage.
@@ -503,10 +506,43 @@ fillJsonbValue(JsonbContainer *container, int index,
503506
*
504507
* Only sequential tokens pertaining to non-container types should pass a
505508
* JsonbValue. There is one exception -- WJB_BEGIN_ARRAY callers may pass a
506-
* "raw scalar" pseudo array to append that.
509+
* "raw scalar" pseudo array to append it - the actual scalar should be passed
510+
* next and it will be added as the only member of the array.
511+
*
512+
* Values of type jvbBinary, which are rolled up arrays and objects,
513+
* are unpacked before being added to the result.
507514
*/
508515
JsonbValue *
509516
pushJsonbValue(JsonbParseState **pstate, JsonbIteratorToken seq,
517+
JsonbValue *jbval)
518+
{
519+
JsonbIterator *it;
520+
JsonbValue *res = NULL;
521+
JsonbValue v;
522+
JsonbIteratorToken tok;
523+
524+
if (!jbval || (seq != WJB_ELEM && seq != WJB_VALUE) ||
525+
jbval->type != jbvBinary)
526+
{
527+
/* drop through */
528+
return pushJsonbValueScalar(pstate, seq, jbval);
529+
}
530+
531+
/* unpack the binary and add each piece to the pstate */
532+
it = JsonbIteratorInit(jbval->val.binary.data);
533+
while ((tok = JsonbIteratorNext(&it, &v, false)) != WJB_DONE)
534+
res = pushJsonbValueScalar(pstate, tok,
535+
tok < WJB_BEGIN_ARRAY ? &v : NULL);
536+
537+
return res;
538+
}
539+
540+
/*
541+
* Do the actual pushing, with only scalar or pseudo-scalar-array values
542+
* accepted.
543+
*/
544+
static JsonbValue *
545+
pushJsonbValueScalar(JsonbParseState **pstate, JsonbIteratorToken seq,
510546
JsonbValue *scalarVal)
511547
{
512548
JsonbValue *result = NULL;
@@ -549,13 +585,11 @@ pushJsonbValue(JsonbParseState **pstate, JsonbIteratorToken seq,
549585
appendKey(*pstate, scalarVal);
550586
break;
551587
case WJB_VALUE:
552-
Assert(IsAJsonbScalar(scalarVal) ||
553-
scalarVal->type == jbvBinary);
588+
Assert(IsAJsonbScalar(scalarVal));
554589
appendValue(*pstate, scalarVal);
555590
break;
556591
case WJB_ELEM:
557-
Assert(IsAJsonbScalar(scalarVal) ||
558-
scalarVal->type == jbvBinary);
592+
Assert(IsAJsonbScalar(scalarVal));
559593
appendElement(*pstate, scalarVal);
560594
break;
561595
case WJB_END_OBJECT:

src/include/utils/jsonb.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -418,7 +418,7 @@ extern JsonbValue *findJsonbValueFromContainer(JsonbContainer *sheader,
418418
extern JsonbValue *getIthJsonbValueFromContainer(JsonbContainer *sheader,
419419
uint32 i);
420420
extern JsonbValue *pushJsonbValue(JsonbParseState **pstate,
421-
JsonbIteratorToken seq, JsonbValue *scalarVal);
421+
JsonbIteratorToken seq, JsonbValue *jbVal);
422422
extern JsonbIterator *JsonbIteratorInit(JsonbContainer *container);
423423
extern JsonbIteratorToken JsonbIteratorNext(JsonbIterator **it, JsonbValue *val,
424424
bool skipNested);

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy