Commit 5302760a authored by Andrew Dunstan's avatar Andrew Dunstan

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.
parent 6d1733fa
...@@ -57,6 +57,9 @@ static void appendElement(JsonbParseState *pstate, JsonbValue *scalarVal); ...@@ -57,6 +57,9 @@ static void appendElement(JsonbParseState *pstate, JsonbValue *scalarVal);
static int lengthCompareJsonbStringValue(const void *a, const void *b); static int lengthCompareJsonbStringValue(const void *a, const void *b);
static int lengthCompareJsonbPair(const void *a, const void *b, void *arg); static int lengthCompareJsonbPair(const void *a, const void *b, void *arg);
static void uniqueifyJsonbObject(JsonbValue *object); static void uniqueifyJsonbObject(JsonbValue *object);
static JsonbValue *pushJsonbValueScalar(JsonbParseState **pstate,
JsonbIteratorToken seq,
JsonbValue *scalarVal);
/* /*
* Turn an in-memory JsonbValue into a Jsonb for on-disk storage. * Turn an in-memory JsonbValue into a Jsonb for on-disk storage.
...@@ -503,10 +506,43 @@ fillJsonbValue(JsonbContainer *container, int index, ...@@ -503,10 +506,43 @@ fillJsonbValue(JsonbContainer *container, int index,
* *
* Only sequential tokens pertaining to non-container types should pass a * Only sequential tokens pertaining to non-container types should pass a
* JsonbValue. There is one exception -- WJB_BEGIN_ARRAY callers may pass a * JsonbValue. There is one exception -- WJB_BEGIN_ARRAY callers may pass a
* "raw scalar" pseudo array to append that. * "raw scalar" pseudo array to append it - the actual scalar should be passed
* next and it will be added as the only member of the array.
*
* Values of type jvbBinary, which are rolled up arrays and objects,
* are unpacked before being added to the result.
*/ */
JsonbValue * JsonbValue *
pushJsonbValue(JsonbParseState **pstate, JsonbIteratorToken seq, pushJsonbValue(JsonbParseState **pstate, JsonbIteratorToken seq,
JsonbValue *jbval)
{
JsonbIterator *it;
JsonbValue *res = NULL;
JsonbValue v;
JsonbIteratorToken tok;
if (!jbval || (seq != WJB_ELEM && seq != WJB_VALUE) ||
jbval->type != jbvBinary)
{
/* drop through */
return pushJsonbValueScalar(pstate, seq, jbval);
}
/* unpack the binary and add each piece to the pstate */
it = JsonbIteratorInit(jbval->val.binary.data);
while ((tok = JsonbIteratorNext(&it, &v, false)) != WJB_DONE)
res = pushJsonbValueScalar(pstate, tok,
tok < WJB_BEGIN_ARRAY ? &v : NULL);
return res;
}
/*
* Do the actual pushing, with only scalar or pseudo-scalar-array values
* accepted.
*/
static JsonbValue *
pushJsonbValueScalar(JsonbParseState **pstate, JsonbIteratorToken seq,
JsonbValue *scalarVal) JsonbValue *scalarVal)
{ {
JsonbValue *result = NULL; JsonbValue *result = NULL;
...@@ -549,13 +585,11 @@ pushJsonbValue(JsonbParseState **pstate, JsonbIteratorToken seq, ...@@ -549,13 +585,11 @@ pushJsonbValue(JsonbParseState **pstate, JsonbIteratorToken seq,
appendKey(*pstate, scalarVal); appendKey(*pstate, scalarVal);
break; break;
case WJB_VALUE: case WJB_VALUE:
Assert(IsAJsonbScalar(scalarVal) || Assert(IsAJsonbScalar(scalarVal));
scalarVal->type == jbvBinary);
appendValue(*pstate, scalarVal); appendValue(*pstate, scalarVal);
break; break;
case WJB_ELEM: case WJB_ELEM:
Assert(IsAJsonbScalar(scalarVal) || Assert(IsAJsonbScalar(scalarVal));
scalarVal->type == jbvBinary);
appendElement(*pstate, scalarVal); appendElement(*pstate, scalarVal);
break; break;
case WJB_END_OBJECT: case WJB_END_OBJECT:
......
...@@ -418,7 +418,7 @@ extern JsonbValue *findJsonbValueFromContainer(JsonbContainer *sheader, ...@@ -418,7 +418,7 @@ extern JsonbValue *findJsonbValueFromContainer(JsonbContainer *sheader,
extern JsonbValue *getIthJsonbValueFromContainer(JsonbContainer *sheader, extern JsonbValue *getIthJsonbValueFromContainer(JsonbContainer *sheader,
uint32 i); uint32 i);
extern JsonbValue *pushJsonbValue(JsonbParseState **pstate, extern JsonbValue *pushJsonbValue(JsonbParseState **pstate,
JsonbIteratorToken seq, JsonbValue *scalarVal); JsonbIteratorToken seq, JsonbValue *jbVal);
extern JsonbIterator *JsonbIteratorInit(JsonbContainer *container); extern JsonbIterator *JsonbIteratorInit(JsonbContainer *container);
extern JsonbIteratorToken JsonbIteratorNext(JsonbIterator **it, JsonbValue *val, extern JsonbIteratorToken JsonbIteratorNext(JsonbIterator **it, JsonbValue *val,
bool skipNested); bool skipNested);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment