Also set the read-only flag for non-electric vars

For some reason, we have two places where a variable can be read-only:

- By key in env.cpp:is_read_only(), which is checked via set*

- By flag on the actual env_var_t, which is checked e.g. in
  parse_execution

The latter didn't happen for non-electric variables like hostname,
because they used the default constructor, because they were
constructed via operator[] (or some such C++-iness).

This caused for-loops to crash on an assert if they used a
non-electric read-only var like $hostname or $SHLVL.

Instead, we explicitly set the flag.

We might want to remove one of the two read-only checks, or something?

Fixes #5548.
This commit is contained in:
Fabian Homborg 2019-01-18 19:24:49 +01:00 committed by ridiculousfish
parent cb09f9aef2
commit f2a1130afd
5 changed files with 23 additions and 0 deletions

View file

@ -1184,6 +1184,7 @@ static int env_set_internal(const wcstring &key, env_mode_flags_t input_var_mode
var.set_vals(std::move(val)); var.set_vals(std::move(val));
var.set_pathvar(var_mode & ENV_PATHVAR); var.set_pathvar(var_mode & ENV_PATHVAR);
var.set_read_only(is_read_only(key));
if (var_mode & ENV_EXPORT) { if (var_mode & ENV_EXPORT) {
// The new variable is exported. // The new variable is exported.

View file

@ -122,6 +122,14 @@ class env_var_t {
} }
} }
void set_read_only(bool read_only) {
if (read_only) {
flags |= flag_read_only;
} else {
flags &= ~flag_read_only;
}
}
static env_var_flags_t flags_for(const wchar_t *name); static env_var_flags_t flags_for(const wchar_t *name);
env_var_t &operator=(const env_var_t &var) = default; env_var_t &operator=(const env_var_t &var) = default;

View file

@ -38,6 +38,12 @@ fish: You cannot use read-only variable 'status' in a for loop
for status in a b c for status in a b c
^ ^
####################
# That goes for non-electric ones as well (#5548)
fish: You cannot use read-only variable 'hostname' in a for loop
for hostname in a b c
^
#################### ####################
# For loop control vars available outside the for block # For loop control vars available outside the for block

View file

@ -163,6 +163,11 @@ for status in a b c
echo $status echo $status
end end
logmsg "That goes for non-electric ones as well (#5548)"
for hostname in a b c
echo $hostname
end
logmsg For loop control vars available outside the for block logmsg For loop control vars available outside the for block
begin begin
set -l loop_var initial-value set -l loop_var initial-value

View file

@ -96,6 +96,9 @@ Checking for infinite loops in no-execute
#################### ####################
# For loops with read-only vars is an error (#4342) # For loops with read-only vars is an error (#4342)
####################
# That goes for non-electric ones as well (#5548)
#################### ####################
# For loop control vars available outside the for block # For loop control vars available outside the for block
$loop_var: set in local scope, unexported, with 1 elements $loop_var: set in local scope, unexported, with 1 elements