[SV 64402] Correct locating "," in ifeq/ifneq conditionals

Ensure that we correctly skip the entirety of a macro or function
reference when searching for the "," separator in an ifeq/ifneq
conditional, including using "$," and also "${foo,bar}".  Note that
this change means that parenthesis OTHER than those used for variable
expansion are not considered special, any longer.

* NEWS: Announce the change.
* src/read.c (conditional_line): Skip variable references when looking
  for "," and ensure that we match closing parens/braces properly.
* tests/scripts/features/conditionals: Add tests for this behavior.
This commit is contained in:
Paul Smith 2024-01-06 17:42:40 -05:00
parent 33932663b0
commit d86448fe5f
3 changed files with 72 additions and 12 deletions

18
NEWS
View File

@ -9,11 +9,6 @@ which is contained in this distribution as the file doc/make.texi.
See the README file and the GNU Make manual for instructions for
reporting bugs.
* 'make --print-data-base' (or 'make -p') now outputs time of day
using the same form as for file timestamps, e.g., "2023-05-10
10:43:57.570558743". Previously it used the form "Wed May 10
10:43:57 2023", which has less detail and is harder to compare.
Version 4.4.90 (26 Feb 2023)
@ -34,6 +29,14 @@ https://sv.gnu.org/bugs/index.php?group=make&report_id=111&fix_release_id=111&se
your initialization function can check the provided ABI version to verify
it's being loaded correctly.
* WARNING: Backward-incompatibility!
Parsing of the first argument in ifeq/ifneq with () has been cleaned up.
When locating the separating "," any variable reference (single char as well
as using $() or ${}) is skipped. However parentheses that are not part of
or contained in variable references will not be counted. This means that
things like "ifeq ((foo,bar),)" are now syntax errors. Use a variable to
hide the comma if needed: "COMMA = ," / "ifeq ((foo$(COMMA)bar),)".
* New feature: Unload function for loaded objects
When a loaded object needs to be unloaded by GNU Make, it will invoke an
unload function (if one is defined) beforehand that allows the object to
@ -53,6 +56,11 @@ https://sv.gnu.org/bugs/index.php?group=make&report_id=111&fix_release_id=111&se
invoked recursively, warnings can be controlled only for the current
instance of make using the .WARNINGS variable.
* 'make --print-data-base' (or 'make -p') now outputs time of day
using the same form as for file timestamps, e.g., "2023-05-10
10:43:57.570558743". Previously it used the form "Wed May 10
10:43:57 2023", which has less detail and is harder to compare.
* Conditional statements starting with the recipe prefix were sometimes
interpreted in previous versions. As per the documentation, lines starting
with the recipe prefix are now never considered conditional statements.

View File

@ -1672,13 +1672,27 @@ conditional_line (char *line, size_t len, const floc *flocp)
if (termin == ',')
{
int count = 0;
for (; *line != '\0'; ++line)
if (*line == '(')
++count;
else if (*line == ')')
--count;
else if (*line == ',' && count <= 0)
break;
char *delim = xmalloc (strlen (line));
while (*line != '\0')
{
if (*line == '$')
{
++line;
if (*line == '(')
delim[count++] = ')';
else if (*line == '{')
delim[count++] = '}';
}
else if (count == 0)
{
if (*line == ',')
break;
}
else if (*line == delim[count-1])
--count;
++line;
}
free (delim);
}
else
while (*line != '\0' && *line != termin)

View File

@ -215,6 +215,44 @@ endif
!,
'', "#MAKE#: 'all' is up to date.");
# SV 64402: parse braces in ifeq/ifneq properly
run_make_test(q!
ifeq ($(and a,b),)
endif
ifeq (${and a,b},)
endif
ifeq (${and $(x),${or $(z),${q}}},)
endif
ifeq (${and ),(},)
endif
ifeq ($(and },{),)
endif
# We can hide the comma in a variable
C = ,
ifeq ((and a$Cb),)
endif
all:;
!,
'', "#MAKE#: 'all' is up to date.");
# The "," in "$," is a variable name not a comma
run_make_test(q!
ifeq ($,,)
$(info ok)
endif
all:;
!,
'', "ok\n#MAKE#: 'all' is up to date.");
# Without variable references we don't do anything special with parens
run_make_test(q!
ifeq ((and a,b),)
endif
all:;
!,
'', "#MAKEFILE#:2: extraneous text after 'ifeq' directive\n#MAKE#: 'all' is up to date.");
# This tells the test driver that the perl test script executed properly.
1;