From fd2f743b3ef543a5b6fe963b2ec8c3c43b8424b9 Mon Sep 17 00:00:00 2001
From: Panu Matilainen <pmatilai@redhat.com>
Date: Thu, 19 Jan 2023 09:55:14 +0200
Subject: [PATCH] Fix macro scoping level on re-entry from %[] expresssion
 (#2354)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Conflict:NA
Reference:https://github.com/rpm-software-management/rpm/commit/fd2f743b3ef543a5b6fe963b2ec8c3c43b8424b9

This is the same issue as commit 1767bc4fd82bfacee622e698f9f0ae42c02126fa
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
---
 rpmio/macro.c     | 13 +++++++++++--
 tests/rpmmacro.at | 37 +++++++++++++++++++++++++++++++++++++
 2 files changed, 48 insertions(+), 2 deletions(-)

diff --git a/rpmio/macro.c b/rpmio/macro.c
index 2a00c22b3..d86b84608 100644
--- a/rpmio/macro.c
+++ b/rpmio/macro.c
@@ -58,8 +58,8 @@ struct rpmMacroEntry_s {
 struct rpmMacroContext_s {
     rpmMacroEntry *tab;  /*!< Macro entry table (array of pointers). */
     int n;      /*!< No. of macros. */
-    int depth;		 /*!< Depth tracking when recursing from Lua  */
-    int level;		 /*!< Scope level tracking when recursing from Lua  */
+    int depth;		 /*!< Depth tracking on external recursion */
+    int level;		 /*!< Scope level tracking when on external recursion */
     pthread_mutex_t lock;
     pthread_mutexattr_t lockattr;
 };
@@ -586,7 +586,16 @@ static void doExpressionExpansion(MacroBuf mb, const char * expr, size_t len)
 {
     char *buf = rstrndup(expr, len);
     char *result;
+    rpmMacroContext mc = mb->mc;
+    int odepth = mc->depth;
+    int olevel = mc->level;
+
+    mc->depth = mb->depth;
+    mc->level = mb->level;
     result = rpmExprStrFlags(buf, RPMEXPR_EXPAND);
+    mc->depth = odepth;
+    mc->level = olevel;
+
     if (!result) {
 	mb->error = 1;
 	goto exit;
diff --git a/tests/rpmmacro.at b/tests/rpmmacro.at
index 2a3052cca..55b7d5fa5 100644
--- a/tests/rpmmacro.at
+++ b/tests/rpmmacro.at
@@ -526,6 +526,43 @@ runroot rpm \
 [])
 AT_CLEANUP
 
+AT_SETUP([expression macro level])
+AT_KEYWORDS([macros])
+AT_CHECK([[
+runroot rpm \
+	--define 'expopt(r) %[%{undefined yyy} ? "aa " : "bb "]%{-r:the -r option was set}%{!-r:the -r option was not set}' \
+	--eval '%expopt' \
+	--eval '%expopt -r' \
+	--define 'yyy 1' \
+	--eval '%expopt' \
+	--eval '%expopt -r'
+]],
+[0],
+[aa the -r option was not set
+aa the -r option was set
+bb the -r option was not set
+bb the -r option was set
+],
+[])
+
+AT_CHECK([[
+runroot rpm \
+	--define 'expopt(r) %{expr:%{undefined yyy} ? "aa " : "bb "}%{-r:the -r option was set}%{!-r:the -r option was not set}' \
+	--eval '%expopt' \
+	--eval '%expopt -r' \
+	--define 'yyy 1' \
+	--eval '%expopt' \
+	--eval '%expopt -r'
+]],
+[0],
+[aa the -r option was not set
+aa the -r option was set
+bb the -r option was not set
+bb the -r option was set
+],
+[])
+AT_CLEANUP
+
 AT_SETUP([short circuiting])
 AT_KEYWORDS([macros])
 AT_CHECK([
-- 
2.33.0

