Problem with tupdesc in jsonb_to_recordset - Mailing list pgsql-hackers

From Dmitry Dolgov
Subject Problem with tupdesc in jsonb_to_recordset
Date
Msg-id CA+q6zcWzN9ztCfR47ZwgTr1KLnuO6BAY6FurxXhovP4hxr+yOQ@mail.gmail.com
Whole thread Raw
Responses Re: Problem with tupdesc in jsonb_to_recordset  (Michael Paquier <michael@paquier.xyz>)
List pgsql-hackers
Hi,

I've found out that currently in some situations jsonb_to_recordset can lead to
a crash. Minimal example that I've managed to create looks like this:

    CREATE OR REPLACE FUNCTION test(data JSONB)
      RETURNS INTEGER AS $$
    DECLARE
      test_var int;
    BEGIN
      WITH jsonb_values AS (
          SELECT
            (SELECT SUM(value)
             FROM jsonb_to_recordset(element #> '{values}')
             AS q(value INTEGER)) AS value_sum
          FROM jsonb_array_elements(data) AS element
      ) SELECT SUM(value_sum) FROM jsonb_values INTO test_var;
      RETURN test_var;
    END;
    $$ LANGUAGE plpgsql;


And then:

    =# SELECT test('[
        {
            "values": [
                {
                    "value": 1
                },
                {
                    "value": 3
                }
            ]
        },
        {
            "values": [
                {
                    "value": 1
                },
                {
                    "value": 3
                }
            ]
        }
    ]' :: JSONB);
    server closed the connection unexpectedly
            This probably means the server terminated abnormally
            before or while processing the request.
    The connection to the server was lost. Attempting reset: Failed.

After brief investigation it looks like an issue with tupdesc from the function
cache:

    if (!cache)
    {
        fcinfo->flinfo->fn_extra = cache =
            MemoryContextAllocZero(fcinfo->flinfo->fn_mcxt, sizeof(*cache));
    //...

    rsi->setDesc = cache->c.io.composite.tupdesc;

Then after the first call of populate_recordset_worker rsi->setDesc is being
reset since we never increased tdrefcount and the next call will use wrong
cache data. Apparently, it can be fixed by incrementing a tdrefcount (see the
attached patch).

Attachment

pgsql-hackers by date:

Previous
From: Alvaro Herrera
Date:
Subject: Re: patch to allow disable of WAL recycling
Next
From: Tomas Vondra
Date:
Subject: Re: cost_sort() improvements