[Rpm-maint] [PATCH 5/5] Fix horrible bug in freeing macro arguments

Panu Matilainen pmatilai at laiskiainen.org
Tue Feb 12 06:11:40 UTC 2013


On 02/10/2013 01:16 PM, Panu Matilainen wrote:
> On 02/05/2013 06:31 AM, Alexey Tourbin wrote:
>> After a macro which takes options/arguments is called, such as
>> %systemd_post,
>> freeArgs() frees ALL macros *previously defined in specfile*.  For
>> example,
>> in amanda.spec, after scriptlet sections which invoke %systemd_*
>> macros are
>> processed, %amanda_user and %amanda_group in %files sections become
>> undefined,
>> resulting in malformed owner/group file metadata.
>>
>> $ rpm -qp --qf '[%{FILEUSERNAME}:%{FILEGROUPNAME}\n]'
>> amanda-3.3.2-2.fc18.x86_64.rpm |
>>> sort | uniq -c | sort -n | tail
>>        3 %amanda_user:%amanda_group
>>      104 root:root
>
> Nope. If you think about it, next to nothing would work if there was
> such a bug, really.
>
> This is the classic rpm "local macro scope" gotcha:
>
> %{!?amanda_user:%define amanda_user amandabackup}
>
> Since the define occurs inside a %{} "block", %amanda_user doesn't get
> defined in the global scope (or level 0 in rpm macro-speak) which you'd
> kinda expect but "local" level 1. Technically the %amanda_user macro
> should fall out of scope at the closing }, but these are only "garbage
> collected" when a parametrized macro is executed. Which leads to
> wonderfully obscure behavior and packaging bugs repeated again and
> again... It's also the reason why Fedora's packaging guidelines
> recommend using %global "everywhere", which in turn leads to other
> issues as %global differs from %define in other ways.
>
> In the meanwhile somebody has spotted the ownership issue and
> brute-forced it:
> http://pkgs.fedoraproject.org/cgit/amanda.git/commit/?h=f18
>
> A better fix would've been just to change the nested %defines into
> %globals, eg:
>
> %{!?amanda_user:%global amanda_user amandabackup}
>
> ...which places the %amanda_user macro in global scope as the original
> intention was, ensuring it wont get mopped out by a parametrized macro.
>
>> This change installs additional name check in freeArgs(), so that, upon
>> finishing macro call, only macro arguments are freed.
>
> NAK. This fundamentally changes the macro "language" behavior. Sort of
> like changing scope of all variables regardless of the place of
> declaration to global in C, but since this is rpm, with extra twists...
>
> I do agree the behavior is horrible, and it would be good to do
> something about it. I once tried to fix it by enforcing the "local
> scoping" for non-parametrized macros but it broke some complex but
> legitimate-looking macros in turn and didn't have the time and/or energy
> to chase it down. And since then largely forgotten about it...
>
> Thinking about it again, we could at least issue warnings about it.

Another possiblity might be a more subtle change towards the behavior 
that people generally expect: %define could be made to use global scope 
when used outside parametrized macro expansion.

That would continue to allow user defined "local variable" macros inside 
parameterized macros as they are now, but make the common
"%{!?foo:%define foo bar}" idiom in specs work reliably.

That is of course a fundamental "language" change too and could break 
somebody's legal macro constructs. It does seem unlikely, considering 
the current wacky behavior wrt user-defined "local" macros, but then you 
never know... It would also introduce another compatibility issue where 
specs relying on the new behavior would silently break on older rpm 
versions, and silent breakage is never nice.

Dunno, thoughts / opinions / better ideas welcome.

	- Panu -


More information about the Rpm-maint mailing list