[PATCH] posix: Don't unnecessarily duplicate the parse tree in regcomp [BZ #20095]
Florian Weimer
fweimer@redhat.com
Fri Oct 17 07:41:03 GMT 2025
* Collin Funk:
> Florian Weimer <fweimer@redhat.com> writes:
>
>>> Currently regcomp duplicates the the parse tree for each repetition
>>> operator. This patch avoids the duplication when the previous repetition
>>> operator is the same as the current operator. This prevents you from
>>> quickly exhausting the system's memory. Here is an example with GNU grep
>>> before and after this change:
>>>
>>> $ (ulimit -v 10000000 \
>>> && grep -Ec 'a++++++++++++++++++++++++' COPYING)
>>> grep: Memory exhausted
>>> $ (ulimit -v 10000000 \
>>> && ./src/grep -Ec 'a++++++++++++++++++++++++' COPYING)
>>> 509
>>
>> Does this change really make a difference? It seems we still run out of
>> memory for ?+?+?+… and similar patterns.
>
> Oops, you are right...
>
> I guess the way to match the current behavior without allocating
> unbounded memory from adjacent duplication symbols is to allow only one
> of each. You could optimize it even further by converting any occurrence
> of "+?" or "?+" into "*" and any sequence of symbols containing "*" into
> only "*".
>
> Let me think about it a bit more and send a v2.
There's also this:
#include <regex.h>
#include <support/check.h>
#include <sys/resource.h>
#include <string>
static int
do_test (void)
{
struct rlimit stack_limit = { 512 * 1024 * 1024, 512 * 1024 * 1024 };
setrlimit (RLIMIT_AS, &stack_limit);
const int count = 512;
std::string pattern;
for (int i = 0; i < count; ++i)
pattern += '(';
pattern += 'a';
for (int i = 0; i < count; ++i)
pattern += ")+";
regex_t re;
TEST_VERIFY_EXIT (regcomp (&re, pattern.c_str(), REG_EXTENDED) == 0);
regfree (&re);
return 0;
}
#include <support/test-driver.c>
So this is much larger issue, I think.
In your test, you should probably remove the setrlimit check, in case
it's raising the limit and not reducing it.
Thanks,
Florian
More information about the Libc-alpha
mailing list