Commit Graph

315 Commits

Author SHA1 Message Date
Panu Matilainen b1db055984 Raise an actual macro error if %{uncompress:...} fails 2019-02-25 16:29:06 +02:00
Panu Matilainen 4fa27e084e Convert %define, %global, %undefine and %dump to work via lookup table too
These are very different from the other built-ins as these do their
own parsing and return a continue address, so we need a separate
prototype for them. Having two pointers for each macro makes the table
a bit ugly but the alternative of tracking type by some other means
would lose type-safety. Other than all the boilerplate needed, this is
remarkably straightforward. No functional changes.

All built-in macros are now invoked via the lookup-table, which means
that adding new built-ins just got more straightforward and less ad hocey
pokey.
2019-01-15 17:03:47 +02:00
Panu Matilainen 93cda82b22 Convert %{trace} to work via the macro lookup table
%trace differs from the others as it doesn't take any arguments,
it just silently eats any passed. Not that it really matters here.
No functional changes.
2019-01-15 15:40:43 +02:00
Panu Matilainen 672c9e378b Convert %{load:...} to work via the macro lookup table
Annoyingly the amount of other boilerplate makes this slightly more code
than the original, but then saner code isn't always smaller, and it does
make expandMacros() smaller, which can only be a good thing.
No functional changes.
2019-01-15 15:31:19 +02:00
Panu Matilainen 311c5fdb0b Convert %{echo:...}, %{warn:...} and %{error:...} to work via lookup table
Handle log level determination inside doOutput() to make the interface
match with the others and as a bonus, make expandMacros() that little
bit smaller again. Empty argument needs to be handled differently
but shouldn't affect functionality.
2019-01-15 15:30:44 +02:00
Panu Matilainen 60327e1865 Convert %{lua:...} to work via builtin lookup table
No functional changes. chkexist and negate arguments are unused for
now, but they could perhaps be used for error condition handling later
(similar to %load)
2019-01-15 15:17:24 +02:00
Panu Matilainen ad0cf2cfa9 Start using the builtin macro table for looking up macro primitives, step 1
Replace the "necessary but clunky" string comparisons in expandMacro()
with a lookup on the builtins. For starters, only the primitives
handled in doFoo() are converted, others will require varying amount
of further changes. chkexist argument is unused by doFoo() but will be
needed later for others, add now to avoid having to change more later.

