Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
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)