mirror of
https://github.com/github/codeql.git
synced 2026-07-31 15:33:00 +02:00
Commit 7: Implement POSIX collating symbol and equivalence class support
Add posixCollatingSymbol([.x.]) and posixEquivalenceClass([=x=]) predicates to ParseRegExp.qll, enabling correct tokenization of all three POSIX bracket atom types inside character classes: - [:name:] — already handled, unchanged - [.x.] — new: posixCollatingSymbol predicate - [=x=] — new: posixEquivalenceClass predicate Refactored: - charSetDelimiter: use inAnyPosixBracket helper (covers all three types) - charSet closing: use inAnyPosixBracket helper - inPosixBracket: updated to cover all three types - simpleCharacter: updated to exclude all three types - namedCharacterProperty: includes posixCollatingSymbol and posixEquivalenceClass - inAnyPosixBracket: new private helper; uses pos in [x..y-1] for QL binding Before this commit (commit 6): [[.a.]] → RegExpCharacterClass([[.a.]) + stray ] (WRONG) [[=a=]] → RegExpCharacterClass([[=a=]) + stray ] (WRONG) After this commit: [[.a.]] → RegExpCharacterClass containing RegExpNamedCharacterProperty [.a.] [[=a=]] → RegExpCharacterClass containing RegExpNamedCharacterProperty [=a=] Regenerated parse.expected and regexp.expected via codeql test run --learn (CodeQL 2.26.1); all 2 tests pass.
This commit is contained in:
committed by
GitHub
parent
9fd7e949c8
commit
cebddbdd42
@@ -102,11 +102,9 @@ class RegExp extends StringLiteral {
|
||||
pos =
|
||||
rank[index](int p |
|
||||
(this.nonEscapedCharAt(p) = "[" or this.nonEscapedCharAt(p) = "]") and
|
||||
// Brackets that art part of POSIX expressions should not count as
|
||||
// Brackets that are part of POSIX expressions should not count as
|
||||
// char-set delimiters.
|
||||
not exists(int x, int y |
|
||||
this.posixStyleNamedCharacterProperty(x, y, _) and pos >= x and pos < y
|
||||
)
|
||||
not this.inAnyPosixBracket(p)
|
||||
) and
|
||||
(
|
||||
this.nonEscapedCharAt(pos) = "[" and result = true
|
||||
@@ -136,9 +134,7 @@ class RegExp extends StringLiteral {
|
||||
min(int e |
|
||||
e > innerStart and
|
||||
this.nonEscapedCharAt(e) = "]" and
|
||||
not exists(int x, int y |
|
||||
this.posixStyleNamedCharacterProperty(x, y, _) and e >= x and e < y
|
||||
)
|
||||
not this.inAnyPosixBracket(e)
|
||||
|
|
||||
e
|
||||
)
|
||||
@@ -289,7 +285,9 @@ class RegExp extends StringLiteral {
|
||||
/** Matches named character properties such as `\p{Word}` and `[[:digit:]]` */
|
||||
predicate namedCharacterProperty(int start, int end, string name) {
|
||||
this.pStyleNamedCharacterProperty(start, end, name) or
|
||||
this.posixStyleNamedCharacterProperty(start, end, name)
|
||||
this.posixStyleNamedCharacterProperty(start, end, name) or
|
||||
this.posixCollatingSymbol(start, end, name) or
|
||||
this.posixEquivalenceClass(start, end, name)
|
||||
}
|
||||
|
||||
/** Gets the name of the character property in start,end */
|
||||
@@ -297,6 +295,21 @@ class RegExp extends StringLiteral {
|
||||
this.namedCharacterProperty(start, end, result)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if the position `pos` falls inside any POSIX bracket atom
|
||||
* (`[:name:]`, `[.x.]`, or `[=x=]`).
|
||||
* Used to prevent the inner brackets from being treated as charSet delimiters.
|
||||
*/
|
||||
private predicate inAnyPosixBracket(int pos) {
|
||||
exists(int x, int y |
|
||||
this.posixStyleNamedCharacterProperty(x, y, _) or
|
||||
this.posixCollatingSymbol(x, y, _) or
|
||||
this.posixEquivalenceClass(x, y, _)
|
||||
|
|
||||
pos in [x .. y - 1]
|
||||
)
|
||||
}
|
||||
|
||||
/** Matches a POSIX bracket expression such as `[:alnum:]` within a character class. */
|
||||
private predicate posixStyleNamedCharacterProperty(int start, int end, string name) {
|
||||
this.getChar(start) = "[" and
|
||||
@@ -318,6 +331,42 @@ class RegExp extends StringLiteral {
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Matches a POSIX collating symbol such as `[.a.]` within a character class.
|
||||
* Example: `[[.a.]]` — the `[.a.]` atom nested inside the outer bracket.
|
||||
*/
|
||||
private predicate posixCollatingSymbol(int start, int end, string name) {
|
||||
this.getChar(start) = "[" and
|
||||
this.getChar(start + 1) = "." and
|
||||
end =
|
||||
min(int e |
|
||||
e > start and
|
||||
this.getChar(e - 2) = "." and
|
||||
this.getChar(e - 1) = "]"
|
||||
|
|
||||
e
|
||||
) and
|
||||
name = this.getText().substring(start + 2, end - 2)
|
||||
}
|
||||
|
||||
/**
|
||||
* Matches a POSIX equivalence class such as `[=a=]` within a character class.
|
||||
* Example: `[[=a=]]` — the `[=a=]` atom nested inside the outer bracket.
|
||||
*/
|
||||
private predicate posixEquivalenceClass(int start, int end, string name) {
|
||||
this.getChar(start) = "[" and
|
||||
this.getChar(start + 1) = "=" and
|
||||
end =
|
||||
min(int e |
|
||||
e > start and
|
||||
this.getChar(e - 2) = "=" and
|
||||
this.getChar(e - 1) = "]"
|
||||
|
|
||||
e
|
||||
) and
|
||||
name = this.getText().substring(start + 2, end - 2)
|
||||
}
|
||||
|
||||
/**
|
||||
* Matches named character properties. For example:
|
||||
* - `\p{Space}`
|
||||
@@ -398,11 +447,17 @@ class RegExp extends StringLiteral {
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if the character at `index` is inside a posix bracket.
|
||||
* Holds if the character at `index` is inside a posix bracket
|
||||
* (`[:name:]`, `[.x.]`, or `[=x=]`).
|
||||
*/
|
||||
predicate inPosixBracket(int index) {
|
||||
exists(int x, int y |
|
||||
this.posixStyleNamedCharacterProperty(x, y, _) and index in [x + 1 .. y - 2]
|
||||
(
|
||||
this.posixStyleNamedCharacterProperty(x, y, _) or
|
||||
this.posixCollatingSymbol(x, y, _) or
|
||||
this.posixEquivalenceClass(x, y, _)
|
||||
) and
|
||||
index in [x + 1 .. y - 2]
|
||||
)
|
||||
}
|
||||
|
||||
@@ -413,11 +468,7 @@ class RegExp extends StringLiteral {
|
||||
end = start + 1 and
|
||||
not this.charSet(start, _) and
|
||||
not this.charSet(_, start + 1) and
|
||||
not exists(int x, int y |
|
||||
this.posixStyleNamedCharacterProperty(x, y, _) and
|
||||
start >= x and
|
||||
end <= y
|
||||
) and
|
||||
not this.inAnyPosixBracket(start) and
|
||||
exists(string c | c = this.getChar(start) |
|
||||
exists(int x, int y, int z |
|
||||
this.charSet(x, z) and
|
||||
|
||||
@@ -245,45 +245,15 @@ test.cpp:
|
||||
|
||||
# 76| [RegExpNamedCharacterProperty] [:space:]
|
||||
|
||||
# 79| [RegExpCharacterClass] [[.a.]
|
||||
#-----| 0 -> [RegExpConstant, RegExpNormalChar] [
|
||||
#-----| 1 -> [RegExpConstant, RegExpNormalChar] .
|
||||
#-----| 2 -> [RegExpConstant, RegExpNormalChar] a
|
||||
#-----| 3 -> [RegExpConstant, RegExpNormalChar] .
|
||||
# 79| [RegExpCharacterClass] [[.a.]]
|
||||
#-----| 0 -> [RegExpNamedCharacterProperty] [.a.]
|
||||
|
||||
# 79| [RegExpSequence] [[.a.]]
|
||||
#-----| 0 -> [RegExpCharacterClass] [[.a.]
|
||||
#-----| 1 -> [RegExpConstant, RegExpNormalChar] ]
|
||||
# 79| [RegExpNamedCharacterProperty] [.a.]
|
||||
|
||||
# 79| [RegExpConstant, RegExpNormalChar] [
|
||||
# 82| [RegExpCharacterClass] [[=a=]]
|
||||
#-----| 0 -> [RegExpNamedCharacterProperty] [=a=]
|
||||
|
||||
# 79| [RegExpConstant, RegExpNormalChar] .
|
||||
|
||||
# 79| [RegExpConstant, RegExpNormalChar] a
|
||||
|
||||
# 79| [RegExpConstant, RegExpNormalChar] .
|
||||
|
||||
# 79| [RegExpConstant, RegExpNormalChar] ]
|
||||
|
||||
# 82| [RegExpCharacterClass] [[=a=]
|
||||
#-----| 0 -> [RegExpConstant, RegExpNormalChar] [
|
||||
#-----| 1 -> [RegExpConstant, RegExpNormalChar] =
|
||||
#-----| 2 -> [RegExpConstant, RegExpNormalChar] a
|
||||
#-----| 3 -> [RegExpConstant, RegExpNormalChar] =
|
||||
|
||||
# 82| [RegExpSequence] [[=a=]]
|
||||
#-----| 0 -> [RegExpCharacterClass] [[=a=]
|
||||
#-----| 1 -> [RegExpConstant, RegExpNormalChar] ]
|
||||
|
||||
# 82| [RegExpConstant, RegExpNormalChar] [
|
||||
|
||||
# 82| [RegExpConstant, RegExpNormalChar] =
|
||||
|
||||
# 82| [RegExpConstant, RegExpNormalChar] a
|
||||
|
||||
# 82| [RegExpConstant, RegExpNormalChar] =
|
||||
|
||||
# 82| [RegExpConstant, RegExpNormalChar] ]
|
||||
# 82| [RegExpNamedCharacterProperty] [=a=]
|
||||
|
||||
# 85| [RegExpCharacterClass] [[:alpha:]0-9]
|
||||
#-----| 0 -> [RegExpNamedCharacterProperty] [:alpha:]
|
||||
|
||||
@@ -100,20 +100,10 @@ term
|
||||
| test.cpp:76:29:76:40 | [a[:space:]] | RegExpCharacterClass |
|
||||
| test.cpp:76:30:76:30 | a | RegExpConstant,RegExpNormalChar |
|
||||
| test.cpp:76:31:76:39 | [:space:] | RegExpNamedCharacterProperty |
|
||||
| test.cpp:79:28:79:33 | [[.a.] | RegExpCharacterClass |
|
||||
| test.cpp:79:28:79:34 | [[.a.]] | RegExpSequence |
|
||||
| test.cpp:79:29:79:29 | [ | RegExpConstant,RegExpNormalChar |
|
||||
| test.cpp:79:30:79:30 | . | RegExpConstant,RegExpNormalChar |
|
||||
| test.cpp:79:31:79:31 | a | RegExpConstant,RegExpNormalChar |
|
||||
| test.cpp:79:32:79:32 | . | RegExpConstant,RegExpNormalChar |
|
||||
| test.cpp:79:34:79:34 | ] | RegExpConstant,RegExpNormalChar |
|
||||
| test.cpp:82:29:82:34 | [[=a=] | RegExpCharacterClass |
|
||||
| test.cpp:82:29:82:35 | [[=a=]] | RegExpSequence |
|
||||
| test.cpp:82:30:82:30 | [ | RegExpConstant,RegExpNormalChar |
|
||||
| test.cpp:82:31:82:31 | = | RegExpConstant,RegExpNormalChar |
|
||||
| test.cpp:82:32:82:32 | a | RegExpConstant,RegExpNormalChar |
|
||||
| test.cpp:82:33:82:33 | = | RegExpConstant,RegExpNormalChar |
|
||||
| test.cpp:82:35:82:35 | ] | RegExpConstant,RegExpNormalChar |
|
||||
| test.cpp:79:28:79:34 | [[.a.]] | RegExpCharacterClass |
|
||||
| test.cpp:79:29:79:33 | [.a.] | RegExpNamedCharacterProperty |
|
||||
| test.cpp:82:29:82:35 | [[=a=]] | RegExpCharacterClass |
|
||||
| test.cpp:82:30:82:34 | [=a=] | RegExpNamedCharacterProperty |
|
||||
| test.cpp:85:29:85:42 | [[:alpha:]0-9] | RegExpCharacterClass |
|
||||
| test.cpp:85:30:85:38 | [:alpha:] | RegExpNamedCharacterProperty |
|
||||
| test.cpp:85:39:85:39 | 0 | RegExpConstant,RegExpNormalChar |
|
||||
@@ -252,16 +242,6 @@ regExpNormalCharValue
|
||||
| test.cpp:57:28:57:28 | f | f |
|
||||
| test.cpp:57:30:57:33 | A-F] | A-F] |
|
||||
| test.cpp:76:30:76:30 | a | a |
|
||||
| test.cpp:79:29:79:29 | [ | [ |
|
||||
| test.cpp:79:30:79:30 | . | . |
|
||||
| test.cpp:79:31:79:31 | a | a |
|
||||
| test.cpp:79:32:79:32 | . | . |
|
||||
| test.cpp:79:34:79:34 | ] | ] |
|
||||
| test.cpp:82:30:82:30 | [ | [ |
|
||||
| test.cpp:82:31:82:31 | = | = |
|
||||
| test.cpp:82:32:82:32 | a | a |
|
||||
| test.cpp:82:33:82:33 | = | = |
|
||||
| test.cpp:82:35:82:35 | ] | ] |
|
||||
| test.cpp:85:39:85:39 | 0 | 0 |
|
||||
| test.cpp:85:41:85:41 | 9 | 9 |
|
||||
| test.cpp:89:23:89:24 | \\w | w |
|
||||
|
||||
Reference in New Issue
Block a user