Skip to content

spack spec does not handle quotes and spaces correctly #35756

@mwkrentel

Description

@mwkrentel

Steps to reproduce

Spack's quoting of specs for the shell is currently broken for the
case of variants containing spaces. For example:

$ spack  spec  zlib  cflags="-g -O"
==> Error: trying to set variant "O" in package "zlib",
but the package has no such variant [happened during concretization of zlib cflags="-g" ~O]

Some compiler or linker flags were provided without quoting their arguments,
which now causes spack to try to parse the *next* argument as a spec component
such as a variant instead of an additional compiler or linker flag. If the
intent was to set multiple flags, try quoting them together as described below.

Possible flag quotation errors (with the correctly-quoted version after the =>):
(1) cflags=-g -O => cflags="-g -O"

Ironically, the suggested "fix" is exactly what I wrote as the original input.

I suspect that the problem is sometime during processing the command
line, spack is passing the line as a string to the shell and failing
to properly re-quote the string in such a way that the shell will
correctly re-tokenize the string.

So, in the above example, the shell is handing spack cflags=-g -O as
a single token. But passing this to shell without any re-quoting
splits the token into two tokens cflags=-g and -O which fails
because there is no boolean variant O.

This works as a workaround:

$ spack  spec  zlib  cflags='"-g -O"'

Here, the shell hands spack cflags="-g -O" as a single token, so
reparsing by the shell keeps cflags=-g -O together as a single
token (and also removes one level of quotes).

The above works as a workaround, but it shouldn't be necessary. You
don't want to go down the road of: "this string will be parsed by the
shell X number of times, so I need X level of quotes."

This also works as a workaround, but it shouldn't.

$ spack  spec  zlib  cflags=\"-g  -O\"

The shell will parse this as separate tokens cflags="-g and -O".
Here, -O" is an invalid variant and this should fail. Instead,
putting this together as a single string, the shell re-combines the
quotes and this "works" as cflags=-g -O.

Here's a truly strange case:

$ spack  spec  zlib  cflags=""  -g
Input spec
--------------------------------
zlib cflags="-g" 

Concretized
--------------------------------
zlib@1.2.13%gcc@8.5.0 cflags="-g" +optimize+pic+shared build_system=makefile arch=linux-rhel8-zen

This should set cflags to empty and fail because -g is not a valid
variant. Instead, spack is combining two separate but adjacent
tokens. In effect, spack is trying to out-think the shell, thinking
that the user wrote cflags= -g or some such.

I believe that the basic problem is that once spack forms an internal
representation of the spec, whenever it passes it to the shell, it
should first add quotes to the tokens in such a way that the shell will
parse (and remove) the quotes to exactly reproduce the original spec.

I tracked down the problem to this commit.

commit 0c7fd9bd8ca0e38cb5a497acdfc40f51170a07f8
Author: Danny McClanahan <1305167+cosmicexplorer@users.noreply.github.com>
Date:   Sat Jun 11 15:35:46 2022 -0400

    fix doubly shell quoting args to `spack spec` (#29282)
    
    * add test to verify fix works
    * fix spec cflags/variants parsing test (breaking change)
    * fix `spack spec` arg quoting issue
    * add error report for deprecated cflags coalescing
    * use .group(n) vs subscript regex group extraction for 3.5 compat
    * add random test for untested functionality to pass codecov
    * fix new test failure since rebase

M       lib/spack/spack/cmd/__init__.py
M       lib/spack/spack/cmd/spec.py
M       lib/spack/spack/test/cmd/common/arguments.py
M       lib/spack/spack/test/cmd/spec.py
M       lib/spack/spack/test/spec_semantics.py

ping @alalazo @becker33 @cosmic

Error message

No response

Information on your system

  • Spack: 0.20.0.dev0 (4e13b53)
  • Python: 3.8.12
  • Platform: linux-rhel8-zen2
  • Concretizer: clingo

General information

  • I have run spack debug report and reported the version of Spack/Python/Platform
  • I have searched the issues of this repo and believe this is not a duplicate
  • I have run the failing commands in debug mode and reported the output

Metadata

Metadata

Labels

Type

No type

Projects

Status

Done

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions