summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Smith <psmith@gnu.org>2023-01-02 11:23:09 -0500
committerPaul Smith <psmith@gnu.org>2023-01-02 23:02:33 -0500
commit8791d2b38ec916ea4206d5cae3b0036bb440c918 (patch)
tree31cfa2e686c1924b26b32636fca03b4b32c9be86
parentf91b8bbb34ff210ad72bc529c9bd5c6102e27adc (diff)
downloadmake-git-8791d2b38ec916ea4206d5cae3b0036bb440c918.tar.gz
[SV 61463] Don't export inherited private variables
If a parent target has an exported variable that is private, don't export it in child targets. * NEWS: Mention this change. * src/variable.c (target_environment): Ignore private inherited variables. * tests/thelp.pl: Add a new "env" operation to show env.var. values. * tests/scripts/variables/private: Verify this new behavior.
-rw-r--r--NEWS7
-rw-r--r--src/variable.c15
-rw-r--r--tests/scripts/variables/private55
-rwxr-xr-xtests/thelp.pl13
4 files changed, 84 insertions, 6 deletions
diff --git a/NEWS b/NEWS
index cb68428e..6e9482b8 100644
--- a/NEWS
+++ b/NEWS
@@ -17,13 +17,18 @@ A complete list of bugs fixed in this version is available here:
https://sv.gnu.org/bugs/index.php?group=make&report_id=111&fix_release_id=110&set=custom
* WARNING: Backward-incompatibility!
- In previous releases is was not well-defined when updates to MAKEFLAGS made
+ In previous releases it was not well-defined when updates to MAKEFLAGS made
inside a makefile would be visible. This release ensures they are visible
immediately, even when invoking $(shell ...) functions. Also, command line
variable assignments are now always present in MAKEFLAGS, even when parsing
makefiles.
Implementation provided by Dmitry Goncharov <dgoncharov@users.sf.net>
+* Previously target-specific variables would inherit their "export" capability
+ from parent target-specific variables even if they were marked private. Now
+ private parent target-specific variables have no affect. For more details
+ see https://savannah.gnu.org/bugs/index.php?61463
+
Version 4.4 (31 Oct 2022)
diff --git a/src/variable.c b/src/variable.c
index 63c4f44f..a0299639 100644
--- a/src/variable.c
+++ b/src/variable.c
@@ -472,7 +472,7 @@ lookup_variable (const char *name, size_t length)
const struct variable_set *set = setlist->set;
struct variable *v;
- v = (struct variable *) hash_find_item ((struct hash_table *) &set->table, &var_key);
+ v = hash_find_item ((struct hash_table *) &set->table, &var_key);
if (v && (!is_parent || !v->private_var))
return v->special ? lookup_special_var (v) : v;
@@ -553,7 +553,7 @@ lookup_variable_in_set (const char *name, size_t length,
var_key.name = (char *) name;
var_key.length = (unsigned int) length;
- return (struct variable *) hash_find_item ((struct hash_table *) &set->table, &var_key);
+ return hash_find_item ((struct hash_table *) &set->table, &var_key);
}
/* Initialize FILE's variable set list. If FILE already has a variable set
@@ -1065,7 +1065,8 @@ target_environment (struct file *file, int recursive)
for (s = set_list; s != 0; s = s->next)
{
struct variable_set *set = s->set;
- int isglobal = set == &global_variable_set;
+ const int islocal = s == set_list;
+ const int isglobal = set == &global_variable_set;
v_slot = (struct variable **) set->table.ht_vec;
v_end = v_slot + set->table.ht_size;
@@ -1075,11 +1076,17 @@ target_environment (struct file *file, int recursive)
struct variable **evslot;
struct variable *v = *v_slot;
+ if (!islocal && v->private_var)
+ continue;
+
evslot = (struct variable **) hash_find_slot (&table, v);
if (HASH_VACANT (*evslot))
{
- /* If we're not global, or we are and should export, add it. */
+ /* We'll always add target-specific variables, since we may
+ discover that they should be exported later: we'll check
+ again below. For global variables only add them if they're
+ exportable. */
if (!isglobal || should_export (v))
hash_insert_at (&table, v, evslot);
}
diff --git a/tests/scripts/variables/private b/tests/scripts/variables/private
index 8967ffb5..16a34c7d 100644
--- a/tests/scripts/variables/private
+++ b/tests/scripts/variables/private
@@ -47,6 +47,17 @@ a: b
',
'', "b: F=b / G=g\na: F= / G=g\n");
+# Exported private global variables
+run_make_test('
+private export F = global
+$(info $(shell #HELPER# env F))
+a: b
+b: export F=b
+a b: ; @#HELPER# raw $@ env F
+',
+ '', "F=global\nbF=b\naF=<unset>");
+
+
# 5: Multiple conditions on the same variable. Test export.
delete $ENV{'_X'};
&run_make_test('
@@ -119,4 +130,48 @@ bar: IA=global b% bar
bar: PA=global b% bar
bar: PS=bar\n");
+# SV 61463: Private parent variables should not be exported
+
+run_make_test(q!
+a: private export FOO := a
+a: b
+b: ; @#HELPER# env FOO
+!,
+ '', 'FOO=<unset>');
+
+run_make_test(q!
+a: private export FOO := a
+a: b
+b: FOO := b
+b: ; @#HELPER# env FOO
+!,
+ '', 'FOO=<unset>');
+
+run_make_test(q!
+export FOO := g
+a: private export FOO := a
+a: b
+b:
+b: ; @#HELPER# env FOO
+!,
+ '', 'FOO=g');
+
+run_make_test(q!
+export FOO := g
+a: private export FOO := a
+a: b
+b: FOO := b
+b: ; @#HELPER# env FOO
+!,
+ '', 'FOO=b');
+
+run_make_test(q!
+private export FOO := g
+a: private export FOO := a
+a: b
+b: FOO := b
+b: ; @#HELPER# env FOO
+!,
+ '', 'FOO=<unset>');
+
1;
diff --git a/tests/thelp.pl b/tests/thelp.pl
index 8d29e5c3..c95b54ae 100755
--- a/tests/thelp.pl
+++ b/tests/thelp.pl
@@ -10,6 +10,7 @@
# It supports the following operators:
# out <word> : echo <word> to stdout with a newline
# raw <word> : echo <word> to stdout without adding anything
+# env <word> : echo the value of the env.var. <word>, or "<unset>"
# file <word> : echo <word> to stdout AND create the file <word>
# dir <word> : echo <word> to stdout AND create the directory <word>
# rm <word> : echo <word> to stdout AND delete the file/directory <word>
@@ -19,7 +20,7 @@
# term <pid> : send SIGTERM to PID <pid>
# fail <err> : echo <err> to stdout then exit with error code err
#
-# If given -q only the "out" command generates output.
+# If given -q only the "out", "raw", and "env" commands generate output.
# Force flush
$| = 1;
@@ -41,6 +42,16 @@ sub op {
return 1;
}
+ if ($op eq 'env') {
+ print "$nm=" unless $quiet;
+ if (exists $ENV{$nm}) {
+ print "$ENV{$nm}\n";
+ } else {
+ print "<unset>\n";
+ }
+ return 1;
+ }
+
# Show the output before creating the file
if ($op eq 'file') {
print "file $nm\n" unless $quiet;