ref: f3d9187d4e0f02294fb1b0e31152070506314e67
parent: 240201426090f9eca923980e388cab5e66ecc0ef
author: Miguel Pineiro Jr <mpj@pineiro.cc>
date: Mon Mar 14 11:00:11 EDT 2022
Fix assignment operand handling to preserve ARGV
After initialization, ARGV is supposed to be under the control of the
application (the awk script). However, when fulfilling the assignment
specified by a "name=value" operand, the implementation modifies the
operand's ARGV entry behind the application's back, truncating it.
This commit undoes the munge before returning control to the
application.
$ echo | ./master 'BEGIN { print ARGV[1] } { print ARGV[1] }' name=value
name=value
name
$ echo | ./a.out 'BEGIN { print ARGV[1] } { print ARGV[1] }' name=value
name=value
name=value
History: setclvar had been modifying its string argument without
ill-effect from the beginning (7th Edition UNIX, 1979) [1], when,
in 1989, SVR4 switched the source of the argument from argv to ARGV
[2]. The former cannot be accessed by the application, the latter
can. Thus, a private implementation detail unintentionally became a
public defect.
[1] https://www.tuhs.org/cgi-bin/utree.pl?file=V7/usr/src/cmd/awk/lib.c
[2] https://github.com/danfuzz/one-true-awk/blob/master/versions/1989-10-11/lib.c
--- a/FIXES
+++ b/FIXES
@@ -25,6 +25,11 @@
This file lists all bug fixes, changes, etc., made since the AWK book
was sent to the printers in August, 1987.
+Mar 14, 2022:
+ The fulfillment of an assignment operand had been truncating its
+ entry in ARGV (since circa 1989). Thanks to Miguel Pineiro Jr.
+ <mpj@pineiro.cc>.
+
Mar 3, 2022:
Fixed file management memory leak that appears to have been
there since the files array was first initialized with stdin,
--- a/lib.c
+++ b/lib.c
@@ -297,12 +297,13 @@
void setclvar(char *s) /* set var=value from s */
{- char *p;
+ char *e, *p;
Cell *q;
double result;
for (p=s; *p != '='; p++)
;
+ e = p;
*p++ = 0;
p = qstring(p, '\0');
q = setsymtab(s, p, 0.0, STR, symtab);
@@ -312,6 +313,7 @@
q->tval |= NUM;
}
DPRINTF("command line set %s to |%s|\n", s, p);+ *e = '=';
}
--- a/main.c
+++ b/main.c
@@ -22,7 +22,7 @@
THIS SOFTWARE.
****************************************************************/
-const char *version = "version 20220303";
+const char *version = "version 20220314";
#define DEBUG
#include <stdio.h>
--- a/testdir/T.argv
+++ b/testdir/T.argv
@@ -97,6 +97,12 @@
$awk '{print L $0}' L=11 foo0 L=22 foo0 >foo2diff foo1 foo2 || echo 'BAD: T.argv (L=11 L=22)'
+echo >foo0
+echo 'name=value
+name=value' >foo1
+$awk 'BEGIN { print ARGV[1] } { print ARGV[1] }' name=value foo0 >foo2+diff foo1 foo2 || echo 'BAD: T.argv assignment operand modified'
+
echo 3.345 >foo1
$awk 'BEGIN { print ARGV[1] + ARGV[2]}' 1 2.345 >foo2diff foo1 foo2 || echo 'BAD: T.argv (ARGV[1] + ARGV[2])'
--
⑨