Loading lib/awk/awk.cpp +16 −1 Changes for lib/awk/awk.cpp: 16 added lines, 1 removed line. Original line number Diff line number Diff line Loading @@ -1310,8 +1310,23 @@ Value Interp::callUser(const std::string &name,std::vector<NodeP> &args){ } } frame[pname].scalar=eval(args[i]); continue; } // extra params with no matching arg stay uninitialized (usable as locals, incl. arrays on first use) // Extra params with no matching arg are the standard awk idiom for // function-local scratch variables (e.g. "function f(realarg, // i,j) {...}"). Still has to land in `frame` as its own (default- // constructed, UNINIT) Cell here -- not skipped entirely -- purely // so the name EXISTS in this frame at all: every variable lookup // below checks locals_.back() first and only falls through to // globals_ when the name isn't a key there. Skipping the insert for // "no matching arg" left exactly that lookup falling through, so // this "local" silently aliased whatever global happened to share // its name -- e.g. a helper using "i"/"j" as loop counters (an // extremely common choice) would clobber a CALLER's own same-named // global loop variable instead of getting its own fresh one, purely // because the helper happened to be called with fewer real // arguments than its full declared parameter list. frame[pname]; } locals_.push_back(std::move(frame)); Value ret; Loading Loading
lib/awk/awk.cpp +16 −1 Changes for lib/awk/awk.cpp: 16 added lines, 1 removed line. Original line number Diff line number Diff line Loading @@ -1310,8 +1310,23 @@ Value Interp::callUser(const std::string &name,std::vector<NodeP> &args){ } } frame[pname].scalar=eval(args[i]); continue; } // extra params with no matching arg stay uninitialized (usable as locals, incl. arrays on first use) // Extra params with no matching arg are the standard awk idiom for // function-local scratch variables (e.g. "function f(realarg, // i,j) {...}"). Still has to land in `frame` as its own (default- // constructed, UNINIT) Cell here -- not skipped entirely -- purely // so the name EXISTS in this frame at all: every variable lookup // below checks locals_.back() first and only falls through to // globals_ when the name isn't a key there. Skipping the insert for // "no matching arg" left exactly that lookup falling through, so // this "local" silently aliased whatever global happened to share // its name -- e.g. a helper using "i"/"j" as loop counters (an // extremely common choice) would clobber a CALLER's own same-named // global loop variable instead of getting its own fresh one, purely // because the helper happened to be called with fewer real // arguments than its full declared parameter list. frame[pname]; } locals_.push_back(std::move(frame)); Value ret; Loading