Re: printing JsonbPair values of input JSONB on server side? - Mailing list pgsql-general

From T L
Subject Re: printing JsonbPair values of input JSONB on server side?
Date
Msg-id CAOb=C0dQJwL-=uv3Q61irz+2meTVrva6ifmARXCtu5XqJtC7HA@mail.gmail.com
Whole thread Raw
In response to Re: printing JsonbPair values of input JSONB on server side?  (Andrew Gierth <andrew@tao11.riddles.org.uk>)
Responses Re: printing JsonbPair values of input JSONB on server side?  (Andrew Gierth <andrew@tao11.riddles.org.uk>)
List pgsql-general

Thanks a lot for the suggestions. I changed the code below (with `pnstrdup` and  `DatumGetCString`).
But the code still crashes at the two problem lines (either one alone crashes the server). The input is:

select print_kv_pair('{"a":1, "b": 2}');

Any further insight?

-- modified code --

PG_FUNCTION_INFO_V1(print_kv_pair);
Datum
print_kv_pair(PG_FUNCTION_ARGS)
{
    Jsonb *jb1 = PG_GETARG_JSONB_P(0);
    JsonbIterator *it1;
    JsonbValue    v1;
    JsonbIteratorToken r1;
    JsonbParseState *state = NULL;

    if (jb1 == NULL)
        PG_RETURN_JSONB_P(jb1);

    if (!JB_ROOT_IS_OBJECT(jb1))
        ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("Can only take objects")));

    elog(NOTICE, "print_kv_pair(): ok0");

    it1 = JsonbIteratorInit(&jb1->root);
    r1 = JsonbIteratorNext(&it1, &v1, false);

    if (r1 != WJB_BEGIN_OBJECT)
        ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("Iterator was not an object")));

    elog(NOTICE, "print_kv_pair(): ok1");
//    pushJsonbValue(&state, r1, NULL); //?? do wee need this?
//    r1 = JsonbIteratorNext(&it1, &v1, false); //this seems unnecessary

    JsonbValue *object = &v1;

    elog(NOTICE, "print_kv_pair(): ok2");
    Assert(object->type == jbvObject);

    elog(NOTICE, "print_kv_pair(): ok3, nPairs = %d", object->val.object.nPairs);

    //iterating through key-value pairs
    JsonbPair  *ptr;
    for (ptr = object->val.object.pairs;
            ptr - object->val.object.pairs < object->val.object.nPairs; ptr++)
    {
        //problem lines!!! //either elog crashes pg server
        char *buf = pnstrdup(ptr->key.val.string.val, ptr->key.val.string.len);
        elog(NOTICE, "print_kv_pair(): k = %s", (ptr->key).val.string.val);  //debug
        elog(NOTICE, "print_kv_pair(): v = %s", DatumGetCString(DirectFunctionCall1(numeric_out,
                NumericGetDatum(ptr->value.val.numeric))) ); //debug
    }

    elog(NOTICE, "print_kv_pair(): ok4");

    PG_RETURN_JSONB_P(JsonbValueToJsonb(object));
}


On Mon, Mar 18, 2019 at 3:20 PM Andrew Gierth <andrew@tao11.riddles.org.uk> wrote:
>>>>> "T" == T L <tinlyx@gmail.com> writes:

 T>     //Problem line!!!
 T>     //            elog(NOTICE, "print_kv_pair(): k = %s, v = %s",
 T>      ptr-> key.val.string.val, numeric_out(ptr->value.val.numeric));

string.val isn't a C string (notice the "not null terminated" comment in
the structure definition), and you can't call numeric_out like that.
Either of those would crash it.

You could use pnstrdup to get a valid C string, and use
DatumGetCString(DirectFunctionCall1(
                  numeric_out,
                  NumericGetDatum(ptr->value.val.numeric)))

to get the numeric value as a C string.

--
Andrew (irc:RhodiumToad)

pgsql-general by date:

Previous
From: Andrew Gierth
Date:
Subject: Re: printing JsonbPair values of input JSONB on server side?
Next
From: "Peter J. Holzer"
Date:
Subject: Re: Facing issue in using special characters