commit:     66bd0378c4ead7c72c40782187463c2d3a19c23d
Author:     Fabian Groffen <grobian <AT> gentoo <DOT> org>
AuthorDate: Thu Feb  5 14:04:14 2026 +0000
Commit:     Fabian Groffen <grobian <AT> gentoo <DOT> org>
CommitDate: Thu Feb  5 14:04:14 2026 +0000
URL:        https://gitweb.gentoo.org/proj/portage-utils.git/commit/?id=66bd0378

libq/dep: be more careful parsing random input

Our assumption that ['s cannot be nested isn't true in reality when we
get unexpanded shell variable things thrown at us.

Bug: https://bugs.gentoo.org/968490
Signed-off-by: Fabian Groffen <grobian <AT> gentoo.org>

 libq/dep.c | 25 ++++++++++++++++++++-----
 1 file changed, 20 insertions(+), 5 deletions(-)

diff --git a/libq/dep.c b/libq/dep.c
index ea89b1b3..4662e842 100644
--- a/libq/dep.c
+++ b/libq/dep.c
@@ -73,7 +73,7 @@ dep_node_t *dep_grow_tree
   const char *ptr             = NULL;
   const char *word;
   size_t      n;
-  int         level           = 0;
+  int         level;
   int         nots            = 0;
 
   /* the language is mostly token oriented, and officially whitespace is
@@ -147,9 +147,23 @@ dep_node_t *dep_grow_tree
     case '[':
       /* these are atom's USE-conditionals which may include ( ) ? !
        * too, so just scan until matching ], luckily these can't be
-       * nested */
-      for (ptr++; *ptr != '\0' && *ptr != ']'; ptr++)
-        ;
+       * nested -- except when we get unexpanded bash stuff like
+       * ${LIB_DEPEND//[static-libs([+-])]} it does, so check it */
+      level = 0;
+      for (ptr++; *ptr != '\0'; ptr++)
+      {
+        if (*ptr == ']')
+        {
+          if (level == 0)
+            break;
+          else
+            level--;
+        }
+        else if (*ptr == '[')
+        {
+          level++;
+        }
+      }
       ptr--;  /* rewind for outer for-loop */
       continue;
     default:
@@ -180,7 +194,8 @@ dep_node_t *dep_grow_tree
   ret->type    = DEP_ALL;
   ret->members = array_new();
   array_append(res, ret);  /* == level */
-  ret = NULL;
+  ret   = NULL;
+  level = 0;
 
   array_for_each(tokens, n, curr_node)
   {

Reply via email to