]> granicus.if.org Git - postgresql/commitdiff
Free SQLSTATE and SQLERRM no earlier than other PL/pgSQL variables.
authorNoah Misch <noah@leadboat.com>
Thu, 26 Feb 2015 04:48:28 +0000 (23:48 -0500)
committerNoah Misch <noah@leadboat.com>
Thu, 26 Feb 2015 04:49:45 +0000 (23:49 -0500)
"RETURN SQLERRM" prompted plpgsql_exec_function() to read from freed
memory.  Back-patch to 9.0 (all supported versions).  Little code ran
between the premature free and the read, so non-assert builds are
unlikely to witness user-visible consequences.

src/pl/plpgsql/src/pl_exec.c
src/test/regress/expected/plpgsql.out
src/test/regress/sql/plpgsql.sql

index 5005361e184f16faef3a0d8a9cea7f4a3529ad17..c1a53db747dac9d55386dabb8162f4dca23e6704 100644 (file)
@@ -1125,8 +1125,9 @@ exec_stmt_block(PLpgSQL_execstate *estate, PLpgSQL_stmt_block *block)
                                {
                                        /*
                                         * Initialize the magic SQLSTATE and SQLERRM variables for
-                                        * the exception block. We needn't do this until we have
-                                        * found a matching exception.
+                                        * the exception block; this also frees values from any
+                                        * prior use of the same exception. We needn't do this
+                                        * until we have found a matching exception.
                                         */
                                        PLpgSQL_var *state_var;
                                        PLpgSQL_var *errm_var;
@@ -1144,13 +1145,6 @@ exec_stmt_block(PLpgSQL_execstate *estate, PLpgSQL_stmt_block *block)
 
                                        rc = exec_stmts(estate, exception->action);
 
-                                       free_var(state_var);
-                                       state_var->value = (Datum) 0;
-                                       state_var->isnull = true;
-                                       free_var(errm_var);
-                                       errm_var->value = (Datum) 0;
-                                       errm_var->isnull = true;
-
                                        /* re-throw error if requested by handler */
                                        if (rc == PLPGSQL_RC_RERAISE)
                                                ReThrowError(edata);
index 4e0f08230179507766f25479b26dc39e07a48bd2..74707ebbe3953829e1fb5b1392b28bcbbf575621 100644 (file)
@@ -2469,9 +2469,21 @@ NOTICE:  P0001 user exception
  
 (1 row)
 
+create function excpt_test4() returns text as $$
+begin
+       begin perform 1/0;
+       exception when others then return sqlerrm; end;
+end; $$ language plpgsql;
+select excpt_test4();
+   excpt_test4    
+------------------
+ division by zero
+(1 row)
+
 drop function excpt_test1();
 drop function excpt_test2();
 drop function excpt_test3();
+drop function excpt_test4();
 -- parameters of raise stmt can be expressions
 create function raise_exprs() returns void as $$
 declare
index 0de60d7073c8968fe162b2f693e3914faa1fe560..f918a76b9dbb8bcb3e83ba25779f58e33df76b6a 100644 (file)
@@ -2093,11 +2093,19 @@ begin
            raise notice '% %', sqlstate, sqlerrm;
     end;
 end; $$ language plpgsql;
-
 select excpt_test3();
+
+create function excpt_test4() returns text as $$
+begin
+       begin perform 1/0;
+       exception when others then return sqlerrm; end;
+end; $$ language plpgsql;
+select excpt_test4();
+
 drop function excpt_test1();
 drop function excpt_test2();
 drop function excpt_test3();
+drop function excpt_test4();
 
 -- parameters of raise stmt can be expressions
 create function raise_exprs() returns void as $$