microsoft / microsoft/STL

`<regex>`: `regex_search()` throws `regex_error(error_complexity)` with an unwisely written pattern

Open
#6,452 1 comment 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

bug regex
Dominant language
C++
Stars
11.1k
Forks
1.7k
Avg merge
4d 15h
Merged PRs (30d)
22

Description

Related to #6347.

This was reported by the compiler back-end team, reduced from an important test case. This was previously accepted (MSVC Build Tools 14.50 and earlier) with regex_search() returning false (the line has been deliberately changed to contain total_WOOF_pushes so total_heap_pushes won't be found). Now with MSVC Build Tools 14.51 and later, it is rejected with a complexity exception.

D:\GitHub\STL\out\x64>type regex_repro.cpp
#include <print>
#include <regex>
#include <string>
using namespace std;

int main() {
    const regex rx(R"(.*total_heap_pushes\s*:\s*(\d+) .*)");

    const string line = "Router Stats: total_nets_routed: 113175 "
                        "total_connections_routed: 437370 "
                        "total_WOOF_pushes: 313639277 "
                        "total_heap_pops: 35866777 "
                        "total_internal_heap_pushes: 0 "
                        "total_internal_heap_pops: 0 "
                        "total_external_heap_pushes: 313639277 "
                        "total_external_heap_pops: 35866777 "
                        "total_external_SOURCE_pushes: 379297 "
                        "total_external_SOURCE_pops: 379297 "
                        "total_internal_SOURCE_pushes: 0 "
                        "total_internal_SOURCE_pops: 0 "
                        "rt_node_SOURCE_pushes: 379297 "
                        "rt_node_SOURCE_high_fanout_pushes: 3797 "
                        "rt_node_SOURCE_entire_tree_pushes: 375500 "
                        "total_external_SINK_pushes: 3488243 "
                        "total_external_SINK_pops: 3260194 "
                        "total_internal_SINK_pushes: 0 "
                        "total_internal_SINK_pops: 0 "
                        "rt_node_SINK_pushes: 0 "
                        "rt_node_SINK_high_fanout_pushes: 0 "
                        "rt_node_SINK_entire_tree_pushes: 0 "
                        "total_external_IPIN_pushes: 5501600 "
                        "total_external_IPIN_pops: 3585046 "
                        "total_internal_IPIN_pushes: 0 "
                        "total_internal_IPIN_pops: 0 "
                        "rt_node_IPIN_pushes: 0 "
                        "rt_node_IPIN_high_fanout_pushes: 0 "
                        "rt_node_IPIN_entire_tree_pushes: 0 "
                        "total_external_OPIN_pushes: 14718566 "
                        "total_external_OPIN_pops: 8542877 "
                        "total_internal_OPIN_pushes: 0 "
                        "total_internal_OPIN_pops: 0 "
                        "rt_node_OPIN_pushes: 342094 "
                        "rt_node_OPIN_high_fanout_pushes: 8165 "
                        "rt_node_OPIN_entire_tree_pushes: 333929 "
                        "total_external_CHANX_pushes: 143852606 "
                        "total_external_CHANX_pops: 10396956 "
                        "total_internal_CHANX_pushes: 0 "
                        "total_internal_CHANX_pops: 0 "
                        "rt_node_CHANX_pushes: 2213020 "
                        "rt_node_CHANX_high_fanout_pushes: 482509 "
                        "rt_node_CHANX_entire_tree_pushes: 1730511 "
                        "total_external_CHANY_pushes: 145698965 "
                        "total_external_CHANY_pops: 9702407 "
                        "total_internal_CHANY_pushes: 0 "
                        "total_internal_CHANY_pops: 0 "
                        "rt_node_CHANY_pushes: 2442282 "
                        "rt_node_CHANY_high_fanout_pushes: 589528 "
                        "rt_node_CHANY_entire_tree_pushes: 1852754 "
                        "total_number_of_adding_all_rt: 8814821 "
                        "total_number_of_adding_high_fanout_rt: 62167 "
                        "total_number_of_adding_all_rt_from_calling_high_fanout_rt: 41981 ";

    try {
        const bool found = regex_search(line, rx);
        println("regex_search() returned {}.", found);
    } catch (const regex_error& re) {
        println("{}", re.what());
    }
}
D:\GitHub\STL\out\x64>cl /EHsc /nologo /W4 /std:c++latest /MTd /Od regex_repro.cpp
regex_repro.cpp

D:\GitHub\STL\out\x64>regex_repro
regex_error(error_complexity): The complexity of an attempted match against a regular expression exceeded a pre-set level.

In this case, telling the user to fix their regex is not especially feasible. (The initial ".*" used with a regex_search() is bad and should feel bad.) I would like to retune the limits to accept this case, while still guarding against severely pathological regex DoS scenarios.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by running the provided regex_repro.cpp case and trace the complexity handling behind regex_search() and regex_error(error_complexity). Identify the existing limits and related regression coverage; done means this case returns false without throwing while pathological regular expressions remain protected from excessive work.

Written by the indexing model from the issue text.

Assessment

Tech stack
cpp
Domain
backend, performance, security
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
48/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.