Skip to content

Commit

Permalink
Collapse unexpanded macro definitions (rpm-software-management#1198)
Browse files Browse the repository at this point in the history
Since the body of a newly defined macro may span multiple lines and
contain %if expressions, we need to make sure the line parser does not
try to interpret those when the corresponding %define or %global macro
appears in a false %if branch and is therefore left unexpanded in the
line buffer.

This is usually not a problem since any macros found in the body itself
would not be expanded anyway, but it can break the syntax check for
conditionals, which follows after expansion.  This is because, with the
recently introduced support for line-continuation markers in %if
expressions (commit 5f4fdce), the parser would be tricked into thinking
that the markers belong to the %if expression itself and collapse them
into a single line, including the matching %endif, and then complain
about the missing %endif (which must be on a separate line).

Instead, similarly to %if, we should collapse the %define/%global macro
itself so that the line parser doesn't pass through the body at all.

A side effect of this change (of commit 5f4fdce from a year ago, in
fact) is that %if constructs are no longer syntax-checked within macros
defined in false %if branches, but that's arguably correct behavior,
since they only come into existence when their definition macro (%define
or %global) is actually expanded, and should merely be treated as text
values until that point.

Fixes: rpm-software-management#1198
  • Loading branch information
dmnks committed Apr 5, 2021
1 parent e838c48 commit 92971cc
Show file tree
Hide file tree
Showing 4 changed files with 40 additions and 1 deletion.
6 changes: 5 additions & 1 deletion build/parseSpec.c
Original file line number Diff line number Diff line change
Expand Up @@ -354,12 +354,16 @@ static parsedSpecLine copyNextLineFinish(rpmSpec spec, int strip)
lineType = parseLineType(s);

while (*spec->nextline && ch != '\n') {
/* for conditionals and %include trim trailing '\' */
/* Interpret line-continuation markers. Unexpanded %define or %global
* that spans multiple lines and thus could interfere with the parser
* is also collapsed here.
*/
if (lineType && (*spec->nextline == '\\') &&
(*spec->nextline+1) && (*(spec->nextline+1) == '\n')) {
*spec->nextline = ' ';
*(spec->nextline+1) = ' ';
}

ch = *spec->nextline++;
if (!risspace(ch))
last = spec->nextline;
Expand Down
4 changes: 4 additions & 0 deletions build/rpmbuild_internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@ typedef enum rpmParseLineType_e {
LINE_ELIF = (1 << 8),
LINE_ELIFARCH = (1 << 9),
LINE_ELIFOS = (1 << 10),
LINE_DEFINE = (1 << 11),
LINE_GLOBAL = (1 << 12),
} rpmParseLineType;

typedef const struct parsedSpecLine_s {
Expand All @@ -69,6 +71,8 @@ static struct parsedSpecLine_s const lineTypes[] = {
{ LINE_ELIFARCH, LEN_AND_STR("%elifarch"), 1, 1, LINE_ENDIF | LINE_ELSE},
{ LINE_ELIFOS, LEN_AND_STR("%elifos"), 1, 1, LINE_ENDIF | LINE_ELSE},
{ LINE_ELIF, LEN_AND_STR("%elif") ,1, 1, LINE_ENDIF | LINE_ELSE},
{ LINE_DEFINE, LEN_AND_STR("%define") , 1, 0, 0},
{ LINE_GLOBAL, LEN_AND_STR("%global") , 1, 0, 0},
{ 0, 0, 0, 0, 0, 0 }
};

Expand Down
22 changes: 22 additions & 0 deletions tests/data/SPECS/ifmultiline-macro.spec
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
Name: ifmultiline-macro
Version: 1.0
Release: 1
Group: Testing
License: GPL
BuildArch: noarch
Summary: Test multiline if conditions

%description
%{summary}

%if 0

%define test() \
%if 1 \
%{echo:hello} \
%endif \
%nil

%endif

%changelog
9 changes: 9 additions & 0 deletions tests/rpmbuild.at
Original file line number Diff line number Diff line change
Expand Up @@ -1832,4 +1832,13 @@ runroot rpmbuild -ba --quiet \
[0],
[],
[])

# multiline %if test (inside of unexpanded macro)
AT_CHECK([
runroot rpmbuild -ba --quiet \
data/SPECS/ifmultiline-macro.spec
],
[0],
[],
[])
AT_CLEANUP

0 comments on commit 92971cc

Please sign in to comment.