mirror of
https://git.postgresql.org/git/postgresql.git
synced 2025-03-13 19:57:53 +08:00
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.
This commit is contained in:
parent
7d0d2b8da1
commit
9b74f32cdb
@ -57,6 +57,9 @@ static void appendElement(JsonbParseState *pstate, JsonbValue *scalarVal);
|
||||
static int lengthCompareJsonbStringValue(const void *a, const void *b);
|
||||
static int lengthCompareJsonbPair(const void *a, const void *b, void *arg);
|
||||
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.
|
||||
@ -503,10 +506,43 @@ fillJsonbValue(JsonbContainer *container, int index,
|
||||
*
|
||||
* Only sequential tokens pertaining to non-container types should 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 *
|
||||
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 *result = NULL;
|
||||
@ -549,13 +585,11 @@ pushJsonbValue(JsonbParseState **pstate, JsonbIteratorToken seq,
|
||||
appendKey(*pstate, scalarVal);
|
||||
break;
|
||||
case WJB_VALUE:
|
||||
Assert(IsAJsonbScalar(scalarVal) ||
|
||||
scalarVal->type == jbvBinary);
|
||||
Assert(IsAJsonbScalar(scalarVal));
|
||||
appendValue(*pstate, scalarVal);
|
||||
break;
|
||||
case WJB_ELEM:
|
||||
Assert(IsAJsonbScalar(scalarVal) ||
|
||||
scalarVal->type == jbvBinary);
|
||||
Assert(IsAJsonbScalar(scalarVal));
|
||||
appendElement(*pstate, scalarVal);
|
||||
break;
|
||||
case WJB_END_OBJECT:
|
||||
|
@ -388,7 +388,7 @@ extern JsonbValue *findJsonbValueFromContainer(JsonbContainer *sheader,
|
||||
extern JsonbValue *getIthJsonbValueFromContainer(JsonbContainer *sheader,
|
||||
uint32 i);
|
||||
extern JsonbValue *pushJsonbValue(JsonbParseState **pstate,
|
||||
JsonbIteratorToken seq, JsonbValue *scalarVal);
|
||||
JsonbIteratorToken seq, JsonbValue *jbVal);
|
||||
extern JsonbIterator *JsonbIteratorInit(JsonbContainer *container);
|
||||
extern JsonbIteratorToken JsonbIteratorNext(JsonbIterator **it, JsonbValue *val,
|
||||
bool skipNested);
|
||||
|
Loading…
Reference in New Issue
Block a user