]> git.ipfire.org Git - thirdparty/util-linux.git/commitdiff
libsmartcols: reject large interval repetition bounds in filter regex
authorKarel Zak <kzak@redhat.com>
Tue, 30 Jun 2026 10:49:26 +0000 (12:49 +0200)
committerKarel Zak <kzak@redhat.com>
Tue, 30 Jun 2026 10:49:26 +0000 (12:49 +0200)
ERE interval expressions like {,32232} cause glibc regcomp() to
allocate gigabytes for the NFA, triggering OOM even on tiny inputs.
The existing consecutive-quantifier and nested-group checks do not
catch this pattern.

Scan numbers inside {...} and reject any bound exceeding
SCOLS_FILTER_MAX_REPCNT (1024). Document the new limit in
scols-filter(5).

Addresses: https://oss-fuzz.com/testcase-detail/6017673394454528
Signed-off-by: Karel Zak <kzak@redhat.com>
libsmartcols/scols-filter.5.adoc
libsmartcols/src/filter-param.c
libsmartcols/src/smartcolsP.h

index 5822ac00a54384059bbae2f7f3001818e8ea3931..315218ede946759c5dab755bf99966d9ccfc2fc3 100644 (file)
@@ -115,8 +115,9 @@ The filter expression string is limited to 1024 bytes. The number of nodes
 (parameters and operators) in a single expression is limited to 256.
 
 Regular expression patterns used with the `=~` and `!~` operators are limited to
-256 bytes. Patterns with consecutive quantifiers (e.g., `a++`, `a**`) or nested
-group repetitions (e.g., `(a+)+`) are rejected because they can cause excessive
+256 bytes. Patterns with consecutive quantifiers (e.g., `a++`, `a**`), nested
+group repetitions (e.g., `(a+)+`), or interval repetitions with bounds larger
+than 1024 (e.g., `{,9999}`) are rejected because they can cause excessive
 memory consumption in the POSIX regex compiler.
 
 == AUTHORS
index b7bff69687db0ffd26099ab45aeaf3700bcfdc5d..c77ae397ca62ef0d22a19808804f0e9a4e5fbf52 100644 (file)
@@ -131,8 +131,9 @@ struct filter_node *filter_new_param(
        return (struct filter_node *) n;
 }
 
-/* Consecutive ERE quantifiers (a++, a**) and nested group repetitions
- * ((a+)+, (a*)*) cause glibc regcomp() to allocate gigabytes for the NFA. */
+/* Consecutive ERE quantifiers (a++, a**), nested group repetitions
+ * ((a+)+, (a*)*), and large interval bounds ({,N} where N is huge)
+ * cause glibc regcomp() to allocate gigabytes for the NFA. */
 static int is_unsafe_regex(const char *pattern)
 {
        size_t i, len = strlen(pattern);
@@ -153,6 +154,25 @@ static int is_unsafe_regex(const char *pattern)
                                        return 1;
                        }
                }
+
+               /* reject large ERE interval bounds like {,32232} or {1,9999} */
+               if (pattern[i] == '{') {
+                       const char *p = &pattern[i + 1];
+
+                       while (*p && *p != '}') {
+                               if (*p >= '0' && *p <= '9') {
+                                       unsigned long val;
+                                       char *end = NULL;
+
+                                       errno = 0;
+                                       val = strtoul(p, &end, 10);
+                                       if (errno || val > SCOLS_FILTER_MAX_REPCNT)
+                                               return 1;
+                                       p = end;
+                               } else
+                                       p++;
+                       }
+               }
        }
        return 0;
 }
index f7504830d6aca32387dd46a1ff80459ece35abec..b252ee02c6514ea638fefd9dce771686fddd5c2f 100644 (file)
@@ -567,6 +567,7 @@ struct libscols_filter {
 #define SCOLS_FILTER_MAX_EXPRSZ        1024
 #define SCOLS_FILTER_MAX_NODES 256
 #define SCOLS_FILTER_MAX_REGSZ 256
+#define SCOLS_FILTER_MAX_REPCNT        1024
 
 struct filter_node *__filter_new_node(enum filter_ntype type, size_t sz);
 void filter_ref_node(struct filter_node *n);