Source-Changes-HG archive

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

[src/trunk]: src/usr.bin/make make(1): make ampersand in ${VAR:from=to&} an o...



details:   https://anonhg.NetBSD.org/src/rev/282feb7c01b1
branches:  trunk
changeset: 936143:282feb7c01b1
user:      rillig <rillig%NetBSD.org@localhost>
date:      Sun Jul 19 22:04:27 2020 +0000

description:
make(1): make ampersand in ${VAR:from=to&} an ordinary character

In SysV substitutions, wildcards are expressed with % instead of &.  The
& is not mentioned in the manual page, and having another wildcard for
the whole word would be such an obscure feature that not even pkgsrc uses
it.  The easiest way to discover this feature had been to read the source
code of make(1) or to use a fuzzer and accidentally stumble upon this
edge case.

diffstat:

 usr.bin/make/unit-tests/sysv.exp |   2 +-
 usr.bin/make/unit-tests/sysv.mk  |  10 +++---
 usr.bin/make/var.c               |  61 +++++++++++++++++++--------------------
 3 files changed, 35 insertions(+), 38 deletions(-)

diffs (161 lines):

diff -r 3c831f46d851 -r 282feb7c01b1 usr.bin/make/unit-tests/sysv.exp
--- a/usr.bin/make/unit-tests/sysv.exp  Sun Jul 19 21:30:49 2020 +0000
+++ b/usr.bin/make/unit-tests/sysv.exp  Sun Jul 19 22:04:27 2020 +0000
@@ -14,5 +14,5 @@
 
 ax:Q b c d eb
 bcd.e
-a.bcd.e
+&
 exit status 0
diff -r 3c831f46d851 -r 282feb7c01b1 usr.bin/make/unit-tests/sysv.mk
--- a/usr.bin/make/unit-tests/sysv.mk   Sun Jul 19 21:30:49 2020 +0000
+++ b/usr.bin/make/unit-tests/sysv.mk   Sun Jul 19 22:04:27 2020 +0000
@@ -1,4 +1,4 @@
-# $Id: sysv.mk,v 1.6 2020/07/19 14:23:02 rillig Exp $
+# $Id: sysv.mk,v 1.7 2020/07/19 22:04:27 rillig Exp $
 
 all: foo fun sam bla words ampersand
 
@@ -47,10 +47,10 @@
 words:
        @echo a${a b c d e:L:%a=x:Q}b
 
-# As of 2020-07-19, an ampersand can be used in the replacement part
-# of a SysV substitution modifier.  This can either be an intentional
-# feature or an implementation mistake, as it is not mentioned in the
-# manual page.
+# Before 2020-07-19, an ampersand could be used in the replacement part
+# of a SysV substitution modifier.  This was probably a copy-and-paste
+# mistake since the SysV modifier code looked a lot like the code for the
+# :S and :C modifiers.  The ampersand is not mentioned in the manual page.
 ampersand:
        @echo ${:U${a.bcd.e:L:a.%=%}:Q}
        @echo ${:U${a.bcd.e:L:a.%=&}:Q}
diff -r 3c831f46d851 -r 282feb7c01b1 usr.bin/make/var.c
--- a/usr.bin/make/var.c        Sun Jul 19 21:30:49 2020 +0000
+++ b/usr.bin/make/var.c        Sun Jul 19 22:04:27 2020 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: var.c,v 1.275 2020/07/19 21:30:49 rillig Exp $ */
+/*     $NetBSD: var.c,v 1.276 2020/07/19 22:04:27 rillig Exp $ */
 
 /*
  * Copyright (c) 1988, 1989, 1990, 1993
@@ -69,14 +69,14 @@
  */
 
 #ifndef MAKE_NATIVE
-static char rcsid[] = "$NetBSD: var.c,v 1.275 2020/07/19 21:30:49 rillig Exp $";
+static char rcsid[] = "$NetBSD: var.c,v 1.276 2020/07/19 22:04:27 rillig Exp $";
 #else
 #include <sys/cdefs.h>
 #ifndef lint
 #if 0
 static char sccsid[] = "@(#)var.c      8.3 (Berkeley) 3/19/94";
 #else
