Commit Graph

445 Commits

Author SHA1 Message Date
Panu Matilainen 7f69da1909 Take advantage of C++ native mutex facilities for macro locking
C++ guarantees initialization of static objects takes place before
threads can run, so we don't need all the locksInitialized fubar.
The native objects also release themselves which fixes a theoretical
leak we had: we never destroyed the lock or lockattr so they remained
reachable until program exit.

We could continue to acquire and release the lock in the corresponding
functions but that's not RAII and would be inconsistent with what we
do elsewhere in rpm, just convert to the local lock variable style.
2024-09-24 10:08:38 +02:00
Florian Festi ef87d25034 Reset recursion depth for error message
$ rpm --define 'aaa %[%aaa]' --eval '%aaa'

let to a core dump due to a stack overflow. This was cause by the
generation of the error message failing due to being too deep in the
recursion of the macro expansion - creating more error messages.

Resetting the depth counter allows rendering the error message. As we are
failing and breaking off the parse run this is fine to do.

Thanks to Miro Hrončok for reporting

Resolves: #3197
2024-07-23 14:24:56 +02:00
Panu Matilainen c00d8a0ed3 Replace typedef's with using = for new internal C++ constructs
typedef's prevent const correctness and have various other issues,
"using" is the native modern version. When in Rome...
2024-06-26 11:07:59 +03:00
Michael Schroeder b871b68706 Always clear the RPMEXPAND_KEEP_QUOTED flag if we do not return the resulting flags
If the resulting flags cannot be returned, the caller has no way to
strip the quote characters. So we must assume that we are not to
return quotes in this case.

Fixes issue #3145
2024-06-05 14:46:01 +03:00
Panu Matilainen 1f66db3459 Untangle the per-name stack from the macro entry struct
Use an STL stack to store the macro entries sharing the name to separate
the data from its containing structure, this lets the macro entries be
proper C++ objects that manage their own business only and thus can be
also directly stored containers, doing away with manual allocation.

And now that these entries no longer need any special care, we can
delete all the copy-control fubar from the main macro context: it's all
standard library storage now and don't need our handholding.
2024-04-30 09:06:24 +03:00
Panu Matilainen a39bb9359e Convert macro table to STL containers + native strings
Use an STL map for the macro entry table, this matches exactly the behavior
we manually did with the C array.

The variable length array at end of macro entry structs is not really
C++, use native strings for the storage. It's slower, but not tragically
so. For now, keep name, opts and body as const char pointers though to
the c_str() items to avoid having to change everything at once.

Popping macros is a bit clunky and repetitive, we'll clean it up later.
findEntry() returns a pointer to the macro entry itself instead of
pointer to pointer, which simplifies things a bit further.

This is a wee bit slower than the "raw C" counterpart, but by no means
tragically so and moving to native structures opens up other opportunities
in turn, both optimization and feature wise. Further work will be easier
now that the highly optimized but also tangled up data structure is
(mostly) untangled.
2024-04-30 09:06:24 +03:00
Panu Matilainen e571df4b9c Add copy control and in particular, destructor to the macro context
The macro contexts being static structs, they get their destructor
automatically called at program end. Which counter-intuitively *causes*
a leak if macros are stored in an STL container and rpmFreeMacros()
isn't called, because then the container clears itself and the macros
are left dangling, whereas without the destructor they are still
reachable. freeMacros() obviously wants to be a member function but
trying to keep things in the struct land for now.

Doesn't really change anything as of now, but this is needed for moving
the macro storage to C++ container.
2024-04-30 09:06:24 +03:00
Panu Matilainen bac494c35c Replace a couple of local IO buffers with a vector 2024-04-25 13:25:02 +03:00
Panu Matilainen 695b5c2521 Fix multiply defined local macros escaping scope
freeArgs() only popped any local macros once, so if a local macro was
pushed multiple times, whether through %define or multiple identical
options getting passed, we leaked any remaining macros to the outside
scope.

Simply pop the local macros in a loop to fix. Have the internal
popMacro() return the previous pointer (if any) to simplify the job.
We even had an expected-fail test for this, now passing, but add a
more straightforward reproducer too.

This bug was circa 26 years old. Some might call it vintage at this point.

