From 5b6cabdc92136594bc141d15f95330b467b682ce Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Thu, 27 Aug 2026 12:50:29 +0100 Subject: [PATCH 1/2] C++: Test edge cases for string literal locations. --- cpp/ql/test/library-tests/regex/locations.expected | 1 + cpp/ql/test/library-tests/regex/parse.expected | 6 ++++++ cpp/ql/test/library-tests/regex/regexp.cpp | 7 +++++++ cpp/ql/test/library-tests/regex/regexp.expected | 6 ++++++ 4 files changed, 20 insertions(+) diff --git a/cpp/ql/test/library-tests/regex/locations.expected b/cpp/ql/test/library-tests/regex/locations.expected index a9f12c020d79..3490d50ab49d 100644 --- a/cpp/ql/test/library-tests/regex/locations.expected +++ b/cpp/ql/test/library-tests/regex/locations.expected @@ -61,3 +61,4 @@ | regexp.cpp:120:41:120:44 | a\\nc | regexp.cpp | 120 | 41 | 120 | 44 | | regexp.cpp:121:25:121:28 | a\\nc | regexp.cpp | 121 | 25 | 121 | 28 | | regexp.cpp:122:29:122:32 | a\\nc | regexp.cpp | 122 | 29 | 122 | 32 | +| regexp.cpp:127:29:127:32 | abc1 | regexp.cpp | 127 | 29 | 127 | 32 | diff --git a/cpp/ql/test/library-tests/regex/parse.expected b/cpp/ql/test/library-tests/regex/parse.expected index e8d84b277514..7a43829eb847 100644 --- a/cpp/ql/test/library-tests/regex/parse.expected +++ b/cpp/ql/test/library-tests/regex/parse.expected @@ -1,3 +1,7 @@ +#-----| [RegExpConstant, RegExpNormalChar] xabc3x + +#-----| [RegExpConstant, RegExpNormalChar] abc2 + regexp.cpp: # 18| [RegExpConstant, RegExpNormalChar] abc @@ -637,3 +641,5 @@ regexp.cpp: # 122| [RegExpConstant, RegExpEscape] \n # 122| [RegExpConstant, RegExpNormalChar] c + +# 127| [RegExpConstant, RegExpNormalChar] abc1 diff --git a/cpp/ql/test/library-tests/regex/regexp.cpp b/cpp/ql/test/library-tests/regex/regexp.cpp index 51986dd59adf..785caae0db3f 100644 --- a/cpp/ql/test/library-tests/regex/regexp.cpp +++ b/cpp/ql/test/library-tests/regex/regexp.cpp @@ -120,3 +120,10 @@ std::basic_regex r_loc_uR(uR"(a\nc)"); std::basic_regex r_loc_UR(UR"(a\nc)"); std::regex r_loc_Rx(R"x(a\nc)x"); std::regex r_loc_Rfoo(R"foo(a\nc)foo"); + +// Composite and stringified string literals +#define STRINGIFY(str) #str +#define WRAP(str) "x" #str "x" +std::regex r_loc_composite("ab" "c1"); +std::regex r_loc_macro1(STRINGIFY(abc2)); +std::regex r_loc_macro2(WRAP(abc3)); diff --git a/cpp/ql/test/library-tests/regex/regexp.expected b/cpp/ql/test/library-tests/regex/regexp.expected index 6e7a4cfc7204..1c08a6cfccdb 100644 --- a/cpp/ql/test/library-tests/regex/regexp.expected +++ b/cpp/ql/test/library-tests/regex/regexp.expected @@ -4,6 +4,8 @@ groupNumber | regexp.cpp:57:20:57:27 | (a\|b\|cd) | 1 | | regexp.cpp:61:21:61:24 | (a+) | 1 | term +| file://:0:0:0:0 | abc2 | RegExpConstant,RegExpNormalChar | +| file://:0:0:0:0 | xabc3x | RegExpConstant,RegExpNormalChar | | regexp.cpp:18:19:18:21 | abc | RegExpConstant,RegExpNormalChar | | regexp.cpp:21:20:21:20 | a | RegExpConstant,RegExpNormalChar | | regexp.cpp:21:20:21:21 | a* | RegExpStar | @@ -238,7 +240,10 @@ term | regexp.cpp:122:29:122:32 | a\\nc | RegExpSequence | | regexp.cpp:122:30:122:31 | \\n | RegExpConstant,RegExpEscape | | regexp.cpp:122:32:122:32 | c | RegExpConstant,RegExpNormalChar | +| regexp.cpp:127:29:127:32 | abc1 | RegExpConstant,RegExpNormalChar | regExpNormalCharValue +| file://:0:0:0:0 | abc2 | abc2 | +| file://:0:0:0:0 | xabc3x | xabc3x | | regexp.cpp:18:19:18:21 | abc | abc | | regexp.cpp:21:20:21:20 | a | a | | regexp.cpp:21:22:21:22 | b | b | @@ -362,3 +367,4 @@ regExpNormalCharValue | regexp.cpp:122:29:122:29 | a | a | | regexp.cpp:122:30:122:31 | \\n | \n | | regexp.cpp:122:32:122:32 | c | c | +| regexp.cpp:127:29:127:32 | abc1 | abc1 | From 04eb1daf15d95610bbc55928c474746a8b7906a3 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Thu, 27 Aug 2026 12:53:58 +0100 Subject: [PATCH 2/2] C++: Address an edge case for regex locations. --- cpp/ql/lib/semmle/code/cpp/regex/RegexTreeView.qll | 5 +++++ cpp/ql/test/library-tests/regex/locations.expected | 2 ++ cpp/ql/test/library-tests/regex/parse.expected | 8 ++++---- cpp/ql/test/library-tests/regex/regexp.expected | 8 ++++---- 4 files changed, 15 insertions(+), 8 deletions(-) diff --git a/cpp/ql/lib/semmle/code/cpp/regex/RegexTreeView.qll b/cpp/ql/lib/semmle/code/cpp/regex/RegexTreeView.qll index 9e659f8168a6..51454ede4e72 100644 --- a/cpp/ql/lib/semmle/code/cpp/regex/RegexTreeView.qll +++ b/cpp/ql/lib/semmle/code/cpp/regex/RegexTreeView.qll @@ -222,6 +222,11 @@ private module Impl implements RegexTreeViewSig { // Find the opening '"'. not re instanceof RawStringLiteral and result = 1 + min(int i | vt.charAt(i) = "\"") + or + // No opening '"'. + not re instanceof RawStringLiteral and + not exists(int i | vt.charAt(i) = "\"") and + result = 0 ) } diff --git a/cpp/ql/test/library-tests/regex/locations.expected b/cpp/ql/test/library-tests/regex/locations.expected index 3490d50ab49d..5bf219789c0d 100644 --- a/cpp/ql/test/library-tests/regex/locations.expected +++ b/cpp/ql/test/library-tests/regex/locations.expected @@ -62,3 +62,5 @@ | regexp.cpp:121:25:121:28 | a\\nc | regexp.cpp | 121 | 25 | 121 | 28 | | regexp.cpp:122:29:122:32 | a\\nc | regexp.cpp | 122 | 29 | 122 | 32 | | regexp.cpp:127:29:127:32 | abc1 | regexp.cpp | 127 | 29 | 127 | 32 | +| regexp.cpp:128:35:128:38 | abc2 | regexp.cpp | 128 | 35 | 128 | 38 | +| regexp.cpp:129:25:129:30 | xabc3x | regexp.cpp | 129 | 25 | 129 | 30 | diff --git a/cpp/ql/test/library-tests/regex/parse.expected b/cpp/ql/test/library-tests/regex/parse.expected index 7a43829eb847..2c7133d90946 100644 --- a/cpp/ql/test/library-tests/regex/parse.expected +++ b/cpp/ql/test/library-tests/regex/parse.expected @@ -1,7 +1,3 @@ -#-----| [RegExpConstant, RegExpNormalChar] xabc3x - -#-----| [RegExpConstant, RegExpNormalChar] abc2 - regexp.cpp: # 18| [RegExpConstant, RegExpNormalChar] abc @@ -643,3 +639,7 @@ regexp.cpp: # 122| [RegExpConstant, RegExpNormalChar] c # 127| [RegExpConstant, RegExpNormalChar] abc1 + +# 128| [RegExpConstant, RegExpNormalChar] abc2 + +# 129| [RegExpConstant, RegExpNormalChar] xabc3x diff --git a/cpp/ql/test/library-tests/regex/regexp.expected b/cpp/ql/test/library-tests/regex/regexp.expected index 1c08a6cfccdb..6980c8e3b962 100644 --- a/cpp/ql/test/library-tests/regex/regexp.expected +++ b/cpp/ql/test/library-tests/regex/regexp.expected @@ -4,8 +4,6 @@ groupNumber | regexp.cpp:57:20:57:27 | (a\|b\|cd) | 1 | | regexp.cpp:61:21:61:24 | (a+) | 1 | term -| file://:0:0:0:0 | abc2 | RegExpConstant,RegExpNormalChar | -| file://:0:0:0:0 | xabc3x | RegExpConstant,RegExpNormalChar | | regexp.cpp:18:19:18:21 | abc | RegExpConstant,RegExpNormalChar | | regexp.cpp:21:20:21:20 | a | RegExpConstant,RegExpNormalChar | | regexp.cpp:21:20:21:21 | a* | RegExpStar | @@ -241,9 +239,9 @@ term | regexp.cpp:122:30:122:31 | \\n | RegExpConstant,RegExpEscape | | regexp.cpp:122:32:122:32 | c | RegExpConstant,RegExpNormalChar | | regexp.cpp:127:29:127:32 | abc1 | RegExpConstant,RegExpNormalChar | +| regexp.cpp:128:35:128:38 | abc2 | RegExpConstant,RegExpNormalChar | +| regexp.cpp:129:25:129:30 | xabc3x | RegExpConstant,RegExpNormalChar | regExpNormalCharValue -| file://:0:0:0:0 | abc2 | abc2 | -| file://:0:0:0:0 | xabc3x | xabc3x | | regexp.cpp:18:19:18:21 | abc | abc | | regexp.cpp:21:20:21:20 | a | a | | regexp.cpp:21:22:21:22 | b | b | @@ -368,3 +366,5 @@ regExpNormalCharValue | regexp.cpp:122:30:122:31 | \\n | \n | | regexp.cpp:122:32:122:32 | c | c | | regexp.cpp:127:29:127:32 | abc1 | abc1 | +| regexp.cpp:128:35:128:38 | abc2 | abc2 | +| regexp.cpp:129:25:129:30 | xabc3x | xabc3x |