-__RCSID("$NetBSD: var.c,v 1.275 2020/07/19 21:30:49 rillig Exp $");
+__RCSID("$NetBSD: var.c,v 1.276 2020/07/19 22:04:27 rillig Exp $");
 #endif
 #endif /* not lint */
 #endif
@@ -1308,22 +1308,27 @@
 }
 
 
+typedef struct {
+    const char *lhs;
+    const char *rhs;
+} VarSYSVSubstArgs;
+
 /* Callback function for VarModify to implement the :%.from=%.to modifier. */
 static Boolean
-VarSYSVMatch(GNode *ctx, Var_Parse_State *vpstate,
+VarSYSVSubst(GNode *ctx, Var_Parse_State *vpstate,
             const char *word, Boolean addSpace, Buffer *buf,
             void *data)
 {
-    size_t len;
-    const char *ptr;
-    Boolean hasPercent;
-    VarPattern *pat = data;
+    const VarSYSVSubstArgs *args = data;
 
     if (addSpace && vpstate->varSpace != '\0')
        Buf_AddByte(buf, vpstate->varSpace);
 
-    if ((ptr = Str_SYSVMatch(word, pat->lhs, &len, &hasPercent)) != NULL) {
-       char *varexp = Var_Subst(NULL, pat->rhs, ctx, VARE_WANTRES);
+    size_t len;
+    Boolean hasPercent;
+    const char *ptr = Str_SYSVMatch(word, args->lhs, &len, &hasPercent);
+    if (ptr != NULL) {
+       char *varexp = Var_Subst(NULL, args->rhs, ctx, VARE_WANTRES);
        Str_SYSVSubst(buf, varexp, ptr, len, hasPercent);
        free(varexp);
     } else {
@@ -3167,15 +3172,7 @@
 static int
 ApplyModifier_SysV(ApplyModifiersState *st)
 {
-    /*
-     * This can either be a bogus modifier or a System-V
-     * substitution command.
-     */
-    VarPattern      pattern;
-    /* FIXME: SysV modifiers have nothing to do with :S or :C pattern matching */
-    Boolean         eqFound = FALSE;
-
-    pattern.pflags = 0;
+    Boolean eqFound = FALSE;
 
     /*
      * First we make a pass through the string trying
@@ -3200,20 +3197,19 @@
 
     st->delim = '=';
     st->cp = st->tstr;
+    VarPatternFlags pflags = 0;
     /* FIXME: There's no point in having a single $ at the end of a
      * SysV substitution since that will not be interpreted as an
      * anchor anyway. */
-    pattern.lhs = ParseModifierPart(
-       st->ctxt, &st->cp, st->delim, st->eflags,
-       &pattern.pflags, &pattern.leftLen, NULL);
-    if (pattern.lhs == NULL)
+    char *lhs = ParseModifierPart(st->ctxt, &st->cp, st->delim, st->eflags,
+                                 &pflags, NULL, NULL);
+    if (lhs == NULL)
        return 'c';
 
     st->delim = st->endc;
-    pattern.rhs = ParseModifierPart(
-       st->ctxt, &st->cp, st->delim, st->eflags,
-       NULL, &pattern.rightLen, &pattern);
-    if (pattern.rhs == NULL)
+    char *rhs = ParseModifierPart(st->ctxt, &st->cp, st->delim, st->eflags,
+                                 NULL, NULL, NULL);
+    if (rhs == NULL)
        return 'c';
 
     /*
@@ -3222,14 +3218,15 @@
      */
     st->termc = *--st->cp;
     st->delim = '\0';
-    if (pattern.leftLen == 0 && *st->nstr == '\0') {
+    if (lhs[0] == '\0' && *st->nstr == '\0') {
        st->newStr = st->nstr;  /* special case */
     } else {
-       st->newStr = VarModify(
-           st->ctxt, &st->parsestate, st->nstr, VarSYSVMatch, &pattern);
+       VarSYSVSubstArgs args = { lhs, rhs };
+       st->newStr = VarModify(st->ctxt, &st->parsestate, st->nstr,
+                              VarSYSVSubst, &args);
     }
-    free(UNCONST(pattern.lhs));
-    free(UNCONST(pattern.rhs));
+    free(lhs);
+    free(rhs);
     return '=';
 }
 #endif



Home | Main Index | Thread Index | Old Index