Fixes: #3056
2024-04-24 11:06:35 +02:00
Panu Matilainen eb561c88bc Use c++ string for rpmExpand() helper buffer 2024-04-23 09:36:51 +03:00
Panu Matilainen 59984c66c5 Use a c++ string for macro expansion buffer
Natively allocate the struct so we can use a string in there.
2024-04-23 09:36:51 +03:00
Panu Matilainen 62840a3cdf Add casts that C++ requires but C doesn't across librpmio
In other words, a whole lot of "yes, really".
2024-04-09 11:00:00 +03:00
Panu Matilainen 437b5a1068 Avoid jumping over variable declarations
C lets us do this but in C++ needs to run destructors at end of scope,
so they better be properly initialized...

These are all over the place but so trivial putting them to different
commits doesn't make much sense.
2024-04-09 08:16:18 +03:00
Panu Matilainen 7445a092f7 Lift %shrink out of doFoo()
This really belongs to a separate function in the first place, and doing
so allows us to turn 'b' into a const char *, which in turn makes
the assignment to string literal "" in the url2path case legitimate.
Fun times and no functional changes.
2024-04-05 13:18:27 +03:00
Panu Matilainen 3a2b04c96d Avoid relying on writable string literals in macros
This hack here is illegal in c++. Just strdup() the silly little string,
it's not like this is a performance critical spot.
2024-04-05 13:18:27 +03:00
Panu Matilainen 8de699ee70 Issue a warning when passing arguments to non-parametric macros
This should be an error for consistency with other macro argument
checking but as there appear to be usages in the wild, make it a
warning for now.

Fixes: #2932
2024-03-14 10:30:30 +01:00
Florian Festi 3ad98187cc Use basename (3) for the %basename macro 2024-03-07 12:39:19 +01:00
Florian Festi 9571e3d9a2 Use dirname (3) for %dirname
This changes the behaviour of %dirname to something sane. No longer
return the argument unchanged if there is no / found. Also handle
several cornercases properly.

Resolves: #2928
2024-03-07 12:39:19 +01:00
Michael Schroeder fff2111af9 Strip quote characters in macro expansion if we do not split the result
A problem with the old handling of %quote was that it leaked to
the outside. This commit strips the quote characters if they are
not used in argument splitting.

We also keep track of the quotes when defining macros so that
we stay compatible to the old implementation.
2023-12-08 09:11:22 +02:00
Michael Schroeder ad1b3d13c6 Make shescape escape all arguments and not just the first one
This makes the %shescape macro work use all arguments like we
already do in the %quote macro.

I.e.:
    %{shescpae:hello world} -> 'hello world'
    %{shescpae hello world} -> 'hello' 'world'
2023-12-08 09:11:22 +02:00
Panu Matilainen 1cd9f9077a Fix integer overflow in memory calculations on 32bit systems
"long int" on at least x86 Linux is exactly the same as a plain "int",
so calculations can easily overflow. 32bit systems are not expected to
have hundreds of gigabytes of memory but a 32bit process on a x86_64 can
run into all sorts of funny things, such having 500GB system memory. At
which point the type capable of addressing all of process memory is
absolutely useless for calculating the total memory.

Use uint64_t in the memory calculations to make the size explicit. Of course
one day we may cross that border too, but I hope to be retired by then.

Fixes https://issues.redhat.com/browse/RHEL-16557
2023-11-27 15:56:19 +02:00
Panu Matilainen c110ad11c3 Fix segfault on %{?getncpus}, regression in 4.19.x
Commit deaebd0c89 assumed there would
always be args, but in the macro existence test none are set up.

Reported as a side-issue in https://issues.redhat.com/browse/RHEL-16557
2023-11-16 11:24:09 +02:00
Panu Matilainen 6714ec7068 Fix %{getncpus proc/thread} potentially returning zero
Add the missing sanity check/fixup for memory starved systems where
we end up returning zero cpus. Should've been in commit
deaebd0c89 originally.

Reported in https://issues.redhat.com/browse/RHEL-16557
2023-11-15 09:31:37 +02:00
Panu Matilainen f9ae0a4da8 Refactor %__file_lineno management into an auxiliary macro
Now that we can, just define __file_lineno as an auxiliary macro that
only does any work in the rare case where an error or warning occurred.
This saves an enormous amount of huffing and puffing defining and
undefining macros that are not used at all in the normal paths, on
every rpm startup and spec parse.

