snprintf assert is broken by plpgsql #option dump - Mailing list pgsql-hackers

From Pavel Stehule
Subject snprintf assert is broken by plpgsql #option dump
Date
Msg-id CAFj8pRA+3f5n4642q2g8BXCKjbTd7yU9JMYAgDyHgozk6cQ-VA@mail.gmail.com
Whole thread Raw
Responses Re: snprintf assert is broken by plpgsql #option dump  (Tom Lane <tgl@sss.pgh.pa.us>)
List pgsql-hackers
Hi

Today I had broken plpgsql_check tests aganst PostgreSQL 12. After command

create or replace function ml_trg()
returns trigger as $$
#option dump
declare
begin
  if TG_OP = 'INSERT' then
    if NEW.status_from IS NULL then
      begin
        -- performance issue only
        select status into NEW.status_from
           from pa
          where pa_id = NEW.pa_id;
        -- nonexist target value
        select status into NEW.status_from_xxx
           from pa
          where pa_id = NEW.pa_id;
      exception
        when DATA_EXCEPTION then
          new.status_from := 'DE';
      end;
    end if;
  end if;
  if TG_OP = 'DELETE' then return OLD; else return NEW; end if;
exception
  when OTHERS then
    NULL;
    if TG_OP = 'DELETE' then return OLD; else return NEW; end if;
end;
$$ language plpgsql;

I got backtrace:
Program received signal SIGABRT, Aborted.
0x00007f2c140e653f in raise () from /lib64/libc.so.6
(gdb) bt
#0  0x00007f2c140e653f in raise () from /lib64/libc.so.6
#1  0x00007f2c140d0895 in abort () from /lib64/libc.so.6
#2  0x00000000008b7903 in ExceptionalCondition (conditionName=conditionName@entry=0xb00d3b "!(strvalue != ((void *)0))",
    errorType=errorType@entry=0x906034 "FailedAssertion", fileName=fileName@entry=0xb00d30 "snprintf.c",
    lineNumber=lineNumber@entry=674) at assert.c:54
#3  0x00000000008ff368 in dopr (target=target@entry=0x7fff4ff6aad0, format=0x7f2bfe4b0de3 " fields",
    format@entry=0x7f2bfe4b0dda "ROW %-16s fields", args=args@entry=0x7fff4ff6ab18) at snprintf.c:674
#4  0x00000000008ff6b7 in pg_vfprintf (stream=<optimized out>, fmt=fmt@entry=0x7f2bfe4b0dda "ROW %-16s fields",
    args=args@entry=0x7fff4ff6ab18) at snprintf.c:261
#5  0x00000000008ff7ff in pg_printf (fmt=fmt@entry=0x7f2bfe4b0dda "ROW %-16s fields") at snprintf.c:286
#6  0x00007f2bfe4a7c67 in plpgsql_dumptree (func=func@entry=0x26811e8) at pl_funcs.c:1676
#7  0x00007f2bfe49a136 in do_compile (fcinfo=fcinfo@entry=0x7fff4ff6afa0, procTup=procTup@entry=0x7f2bfe4ba100, function=0x26811e8,
    function@entry=0x0, hashkey=hashkey@entry=0x7fff4ff6ad20, forValidator=forValidator@entry=true) at pl_comp.c:794
#8  0x00007f2bfe49a27a in plpgsql_compile (fcinfo=fcinfo@entry=0x7fff4ff6afa0, forValidator=forValidator@entry=true) at pl_comp.c:224
#9  0x00007f2bfe497126 in plpgsql_validator (fcinfo=<optimized out>) at pl_handler.c:504
#10 0x00000000008c03df in OidFunctionCall1Coll (functionId=functionId@entry=13392, collation=collation@entry=0, arg1=arg1@entry=40960)
    at fmgr.c:1418
#11 0x0000000000563444 in ProcedureCreate (procedureName=<optimized out>, procNamespace=procNamespace@entry=2200,
    replace=<optimized out>, returnsSet=<optimized out>, returnType=<optimized out>, proowner=16384, languageObjectId=13393,
    languageValidator=13392,
    prosrc=0x264feb8 "\n#option

There are new assert

Assert(strvalue != NULL);

probably all refname usage inside plpgsql dump functions has problem with it.

I found two parts

diff --git a/src/pl/plpgsql/src/pl_funcs.c b/src/pl/plpgsql/src/pl_funcs.c
index b93f866223..d97997c001 100644
--- a/src/pl/plpgsql/src/pl_funcs.c
+++ b/src/pl/plpgsql/src/pl_funcs.c
@@ -1519,7 +1519,7 @@ dump_execsql(PLpgSQL_stmt_execsql *stmt)
        dump_ind();
        printf("    INTO%s target = %d %s\n",
               stmt->strict ? " STRICT" : "",
-              stmt->target->dno, stmt->target->refname);
+              stmt->target->dno, stmt->target->refname ? stmt->target->refname : "null");
    }
    dump_indent -= 2;
 }
@@ -1673,7 +1673,7 @@ plpgsql_dumptree(PLpgSQL_function *func)
                    PLpgSQL_row *row = (PLpgSQL_row *) d;
                    int         i;
 
-                   printf("ROW %-16s fields", row->refname);
+                   printf("ROW %-16s fields", row->refname ? row->refname : "null");
                    for (i = 0; i < row->nfields; i++)
                    {
                        printf(" %s=var %d", row->fieldnames[i],

Regards

Pavel

pgsql-hackers by date:

Previous
From: Tom Lane
Date:
Subject: Re: executor relation handling
Next
From: Tom Lane
Date:
Subject: Re: executor relation handling