No functional changes intended, anything like that would simply be a bug.
2019-01-15 15:16:17 +02:00
Panu Matilainen 1c069fe246 Add two missing builtin macros (u2p and F) to the builtins table 2019-01-15 14:21:08 +02:00
Panu Matilainen 858e8c58f6 Make macro lookupBuiltin() work with non-terminated strings
For current uses this shouldn't make any difference, but much of the
macro engine works with string lengths so to avoid having to create
\0-terminated versions of all strings we might look at...
2019-01-15 13:36:46 +02:00
Panu Matilainen 69e8b91dcc Add a built-in macro for fetching number of CPUs, affinity aware and all
There's an increasing number of placing wanting to know the number of
CPU's for parallel processing, and increasingly these things are running
in containers and such where the total host CPU count is not meaningful.
2019-01-15 11:16:04 +02:00
Pavlina Moravcova Varekova 2456c12894 Fix a macro end detection if the first char of a macro line is '}' (#401)
The algorithm that detects the end of a macro counts for all macro chars their level of nested. It iteratively moves from the first char of the macro further.
Before the patch the rpm function does not implement this algorithm correctly. After finishing with the last char of a macro line, it additionally skips one char of the next line. The first char in the line was omitted.

Probably affects every rpm version from this millenium.
2018-03-27 12:29:56 +02:00
Panu Matilainen f7aff1193e Track and log failures when loading macro files
It's much easier for rpm to point out the location of invalid macro
definitions than it is for humans to grep all the places a given rpm
version might look at. Log the macro file path once per file in case
of failures, and additionally return and error if all definitions fail.

Based on patch by Pavlina Moravcova Varekova.
2018-01-08 13:08:45 +02:00
Pavlina Moravcova Varekova 9343ecd94c Disable redefinition or undefinition of a built-in macro
Prior to this patch if a name of a newly created macro was the same as a built-in macro name, the macro looked correctly defined. But the newly defined macro could not be used.

It is obvious that a built-in macro can not be undefined.
2018-01-08 12:53:43 +02:00
Pavlina Moravcova Varekova 25653e5db6 Consolidate macro name verification to helper function 2018-01-08 12:53:31 +02:00
Pavlina Moravcova Varekova 0032ee8c23 Don't expand %{verbose:...} argument on false condition
Prior to this patch %{verbose:...} argument was always expanded, eg:

	rpm -v --eval '%{verbose:%{echo:is verbose}}' \
	       --eval '%{!verbose:%{echo:is not verbose}}'

	is verbose

	is not verbose

Obviously both cannot be true.
2017-10-18 11:27:54 +03:00
Mark Wielaard 62bde9545a Avoid warning about mbAppendStr if lui support isn't enabled.
Guard the whole mbAppendStr function with ifdef WITH_LUA to avoid a
warning when lua support isn't enabled because it is only used inside
the doLua function (which is empty unles WITH_LUA is defined).

Signed-off-by: Mark Wielaard <mark@klomp.org>
2017-10-10 07:39:54 +03:00
Pavlina Moravcova Varekova e9d1ec565d Remove an outdated todo for %trace
I cannot find any reason for the TODO in these days.
2017-09-26 13:14:48 +03:00
Panu Matilainen 44570e253d Remove leftover parentheses, no functional change.
Should've been in commit 206c12acc2.
2017-09-01 11:17:48 +03:00
Panu Matilainen 206c12acc2 Don't assume %{quote:...} is surrounded by whitespace
As implemented in commit cdbc7e1d8b,
%{quote:...} only works when its used to quote the entire argument
and produces garbage when used in middle of other text, such as
"x%{quote:y}z". Not sure there's actual need to do that, but producing
garbage is never good.

Only unquoted separators can split an argument, copy argument manually
to strip any quote characters and adjust the math to match. Oh and
add testcases too.

Thanks to Pavlina Moravcova Varekova for pointing this out.
2017-09-01 10:59:21 +03:00
Panu Matilainen cdbc7e1d8b Support parametric macro argument quoting, take three (#222)
All the nice quote-characters are already spoken for, we need to
do something more special here. Add a special-purpose built-in %{quote:...}
macro which quotes its argument using ASCII unit separator character 0x1f
(so it really shouldn't get into anybodys way) and teach macro argument
splitting to support that.

So with %{quote:...} it's now possible to pass strings containing
whitespace and empty strings as arguments. It might not be pretty, but
it's at least POSSIBLE, and no existing user is bothered by this.
2017-08-31 12:36:32 +03:00
Pavlina Moravcova Varekova d78813fa94 When printMacro() is used, print newline after "(empty)" macro 2017-08-30 10:37:01 +03:00
Pavlina Moravcova Varekova fa39cb730d %trace mb states at the beginning/end of expandMacro must be equal
Macro %trace switched on in a nested stage level writes the trace
until the level is leaved to a lower stage level. This did not
work e.g. for macros containing several condition macros.

For example:
%prep
%define Branch1() {%trace %global Leaf1 "1"}
%define Branch2() {%global Leaf2 "2"}
%define Main() {%{?test1: %Branch1} %{?test1: %Branch2}}
%Main

with the result:
  4>         %global^Leaf1 "1"
  2>     %{?test1: %Branch2}^
  3>       %Branch2^
  4>         %global^Leaf2 "2"

It was because macro expansion is context free. This patch fixes it.
2017-08-30 10:33:14 +03:00
Panu Matilainen 4e647cd979 Eliminate unnecessary "delete" argument to freeArgs()
This became unused and useless with the big scoping change in
commit 237f35f16f. No functional
changes here.
2017-08-22 10:25:56 +03:00
Panu Matilainen 609adaa758 Bump macro max recursion limit up
Fedora java packages are running into the old limit of sixteen nesting
levels (commit b3179e6de3), bump it up
to 64. The old limit lasted almost twenty years, lets see how far this
gets us.
2017-08-21 16:36:32 +03:00
Panu Matilainen 2986e7659d Remove redundant max_macro_depth initialization
Oldies but goodies: the max depth is already initialized in declaration
to _MAX_MACRO_DEPTH which has been the same 16 since late nineties. This
wasn't always the case of course...
2017-08-18 17:12:47 +03:00
Pavlina Moravcova Varekova 94e8cd6058 Make macro %{error:...} cause an actual failure 2017-08-17 16:16:23 +03:00
Pavlina Moravcova Varekova a3b153eb47 Unified messages printed by %{echo:...}, %{warn:...}, and %{error:...}
Send all through rpmlog(), unify formatting - previously echo and
warn were missing the trailing newline. The other change is that
echo now goes to stdout.
2017-08-17 16:15:39 +03:00
Panu Matilainen a3c1f733e0 Revert "Support quoting of macro arguments (#222)"
This simply breaks too many things - whole macro ecosystems exist based
on the assumption that quotes in arguments will pass to macros
untouched. Macro argument quoting support is necessary but it'll
need some entirely different approach that is either opt-in or
based on a different syntax altogether.

This reverts commit 47f0a899ef.
2017-08-14 14:28:10 +03:00
Jeff Johnson 3684424fe2 Add support for zstd compressed payload
v2 (Igor Gnatenko):
    * Switch off from RPM_CHECK_LIB
    * Reference zstd from rpm.pc
    * Link rpmio with zstd
  v3 (Florian Festi):
    * move changes to cvtfmode into separate patches
    * do not error out on wrong compression levels
    * ifdef out zstdio
    Closes: https://github.com/rpm-software-management/rpm/issues/256
    Closes: https://github.com/rpm-software-management/rpm/issues/297
    Signed-off-by: Igor Gnatenko <i.gnatenko.brain@gmail.com>
2017-08-09 17:41:03 +02:00
Pavlina Moravcova Varekova c4d41c30ce Shift macro scoping level values as they are defined
Some of scoping level values are defined in rpmmacros.h:
 #define RMIL_DEFAULT    -15
 #define RMIL_MACROFILES -13
...
 #define RMIL_GLOBAL     0

Before this patch RPM set these values decreased of 1 (for all macros).
Because of the (level - 1) in
    pushMacro(dst, me->name, me->opts, me->body, (level - 1), me->flags);
in function copyMacros scoping level for some CMDLINE macros was decreased of 1.
Because of the (level - 1) in
    pushMacro(mb->mc, n, o, b, (level - 1), ME_NONE);
in function doDefine scoping level values of all other macro types and
some CMDLINE macros was decreased of 1.
The patch shifts scoping level values back to the numbers defined
in rpmmacros.h.

This was spotted when investigating a regression introduced in
commit 237f35f16f where locally scoped
scoped macros did not get deleted on scope closing.
This also fixes the regression in question.

The first test in this patch tests automatic deleting of %defined macros.
The second test checks whether the behavior changed by
237f35f16f is still working correctly.

Thanks to Panu Matilainen for investigation and proposal of the main part
of the patch!
2017-08-09 14:36:15 +03:00
Pavlina Moravcova Varekova 6ca89685e3 Distinguish %define and %global in the illegal macro name error message 2017-08-09 13:31:18 +03:00
Pavlina Moravcova Varekova 47f0a899ef Support quoting of macro arguments (#222)
Single or double quotes can be used in macro arguments
as expected - they denote the begin and the end of the argument.

Example with 2-nd and 3-rd argument in double quotes:
./rpm --define "%foo() 1:%1 2:%2 3:%3" \
         --eval '%foo Next_argument_will_be_empty "" "Last argument"'
1:Next_argument_will_be_empty 2: 3:Last argument

Example with all arguments in single quotes,
without spaces between arguments:

./rpm --define "%foo() 1:%1 2:%2 3:%3" \
         --eval "%foo 'Next argument will be empty''''Last argument'"
1:Next argument will be empty 2: 3:Last argument
2017-08-09 13:02:54 +03:00
Per Øyvind Karlsen 7fe183d660 Add support for %{shrink:} (ported from rpm5.org)
Shrinks body by removing all leading and trailing whitespaces and
reducing intermediate whitespaces to a single space character.
2017-08-09 12:57:22 +03:00
Ville Skyttä 2901e265a0 Spelling fixes 2017-06-27 14:42:21 +02:00
Panu Matilainen 85953c0d72 Revert "Expand parameterized macro arguments one by one after splitting"
This essentially reverts commit 9ae7d1df31.
Leaving the testcase in place, just adjusting it to the expected
behavior where arguments that expand to empty are eaten away.

This actually matches what the shell does, so it follows the path of
least surprise in that sense - we emulate shell behavior with the
arguments etc already in many ways. What the shell has and rpm
has not is a way to pass those empty arguments by quoting. So
now we need a way to quote arguments - not just for passing empty
arguments but arguments containing whitespaces too.
2017-05-23 11:15:31 +03:00
Panu Matilainen 767d61ca3d Preserve %%-escapes when expanding parametric macro arguments (#217)
There needs to be a way to pass escaped macros names (and other strings
containging %%) as parametric macro arguments. Add an internal mode
to preserve %% when expanding the arguments. Fixes a regression introduced
in commit 5adc56897b.

Thanks to Michael Schroeder for pointing this out!
2017-05-18 13:47:21 +03:00
Panu Matilainen 9ae7d1df31 Expand parameterized macro arguments one by one after splitting
This makes makes the behavior much more sensible eg in case an
argument expands to an empty strings, such as:
    $ rpm --define '%foo() 1:%1 2:%2' --eval '%foo %nil bar'
After commit 5adc56897b rpm was
evaluating that to "1:bar 2:%2" which is hardly what you'd expect.

Thanks to Michael Schroeder for pointing this out! (#217)
2017-05-18 12:48:14 +03:00
Panu Matilainen 117b337fb2 Remember flags passed to rpmExpandMacros() in the expansion state buffer
Of course right now there are no implemented flags so this doesn't
actually do anything.
2017-05-18 11:19:13 +03:00
Panu Matilainen 5adc56897b Expand parametric macro arguments before processing (#127, RhBug:1397209)
This too is quite a fundamental change for macros: up to now, arguments
to parametric macros have not been expanded. It doesn't sound so bad
until you consider something like the case in RhBug:1397209:

        %global rev 133
        ...
        %setup %{?rev:-c}
        %autosetup %{?rev:-c}

One would expect %setup and %autosetup behave the same when you replace
one with the other, but no.  %setup gets "called" with -c, %autosetup
does not. Instead %autosetup receives a completely useless, literal
"%{?rev:-c}" as its argument.  That's just brain-meltingly non-sensical.

This certainly has the potential to break advanced macro constructs,
but OTOH what breaks might well be only written that way in order to
work around the former behavior.

There are some funny subtleties involved as the argument expansion
must occur in the callers scope, ie before we create any of the
automatic macros. For example, Fedora's font packages break if only
this or the macro scope visibility enforcement is applied but start
working again once both are present.
2017-03-07 14:26:45 +02:00
Panu Matilainen 307627993e Enforce visibility scoping for automatic macros
When a parametric macro "calls" another parametric macro with fewer
arguments than it received, the inner macro would see the %<n>
macros of the outer call which is an obvious scoping violation
and quirky behavior, making macro writing harder than it needs be.

Similar scoping issues exist for manually defined macros but those
have further complications (because of %undefine semantics)  that we
sheepishly avoid here by limiting the visibility enforcing to automatic
macros only (for now at least).
2017-03-07 14:06:55 +02:00
Panu Matilainen 237f35f16f Change macro scoping to be global / local to parametric macros
This changes the macro scoping rules quite fundamentally: macro
definitions are local to the parametric macro they were defined in,
and everything else is global. Among other things, this makes this
common spec idiom (RhBug:552944, RhBug:551971 etc) behave
deterministically because "foo" is placed into global scope:

        %{?!foo: %define foo bar}

In theory it's certainly possible that this breaks somebodys carefully
crafted advanced macros but it seems quite unlikely, considering how
broken the alleged block-scoping has been. OTOH for macros defined
within parametric macros, nothing actually changes as that scoping has
always been enforced by rpm. The non-global define tracking is also
no longer needed for emitting warnings, because the case where it
was needed simply no longer exists.

Note that macro recursion depth is a different thing and still needs
to be tracked separately.
2017-03-07 14:03:12 +02:00
Panu Matilainen e2f4347356 Consolidate all macro argument setup to grabArgs()
Since we actually setup all the same automatic macros whether there
are arguments or not, doing it centrally only makes sense. Shuffle
things around a bit in preparation for the next steps.
2017-03-07 13:58:56 +02:00
Panu Matilainen 3b1f4b0c6c Cosmetics: if, while and switch are followed by a space
The missing space style-error has been recently coming common enough
somebody might think that IS the expected style, its not. Some of these
are actually very old, but fix across the board for consistency..

Strictly white-space only change.
2017-02-27 17:41:37 +02:00
Peter Jones e6f346ead4 Don't nerf "rpmspec --eval '%trace' -P foo.spec" output with ellipses.
The whole point of %trace is that some macro is being evaluated in a
surprising way, and you want to know what it is.  This is often the
result of an unfortunately complex macro with difficult to see
intermediate results.

Shortening the output because it doesn't fit past 61 or so characters
does not help, and we have big screens these days.  Don't do it.

Signed-off-by: Peter Jones <pjones@redhat.com>
2017-02-24 13:23:16 +01:00
Peter Jones bf248badd3 Bounds check strings to print correctly in %trace mode.
In %trace mode, evaluating a macro which is undefined causes an invalid
read of 1 byte when searching for the end of the string:

trillian:~$ valgrind rpmspec --eval '%trace' --eval '%{?myUndefinedMacro}'
==21534== Memcheck, a memory error detector
==21534== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al.
==21534== Using Valgrind-3.12.0 and LibVEX; rerun with -h for copyright info
==21534== Command: rpmspec --trace --eval %{?myUndefinedMacro}
==21534==

  1>   %{?myUndefinedMacro}^==21534== Invalid read of size 1
==21534==    at 0x55018D4: printMacro (macro.c:296)
==21534==    by 0x5502DFC: expandMacro (macro.c:1077)
==21534==    by 0x5503710: doExpandMacros (macro.c:1280)
==21534==    by 0x5504AB6: rpmExpand (macro.c:1629)
==21534==    by 0x508F59A: rpmcliAllArgCallback (poptALL.c:120)
==21534==    by 0x6DAF71D: invokeCallbacksOPTION (popt.c:156)
==21534==    by 0x6DAF75B: invokeCallbacksOPTION (popt.c:139)
==21534==    by 0x6DB1428: poptGetNextOpt (popt.c:1515)
==21534==    by 0x508F912: rpmcliInit (poptALL.c:302)
==21534==    by 0x1095B2: main (rpmspec.c:63)
==21534==  Address 0x8a010f3 is 0 bytes after a block of size 19 alloc'd
==21534==    at 0x4C2DB9D: malloc (vg_replace_malloc.c:299)
==21534==    by 0x5507C17: rmalloc (rpmmalloc.c:44)
==21534==    by 0x5502788: expandMacro (macro.c:927)
==21534==    by 0x5503710: doExpandMacros (macro.c:1280)
==21534==    by 0x5504AB6: rpmExpand (macro.c:1629)
==21534==    by 0x508F59A: rpmcliAllArgCallback (poptALL.c:120)
==21534==    by 0x6DAF71D: invokeCallbacksOPTION (popt.c:156)
==21534==    by 0x6DAF75B: invokeCallbacksOPTION (popt.c:139)
==21534==    by 0x6DB1428: poptGetNextOpt (popt.c:1515)
==21534==    by 0x508F912: rpmcliInit (poptALL.c:302)
==21534==    by 0x1095B2: main (rpmspec.c:63)
==21534==

  1>   %{?_transaction_color}^
  1>   %{?_prefer_color}^
  1>   %{_netsharedpath}^
  1>   %{_install_langs}^
==21534==
==21534== HEAP SUMMARY:
==21534==     in use at exit: 7,183 bytes in 71 blocks
==21534==   total heap usage: 7,811 allocs, 7,740 frees, 3,500,361 bytes allocated
==21534==
==21534== LEAK SUMMARY:
==21534==    definitely lost: 19 bytes in 1 blocks
==21534==    indirectly lost: 0 bytes in 0 blocks
==21534==      possibly lost: 0 bytes in 0 blocks
==21534==    still reachable: 7,164 bytes in 70 blocks
==21534==         suppressed: 0 bytes in 0 blocks
==21534== Rerun with --leak-check=full to see details of leaked memory
==21534==
==21534== For counts of detected and suppressed errors, rerun with: -v
==21534== ERROR SUMMARY: 5 errors from 1 contexts (suppressed: 0 from 0)
trillian:~$

This can easily be avoided by checking the first byte as well as the
second for our sentinal value (NUL).

Signed-off-by: Peter Jones <pjones@redhat.com>
2017-02-24 13:23:16 +01:00
Panu Matilainen 1767bc4fd8 Preserve macro scoping level on re-entry from Lua
When a %{lua:...} macro calls rpm.expand(), it re-enters the macro
environment at depth zero regardless of what the "calling" nesting
level was. This could lead to wrong macros getting mopped out on
complex, nested lua + native macro calls.

Store the depth in global macro context and pick up the initial value
from there to keep the nesting level increasing on when entering %{lua:...}
space.
2017-01-20 15:23:01 +02:00
Panu Matilainen f95825ef1b Add return code to rpmPushMacro() and rpmPopMacro()
These haven't been in any public release yet so there's time to
fiddle with stuff like this. Both always succeed currently so no
change in that respect but it's better to have room for expansion...
2017-01-19 16:03:15 +02:00
Panu Matilainen 31bc44c5a9 Actually return errors from macro definition 2017-01-19 14:24:26 +02:00
Panu Matilainen bd942d5fee Raise actual error on unknown option to parametric macro 2017-01-19 14:18:29 +02:00
Panu Matilainen 02dea59e3a Flag real errors from macro define and undefine errors
This WILL cause behavior changes in cases where there have been
illegal macro names etc which have previously been more or less
ignored with an logged error, but now they will actually abort.
2017-01-19 14:15:38 +02:00