Technically we could use a common macro function for both but as they're
in separate libraries, this doesn't seem worth the few lines of saving.
2023-11-07 10:09:52 +02:00
Panu Matilainen e9c997f637 Add support for defining auxiliary macro functions
Add rpmPushMacroAux() function which allows registering auxiliary macros
implemented in C and some required helper facilities: export the types,
rpmMacroBufAppend*() and rpmMacroBufErr() functions, and finally
add rpmMacroEntryPriv() to let macro retrieve their private data.
And that's all folks.
2023-10-27 10:08:04 +03:00
Panu Matilainen 336c07c2e9 Rename mbErr() and mbAppend*() to rpmMacroBuf*() for exporting
Just preparing to export in the next steps. No functional changes.
2023-10-27 10:08:04 +03:00
Panu Matilainen 0758d03f7f Rename MacroBuf to rpmMacroBuf for exporting
This is just in preparation for exposing the handle in some APIs.
No functional changes.
2023-10-27 10:08:04 +03:00
Panu Matilainen 1c98b67911 Drop top-level source for our global include directories
Having everything accessible to everything encourages fast and loose
includes from places one shouldn't be using, and makes it easy for
those cases to hide in plain sight as well. There were reasons for
the top-level include back in 2007 but our codebase is a rather
different beast these days. Limiting access through per-target
include directories on everything nicely highlights the exceptions
and makes the whole more controllable and manageable.

This change looks huge, but it's just due to stripping no longer valid
prefixes from all the gazillion internal includes. No rpm-side
functionality is affected, this is just source-level hygiene operation.
2023-09-13 13:34:17 +03:00
Panu Matilainen b38077eae0 Add %{rpmversion} builtin macro for getting the running rpm version
Seems like a useful thing to have, and a bit crazy that we haven't had any
reasonable mechanism for this before now.

Fixes: #2523
2023-05-30 10:34:08 +03:00
Panu Matilainen deaebd0c89 Add optional total/proc/thread arguments to %{getncpus} macro
"total" equals calling with no arguments, "proc" and "thread" consider
further constraints, what is implemented here is heuristics based on
available physical memory and address-space and %_smp_tasksize_proc /
%_smp_tasksize_thread tunables.

