diff --git a/array.c b/array.c index 88d3b0010..5dcb747a9 100644 --- a/array.c +++ b/array.c @@ -333,8 +333,15 @@ force_array(NODE *symbol, bool canfatal) symbol = symbol->orig_array; } + NODE * elem_new_parent = NULL; + char * elem_new_vname = NULL; + switch (symbol->type) { case Node_elem_new: + elem_new_parent = symbol->eln_pa; + symbol->eln_pa = NULL; + elem_new_vname = symbol->eln_vn; + symbol->eln_vn = NULL; efree(symbol->stptr); symbol->stptr = NULL; symbol->stlen = 0; @@ -345,6 +352,10 @@ force_array(NODE *symbol, bool canfatal) symbol->parent_array = NULL; /* main array has no parent */ /* fall through */ case Node_var_array: + if (elem_new_parent != NULL) + symbol->parent_array = elem_new_parent; + if (elem_new_vname != NULL) + symbol->vname = elem_new_vname; break; case Node_array_ref: @@ -435,6 +446,30 @@ concat_exp(int nargs, bool do_subsep) } +/* + * adjust_param_node: change a parameter node when adjusting the call stack + * (code factored out from the adjust_fcall_stack function) + */ + +static void +adjust_param_node(NODE *r) +{ + if (r->orig_array != NULL) + if (r->orig_array->valref > 0) + DEREF(r->orig_array); + if (r->prev_array != NULL && r->prev_array != r->orig_array) + if (r->prev_array->valref > 0) + DEREF(r->prev_array); + if (r->orig_array->type == Node_var_array) { + r->orig_array = r->prev_array = NULL; + null_array(r); + } else { /* Node_elem_new */ + r->type = Node_var_new; + } + r->parent_array = NULL; +} + + /* * adjust_fcall_stack: remove subarray(s) of symbol[] from * function call stack. @@ -475,13 +510,17 @@ adjust_fcall_stack(NODE *symbol, int nsubs) for (; pcount > 0; pcount--) { r = *sp++; if (r->type != Node_array_ref - || r->orig_array->type != Node_var_array) + || ( r->orig_array->type != Node_var_array + && r->orig_array->type != Node_elem_new + ) + ) continue; n = r->orig_array; +#define NPAR(n) ((n->type == Node_elem_new)?n->eln_pa:n->parent_array) /* Case 1 */ if (n == symbol - && symbol->parent_array != NULL + && NPAR(symbol) != NULL && nsubs > 0 ) { /* @@ -496,13 +535,12 @@ adjust_fcall_stack(NODE *symbol, int nsubs) * BEGIN { a[0][0] = 1; f(a[0], a[0]); ...} */ - null_array(r); - r->parent_array = NULL; + adjust_param_node(r); continue; } /* Case 2 */ - for (n = n->parent_array; n != NULL; n = n->parent_array) { + for (n = NPAR(n); n != NULL; n = NPAR(n)) { assert(n->type == Node_var_array); if (n == symbol) { /* @@ -514,8 +552,7 @@ adjust_fcall_stack(NODE *symbol, int nsubs) * BEGIN { a[0][0][0][0] = 1; f(a[0], a[0][0][0]); .. } * */ - null_array(r); - r->parent_array = NULL; + adjust_param_node(r); break; } } @@ -608,8 +645,20 @@ do_delete(NODE *symbol, int nsubs) /* cleared a sub-array, free Node_var_array */ efree(val->vname); freenode(val); - } else + } else if (val->type == Node_elem_new) { + adjust_fcall_stack(val, nsubs); /* fix function call stack; See above. */ + elem_new_reset(val); + if ((val->flags & (MALLOC|STRCUR)) == (MALLOC|STRCUR)) + efree(val->stptr); + + mpfr_unset(val); +#ifdef MEMDEBUG + memset(val,0,sizeof(NODE)); val->type = 0xbaad; +#endif + freenode(val); + } else { unref(val); + } (void) assoc_remove(symbol, subs); DEREF(subs); diff --git a/awk.h b/awk.h index 2c2af80d8..b8f01329d 100644 --- a/awk.h +++ b/awk.h @@ -375,8 +375,13 @@ typedef struct exp_node { char *sp; size_t slen; int idx; - wchar_t *wsp; - size_t wslen; + union { + struct { + wchar_t *wsp; + size_t wslen; + } ws; + char * vn; + } worn; struct exp_node *typre; enum commenttype comtype; } val; @@ -499,8 +504,13 @@ typedef struct exp_node { #define stlen sub.val.slen #define stfmt sub.val.idx #define strndmode sub.val.rndmode -#define wstptr sub.val.wsp -#define wstlen sub.val.wslen +#define wstptr sub.val.worn.ws.wsp +#define wstlen sub.val.worn.ws.wslen + +/* Node_elem_new */ +#define eln_vn sub.val.worn.vn +#define eln_pa sub.val.typre + #ifdef HAVE_MPFR #define mpg_numbr sub.val.nm.mpnum #define mpg_i sub.val.nm.mpi @@ -1562,6 +1572,7 @@ extern STACK_ITEM *grow_stack(void); extern void dump_fcall_stack(FILE *fp); extern int register_exec_hook(Func_pre_exec preh, Func_post_exec posth); extern NODE **r_get_field(NODE *n, Func_ptr *assign, bool reference); +extern void elem_new_reset(NODE *n); extern NODE *elem_new_to_scalar(NODE *n); /* ext.c */ extern NODE *do_ext(int nargs); @@ -1964,6 +1975,7 @@ static inline NODE * force_string_fmt(NODE *s, const char *fmtstr, int fmtidx) { if (s->type == Node_elem_new) { + elem_new_reset(s); s->type = Node_val; return s; @@ -2005,6 +2017,7 @@ static inline NODE * force_number(NODE *n) { if (n->type == Node_elem_new) { + elem_new_reset(n); n->type = Node_val; return n; diff --git a/eval.c b/eval.c index 6e18344fd..67bfae0ac 100644 --- a/eval.c +++ b/eval.c @@ -1897,6 +1897,20 @@ init_interpret() interpret = r_interpret; } +/* elem_new_reset --- clear the eln_pa and eln_vn fields of a Node_elem_new */ + +void +elem_new_reset(NODE *n) +{ + assert(n->type == Node_elem_new); + + if (n->eln_vn != NULL) { + efree(n->eln_vn); + n->eln_vn = NULL; + } + n->eln_pa = NULL; +} + /* elem_new_to_scalar --- convert Node_elem_new to untyped scalar */ NODE * @@ -1905,6 +1919,8 @@ elem_new_to_scalar(NODE *n) if (n->type != Node_elem_new) return n; + elem_new_reset(n); + if (n->valref > 1) { unref(n); return dupnode(Nnull_string); diff --git a/ext.c b/ext.c index 26894bf1d..b31181f89 100644 --- a/ext.c +++ b/ext.c @@ -204,6 +204,11 @@ get_actual_argument(NODE *t, int i, bool want_array) if (want_array) return force_array(t, false); else { + if (t->type == Node_elem_new) { + elem_new_reset(t); + if (t->valref > 1) + unref(t); + } t->type = Node_var; t->var_value = dupnode(Nnull_string); return t->var_value; diff --git a/gawkapi.c b/gawkapi.c index c32df77a5..6a2bca435 100644 --- a/gawkapi.c +++ b/gawkapi.c @@ -910,9 +910,12 @@ api_sym_update(awk_ext_id_t id, unref(node->var_value); node->var_value = awk_value_to_node(value); if ((node->type == Node_var_new || node->type == Node_elem_new) - && value->val_type != AWK_UNDEFINED) + && value->val_type != AWK_UNDEFINED) { + if (node->type == Node_elem_new) { + elem_new_reset(node); + } node->type = Node_var; - + } return awk_true; } diff --git a/interpret.h b/interpret.h index afba82f89..118ec5112 100644 --- a/interpret.h +++ b/interpret.h @@ -241,6 +241,7 @@ uninitialized_scalar: if (op != Op_push_arg_untyped) { // convert very original untyped to scalar + elem_new_reset(m); m->type = Node_var; m->var_value = dupnode(Nnull_string); m->flags &= ~(MPFN | MPZN); @@ -326,7 +327,6 @@ uninitialized_scalar: r = *assoc_lookup(t1, t2); } - DEREF(t2); /* for SYMTAB, step through to the actual variable */ if (t1 == symbol_table) { @@ -345,6 +345,16 @@ uninitialized_scalar: } } + if (r->type == Node_elem_new && r->eln_pa == NULL) { + r->eln_pa = t1; + t2 = force_string(t2); + assert(r->eln_vn == NULL); /* if (r->eln_vn != NULL) */ + /* efree(r->eln_vn); */ + r->eln_vn = estrdup(t2->stptr, t2->stlen); /* the subscript in parent array */ + } + + DEREF(t2); + if (r->type == Node_val || r->type == Node_var || r->type == Node_elem_new) @@ -384,7 +394,8 @@ uninitialized_scalar: r = force_array(r, false); r->parent_array = t1; t2 = force_string(t2); - r->vname = estrdup(t2->stptr, t2->stlen); /* the subscript in parent array */ + if (r->vname == NULL) + r->vname = estrdup(t2->stptr, t2->stlen); /* the subscript in parent array */ } else if (r->type != Node_var_array) { t2 = force_string(t2); fatal(_("attempt to use scalar `%s[\"%.*s\"]' as an array"), diff --git a/mpfr.c b/mpfr.c index e783a5bbe..a80d0c843 100644 --- a/mpfr.c +++ b/mpfr.c @@ -350,6 +350,7 @@ mpg_force_number(NODE *n) char *cp, *cpend; if (n->type == Node_elem_new) { + elem_new_reset(n); n->type = Node_val; return n; diff --git a/node.c b/node.c index 3e3bd1097..77de60c65 100644 --- a/node.c +++ b/node.c @@ -61,6 +61,7 @@ r_force_number(NODE *n) char *ptr; if (n->type == Node_elem_new) { + elem_new_reset(n); n->type = Node_val; return n; @@ -540,6 +541,8 @@ r_unref(NODE *tmp) mpfr_unset(tmp); + if (tmp->type == Node_elem_new && tmp->eln_vn != NULL) + efree(tmp->eln_vn); free_wstr(tmp); freenode(tmp); } diff --git a/ChangeLog b/ChangeLog index 1ddc86134..cd76977ca 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,38 @@ +2025-01-03 Cristian Ioneci + + Fix issues triggered by using in certain ways array elements passed to + a function; issues include crash dumps, reads-after-free, internal errors, + incorrect results. + See test cases in test/ar2fn_*.awk. + + * awk.h: Add an union around `wsp', `wslen', part of NODE's `sub.val', in + order to overlap a char* over `wsp'; adjust/add #defines to access the + moved/added members. + (force_string_fmt, force_number): Clear Node_elem_new specific members + when the type is changed. + * interpret.h (r_interpret): Make a newborn Node_elem_new remember its + parent and a string representation of the index in the parent; for that + use `typre' and the added char* mentioned above (in awk.h) + (r_interpret): Clear Node_elem_new specific members when the type is + changed. + * array.c (force_array): The node will become a Node_var_array: if + present, use the values stashed in the previously mentioned fields to + properly set its `parent_array' and `vname'. + (adjust_param_node): New function. + (adjust_fcall_stack): Extra handling of Node_elem_new nodes. + * eval.c (elem_new_reset): New function. + (elem_new_to_scalar): Clear Node_elem_new specific members using the newly + introduced function above. + * ext.c (get_actual_argument): Clear Node_elem_new specific members when + the type is changed. + * gawkapi.c (api_sym_update): Clear Node_elem_new specific members when + the type is changed. + * mpfr.c (mpg_force_number): Clear Node_elem_new specific members when + the type is changed. + * node.c (r_force_number): Clear Node_elem_new specific members when + the type is changed. + (r_unref): Add code to free the eln_vn member of a Node_elem_new. + 2025-01-02 Arnold D. Robbins * NEWS: Updated. Copyright year updated, too. diff --git a/pc/Makefile.tst b/pc/Makefile.tst index a32b84f9e..8dd1e0325 100644 --- a/pc/Makefile.tst +++ b/pc/Makefile.tst @@ -190,6 +190,7 @@ UNIX_TESTS = \ GAWK_EXT_TESTS = \ aadelete1 aadelete2 aarray1 aasort aasorti argtest arraysort \ arraysort2 arraytype asortbool asortsymtab backw badargs \ + ar2fn_elnew_sc ar2fn_elnew_sc2 ar2fn_fmod ar2fn_unxptyp_aref ar2fn_unxptyp_val \ beginfile1 beginfile2 binmode1 charasbytes clos1way clos1way2 \ clos1way3 clos1way4 clos1way5 clos1way6 colonwarn commas crlf \ csv1 csv2 csv3 csvodd dbugarray1 dbugarray2 dbugarray3 dbugarray4 \ @@ -2737,6 +2738,31 @@ backw: @-AWKPATH="$(srcdir)" $(AWK) -f $@.awk < "$(srcdir)"/$@.in >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@ @-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@ +ar2fn_elnew_sc: + @echo $@ + @-AWKPATH="$(srcdir)" $(AWK) -f $@.awk >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@ + @-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@ + +ar2fn_elnew_sc2: + @echo $@ + @-AWKPATH="$(srcdir)" $(AWK) -f $@.awk >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@ + @-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@ + +ar2fn_fmod: + @echo $@ + @-AWKPATH="$(srcdir)" $(AWK) -f $@.awk >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@ + @-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@ + +ar2fn_unxptyp_aref: + @echo $@ + @-AWKPATH="$(srcdir)" $(AWK) -f $@.awk >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@ + @-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@ + +ar2fn_unxptyp_val: + @echo $@ + @-AWKPATH="$(srcdir)" $(AWK) -f $@.awk >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@ + @-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@ + clos1way: @echo $@ @-[ -z "$$GAWKLOCALE" ] && GAWKLOCALE=C; export GAWKLOCALE; \ diff --git a/test/ChangeLog b/test/ChangeLog index fedb6c2d0..e864bdcd0 100644 --- a/test/ChangeLog +++ b/test/ChangeLog @@ -1,3 +1,13 @@ +2025-01-03 Cristian Ioneci + + * Makefile.am (EXTRADIST): New tests: ar2fn_elnew_sc, ar2fn_elnew_sc2, + ar2fn_fmod, ar2fn_unxptyp_aref, ar2fn_unxptyp_val + + * ar2fn_elnew_sc.awk, ar2fn_elnew_sc.ok, ar2fn_elnew_sc2.awk, + ar2fn_elnew_sc2.ok, ar2fn_fmod.awk, ar2fn_fmod.ok, ar2fn_unxptyp_aref.awk, + ar2fn_unxptyp_aref.ok, ar2fn_unxptyp_val.awk, ar2fn_unxptyp_val.ok: New + files. + 2024-10-25 Arnold D. Robbins * Makefile.am (diffout): Use ${PAGER:-more} instead of diff --git a/test/Makefile.am b/test/Makefile.am index b2e5a728b..a0f69c737 100644 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -122,6 +122,16 @@ EXTRA_DIST = \ arysubnm.ok \ aryunasgn.awk \ aryunasgn.ok \ + ar2fn_elnew_sc.awk \ + ar2fn_elnew_sc.ok \ + ar2fn_elnew_sc2.awk \ + ar2fn_elnew_sc2.ok \ + ar2fn_fmod.awk \ + ar2fn_fmod.ok \ + ar2fn_unxptyp_aref.awk \ + ar2fn_unxptyp_aref.ok \ + ar2fn_unxptyp_val.awk \ + ar2fn_unxptyp_val.ok \ asgext.awk \ asgext.in \ asgext.ok \ @@ -1568,6 +1578,7 @@ UNIX_TESTS = \ GAWK_EXT_TESTS = \ aadelete1 aadelete2 aarray1 aasort aasorti argtest arraysort \ arraysort2 arraytype asortbool asortsymtab backw badargs \ + ar2fn_elnew_sc ar2fn_elnew_sc2 ar2fn_fmod ar2fn_unxptyp_aref ar2fn_unxptyp_val \ beginfile1 beginfile2 binmode1 charasbytes clos1way clos1way2 \ clos1way3 clos1way4 clos1way5 clos1way6 colonwarn commas crlf \ csv1 csv2 csv3 csvodd dbugarray1 dbugarray2 dbugarray3 dbugarray4 \ diff --git a/test/Makefile.in b/test/Makefile.in index 9dcfc905c..708bf4991 100644 --- a/test/Makefile.in +++ b/test/Makefile.in @@ -386,6 +386,16 @@ EXTRA_DIST = \ arysubnm.ok \ aryunasgn.awk \ aryunasgn.ok \ + ar2fn_elnew_sc.awk \ + ar2fn_elnew_sc.ok \ + ar2fn_elnew_sc2.awk \ + ar2fn_elnew_sc2.ok \ + ar2fn_fmod.awk \ + ar2fn_fmod.ok \ + ar2fn_unxptyp_aref.awk \ + ar2fn_unxptyp_aref.ok \ + ar2fn_unxptyp_val.awk \ + ar2fn_unxptyp_val.ok \ asgext.awk \ asgext.in \ asgext.ok \ @@ -1832,6 +1842,7 @@ UNIX_TESTS = \ GAWK_EXT_TESTS = \ aadelete1 aadelete2 aarray1 aasort aasorti argtest arraysort \ arraysort2 arraytype asortbool asortsymtab backw badargs \ + ar2fn_elnew_sc ar2fn_elnew_sc2 ar2fn_fmod ar2fn_unxptyp_aref ar2fn_unxptyp_val \ beginfile1 beginfile2 binmode1 charasbytes clos1way clos1way2 \ clos1way3 clos1way4 clos1way5 clos1way6 colonwarn commas crlf \ csv1 csv2 csv3 csvodd dbugarray1 dbugarray2 dbugarray3 dbugarray4 \ @@ -4562,6 +4573,31 @@ backw: @-AWKPATH="$(srcdir)" $(AWK) -f $@.awk < "$(srcdir)"/$@.in >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@ @-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@ +ar2fn_elnew_sc: + @echo $@ + @-AWKPATH="$(srcdir)" $(AWK) -f $@.awk >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@ + @-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@ + +ar2fn_elnew_sc2: + @echo $@ + @-AWKPATH="$(srcdir)" $(AWK) -f $@.awk >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@ + @-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@ + +ar2fn_fmod: + @echo $@ + @-AWKPATH="$(srcdir)" $(AWK) -f $@.awk >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@ + @-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@ + +ar2fn_unxptyp_aref: + @echo $@ + @-AWKPATH="$(srcdir)" $(AWK) -f $@.awk >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@ + @-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@ + +ar2fn_unxptyp_val: + @echo $@ + @-AWKPATH="$(srcdir)" $(AWK) -f $@.awk >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@ + @-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@ + clos1way: @echo $@ @-[ -z "$$GAWKLOCALE" ] && GAWKLOCALE=C; export GAWKLOCALE; \ diff --git a/test/Maketests b/test/Maketests index 9236de5bb..218d164dd 100644 --- a/test/Maketests +++ b/test/Maketests @@ -1420,6 +1420,31 @@ backw: @-AWKPATH="$(srcdir)" $(AWK) -f $@.awk < "$(srcdir)"/$@.in >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@ @-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@ +ar2fn_elnew_sc: + @echo $@ + @-AWKPATH="$(srcdir)" $(AWK) -f $@.awk >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@ + @-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@ + +ar2fn_elnew_sc2: + @echo $@ + @-AWKPATH="$(srcdir)" $(AWK) -f $@.awk >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@ + @-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@ + +ar2fn_fmod: + @echo $@ + @-AWKPATH="$(srcdir)" $(AWK) -f $@.awk >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@ + @-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@ + +ar2fn_unxptyp_aref: + @echo $@ + @-AWKPATH="$(srcdir)" $(AWK) -f $@.awk >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@ + @-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@ + +ar2fn_unxptyp_val: + @echo $@ + @-AWKPATH="$(srcdir)" $(AWK) -f $@.awk >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@ + @-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@ + clos1way: @echo $@ @-[ -z "$$GAWKLOCALE" ] && GAWKLOCALE=C; export GAWKLOCALE; \ diff --git a/test/ar2fn_elnew_sc.awk b/test/ar2fn_elnew_sc.awk new file mode 100644 index 000000000..1f4288d13 --- /dev/null +++ b/test/ar2fn_elnew_sc.awk @@ -0,0 +1,9 @@ +function f(y) +{ + y[3] = 14 + y +} + +BEGIN { + f(a[10]) +} diff --git a/test/ar2fn_elnew_sc.ok b/test/ar2fn_elnew_sc.ok new file mode 100644 index 000000000..ee1fcb7b0 --- /dev/null +++ b/test/ar2fn_elnew_sc.ok @@ -0,0 +1,2 @@ +gawk: ar2fn_elnew_sc.awk:4: fatal: attempt to use array `y (from a["10"])' in a scalar context +EXIT CODE: 2 diff --git a/test/ar2fn_elnew_sc2.awk b/test/ar2fn_elnew_sc2.awk new file mode 100644 index 000000000..7c6d5dcbd --- /dev/null +++ b/test/ar2fn_elnew_sc2.awk @@ -0,0 +1,9 @@ +function f(y) +{ + y[3] = 14 +} + +BEGIN { + f(a[10]) + a[10] +} diff --git a/test/ar2fn_elnew_sc2.ok b/test/ar2fn_elnew_sc2.ok new file mode 100644 index 000000000..a2630eeb8 --- /dev/null +++ b/test/ar2fn_elnew_sc2.ok @@ -0,0 +1,2 @@ +gawk: ar2fn_elnew_sc2.awk:8: fatal: attempt to use array `a["10"]' in a scalar context +EXIT CODE: 2 diff --git a/test/ar2fn_fmod.awk b/test/ar2fn_fmod.awk new file mode 100644 index 000000000..1bc060ce5 --- /dev/null +++ b/test/ar2fn_fmod.awk @@ -0,0 +1,16 @@ +function f(y) +{ + delete a + g(y) + print typeof(a) + print typeof(y) +} + +function g(x) +{ + x +} + +BEGIN { + f(a[10]) +} diff --git a/test/ar2fn_fmod.ok b/test/ar2fn_fmod.ok new file mode 100644 index 000000000..92afc9412 --- /dev/null +++ b/test/ar2fn_fmod.ok @@ -0,0 +1,2 @@ +array +unassigned diff --git a/test/ar2fn_unxptyp_aref.awk b/test/ar2fn_unxptyp_aref.awk new file mode 100644 index 000000000..3ab9ef0f4 --- /dev/null +++ b/test/ar2fn_unxptyp_aref.awk @@ -0,0 +1,16 @@ +function f(y) +{ + delete a + print typeof(y) + print y + g(y) +} + +function g(x) +{ + print "hey", x +} + +BEGIN { + f(a[10]) +} diff --git a/test/ar2fn_unxptyp_aref.ok b/test/ar2fn_unxptyp_aref.ok new file mode 100644 index 000000000..d7b4d782f --- /dev/null +++ b/test/ar2fn_unxptyp_aref.ok @@ -0,0 +1,3 @@ +untyped + +hey diff --git a/test/ar2fn_unxptyp_val.awk b/test/ar2fn_unxptyp_val.awk new file mode 100644 index 000000000..ca261a5ef --- /dev/null +++ b/test/ar2fn_unxptyp_val.awk @@ -0,0 +1,25 @@ +function f1(y) +{ + delete a1 + y + print typeof(a1) + print typeof(y) +} + +BEGIN { + a1[10] = 14 + delete a1[10] + f1(a1[10]) +} + +function f2(y) +{ + delete a2 + y + print typeof(a2) + print typeof(y) +} + +BEGIN { + f2(a2[10]) +} diff --git a/test/ar2fn_unxptyp_val.ok b/test/ar2fn_unxptyp_val.ok new file mode 100644 index 000000000..bf6c74f85 --- /dev/null +++ b/test/ar2fn_unxptyp_val.ok @@ -0,0 +1,4 @@ +array +unassigned +array +unassigned