bug-bash
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

nameref/subscript fixes for unset builtin


From: Grisha Levit
Subject: nameref/subscript fixes for unset builtin
Date: Tue, 31 May 2016 23:40:40 -0400

The patch below addresses the following three issues:


Doing unset -n n[0] actually unsets the target variable

$ v=(0 1); declare -n n=v
$ unset -n n[0]
$ declare -p n v
declare -n n="v"
bash: declare: v: not found

Unsetting namerefs that are array references does not work

$ v=(0 1); declare -n n=v[1]
$ unset n
$ declare -p n v
declare -n n="v[1]"
declare -a v=([0]="0" [1]="1")

Same as with no options, unset -n will search for functions if it doesn’t find a variable. If the nameref is invisble, it will unset any function with the same name instead of the nameref.

While this might meet the posix requirement of “if neither -f nor -v…” I suspect it would make more sense to follow the behavior as specified in the bash docs

Without options, unset first tries to unset a variable, and if that fails, tries to unset a function.

$ unset -n n; declare -n n; n() { :; }
$ unset -n n
$ declare -p n; declare -F n
declare -n n

It’s also the case that if a function has a name that is also a valid array reference, unset with no options will not find it and unset -f must be used, but this seems reasonable.


diff --git a/builtins/set.def b/builtins/set.def
index 8f74f0e..c563fe7 100644
--- a/builtins/set.def
+++ b/builtins/set.def
@@ -808,7 +808,7 @@ unset_builtin (list)
 {
   int unset_function, unset_variable, unset_array, opt, nameref, any_failed;
   int global_unset_func, global_unset_var;
-  char *name;
+  char *name, *tname;

   unset_function = unset_variable = unset_array = nameref = any_failed = 0;
   global_unset_func = global_unset_var = 0;
@@ -859,7 +859,7 @@ unset_builtin (list)

 #if defined (ARRAY_VARS)
       unset_array = 0;
-      if (!unset_function && valid_array_reference (name, 0))
+      if (!unset_function && nameref == 0 && valid_array_reference (name, 0))
        {
          t = strchr (name, '[');
          *t++ = '\0';
@@ -897,7 +897,7 @@ unset_builtin (list)
         find a function after unsuccessfully searching for a variable,
         note that we're acting on a function now as if -f were
         supplied.  The readonly check below takes care of it. */
-      if (var == 0 && unset_variable == 0 && unset_function == 0)
+      if (var == 0 && unset_variable == 0 && unset_function == 0 && nameref == 0)
        {
          if (var = find_function (name))
            unset_function = 1;
@@ -932,7 +932,20 @@ unset_builtin (list)
       if (var == 0 && nameref == 0 && unset_function == 0)
        {
          var = find_variable_last_nameref (name, 0);
-         tem = (var && nameref_p (var)) ? unbind_variable (nameref_cell (var)) : unbind_variable (name);
+     if (var && nameref_p (var))
+#if defined (ARRAY_VARS)
+       if (valid_array_reference (nameref_cell (var), 0))
+         {
+           tname = savestring(nameref_cell (var));
+           var = array_variable_part(tname, &t, 0);
+           if (var)
+             tem = unbind_array_element (array_variable_part (tname, &t, 0), t);
+         }
+       else
+#endif /* ARRAY_VARS */
+         tem = unbind_variable (nameref_cell (var));
+     else
+       tem = unbind_variable (name);
        }
       else
        tem = unset_function ? unbind_func (name) : (nameref ? unbind_nameref (name) : unbind_variable (name));
@@ -941,7 +954,7 @@ unset_builtin (list)
         is specified, the name refers to a variable; if a variable by
         that name does not exist, a function by that name, if any,
         shall be unset.'' */
-      if (tem == -1 && unset_function == 0 && unset_variable == 0)
+      if (tem == -1 && unset_function == 0 && unset_variable == 0 && nameref == 0)
        tem = unbind_func (name);

       name = list->word->word;         /* reset above for namerefs */

Attachment: unset_nameref_subscripts.patch
Description: Binary data


reply via email to

[Prev in Thread] Current Thread [Next in Thread]