From 8791d2b38ec916ea4206d5cae3b0036bb440c918 Mon Sep 17 00:00:00 2001 From: Paul Smith Date: Mon, 2 Jan 2023 11:23:09 -0500 Subject: [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. --- NEWS | 7 +++++- src/variable.c | 15 ++++++++--- tests/scripts/variables/private | 55 +++++++++++++++++++++++++++++++++++++++++ tests/thelp.pl | 13 +++++++++- 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 +* 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="); + + # 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='); + +run_make_test(q! +a: private export FOO := a +a: b +b: FOO := b +b: ; @#HELPER# env FOO +!, + '', 'FOO='); + +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='); + 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 : echo to stdout with a newline # raw : echo to stdout without adding anything +# env : echo the value of the env.var. , or "" # file : echo to stdout AND create the file # dir : echo to stdout AND create the directory # rm : echo to stdout AND delete the file/directory @@ -19,7 +20,7 @@ # term : send SIGTERM to PID # fail : echo 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 "\n"; + } + return 1; + } + # Show the output before creating the file if ($op eq 'file') { print "file $nm\n" unless $quiet; -- cgit v1.2.1