summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPanu Matilainen <pmatilai@redhat.com>2017-03-07 14:06:55 +0200
committerPanu Matilainen <pmatilai@redhat.com>2017-03-07 14:06:55 +0200
commit307627993ec0c3eed729aea34843a87aa5bde6d2 (patch)
treef40de8972fad2bd00de2b8426cc15c256aaa7a70
parent237f35f16f978bb20e4cafd78abfab1f2e5db480 (diff)
downloadrpm-307627993ec0c3eed729aea34843a87aa5bde6d2.tar.gz
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).
-rw-r--r--rpmio/macro.c12
-rw-r--r--tests/rpmmacro.at13
2 files changed, 22 insertions, 3 deletions
diff --git a/rpmio/macro.c b/rpmio/macro.c
index 6428b9caa..69f5c9d81 100644
--- a/rpmio/macro.c
+++ b/rpmio/macro.c
@@ -1211,9 +1211,15 @@ expandMacro(MacroBuf mb, const char *src, size_t slen)
mep = findEntry(mb->mc, f, fn, NULL);
me = (mep ? *mep : NULL);
- /* If we looked up a macro, consider it used */
- if (me)
- me->flags |= ME_USED;
+ if (me) {
+ if ((me->flags & ME_AUTO) && mb->level > me->level) {
+ /* Ignore out-of-scope automatic macros */
+ me = NULL;
+ } else {
+ /* If we looked up a macro, consider it used */
+ me->flags |= ME_USED;
+ }
+ }
/* XXX Special processing for flags */
if (*f == '-') {
diff --git a/tests/rpmmacro.at b/tests/rpmmacro.at
index e1d9ccfd7..e238edcea 100644
--- a/tests/rpmmacro.at
+++ b/tests/rpmmacro.at
@@ -79,6 +79,19 @@ foo 5
[])
AT_CLEANUP
+AT_SETUP([parametrized macro 2])
+AT_KEYWORDS([macros])
+AT_CHECK([
+runroot rpm \
+ --define '%bar() "Bar %#: %{?1} %{?2}"' \
+ --define '%foo() "Foo %#: %{?1} %{?2}" %bar a' \
+ --eval '%foo 1 2'
+],
+[0],
+["Foo 2: 1 2" "Bar 1: a "
+])
+AT_CLEANUP
+
AT_SETUP([uncompress macro])
AT_KEYWORDS([macros])
AT_CHECK([