]> git.ipfire.org Git - thirdparty/make.git/commitdiff
[SV 61463] Don't export inherited private variables
authorPaul Smith <psmith@gnu.org>
Mon, 2 Jan 2023 16:23:09 +0000 (11:23 -0500)
committerPaul Smith <psmith@gnu.org>
Tue, 3 Jan 2023 04:02:33 +0000 (23:02 -0500)
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
src/variable.c
tests/scripts/variables/private
tests/thelp.pl

diff --git a/NEWS b/NEWS
index cb68428e3c07eae673b61ce876cd507fa4acd040..6e9482b8146094e574788b31315cf80ef22175aa 100644 (file)
--- 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
+
 \f
 Version 4.4 (31 Oct 2022)
 
index 63c4f44f99956ef6400fc6e372e058927ac989ec..a0299639202b5651d4796e3f4869d97bacd17d87 100644 (file)
@@ -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);
 }
 \f
 /* 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);
               }
index 8967ffb55f5bf1b8dea68feb4b0c346dbfe7d3cf..16a34c7d01585e00c7e824e8ab1a51be58d8ecf5 100644 (file)
@@ -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;
index 8d29e5c3a12bc342e76e6e111cec1cb9ea1d7685..c95b54aec1b9a22259d6d0eb93d2ed4dbd0f1e70 100755 (executable)
@@ -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;