Skip to content

A multi-word environment value in toolchain/modules is silently truncated to its first word #1690

Description

@sbryngelson

Summary

toolchain/modules supports KEY=value lines, which the loader exports here:

https://github.com/MFlowCode/MFC/blob/master/toolchain/bootstrap/modules.sh#L124-L127

if echo "$_entry" | grep -q '='; then
    log " $ export $(eval "echo \"$_entry\"")"
    eval "export $_entry"
fi

Because the entry is not quoted, eval "export $_entry" word-splits the value. Everything after the first word is treated as a further name to export, fails, and the failure goes to stderr — which ./mfc.sh load output is routinely redirected away from. The result is an environment variable that looks set but holds only its first word, and no visible error.

Reproduce

line='CRAY_CCE_LLD_ARGS=-plugin-opt=-mattr=-mai-insts -plugin-opt=-disable-promote-alloca-to-vector'
eval "export $line"
echo "[$CRAY_CCE_LLD_ARGS]"
[-plugin-opt=-mattr=-mai-insts]
bash: export: `-plugin-opt=-disable-promote-alloca-to-vector': not a valid identifier

With the value quoted in the modules file, both survive:

[-plugin-opt=-mattr=-mai-insts -plugin-opt=-disable-promote-alloca-to-vector]

Why it matters

The failure is silent and the consequences can be severe rather than cosmetic. On OLCF Frontier we need two -plugin-opt flags in CRAY_CCE_LLD_ARGS for CCE 21: one to work around a back-end assertion that blocks linking, and one to work around a code-generation bug that silently discards stores and produces wrong numbers. Written unquoted, only the first is applied. The build succeeds, the tests run, and the numerical workaround is simply absent — with nothing anywhere in the output to say so.

Any future multi-word value (compiler flags, linker args, search paths with spaces) hits the same trap.

Suggested fix

Quoting at the call site works but relies on every future contributor remembering. More robust is to split on the first = in the loader and export without re-evaluating the value:

if echo "$_entry" | grep -q '='; then
    _k=${_entry%%=*}
    _v=${_entry#*=}
    log " $ export $_k=$_v"
    export "$_k=$(eval "echo \"$_v\"")"
fi

That keeps the existing variable-expansion behaviour (entries referencing previously exported vars) while making word-splitting impossible. Failing that, a validation pass that rejects unquoted multi-word values with a clear error would at least make the truncation loud.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions