Module Name: src
Committed By: rillig
Date: Sat Jun 15 22:06:31 UTC 2024
Modified Files:
src/usr.bin/make: var.c
src/usr.bin/make/unit-tests: varname-dot-newline.exp
varname-dot-newline.mk
Log Message:
make: error out if an internal read-only variable is overwritten
The affected variables are:
* .newline
* .MAKE.OS
* .MAKE.JOBS.C
* .MAKE.LEVEL.ENV
* .MAKE.PID
* .MAKE.PPID
* .MAKE.UID
* .MAKE.GID
This change does not affect the .SHELL and .SUFFIXES variables, as well
as variables that are manually turned read-only by the special .READONLY
target.
To generate a diff of this commit:
cvs rdiff -u -r1.1120 -r1.1121 src/usr.bin/make/var.c
cvs rdiff -u -r1.4 -r1.5 src/usr.bin/make/unit-tests/varname-dot-newline.exp
cvs rdiff -u -r1.6 -r1.7 src/usr.bin/make/unit-tests/varname-dot-newline.mk
Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.
Modified files:
Index: src/usr.bin/make/var.c
diff -u src/usr.bin/make/var.c:1.1120 src/usr.bin/make/var.c:1.1121
--- src/usr.bin/make/var.c:1.1120 Sat Jun 15 20:02:45 2024
+++ src/usr.bin/make/var.c Sat Jun 15 22:06:30 2024
@@ -1,4 +1,4 @@
-/* $NetBSD: var.c,v 1.1120 2024/06/15 20:02:45 rillig Exp $ */
+/* $NetBSD: var.c,v 1.1121 2024/06/15 22:06:30 rillig Exp $ */
/*
* Copyright (c) 1988, 1989, 1990, 1993
@@ -132,7 +132,7 @@
#include "metachar.h"
/* "@(#)var.c 8.3 (Berkeley) 3/19/94" */
-MAKE_RCSID("$NetBSD: var.c,v 1.1120 2024/06/15 20:02:45 rillig Exp $");
+MAKE_RCSID("$NetBSD: var.c,v 1.1121 2024/06/15 22:06:30 rillig Exp $");
/*
* Variables are defined using one of the VAR=value assignments. Their
@@ -192,6 +192,12 @@ typedef struct Var {
bool readOnly:1;
/*
+ * The variable is read-only and immune to the .NOREADONLY special
+ * target. Any attempt to modify it results in an error.
+ */
+ bool readOnlyLoud:1;
+
+ /*
* The variable is currently being accessed by Var_Parse or Var_Subst.
* This temporary marker is used to avoid endless recursion.
*/
@@ -393,6 +399,7 @@ VarNew(FStr name, const char *value,
var->shortLived = shortLived;
var->fromEnvironment = fromEnvironment;
var->readOnly = readOnly;
+ var->readOnlyLoud = false;
var->inUse = false;
var->exported = false;
var->reexport = false;
@@ -552,6 +559,12 @@ Var_Delete(GNode *scope, const char *var
}
v = he->value;
+ if (v->readOnlyLoud) {
+ Parse_Error(PARSE_FATAL,
+ "Cannot delete \"%s\" as it is read-only",
+ v->name.str);
+ return;
+ }
if (v->readOnly) {
DEBUG2(VAR, "%s: ignoring delete '%s' as it is read-only\n",
scope->name, varname);
@@ -1025,6 +1038,12 @@ Var_SetWithFlags(GNode *scope, const cha
}
v = VarAdd(name, val, scope, flags);
} else {
+ if (v->readOnlyLoud) {
+ Parse_Error(PARSE_FATAL,
+ "Cannot overwrite \"%s\" as it is read-only",
+ name);
+ return;
+ }
if (v->readOnly && !(flags & VAR_SET_READONLY)) {
DEBUG3(VAR,
"%s: ignoring '%s = %s' as it is read-only\n",
@@ -1117,7 +1136,8 @@ Global_Delete(const char *name)
void
Global_Set_ReadOnly(const char *name, const char *value)
{
- Var_SetWithFlags(SCOPE_GLOBAL, name, value, VAR_SET_READONLY);
+ Var_SetWithFlags(SCOPE_GLOBAL, name, value, VAR_SET_NONE);
+ VarFind(name, SCOPE_GLOBAL, false)->readOnlyLoud = true;
}
/*
@@ -1135,6 +1155,10 @@ Var_Append(GNode *scope, const char *nam
if (v == NULL) {
Var_SetWithFlags(scope, name, val, VAR_SET_NONE);
+ } else if (v->readOnlyLoud) {
+ Parse_Error(PARSE_FATAL,
+ "Cannot append to \"%s\" as it is read-only", name);
+ return;
} else if (v->readOnly) {
DEBUG3(VAR, "%s: ignoring '%s += %s' as it is read-only\n",
scope->name, name, val);
Index: src/usr.bin/make/unit-tests/varname-dot-newline.exp
diff -u src/usr.bin/make/unit-tests/varname-dot-newline.exp:1.4 src/usr.bin/make/unit-tests/varname-dot-newline.exp:1.5
--- src/usr.bin/make/unit-tests/varname-dot-newline.exp:1.4 Thu Jan 26 20:48:18 2023
+++ src/usr.bin/make/unit-tests/varname-dot-newline.exp Sat Jun 15 22:06:31 2024
@@ -1,3 +1,8 @@
+make: "varname-dot-newline.mk" line 28: Cannot overwrite ".newline" as it is read-only
+make: "varname-dot-newline.mk" line 30: Cannot append to ".newline" as it is read-only
+make: "varname-dot-newline.mk" line 32: Cannot delete ".newline" as it is read-only
+make: Fatal errors encountered -- cannot continue
+make: stopped in unit-tests
first
second
backslash newline: <\
Index: src/usr.bin/make/unit-tests/varname-dot-newline.mk
diff -u src/usr.bin/make/unit-tests/varname-dot-newline.mk:1.6 src/usr.bin/make/unit-tests/varname-dot-newline.mk:1.7
--- src/usr.bin/make/unit-tests/varname-dot-newline.mk:1.6 Thu Jan 26 20:48:18 2023
+++ src/usr.bin/make/unit-tests/varname-dot-newline.mk Sat Jun 15 22:06:31 2024
@@ -1,4 +1,4 @@
-# $NetBSD: varname-dot-newline.mk,v 1.6 2023/01/26 20:48:18 sjg Exp $
+# $NetBSD: varname-dot-newline.mk,v 1.7 2024/06/15 22:06:31 rillig Exp $
#
# Tests for the special .newline variable, which contains a single newline
# character (U+000A).
@@ -20,12 +20,23 @@ BACKSLASH_NEWLINE:= \${.newline}
NEWLINE:= ${.newline}
+.if make(try-to-modify)
+# A '?=' assignment is fine. This pattern can be used to provide the variable
+# to older or other variants of make that don't know that variable.
+.newline?= fallback
+# expect+1: Cannot overwrite ".newline" as it is read-only
.newline= overwritten
+# expect+1: Cannot append to ".newline" as it is read-only
+.newline+= appended
+# expect+1: Cannot delete ".newline" as it is read-only
+.undef .newline
+.endif
.if ${.newline} != ${NEWLINE}
. error The .newline variable can be overwritten. It should be read-only.
.endif
all:
+ @${MAKE} -f ${MAKEFILE} try-to-modify || true
@echo 'first${.newline}second'
@echo 'backslash newline: <${BACKSLASH_NEWLINE}>'