"Asif Ali" <[EMAIL PROTECTED]> writes:
> I have compiled postgres 8.2.1 with gcc 4.1. and when executed this function
> it crashes the server.

The attached patch (against HEAD) fixes your test case, but please see
whether it fixes your original problem; I'm not 100% confident in it
yet.  There seem to be two different bugs here...

                        regards, tom lane

? libplpgsql.sl.1
Index: gram.y
===================================================================
RCS file: /cvsroot/pgsql/src/pl/plpgsql/src/gram.y,v
retrieving revision 1.97
diff -c -r1.97 gram.y
*** gram.y      1 Feb 2007 19:10:29 -0000       1.97
--- gram.y      8 Feb 2007 01:06:24 -0000
***************
*** 272,278 ****
                                                $$.label          = $1;
                                                $$.n_initvars = 0;
                                                $$.initvarnos = NULL;
-                                               plpgsql_add_initdatums(NULL);
                                        }
                                | opt_block_label decl_start
                                        {
--- 272,277 ----
***************
*** 280,286 ****
                                                $$.label          = $1;
                                                $$.n_initvars = 0;
                                                $$.initvarnos = NULL;
-                                               plpgsql_add_initdatums(NULL);
                                        }
                                | opt_block_label decl_start decl_stmts
                                        {
--- 279,284 ----
***************
*** 289,300 ****
--- 287,302 ----
                                                        $$.label = $3;
                                                else
                                                        $$.label = $1;
+                                               /* Remember variables declared 
in decl_stmts */
                                                $$.n_initvars = 
plpgsql_add_initdatums(&($$.initvarnos));
                                        }
                                ;
  
  decl_start            : K_DECLARE
                                        {
+                                               /* Forget any variables created 
before block */
+                                               plpgsql_add_initdatums(NULL);
+                                               /* Make variable names be local 
to block */
                                                plpgsql_ns_setlocal(true);
                                        }
                                ;
***************
*** 990,998 ****
                                                                                
                                                                                
  -1),
                                                                                
                                   true);
  
-                                                               /* put the 
for-variable into the local block */
-                                                               
plpgsql_add_initdatums(NULL);
- 
                                                                new = 
palloc0(sizeof(PLpgSQL_stmt_fori));
                                                                new->cmd_type = 
PLPGSQL_STMT_FORI;
                                                                new->lineno   = 
$1;
--- 992,997 ----
Index: pl_comp.c
===================================================================
RCS file: /cvsroot/pgsql/src/pl/plpgsql/src/pl_comp.c,v
retrieving revision 1.111
diff -c -r1.111 pl_comp.c
*** pl_comp.c   1 Feb 2007 19:10:29 -0000       1.111
--- pl_comp.c   8 Feb 2007 01:06:24 -0000
***************
*** 667,677 ****
        function->found_varno = var->dno;
  
        /*
-        * Forget about the above created variables
-        */
-       plpgsql_add_initdatums(NULL);
- 
-       /*
         * Now parse the function's text
         */
        parse_rc = plpgsql_yyparse();
--- 667,672 ----
***************
*** 1893,1903 ****
  
  
  /* ----------
!  * plpgsql_add_initdatums             Put all datum entries created
!  *                                    since the last call into the
!  *                                    finishing code block so the
!  *                                    block knows which variables to
!  *                                    reinitialize when entered.
   * ----------
   */
  int
--- 1888,1904 ----
  
  
  /* ----------
!  * plpgsql_add_initdatums             Make an array of the datum numbers of
!  *                                    all the simple VAR datums created since 
the last call
!  *                                    to this function.
!  *
!  * If varnos is NULL, we just forget any datum entries created since the
!  * last call.
!  *
!  * This is used around a DECLARE section to create a list of the VARs
!  * that have to be initialized at block entry.  Note that VARs can also
!  * be created elsewhere than DECLARE, eg by a FOR-loop, but it is then
!  * the responsibility of special-purpose code to initialize them.
   * ----------
   */
  int