Change the previous %getncpus related tests to use %getconfdir instead,
they are testing unexpected arguments behavior for this type of macro,
not %getncpus itself. Add a test for the actual functionality: if nproc
is available, test that our total matches with that, and that defining
tasksize to total memory only allocates one thread. Optimally we'd
test separately for 32bit address space limitations but that gets tough
when we have no idea where this will be executed.
2023-03-30 13:58:04 +03:00
Panu Matilainen fd2f743b3e Fix macro scoping level on re-entry from %[] expresssion (#2354)
This is the same issue as commit 1767bc4fd8
was with Lua, and so the same fix works: restore the nesting level
from the macro context when re-entering macro engine from %[]
expression. Analysis and suggested fix by Michael Schroeder,
reproducer from Miro Hrončok.

Add tests for both %[] and %{expr:...}, although the latter isn't
affected because the expression is macro-expanded beforehand.

Fixes: #2354
2023-01-20 07:58:48 +02:00
Panu Matilainen cad5affacd Add shorthand macros for some conventient Lua string operations
Despite all the Lua magic we already do, it's annoyingly often the case
that shelling out is easier (or at least shorter) than doing the same in
Lua (substrings, length etc)

Add shorthand macros %gsub, %len, %lower, %rep, %reverse, %sub and
%upper which simply wrap the corresponding Lua string.* functions for
convenience.
2022-09-15 10:32:08 +03:00
Panu Matilainen 48d0fa954c Test for preprocessor definition rather than value consistently everywhere
This is not supposed to actually change anything as such but
inconsistency is bad and causes other kinds of headaches.
2022-06-15 16:24:51 +03:00
Panu Matilainen 10804d32d9 Use rpmuncompress to handle %{uncompress:...}
This means that finally there's just one place that when adding support
for new compress formats, there's in theory there's just one place to
update. Reality is a little more complicated, but hey...

Adjust tests a bit, and rather test functionality than command output
because those reflect command paths which we can't easily adjust now.
2022-04-04 10:04:25 +03:00
Michael Schroeder 718295d91e Support multiple args in %quote and make split/unsplit available to lua
This allows to manipulate an argument array from lua.
2021-11-18 09:44:44 +02:00
Michael Schroeder 3c793a653d Simplify shrink macro implementation
Less code and easier to understand.
2021-11-08 11:10:25 +02:00
Michael Schroeder efc3f10754 Do not always strdup the argument in doFoo
Only a small subset of the doFoo macros needs to modify the
argument, so only do the strdup call in them.
2021-11-08 11:10:25 +02:00
Michael Schroeder 162b2d3a33 Do not setup macro args for literal macros
They cannot make use of the arguments, so it makes no sense to set
them up.
2021-11-08 11:10:25 +02:00
Michael Schroeder 48825725e6 Remove duplicated body copying code
Put the name first in the string arena so that the macro body
copying code is identical for both macro setting cases.
2021-11-08 11:10:25 +02:00
Michael Schroeder 263f70b204 Split new macro table entry generation into newEntry()
No functional changes, just to make the code easier to understand.
2021-11-08 11:10:25 +02:00
Michael Schroeder 26767d4646 Allow an optional argument for the %verbose macro
This improves compatibility with old rpm versions. If an argument
is present, the macro expands to it in verbose mode and to an
empty string if not in verbose mode.
2021-10-26 16:12:29 +03:00
Michael Schroeder bfbd0b3e7f Support non-parametric builtins again
Macros like %getncpus should not treat the following text as
macro arguments. E.g. 'make -j %getncpus all' should work and
not complain about an unexpected argument.

We still treat arguments passed via %{foo:arg} or %{foo arg} as an
error for builtin macros. (They are silently ignored for user
defined macros.)
2021-10-26 10:01:56 +03:00
Michael Schroeder c00d85fb5e Make %{define foo body} not use the free-field parsing
This means no special new line processing and '\' unescaping. Thus
"%{define foo body}" works similar to "%define foo {body}" except
that the parsing in spec files works because copyNextLineFromOFI()
knows how to deal with macros.
2021-10-26 10:01:56 +03:00
Michael Schroeder 374c0edac0 Special case the non-parametric and the free-field macro expansion
This makes the code easier to understand and also has the advantage
that "parsed" will be NULL for the normal cases.

No functual changes.
2021-10-26 10:01:56 +03:00
Michael Schroeder 243d01ff46 Rename doExpandThisMacro to doMacro
The doXXX functions now have the same argument signature and I
never liked the doExpandThisMacro name.
2021-10-26 10:01:56 +03:00
Michael Schroeder 1d1f461f80 Add a "parsed" argument to the doXXX() functions
doXXX() used to return the parsed characters for ME_PARSE macros
and the caller added them to the "parsed" variable.

We now directly pass parsed as argument and let the doXXX()
functions do the adding. This will allow us to differentiate
between "%define foo bar" and "%{define foo bar}" in a
future commit.

No functual changes.
2021-10-26 10:01:56 +03:00
Michael Schroeder 80f025863f Fix consistency issues in macro expansion for builtin macros
The builtin macros used to expand the arguments themselfs. This
works for the %{foo:bar} syntax, but it means that for %{foo bar}
the argument is expanded twice: once before the argument is split
and then in the macro function.

Simplify the code by always doing the expansion when creating
the argument vector.
2021-10-26 10:01:56 +03:00
Michael Schroeder 79e8c46b12 Get rid of the ME_BUILTIN macro
Always set ME_FUNC for builtin functions.
2021-10-26 10:01:56 +03:00
Panu Matilainen 5e97c0a3ac Clean up shescape macro implementation
Realizing that we have dynamic string buffer available in the macro
engine... so we don't need a dumb worst case malloc and all the other
crap in the old tag format era implementation.
2021-10-08 14:36:27 +02:00
Panu Matilainen f64ad44ccd Add %{shescape:...} macro for single quoting with escapes for the shell
This is exactly the same as :shescape query format, hence the name.
2021-09-24 14:55:44 +02:00