mirror of
https://github.com/github/codeql.git
synced 2026-07-31 15:33:00 +02:00
Commit 9: Fix hasLocationInfo for all string literal forms; fix unicode escape
RegexTreeView.qll - hasLocationInfo fix (RULE 4):
- Add regexpContentOffset(RegExp re) private helper that computes the correct
number of source chars before the first content char, from getValueText():
- Plain "...": offset 1
- L"...": offset 2 (L" prefix)
- u8"...": offset 3 (u8" prefix)
- R"(...)": offset 3 (R"( opener)
- R"x(...)x": offset 4 (R"x( with custom delim)
- LR"(...)": offset 4 (LR"()
- Uses vt.matches("%R\"%(%") to detect raw strings; finds '(' position
- For non-raw, finds '"' position
- Replace hardcoded `+ 1` with `+ regexpContentOffset(re)` in hasLocationInfo
- Update comment: documents plain/encoding/raw/combined forms, notes that
escaped non-raw strings are approximate (mirroring Java/Python)
test.cpp:
- Fix r_uni: change "\\u{9879}" to "\\u9879" — braced \u{...} is not standard
C++ regex syntax; the 4-digit \uHHHH form is valid ECMAScript \u escape
Regenerated all 3 .expected files via codeql test run --learn (CodeQL 2.26.1).
All 3 tests pass.
Location test confirms:
- Plain "a+b" (line 144): litStartCol 22 → termStartCol 23 (22+1) UNCHANGED ✓
- Raw R"(a+b)" (line 147): litStartCol 20 → termStartCol 23 (20+3) FIXED ✓
- Raw R"x(a+b)x" (line 156): litStartCol 21 → termStartCol 25 (21+4) FIXED ✓
- L"a+b" (line 159): litStartCol 22 → termStartCol 24 (22+2) FIXED ✓
- LR"(a+b)" (line 162): litStartCol 26 → termStartCol 30 (26+4) FIXED ✓
This commit is contained in:
committed by
GitHub
parent
e7ccb1f2ce
commit
bfa65301f1
@@ -114,6 +114,36 @@ private module Impl implements RegexTreeViewSig {
|
||||
override string getAPrimaryQlClass() { result = "RegExpLiteral" }
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the number of source characters from the start of the string literal `re`
|
||||
* to the first content character (i.e., past the opening delimiter).
|
||||
*
|
||||
* This is derived from the raw source spelling via `StringLiteral.getValueText()`:
|
||||
* - Plain `"..."`: offset 1 (just the `"`)
|
||||
* - Encoding prefix `L"..."`: offset 2 (`L"`)
|
||||
* - Encoding prefix `u8"..."`: offset 3 (`u8"`)
|
||||
* - Raw `R"(...)"` offset 3 (`R"(`)
|
||||
* - Custom-delim raw `R"x(...)x"` offset 4 (`R"x(` — delim length 1)
|
||||
* - Combined `LR"(...)"` offset 4 (`LR"(`)
|
||||
*
|
||||
* For non-raw strings, the value-offset maps 1:1 to source columns only when
|
||||
* there are no escape sequences; escaped non-raw strings are approximate
|
||||
* (mirroring Java/Python regex libraries).
|
||||
*/
|
||||
private int regexpContentOffset(RegExp re) {
|
||||
exists(string vt | vt = re.getValueText() |
|
||||
// Raw string: find the '(' that opens the raw content.
|
||||
// getValueText() for raw strings looks like: [prefix]R"[delim](...)[delim]"
|
||||
// The opening '(' is after the optional prefix, 'R', '"', and custom delimiter.
|
||||
vt.matches("%R\"%(%") and
|
||||
result = 1 + min(int i | vt.charAt(i) = "(" and i >= 1)
|
||||
or
|
||||
// Non-raw string: find the opening '"'.
|
||||
not vt.matches("%R\"%(%") and
|
||||
result = 1 + min(int i | vt.charAt(i) = "\"")
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* A regular expression term, that is, a syntactic part of a regular expression.
|
||||
*/
|
||||
@@ -211,18 +241,30 @@ private module Impl implements RegexTreeViewSig {
|
||||
*/
|
||||
Location getLocation() { result = re.getLocation() }
|
||||
|
||||
/** Holds if this term is found at the specified location offsets.
|
||||
/**
|
||||
* Holds if this term is found at the specified location offsets.
|
||||
*
|
||||
* Note: for commit 2, this uses an approximate offset of 1 for the
|
||||
* opening delimiter. Commits 8-9 fix this for all string literal forms.
|
||||
* The content offset is computed from `StringLiteral.getValueText()` (the raw source
|
||||
* spelling including delimiters), so it is correct for:
|
||||
* - Plain `"..."`: offset 1 (`"`)
|
||||
* - Encoding prefixes `L"..."`: offset 2 (`L"`)
|
||||
* - Encoding prefix `u8"..."`: offset 3 (`u8"`)
|
||||
* - Raw `R"(...)"` offset 3 (`R"(`)
|
||||
* - Custom-delim raw `R"x(...)x"`: offset 4+len(delim) (`R"` + delim + `(`)
|
||||
* - Combined, e.g. `LR"(...)"` offset 4 (`LR"(`)
|
||||
*
|
||||
* Note: for non-raw strings, the value-string offset equals the source-column offset
|
||||
* only when there are no escape sequences. Escaped characters are an approximation,
|
||||
* mirroring the Java/Python regex libraries.
|
||||
*/
|
||||
predicate hasLocationInfo(
|
||||
string filepath, int startline, int startcolumn, int endline, int endcolumn
|
||||
) {
|
||||
exists(int re_start |
|
||||
exists(int re_start, int offset |
|
||||
re.getLocation().hasLocationInfo(filepath, startline, re_start, endline, _) and
|
||||
startcolumn = re_start + 1 + start and
|
||||
endcolumn = re_start + 1 + end - 1
|
||||
offset = regexpContentOffset(re) and
|
||||
startcolumn = re_start + offset + start and
|
||||
endcolumn = re_start + offset + end - 1
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -2,36 +2,36 @@
|
||||
| test.cpp:144:23:144:24 | a+ | 22 | 0 | 2 | 23 | 24 |
|
||||
| test.cpp:144:23:144:25 | a+b | 22 | 0 | 3 | 23 | 25 |
|
||||
| test.cpp:144:25:144:25 | b | 22 | 2 | 3 | 25 | 25 |
|
||||
| test.cpp:147:21:147:21 | a | 20 | 0 | 1 | 21 | 21 |
|
||||
| test.cpp:147:21:147:22 | a+ | 20 | 0 | 2 | 21 | 22 |
|
||||
| test.cpp:147:21:147:23 | a+b | 20 | 0 | 3 | 21 | 23 |
|
||||
| test.cpp:147:23:147:23 | b | 20 | 2 | 3 | 23 | 23 |
|
||||
| test.cpp:150:22:150:23 | \\s | 21 | 0 | 2 | 22 | 23 |
|
||||
| test.cpp:150:22:150:24 | \\s+ | 21 | 0 | 3 | 22 | 24 |
|
||||
| test.cpp:150:22:150:25 | \\s+$ | 21 | 0 | 4 | 22 | 25 |
|
||||
| test.cpp:150:25:150:25 | $ | 21 | 3 | 4 | 25 | 25 |
|
||||
| test.cpp:153:22:153:23 | \\( | 21 | 0 | 2 | 22 | 23 |
|
||||
| test.cpp:153:22:153:35 | \\(([,\\w]+)+\\)$ | 21 | 0 | 14 | 22 | 35 |
|
||||
| test.cpp:153:24:153:31 | ([,\\w]+) | 21 | 2 | 10 | 24 | 31 |
|
||||
| test.cpp:153:24:153:32 | ([,\\w]+)+ | 21 | 2 | 11 | 24 | 32 |
|
||||
| test.cpp:153:25:153:29 | [,\\w] | 21 | 3 | 8 | 25 | 29 |
|
||||
| test.cpp:153:25:153:30 | [,\\w]+ | 21 | 3 | 9 | 25 | 30 |
|
||||
| test.cpp:153:26:153:26 | , | 21 | 4 | 5 | 26 | 26 |
|
||||
| test.cpp:153:27:153:28 | \\w | 21 | 5 | 7 | 27 | 28 |
|
||||
| test.cpp:153:33:153:34 | \\) | 21 | 11 | 13 | 33 | 34 |
|
||||
| test.cpp:153:35:153:35 | $ | 21 | 13 | 14 | 35 | 35 |
|
||||
| test.cpp:156:22:156:22 | a | 21 | 0 | 1 | 22 | 22 |
|
||||
| test.cpp:156:22:156:23 | a+ | 21 | 0 | 2 | 22 | 23 |
|
||||
| test.cpp:156:22:156:24 | a+b | 21 | 0 | 3 | 22 | 24 |
|
||||
| test.cpp:156:24:156:24 | b | 21 | 2 | 3 | 24 | 24 |
|
||||
| test.cpp:159:23:159:23 | a | 22 | 0 | 1 | 23 | 23 |
|
||||
| test.cpp:159:23:159:24 | a+ | 22 | 0 | 2 | 23 | 24 |
|
||||
| test.cpp:159:23:159:25 | a+b | 22 | 0 | 3 | 23 | 25 |
|
||||
| test.cpp:159:25:159:25 | b | 22 | 2 | 3 | 25 | 25 |
|
||||
| test.cpp:162:27:162:27 | a | 26 | 0 | 1 | 27 | 27 |
|
||||
| test.cpp:162:27:162:28 | a+ | 26 | 0 | 2 | 27 | 28 |
|
||||
| test.cpp:162:27:162:29 | a+b | 26 | 0 | 3 | 27 | 29 |
|
||||
| test.cpp:162:29:162:29 | b | 26 | 2 | 3 | 29 | 29 |
|
||||
| test.cpp:147:23:147:23 | a | 20 | 0 | 1 | 23 | 23 |
|
||||
| test.cpp:147:23:147:24 | a+ | 20 | 0 | 2 | 23 | 24 |
|
||||
| test.cpp:147:23:147:25 | a+b | 20 | 0 | 3 | 23 | 25 |
|
||||
| test.cpp:147:25:147:25 | b | 20 | 2 | 3 | 25 | 25 |
|
||||
| test.cpp:150:24:150:25 | \\s | 21 | 0 | 2 | 24 | 25 |
|
||||
| test.cpp:150:24:150:26 | \\s+ | 21 | 0 | 3 | 24 | 26 |
|
||||
| test.cpp:150:24:150:27 | \\s+$ | 21 | 0 | 4 | 24 | 27 |
|
||||
| test.cpp:150:27:150:27 | $ | 21 | 3 | 4 | 27 | 27 |
|
||||
| test.cpp:153:24:153:25 | \\( | 21 | 0 | 2 | 24 | 25 |
|
||||
| test.cpp:153:24:153:37 | \\(([,\\w]+)+\\)$ | 21 | 0 | 14 | 24 | 37 |
|
||||
| test.cpp:153:26:153:33 | ([,\\w]+) | 21 | 2 | 10 | 26 | 33 |
|
||||
| test.cpp:153:26:153:34 | ([,\\w]+)+ | 21 | 2 | 11 | 26 | 34 |
|
||||
| test.cpp:153:27:153:31 | [,\\w] | 21 | 3 | 8 | 27 | 31 |
|
||||
| test.cpp:153:27:153:32 | [,\\w]+ | 21 | 3 | 9 | 27 | 32 |
|
||||
| test.cpp:153:28:153:28 | , | 21 | 4 | 5 | 28 | 28 |
|
||||
| test.cpp:153:29:153:30 | \\w | 21 | 5 | 7 | 29 | 30 |
|
||||
| test.cpp:153:35:153:36 | \\) | 21 | 11 | 13 | 35 | 36 |
|
||||
| test.cpp:153:37:153:37 | $ | 21 | 13 | 14 | 37 | 37 |
|
||||
| test.cpp:156:25:156:25 | a | 21 | 0 | 1 | 25 | 25 |
|
||||
| test.cpp:156:25:156:26 | a+ | 21 | 0 | 2 | 25 | 26 |
|
||||
| test.cpp:156:25:156:27 | a+b | 21 | 0 | 3 | 25 | 27 |
|
||||
| test.cpp:156:27:156:27 | b | 21 | 2 | 3 | 27 | 27 |
|
||||
| test.cpp:159:24:159:24 | a | 22 | 0 | 1 | 24 | 24 |
|
||||
| test.cpp:159:24:159:25 | a+ | 22 | 0 | 2 | 24 | 25 |
|
||||
| test.cpp:159:24:159:26 | a+b | 22 | 0 | 3 | 24 | 26 |
|
||||
| test.cpp:159:26:159:26 | b | 22 | 2 | 3 | 26 | 26 |
|
||||
| test.cpp:162:30:162:30 | a | 26 | 0 | 1 | 30 | 30 |
|
||||
| test.cpp:162:30:162:31 | a+ | 26 | 0 | 2 | 30 | 31 |
|
||||
| test.cpp:162:30:162:32 | a+b | 26 | 0 | 3 | 30 | 32 |
|
||||
| test.cpp:162:32:162:32 | b | 26 | 2 | 3 | 32 | 32 |
|
||||
| test.cpp:166:22:166:23 | \\s | 21 | 0 | 2 | 22 | 23 |
|
||||
| test.cpp:166:22:166:24 | \\s+ | 21 | 0 | 3 | 22 | 24 |
|
||||
| test.cpp:169:22:169:22 | a | 21 | 0 | 1 | 22 | 22 |
|
||||
|
||||
@@ -521,7 +521,7 @@ test.cpp:
|
||||
|
||||
# 131| [RegExpNamedCharacterProperty] [:digit:]
|
||||
|
||||
# 136| [RegExpConstant, RegExpEscape] \u{987
|
||||
# 136| [RegExpConstant, RegExpEscape] \u9879
|
||||
|
||||
# 144| [RegExpConstant, RegExpNormalChar] a
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ groupNumber
|
||||
| test.cpp:108:21:108:30 | (?<id>\\w+) | 1 |
|
||||
| test.cpp:112:23:112:26 | (a+) | 1 |
|
||||
| test.cpp:113:23:113:32 | (?<qux>q+) | 1 |
|
||||
| test.cpp:153:24:153:31 | ([,\\w]+) | 1 |
|
||||
| test.cpp:153:26:153:33 | ([,\\w]+) | 1 |
|
||||
term
|
||||
| test.cpp:33:21:33:23 | abc | RegExpConstant,RegExpNormalChar |
|
||||
| test.cpp:36:22:36:22 | a | RegExpConstant,RegExpNormalChar |
|
||||
@@ -201,41 +201,41 @@ term
|
||||
| test.cpp:128:37:128:39 | a-f | RegExpCharacterRange |
|
||||
| test.cpp:128:39:128:39 | f | RegExpConstant,RegExpNormalChar |
|
||||
| test.cpp:131:24:131:32 | [:digit:] | RegExpNamedCharacterProperty |
|
||||
| test.cpp:136:21:136:26 | \\u{987 | RegExpConstant,RegExpEscape |
|
||||
| test.cpp:136:21:136:26 | \\u9879 | RegExpConstant,RegExpEscape |
|
||||
| test.cpp:144:23:144:23 | a | RegExpConstant,RegExpNormalChar |
|
||||
| test.cpp:144:23:144:24 | a+ | RegExpPlus |
|
||||
| test.cpp:144:23:144:25 | a+b | RegExpSequence |
|
||||
| test.cpp:144:25:144:25 | b | RegExpConstant,RegExpNormalChar |
|
||||
| test.cpp:147:21:147:21 | a | RegExpConstant,RegExpNormalChar |
|
||||
| test.cpp:147:21:147:22 | a+ | RegExpPlus |
|
||||
| test.cpp:147:21:147:23 | a+b | RegExpSequence |
|
||||
| test.cpp:147:23:147:23 | b | RegExpConstant,RegExpNormalChar |
|
||||
| test.cpp:150:22:150:23 | \\s | RegExpCharacterClassEscape |
|
||||
| test.cpp:150:22:150:24 | \\s+ | RegExpPlus |
|
||||
| test.cpp:150:22:150:25 | \\s+$ | RegExpSequence |
|
||||
| test.cpp:150:25:150:25 | $ | RegExpDollar |
|
||||
| test.cpp:153:22:153:23 | \\( | RegExpConstant,RegExpEscape |
|
||||
| test.cpp:153:22:153:35 | \\(([,\\w]+)+\\)$ | RegExpSequence |
|
||||
| test.cpp:153:24:153:31 | ([,\\w]+) | RegExpGroup |
|
||||
| test.cpp:153:24:153:32 | ([,\\w]+)+ | RegExpPlus |
|
||||
| test.cpp:153:25:153:29 | [,\\w] | RegExpCharacterClass |
|
||||
| test.cpp:153:25:153:30 | [,\\w]+ | RegExpPlus |
|
||||
| test.cpp:153:26:153:26 | , | RegExpConstant,RegExpNormalChar |
|
||||
| test.cpp:153:27:153:28 | \\w | RegExpCharacterClassEscape |
|
||||
| test.cpp:153:33:153:34 | \\) | RegExpConstant,RegExpEscape |
|
||||
| test.cpp:153:35:153:35 | $ | RegExpDollar |
|
||||
| test.cpp:156:22:156:22 | a | RegExpConstant,RegExpNormalChar |
|
||||
| test.cpp:156:22:156:23 | a+ | RegExpPlus |
|
||||
| test.cpp:156:22:156:24 | a+b | RegExpSequence |
|
||||
| test.cpp:156:24:156:24 | b | RegExpConstant,RegExpNormalChar |
|
||||
| test.cpp:159:23:159:23 | a | RegExpConstant,RegExpNormalChar |
|
||||
| test.cpp:159:23:159:24 | a+ | RegExpPlus |
|
||||
| test.cpp:159:23:159:25 | a+b | RegExpSequence |
|
||||
| test.cpp:159:25:159:25 | b | RegExpConstant,RegExpNormalChar |
|
||||
| test.cpp:162:27:162:27 | a | RegExpConstant,RegExpNormalChar |
|
||||
| test.cpp:162:27:162:28 | a+ | RegExpPlus |
|
||||
| test.cpp:162:27:162:29 | a+b | RegExpSequence |
|
||||
| test.cpp:162:29:162:29 | b | RegExpConstant,RegExpNormalChar |
|
||||
| test.cpp:147:23:147:23 | a | RegExpConstant,RegExpNormalChar |
|
||||
| test.cpp:147:23:147:24 | a+ | RegExpPlus |
|
||||
| test.cpp:147:23:147:25 | a+b | RegExpSequence |
|
||||
| test.cpp:147:25:147:25 | b | RegExpConstant,RegExpNormalChar |
|
||||
| test.cpp:150:24:150:25 | \\s | RegExpCharacterClassEscape |
|
||||
| test.cpp:150:24:150:26 | \\s+ | RegExpPlus |
|
||||
| test.cpp:150:24:150:27 | \\s+$ | RegExpSequence |
|
||||
| test.cpp:150:27:150:27 | $ | RegExpDollar |
|
||||
| test.cpp:153:24:153:25 | \\( | RegExpConstant,RegExpEscape |
|
||||
| test.cpp:153:24:153:37 | \\(([,\\w]+)+\\)$ | RegExpSequence |
|
||||
| test.cpp:153:26:153:33 | ([,\\w]+) | RegExpGroup |
|
||||
| test.cpp:153:26:153:34 | ([,\\w]+)+ | RegExpPlus |
|
||||
| test.cpp:153:27:153:31 | [,\\w] | RegExpCharacterClass |
|
||||
| test.cpp:153:27:153:32 | [,\\w]+ | RegExpPlus |
|
||||
| test.cpp:153:28:153:28 | , | RegExpConstant,RegExpNormalChar |
|
||||
| test.cpp:153:29:153:30 | \\w | RegExpCharacterClassEscape |
|
||||
| test.cpp:153:35:153:36 | \\) | RegExpConstant,RegExpEscape |
|
||||
| test.cpp:153:37:153:37 | $ | RegExpDollar |
|
||||
| test.cpp:156:25:156:25 | a | RegExpConstant,RegExpNormalChar |
|
||||
| test.cpp:156:25:156:26 | a+ | RegExpPlus |
|
||||
| test.cpp:156:25:156:27 | a+b | RegExpSequence |
|
||||
| test.cpp:156:27:156:27 | b | RegExpConstant,RegExpNormalChar |
|
||||
| test.cpp:159:24:159:24 | a | RegExpConstant,RegExpNormalChar |
|
||||
| test.cpp:159:24:159:25 | a+ | RegExpPlus |
|
||||
| test.cpp:159:24:159:26 | a+b | RegExpSequence |
|
||||
| test.cpp:159:26:159:26 | b | RegExpConstant,RegExpNormalChar |
|
||||
| test.cpp:162:30:162:30 | a | RegExpConstant,RegExpNormalChar |
|
||||
| test.cpp:162:30:162:31 | a+ | RegExpPlus |
|
||||
| test.cpp:162:30:162:32 | a+b | RegExpSequence |
|
||||
| test.cpp:162:32:162:32 | b | RegExpConstant,RegExpNormalChar |
|
||||
| test.cpp:166:22:166:23 | \\s | RegExpCharacterClassEscape |
|
||||
| test.cpp:166:22:166:24 | \\s+ | RegExpPlus |
|
||||
| test.cpp:169:22:169:22 | a | RegExpConstant,RegExpNormalChar |
|
||||
@@ -318,22 +318,22 @@ regExpNormalCharValue
|
||||
| test.cpp:128:27:128:27 | F | F |
|
||||
| test.cpp:128:37:128:37 | a | a |
|
||||
| test.cpp:128:39:128:39 | f | f |
|
||||
| test.cpp:136:21:136:26 | \\u{987 | \u0987 |
|
||||
| test.cpp:136:21:136:26 | \\u9879 | \u9879 |
|
||||
| test.cpp:144:23:144:23 | a | a |
|
||||
| test.cpp:144:25:144:25 | b | b |
|
||||
| test.cpp:147:21:147:21 | a | a |
|
||||
| test.cpp:147:23:147:23 | b | b |
|
||||
| test.cpp:150:22:150:23 | \\s | s |
|
||||
| test.cpp:153:22:153:23 | \\( | ( |
|
||||
| test.cpp:153:26:153:26 | , | , |
|
||||
| test.cpp:153:27:153:28 | \\w | w |
|
||||
| test.cpp:153:33:153:34 | \\) | ) |
|
||||
| test.cpp:156:22:156:22 | a | a |
|
||||
| test.cpp:156:24:156:24 | b | b |
|
||||
| test.cpp:159:23:159:23 | a | a |
|
||||
| test.cpp:159:25:159:25 | b | b |
|
||||
| test.cpp:162:27:162:27 | a | a |
|
||||
| test.cpp:162:29:162:29 | b | b |
|
||||
| test.cpp:147:23:147:23 | a | a |
|
||||
| test.cpp:147:25:147:25 | b | b |
|
||||
| test.cpp:150:24:150:25 | \\s | s |
|
||||
| test.cpp:153:24:153:25 | \\( | ( |
|
||||
| test.cpp:153:28:153:28 | , | , |
|
||||
| test.cpp:153:29:153:30 | \\w | w |
|
||||
| test.cpp:153:35:153:36 | \\) | ) |
|
||||
| test.cpp:156:25:156:25 | a | a |
|
||||
| test.cpp:156:27:156:27 | b | b |
|
||||
| test.cpp:159:24:159:24 | a | a |
|
||||
| test.cpp:159:26:159:26 | b | b |
|
||||
| test.cpp:162:30:162:30 | a | a |
|
||||
| test.cpp:162:32:162:32 | b | b |
|
||||
| test.cpp:166:22:166:23 | \\s | s |
|
||||
| test.cpp:169:22:169:22 | a | a |
|
||||
| test.cpp:169:23:169:24 | \\. | . |
|
||||
|
||||
@@ -132,8 +132,8 @@ void test() {
|
||||
|
||||
// Dropped: /#{A}bc/ — Ruby string interpolation, no C++ string-literal form.
|
||||
|
||||
// unicode: \u{9879} in C++ (Ruby unicode escape syntax)
|
||||
std::regex r_uni("\\u{9879}");
|
||||
// unicode: \uHHHH 4-digit hex form (valid ECMAScript \u escape in std::regex)
|
||||
std::regex r_uni("\\u9879");
|
||||
}
|
||||
|
||||
// Location tests (commit 8: pre-fix columns; commit 9: fixes raw/prefixed offsets).
|
||||
|
||||
Reference in New Issue
Block a user