Index: pl_exec.c
===================================================================
RCS file: /cvsroot/pgsql/src/pl/plpgsql/src/pl_exec.c,v
retrieving revision 1.187
diff -c -r1.187 pl_exec.c
*** pl_exec.c   1 Feb 2007 19:22:07 -0000       1.187
--- pl_exec.c   8 Feb 2007 01:06:25 -0000
***************
*** 885,927 ****
                                {
                                        PLpgSQL_var *var = (PLpgSQL_var *) 
(estate->datums[n]);
  
                                        free_var(var);
!                                       if (!var->isconst || var->isnull)
                                        {
!                                               if (var->default_val == NULL)
                                                {
!                                                       /* Initially it 
contains a NULL */
!                                                       var->value = (Datum) 0;
!                                                       var->isnull = true;
!                                                       /*
!                                                        * If needed, give the 
datatype a chance to reject
!                                                        * NULLs, by assigning 
a NULL to the variable.
!                                                        * We claim the value 
is of type UNKNOWN, not the
!                                                        * var's datatype, else 
coercion will be skipped.
!                                                        * (Do this before the 
notnull check to be
!                                                        * consistent with 
exec_assign_value.)
!                                                        */
!                                                       if 
(!var->datatype->typinput.fn_strict)
!                                                       {
!                                                               bool    
valIsNull = true;
! 
!                                                               
exec_assign_value(estate,
!                                                                               
                  (PLpgSQL_datum *) var,
!                                                                               
                  (Datum) 0,
!                                                                               
                  UNKNOWNOID,
!                                                                               
                  &valIsNull);
!                                                       }
!                                                       if (var->notnull)
!                                                               ereport(ERROR,
                                                                        
(errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
                                                                         
errmsg("variable \"%s\" declared NOT NULL cannot default to NULL",
                                                                                
        var->refname)));
!                                               }
!                                               else
!                                               {
!                                                       
exec_assign_expr(estate, (PLpgSQL_datum *) var,
!                                                                               
         var->default_val);
!                                               }
                                        }
                                }
                                break;
--- 885,927 ----
                                {
                                        PLpgSQL_var *var = (PLpgSQL_var *) 
(estate->datums[n]);
  
+                                       /* free any old value, in case 
re-entering block */
                                        free_var(var);
! 
!                                       /* Initially it contains a NULL */
!                                       var->value = (Datum) 0;
!                                       var->isnull = true;
! 
!                                       if (var->default_val == NULL)
                                        {
!                                               /*
!                                                * If needed, give the datatype 
a chance to reject
!                                                * NULLs, by assigning a NULL 
to the variable.
!                                                * We claim the value is of 
type UNKNOWN, not the
!                                                * var's datatype, else 
coercion will be skipped.
!                                                * (Do this before the notnull 
check to be
!                                                * consistent with 
exec_assign_value.)
!                                                */
!                                               if 
(!var->datatype->typinput.fn_strict)
                                                {
!                                                       bool    valIsNull = 
true;
! 
!                                                       
exec_assign_value(estate,
!                                                                               
          (PLpgSQL_datum *) var,
!                                                                               
          (Datum) 0,
!                                                                               
          UNKNOWNOID,
!                                                                               
          &valIsNull);
!                                               }
!                                               if (var->notnull)
!                                                       ereport(ERROR,
                                                                        
(errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
                                                                         
errmsg("variable \"%s\" declared NOT NULL cannot default to NULL",
                                                                                
        var->refname)));
!                                       }
!                                       else
!                                       {
!                                               exec_assign_expr(estate, 
(PLpgSQL_datum *) var,
!                                                                               
 var->default_val);
                                        }
                                }
                                break;
***************
*** 1065,1071 ****
--- 1065,1073 ----
                                        rc = exec_stmts(estate, 
exception->action);
  
                                        free_var(state_var);
+                                       state_var->value = (Datum) 0;
                                        free_var(errm_var);
+                                       errm_var->value = (Datum) 0;
                                        break;
                                }
                        }
***************
*** 4867,4872 ****
--- 4869,4880 ----
        }
  }
  
+ /*
+  * free_var --- pfree any pass-by-reference value of the variable.
+  *
+  * This should always be followed by some assignment to var->value,
+  * as it leaves a dangling pointer.
+  */
  static void
  free_var(PLpgSQL_var *var)
  {
---------------------------(end of broadcast)---------------------------
TIP 4: Have you searched our list archives?

               http://archives.postgresql.org

Reply via email to