bug-gawk
[Top][All Lists]
Advanced

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

Re: [bug-gawk] gawk 4.2.1 critical issue


From: arnold
Subject: Re: [bug-gawk] gawk 4.2.1 critical issue
Date: Sun, 25 Mar 2018 22:48:03 -0600
User-agent: Heirloom mailx 12.4 7/29/08

Hi.

Denis Shirokov <address@hidden> wrote:

> # hello
> #
> # found another critical issue for gawk 4.2.1
> #
> # the following is the gawk 4.2.1 code for reproducing the issue
> #
>
> func  abc(c, A, B) {
>    print "abc(" c ", " length(A) ")"
>    if ( !c-- )
>       return
>       
>    B[""]; print length(B)
>    return abc(c, B) }
>
> BEGIN {
>    abc(2)
>    }
>
> output:
>
> >gawk -f r.gwk
>  abc(2, 0)
>  1
>  abc(1, 0)

As I mentioned earlier, gawk's tail recursion elimnation optimization
is broken.  It looks fundamentally flawed to me (another project member
did it and he is no longer involved) so I have simply removed it.
I am not sure that it saved a whole lot of time and/or space, anyway.

The patch is below and I will push it to the git repo shortly.

Thanks for the report and test case.

Arnold
---------------------------------
diff --git a/awk.h b/awk.h
index 1e334bf..c758064 100644
--- a/awk.h
+++ b/awk.h
@@ -527,7 +527,6 @@ typedef struct exp_node {
 #define func_node    sub.nodep.x.extra
 #define prev_frame_size        sub.nodep.reflags
 #define reti         sub.nodep.l.li
-#define num_tail_calls    sub.nodep.cnt
 
 /* Node_var: */
 #define var_value    lnode
diff --git a/eval.c b/eval.c
index 6ece236..34ba174 100644
--- a/eval.c
+++ b/eval.c
@@ -674,7 +674,7 @@ void
 dump_fcall_stack(FILE *fp)
 {
        NODE *f, *func;
-       long i = 0, j, k = 0;
+       long i = 0, k = 0;
 
        if (fcall_count == 0)
                return;
@@ -682,15 +682,13 @@ dump_fcall_stack(FILE *fp)
 
        /* current frame */
        func = frame_ptr->func_node;
-       for (j = 0; j <= frame_ptr->num_tail_calls; j++)
-               fprintf(fp, "\t# %3ld. %s\n", k++, func->vname);
+       fprintf(fp, "\t# %3ld. %s\n", k++, func->vname);
 
        /* outer frames except main */
        for (i = 1; i < fcall_count; i++) {
                f = fcall_list[i];
                func = f->func_node;
-               for (j = 0; j <= f->num_tail_calls; j++)
-                       fprintf(fp, "\t# %3ld. %s\n", k++, func->vname);
+               fprintf(fp, "\t# %3ld. %s\n", k++, func->vname);
        }
 
        fprintf(fp, "\t# %3ld. -- main --\n", k);
@@ -1242,38 +1240,16 @@ setup_frame(INSTRUCTION *pc)
        NODE *m, *f, *fp;
        NODE **sp = NULL;
        int pcount, arg_count, i, j;
-       bool tail_optimize = false;
 
        f = pc->func_body;
        pcount = f->param_cnt;
        fp = f->fparms;
        arg_count = (pc + 1)->expr_count;
 
-       /* tail recursion optimization */
-       tail_optimize =  ((pc + 1)->tail_call && do_optimize
-                               && ! do_debug && ! do_profile);
-
-       if (tail_optimize) {
-               /* free local vars of calling frame */
-
-               NODE *func;
-               int n;
-
-               func = frame_ptr->func_node;
-               for (n = func->param_cnt, sp = frame_ptr->stack; n > 0; n--) {
-                       r = *sp++;
-                       if (r->type == Node_var)     /* local variable */
-                               DEREF(r->var_value);
-                       else if (r->type == Node_var_array)     /* local array 
*/
-                               assoc_clear(r);
-               }
-               sp = frame_ptr->stack;
-
-       } else if (pcount > 0) {
+       if (pcount > 0) {
                ezalloc(sp, NODE **, pcount * sizeof(NODE *), "setup_frame");
        }
 
-
        /* check for extra args */
        if (arg_count > pcount) {
                warning(
@@ -1287,13 +1263,9 @@ setup_frame(INSTRUCTION *pc)
        }
 
        for (i = 0, j = arg_count - 1; i < pcount; i++, j--) {
-               if (tail_optimize)
-                       r = sp[i];
-               else {
-                       getnode(r);
-                       memset(r, 0, sizeof(NODE));
-                       sp[i] = r;
-               }
+               getnode(r);
+               memset(r, 0, sizeof(NODE));
+               sp[i] = r;
 
                if (i >= arg_count) {
                        /* local variable */
@@ -1348,11 +1320,6 @@ setup_frame(INSTRUCTION *pc)
 
        stack_adj(-arg_count);  /* adjust stack pointer */
 
-       if (tail_optimize) {
-               frame_ptr->num_tail_calls++;
-               return f->code_ptr;
-       }
-
        if (pc->opcode == Op_indirect_func_call) {
                r = POP();      /* indirect var */
                DEREF(r);
@@ -1372,7 +1339,6 @@ setup_frame(INSTRUCTION *pc)
        frame_ptr->stack = sp;
        frame_ptr->prev_frame_size = (stack_ptr - stack_bottom); /* size of the 
previous stack frame */
        frame_ptr->func_node = f;
-       frame_ptr->num_tail_calls = 0;
        frame_ptr->vname = NULL;
        frame_ptr->reti = pc; /* on return execute pc->nexti */
 
@@ -1774,7 +1740,6 @@ init_interpret()
        frame_ptr->type = Node_frame;
        frame_ptr->stack = NULL;
        frame_ptr->func_node = NULL;    /* in main */
-       frame_ptr->num_tail_calls = 0;
        frame_ptr->vname = NULL;
 
        /* initialize true and false nodes */



reply via email to

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