Обсуждение: segmentation fault in pg head with SQL function.

Поиск
Список
Период
Сортировка

segmentation fault in pg head with SQL function.

От
Prabhat Sahu
Дата:
Hi,

I found a segmentation fault  on pg master Head with below steps and stacktrace.

postgres=# CREATE OR REPLACE FUNCTION func1() RETURNS VOID
LANGUAGE SQL 
AS $$
select 10;
$$;
CREATE FUNCTION

postgres=# select func1();
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.
!> \q


-- stack trace:
[edb@localhost bin]$ gdb -q -c data/core.31498 postgres
Reading symbols from /home/edb/PG/PGsrcNew/postgresql/inst/bin/postgres...done.
[New LWP 31498]
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/usr/lib64/libthread_db.so.1".
Core was generated by `postgres: edb postgres [local] SELECT                             '.
Program terminated with signal 6, Aborted.
#0  0x00007fb376a001f7 in raise () from /usr/lib64/libc.so.6
Missing separate debuginfos, use: debuginfo-install glibc-2.17-196.el7.x86_64 keyutils-libs-1.5.8-3.el7.x86_64 krb5-libs-1.15.1-8.el7.x86_64 libcom_err-1.42.9-10.el7.x86_64 libselinux-2.5-11.el7.x86_64 openssl-libs-1.0.2k-8.el7.x86_64 pcre-8.32-17.el7.x86_64 zlib-1.2.7-17.el7.x86_64
(gdb) bt
#0  0x00007fb376a001f7 in raise () from /usr/lib64/libc.so.6
#1  0x00007fb376a018e8 in abort () from /usr/lib64/libc.so.6
#2  0x0000000000a01368 in ExceptionalCondition (conditionName=0xbea4a0 "!(exprType(newexpr) == result_type)", errorType=0xbe98c6 "FailedAssertion", 
    fileName=0xbe9916 "clauses.c", lineNumber=4627) at assert.c:54
#3  0x00000000007d1611 in inline_function (funcid=16384, result_type=2278, result_collid=0, input_collid=0, args=0x0, funcvariadic=0 '\000', func_tuple=0x7fb377ebc918, 
    context=0x7fff01e5fca0) at clauses.c:4627
#4  0x00000000007d0781 in simplify_function (funcid=16384, result_type=2278, result_typmod=-1, result_collid=0, input_collid=0, args_p=0x7fff01e5eb70, funcvariadic=0 '\000', 
    process_args=1 '\001', allow_non_const=1 '\001', context=0x7fff01e5fca0) at clauses.c:4095
#5  0x00000000007ce15f in eval_const_expressions_mutator (node=0x2a88cf8, context=0x7fff01e5fca0) at clauses.c:2676
#6  0x000000000073727b in expression_tree_mutator (node=0x2a88d88, mutator=0x7cdc5c <eval_const_expressions_mutator>, context=0x7fff01e5fca0) at nodeFuncs.c:2854
#7  0x00000000007d007c in eval_const_expressions_mutator (node=0x2a88d88, context=0x7fff01e5fca0) at clauses.c:3671
#8  0x0000000000737464 in expression_tree_mutator (node=0x2a88d50, mutator=0x7cdc5c <eval_const_expressions_mutator>, context=0x7fff01e5fca0) at nodeFuncs.c:2903
#9  0x00000000007d007c in eval_const_expressions_mutator (node=0x2a88d50, context=0x7fff01e5fca0) at clauses.c:3671
#10 0x00000000007cdc09 in eval_const_expressions (root=0x2a88f00, node=0x2a88d50) at clauses.c:2474
#11 0x00000000007ae7cb in preprocess_expression (root=0x2a88f00, expr=0x2a88d50, kind=1) at planner.c:996
#12 0x00000000007adf40 in subquery_planner (glob=0x2a88b68, parse=0x2a888e0, parent_root=0x0, hasRecursion=0 '\000', tuple_fraction=0) at planner.c:687
#13 0x00000000007ad541 in standard_planner (parse=0x2a888e0, cursorOptions=256, boundParams=0x0) at planner.c:385
#14 0x00000000007ad2d2 in planner (parse=0x2a888e0, cursorOptions=256, boundParams=0x0) at planner.c:243
#15 0x000000000089980c in pg_plan_query (querytree=0x2a888e0, cursorOptions=256, boundParams=0x0) at postgres.c:807
#16 0x0000000000899939 in pg_plan_queries (querytrees=0x2a88ec8, cursorOptions=256, boundParams=0x0) at postgres.c:873
#17 0x0000000000899c08 in exec_simple_query (query_string=0x2a87a28 "select func1();") at postgres.c:1048
#18 0x000000000089dfb0 in PostgresMain (argc=1, argv=0x2ab3550, dbname=0x2ab33b0 "postgres", username=0x2a84428 "edb") at postgres.c:4144
#19 0x00000000007feed4 in BackendRun (port=0x2aab390) at postmaster.c:4409
#20 0x00000000007fe64d in BackendStartup (port=0x2aab390) at postmaster.c:4081
#21 0x00000000007fab64 in ServerLoop () at postmaster.c:1754
#22 0x00000000007fa19d in PostmasterMain (argc=5, argv=0x2a82330) at postmaster.c:1362
#23 0x0000000000731fb8 in main (argc=5, argv=0x2a82330) at main.c:228
(gdb) 


--

With Regards,

Prabhat Kumar Sahu
Skype ID: prabhat.sahu1984
EnterpriseDB Corporation

The Postgres Database Company

Re: segmentation fault in pg head with SQL function.

От
Michael Paquier
Дата:
On Fri, Mar 16, 2018 at 11:35:13AM +0530, Prabhat Sahu wrote:
> I found a segmentation fault  on pg master Head with below steps and
> stacktrace.
>
> postgres=# CREATE OR REPLACE FUNCTION func1() RETURNS VOID
> LANGUAGE SQL
> AS $$
> select 10;
> $$;
> CREATE FUNCTION
>
> postgres=# select func1();
> 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.
> !> \q

(Adding Peter and Tom in CC)

Problem reproducible here, and the bug has been introduced by fd1a421f.
It seems to me that the function should not be authorized to be created
to begin with, as it returns an integer in its last query, where I think
that check_sql_fn_retval is doing it wrong when called in
inline_function() as we know that it handles a function, and not a
procedure thanks to the first sanity checks at the top of the function.

Here is what happens before this commit:
=# CREATE OR REPLACE FUNCTION func1() RETURNS VOID
LANGUAGE SQL
AS $$
select 10;
$;
ERROR:  42P13: return type mismatch in function declared to return void
DETAIL:  Actual return type is integer.
CONTEXT:  SQL function "func1"
LOCATION:  check_sql_fn_retval, functions.c:1655

As far as I can see, here is the faulty code:
-   if (!rettype)
+   /*
+    * If it's declared to return VOID, we don't care what's in the function.
+    * (This takes care of the procedure case, as well.)
+    */
+   if (rettype == VOIDOID)
        return false;

While this can be bypassed for a procedure, we should fall down and fail
for a SQL function returning void depending on the tlist generated by
the last SQL query.

@@ -1624,8 +1622,7 @@ check_sql_fn_retval(Oid func_id, Oid rettype, List *queryTreeList,
    if (fn_typtype == TYPTYPE_BASE ||
        fn_typtype == TYPTYPE_DOMAIN ||
        fn_typtype == TYPTYPE_ENUM ||
-       fn_typtype == TYPTYPE_RANGE ||
-       rettype == VOIDOID)
+       fn_typtype == TYPTYPE_RANGE
This also causes the error message generated to change.

Peter, what's the intention here?  Shouldn't void still be treated as a
scalar type?
--
Michael

Вложения

Re: segmentation fault in pg head with SQL function.

От
Tom Lane
Дата:
Michael Paquier <michael@paquier.xyz> writes:
> On Fri, Mar 16, 2018 at 11:35:13AM +0530, Prabhat Sahu wrote:
>> postgres=# CREATE OR REPLACE FUNCTION func1() RETURNS VOID
>> LANGUAGE SQL
>> AS $$
>> select 10;
>> $$;

> Problem reproducible here, and the bug has been introduced by fd1a421f.
> It seems to me that the function should not be authorized to be created
> to begin with, as it returns an integer in its last query, where I think
> that check_sql_fn_retval is doing it wrong when called in
> inline_function() as we know that it handles a function, and not a
> procedure thanks to the first sanity checks at the top of the function.

Hm.  Actually, I think this is my fault.  It is true that previous PG
versions would have rejected this function definition, but my intention
while revising Peter's prokind patch was that we'd start allowing a
VOID-returning SQL function to contain anything, and just ignore whatever
the last statement within it might be.  The documentation doesn't say
much about VOID-returning SQL functions, but I certainly don't see
anything saying that they can't end with a SELECT, so arguably the old
behavior is a POLA violation.  In any case, this is the behavior we
need for VOID-returning procedures, and there seems little reason not
to make functions act similarly.

So apparently I missed something with that.  Will look more closely.

            regards, tom lane


Re: segmentation fault in pg head with SQL function.

От
Peter Eisentraut
Дата:
On 3/16/18 11:40, Tom Lane wrote:
> Michael Paquier <michael@paquier.xyz> writes:
>> On Fri, Mar 16, 2018 at 11:35:13AM +0530, Prabhat Sahu wrote:
>>> postgres=# CREATE OR REPLACE FUNCTION func1() RETURNS VOID
>>> LANGUAGE SQL
>>> AS $$
>>> select 10;
>>> $$;
> 
>> Problem reproducible here, and the bug has been introduced by fd1a421f.
>> It seems to me that the function should not be authorized to be created
>> to begin with, as it returns an integer in its last query, where I think
>> that check_sql_fn_retval is doing it wrong when called in
>> inline_function() as we know that it handles a function, and not a
>> procedure thanks to the first sanity checks at the top of the function.
> 
> Hm.  Actually, I think this is my fault.  It is true that previous PG
> versions would have rejected this function definition, but my intention
> while revising Peter's prokind patch was that we'd start allowing a
> VOID-returning SQL function to contain anything, and just ignore whatever
> the last statement within it might be.  The documentation doesn't say
> much about VOID-returning SQL functions, but I certainly don't see
> anything saying that they can't end with a SELECT, so arguably the old
> behavior is a POLA violation.  In any case, this is the behavior we
> need for VOID-returning procedures, and there seems little reason not
> to make functions act similarly.
> 
> So apparently I missed something with that.  Will look more closely.

This was listed as an open item, but it was already fixed by
877cdf11eaa9cabcb9b1e3c1bef0760fe08efdc3, so I'll remove it.

-- 
Peter Eisentraut              http://www.2ndQuadrant.com/
PostgreSQL Development, 24x7 Support, Remote DBA, Training & Services