bug-gnu-utils
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

an alternative patch for gawk-3.1.3


From: Stepan Kasal
Subject: an alternative patch for gawk-3.1.3
Date: Tue, 22 Jul 2003 09:16:47 +0200
User-agent: Mutt/1.2.5.1i

Hello,
        as pointed out by Arnold, the current GNU awk, 3.1.3,
has a bug in parameter passing.

A simple workaround is: don't pass uninitialized variables
as parameters.  Then you are safe and don't need any patch.

Problem description: when you pass an uninitialized variable as
a parameter to a user function, and gawk doesn't know whether the
variable is scalar or an array.  Later on, when it discovers that
it has been a scalar variable, it has to clean up.  And that clean
up is where the bug resides.

Arnold has posted a patch to solve the problem.
I think I have found a problem with his patch, so I created an
alternative one.  I hope it corrects the problem, and I also hope that
it doesn't introduce too much new ones.  But, unfortunately, this one
has not yet been reviewed by Arnold, so use at your own risk.

The patch is attached below.

Regards,
        Stepan Kasal


2003-07-14  Stepan Kasal  <address@hidden>

        * eval.c (make_scalar): New function; takes care of everything
          what has to be done when a node of type Node_var_new or
          Node_array_ref changes to a scalar variable.
          (tree_eval, get_lhs): Call it.

diff -urpN gawk-3.1.3.a0/eval.c gawk-3.1.3.a1/eval.c
--- gawk-3.1.3.a0/eval.c        Sun Jun 22 10:56:04 2003
+++ gawk-3.1.3.a1/eval.c        Mon Jul 14 14:00:33 2003
@@ -29,6 +29,7 @@ extern double pow P((double x, double y)
 extern double modf P((double x, double *yp));
 extern double fmod P((double x, double y));
 
+static inline void make_scalar P((NODE *tree));
 static int eval_condition P((NODE *tree));
 static NODE *op_assign P((NODE *tree));
 static NODE *func_call P((NODE *tree));
@@ -327,6 +328,38 @@ genflags2str(int flagval, const struct f
 }
 
 /*
+ * tree is in a scalar context.  If it is a variable, acomplish
+ * what's needed.; otherwise, do nothing.
+ */
+static inline void make_scalar P((NODE *tree))
+{
+       switch (tree->type) {
+       case Node_var_array:
+               fatal(_("attempt to use array `%s' in a scalar context"),
+                       array_vname(tree));
+
+       case Node_array_ref:
+               switch (tree->orig_array->type) {
+               case Node_var_array:
+                       fatal(_("attempt to use array `%s' in a scalar 
context"),
+                               array_vname(tree));
+               case Node_var_new:
+                       tree->orig_array->type = Node_var;
+                       tree->orig_array->var_value = Nnull_string;
+                       break;
+               case Node_var:
+                       break;
+               default:
+                       cant_happen();
+               }
+               /* fall through */
+       case Node_var_new:
+               tree->type = Node_var;
+               tree->var_value = Nnull_string;
+       }
+}
+
+/*
  * interpret:
  * Tree is a bunch of rules to run. Returns zero if it hit an exit()
  * statement 
@@ -842,17 +875,9 @@ r_tree_eval(register NODE *tree, int isc
                              tree->vname);
        }
 
+       make_scalar (tree);
+
        switch (tree->type) {
-       case Node_array_ref:
-               if (tree->orig_array->type == Node_var_array)
-                       fatal(_("attempt to use array `%s' in a scalar 
context"),
-                               array_vname(tree));
-               tree->orig_array->type = Node_var;
-               /* fall through */
-       case Node_var_new:
-               tree->type = Node_var;
-               tree->var_value = Nnull_string;
-               /* fall through */
        case Node_var:
                if (do_lint && var_uninitialized(tree))
                        lintwarn(_("reference to uninitialized variable `%s'"),
@@ -903,10 +928,6 @@ r_tree_eval(register NODE *tree, int isc
                lhs = get_lhs(tree, (Func_ptr *) NULL, TRUE);
                return *lhs;
 
-       case Node_var_array:
-               fatal(_("attempt to use array `%s' in a scalar context"),
-                       array_vname(tree));
-
        case Node_unary_minus:
                t1 = tree_eval(tree->subnode);
                x = -force_number(t1);
@@ -1727,26 +1748,9 @@ r_get_lhs(register NODE *ptr, Func_ptr *
                ptr = stack_ptr[ptr->param_cnt];
        }
 
-       switch (ptr->type) {
-       case Node_var_array:
-               fatal(_("attempt to use array `%s' in a scalar context"),
-                       array_vname(ptr));
+       make_scalar(ptr);
 
-       /*
-        * The following goop ensures that uninitialized variables
-        * used as parameters eventually get their type set correctly
-        * to scalar (i.e., Node_var).
-        */
-       case Node_array_ref:
-               if (ptr->orig_array->type == Node_var_array)
-                       fatal(_("attempt to use array `%s' in a scalar 
context"),
-                               array_vname(ptr));
-               ptr->orig_array->type = Node_var;
-               /* fall through */
-       case Node_var_new:
-               ptr->type = Node_var;
-               ptr->var_value = Nnull_string;
-               /* fall through */
+       switch (ptr->type) {
        case Node_var:
                if (do_lint && reference && var_uninitialized(ptr))
                        lintwarn(_("reference to uninitialized variable `%s'"),




reply via email to

[Prev in Thread] Current Thread [Next in Thread]