Skip to content

Supershells evaluated when they're not needed #10

@rail5

Description

@rail5
true || echo $(rm -rf /) # Will NEVER delete any files
false && echo $(rm -rf /) # Will NEVER delete any files

Supershells however are evaluated in advance of the line that asks for them, and their result stored in a variable so that they can be accessed where needed. Therefore:

true || echo @(rm -rf /) # Will delete your files
false && echo @(rm -rf /) # Will delete your files

Because the compiler spots the supershell, and evaluates it on the line before.

This was noticed while working on #8

echo ${var_which_does_not_exist-$(echo hi | tee file)} # Echoes "hi", creates 'file', and write "hi" to that file
echo ${var_which_exists-$(echo hi | tee file)} # Echoes the contents of $var_which_exists, does NOT create any files or write to any files

If supershells are not changed, they would be evaluated in the case that we use them in parameter expansion as well, even when not needed

Another example of the same problem:

if condition1; then
    some-action
elif [[ @(supershell) == "expected output" ]]; then
    some-other-action
fi

In this case, the supershell will again be evaluated before the entire conditional, where it should only be evaluated in the event that the first condition was false


Possible solution: equivalent logic re-writing. Watch for connectives, parameter expansions, etc, cases where the program flow is determined at runtime, and re-write the logic in an equivalent way. For example:

true || echo @(rm -rf /)

Could be automatically re-written to the equivalent:

if ! true; then
    echo @(rm -rf /)
fi

Or:

echo ${var_which_exists-@(echo hi | tee file)}

Could be automatically re-written to the equivalent:

temporary_variable=
if [[ -v var_which_exists ]]; then
    temporary_variable=${var_which_exists}
else
    temporary_variable=@(echo hi | tee file)
fi
echo ${temporary_variable}
unset temporary_variable

That last case (with the IFs) would not have to be rewritten, but could simply be compiled so that the supershell evaluation is part of the conditional (as we do in while statements already)

I'm not a big fan of this solution, since the logic requires different specific courses of action in different specific cases, as opposed to being a general solution for all such cases.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions