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}>'