Makefile: escape single-quotes in VERBOSE $(ECHO) argument

When the command string run through $(call VERBOSE,…) contains a single-quote
character followed by shell metacharacters, the shell executing the VERBOSE
template's $(ECHO) command will attempt to interpret those metacharacters. This
could be disastrous, such as if someone were to put in a Makefile recipe:

	$(call VERBOSE, , $(ECHO) 'Will not `rm -rf ~`')

When run with V=1, which causes VERBOSE to be defined as…

	VERBOSE = $(ECHO) '$(2)'; $(2)

…Make would evaluate the above call into:

	echo 'echo 'Will not `rm -rf ~`''; echo 'Will not `rm -rf ~`'

And oops, there goes the neighborhood.

The real-world motivating case for this fix is the sed call in the recipe for
doc/index.rst in doc/Makefile. It contains a sed expression enclosed in single
quotes, containing parentheses. When run through VERBOSE with V=1, the single
quotes around the sed expression actually escape _out_ of the single-quoted
string that is intended to be the whole command line, and you get:

	/bin/sh: -c: line 1: syntax error near unexpected token `('

The fix is for VERBOSE to escape any single quotes embedded in the command line
argument when echoing it:

	VERBOSE = $(ECHO) '$(subst ','\'',$(2))'; $(2)

Note that this is still wrong, as it will not do the right thing if $(2) happens
to begin with a hyphen, but I didn't want to introduce a new "PRINTF" variable
(or do something unsavory like calling cat with a here-doc) to squash a bug that
currently has no known manifestations.

Changelog-None
This commit is contained in:
Matt Whitlock
2025-05-14 03:00:39 -04:00
committed by Rusty Russell
parent 968bb63739
commit f816393095

View File

@@ -36,7 +36,7 @@ SORT=LC_ALL=C sort
ifeq ($V,1)
VERBOSE = $(ECHO) '$(2)'; $(2)
VERBOSE = $(ECHO) '$(subst ','\'',$(2))'; $(2)
else
VERBOSE = $(ECHO) $(1); $(2)
endif