Ruby: interpret string escape sequences in getConstantValue()

This commit is contained in:
Nick Rolfe
2022-02-21 17:59:21 +00:00
parent bcdbfefb2b
commit 6bd9616c6e
13 changed files with 712 additions and 58 deletions

View File

@@ -0,0 +1,97 @@
/**
* Provides predicates for working with numeric values and their string
* representations.
*/
/**
* Gets the integer value of `hex` when interpreted as hex. `hex` must be a
* valid hexadecimal string and, for integer-wrapping reasons, no longer than 6
* digits.
*
* ```
* "0" => 0
* "FF" => 255
* "f00d" => 61453
* ```
*/
bindingset[hex]
int parseHexInt(string hex) {
hex.length() <= 6 and
result =
sum(int index, string c |
c = hex.charAt(index)
|
sixteenToThe(hex.length() - 1 - index) * toHex(c)
)
}
/**
* Gets the integer value of `octal` when interpreted as octal. `octal` must be
* a valid octal string and, for integer-wrapping reasons, no longer than 10
* digits.
*
* ```
* "0" => 0
* "77" => 63
* "76543210" => 16434824
* ```
*/
bindingset[octal]
int parseOctalInt(string octal) {
octal.length() <= 10 and
result =
sum(int index, string c |
c = octal.charAt(index)
|
eightToThe(octal.length() - 1 - index) * toOctal(c)
)
}
/** Gets the integer value of the `hex` char. */
private int toHex(string hex) {
hex = [0 .. 9].toString() and
result = hex.toInt()
or
result = 10 and hex = ["a", "A"]
or
result = 11 and hex = ["b", "B"]
or
result = 12 and hex = ["c", "C"]
or
result = 13 and hex = ["d", "D"]
or
result = 14 and hex = ["e", "E"]
or
result = 15 and hex = ["f", "F"]
}
/** Gets the integer value of the `octal` char. */
private int toOctal(string octal) {
octal = "0" and result = 0
or
octal = "1" and result = 1
or
octal = "2" and result = 2
or
octal = "3" and result = 3
or
octal = "4" and result = 4
or
octal = "5" and result = 5
or
octal = "6" and result = 6
or
octal = "7" and result = 7
}
/** Gets the value of 16 to the power of `n`. */
int sixteenToThe(int n) {
// 16**7 is the largest power of 16 that fits in an int.
n in [0 .. 7] and result = 1.bitShiftLeft(4 * n)
}
/** Gets the value of 8 to the power of `n`. */
int eightToThe(int n) {
// 8**10 is the largest power of 8 that fits in an int.
n in [0 .. 10] and result = 1.bitShiftLeft(3 * n)
}

View File

@@ -230,13 +230,18 @@ class StringTextComponent extends StringComponent, TStringTextComponentNonRegexp
StringTextComponent() { this = TStringTextComponentNonRegexp(g) }
final override string toString() { result = g.getValue() }
final override string toString() { result = this.getRawText() }
final override ConstantValue::ConstantStringValue getConstantValue() {
result.isString(g.getValue())
result.isString(this.getUnescapedText())
}
final override string getAPrimaryQlClass() { result = "StringTextComponent" }
/** Gets the text of this component as it appears in the source code. */
final string getRawText() { result = g.getValue() }
final private string getUnescapedText() { result = unescapeTextComponent(this.getRawText()) }
}
/**
@@ -247,13 +252,18 @@ class StringEscapeSequenceComponent extends StringComponent, TStringEscapeSequen
StringEscapeSequenceComponent() { this = TStringEscapeSequenceComponentNonRegexp(g) }
final override string toString() { result = g.getValue() }
final override string toString() { result = this.getRawText() }
final override ConstantValue::ConstantStringValue getConstantValue() {
result.isString(g.getValue())
result.isString(this.getUnescapedText())
}
final override string getAPrimaryQlClass() { result = "StringEscapeSequenceComponent" }
/** Gets the text of this component as it appears in the source code. */
final string getRawText() { result = g.getValue() }
final private string getUnescapedText() { result = unescapeEscapeSequence(this.getRawText()) }
}
/**

View File

@@ -3,6 +3,7 @@ private import AST
private import Constant
private import TreeSitter
private import codeql.ruby.controlflow.CfgNodes
private import codeql.NumberUtils
int parseInteger(Ruby::Integer i) {
exists(string s | s = i.getValue().toLowerCase().replaceAll("_", "") |
@@ -148,16 +149,85 @@ private class RequiredFileLiteralConstantValue extends RequiredConstantValue {
private class RequiredStringTextComponentConstantValue extends RequiredConstantValue {
override predicate requiredString(string s) {
s = any(Ruby::Token t | exists(TStringTextComponentNonRegexp(t))).getValue()
s =
unescapeTextComponent(any(Ruby::Token t | exists(TStringTextComponentNonRegexp(t))).getValue())
}
}
private class RequiredStringEscapeSequenceComponentConstantValue extends RequiredConstantValue {
override predicate requiredString(string s) {
s = any(Ruby::Token t | exists(TStringEscapeSequenceComponentNonRegexp(t))).getValue()
s =
unescapeEscapeSequence(any(Ruby::Token t | exists(TStringEscapeSequenceComponentNonRegexp(t)))
.getValue())
}
}
/**
* Gets the string represented by the escape sequence in `escaped`. For example:
*
* ```
* \\ => \
* \141 => a
* \u0078 => x
* ```
*/
bindingset[escaped]
string unescapeEscapeSequence(string escaped) {
result = unescapeKnownEscapeSequence(escaped)
or
// Any other character following a backslash is just that character.
not exists(unescapeKnownEscapeSequence(escaped)) and
result = escaped.suffix(1)
}
bindingset[escaped]
private string unescapeKnownEscapeSequence(string escaped) {
escaped = "\\\\" and result = "\\"
or
escaped = "\\'" and result = "'"
or
escaped = "\\\"" and result = "\""
or
escaped = "\\a" and result = 7.toUnicode()
or
escaped = "\\b" and result = 8.toUnicode()
or
escaped = "\\t" and result = "\t"
or
escaped = "\\n" and result = "\n"
or
escaped = "\\v" and result = 11.toUnicode()
or
escaped = "\\f" and result = 12.toUnicode()
or
escaped = "\\r" and result = "\r"
or
escaped = "\\e" and result = 27.toUnicode()
or
escaped = "\\s" and result = " "
or
escaped = ["\\c?", "\\C-?"] and result = 127.toUnicode()
or
result = parseOctalInt(escaped.regexpCapture("\\\\([0-7]{1,3})", 1)).toUnicode()
or
result = parseHexInt(escaped.regexpCapture("\\\\x([0-9a-fA-F]{1,2})", 1)).toUnicode()
or
result = parseHexInt(escaped.regexpCapture("\\\\u([0-9a-fA-F]{4})", 1)).toUnicode()
or
result = parseHexInt(escaped.regexpCapture("\\\\u\\{([0-9a-fA-F]{1,6})\\}", 1)).toUnicode()
}
/**
* Gets the result of unescaping a string text component by replacing `\\` and
* `\'` with `\` and `'`, respectively.
*
* ```rb
* 'foo\\bar \'baz\'' # foo\bar 'baz'
* ```
*/
bindingset[text]
string unescapeTextComponent(string text) { result = text.regexpReplaceAll("\\\\(['\\\\])", "$1") }
class TRegExpComponent =
TStringTextComponentRegexp or TStringEscapeSequenceComponentRegexp or
TStringInterpolationComponentRegexp;

View File

@@ -1,5 +1,6 @@
private import codeql.ruby.ast.Literal as AST
private import ParseRegExp
private import codeql.NumberUtils
import codeql.Locations
private import codeql.ruby.DataFlow
@@ -423,21 +424,8 @@ class RegExpEscape extends RegExpNormalChar {
* E.g. for `\u0061` this returns "a".
*/
private string getUnicode() {
exists(int codepoint | codepoint = sum(this.getHexValueFromUnicode(_)) |
result = codepoint.toUnicode()
)
}
/**
* Gets int value for the `index`th char in the hex number of the unicode escape.
* E.g. for `\u0061` and `index = 2` this returns 96 (the number `6` interpreted as hex).
*/
private int getHexValueFromUnicode(int index) {
this.isUnicode() and
exists(string hex, string char | hex = this.getText().suffix(2) |
char = hex.charAt(index) and
result = 16.pow(hex.length() - index - 1) * toHex(char)
)
result = parseHexInt(this.getText().suffix(2)).toUnicode()
}
string getUnescaped() { result = this.getText().suffix(1) }
@@ -445,26 +433,6 @@ class RegExpEscape extends RegExpNormalChar {
override string getAPrimaryQlClass() { result = "RegExpEscape" }
}
/**
* Gets the hex number for the `hex` char.
*/
private int toHex(string hex) {
hex = [0 .. 9].toString() and
result = hex.toInt()
or
result = 10 and hex = ["a", "A"]
or
result = 11 and hex = ["b", "B"]
or
result = 12 and hex = ["c", "C"]
or
result = 13 and hex = ["d", "D"]
or
result = 14 and hex = ["e", "E"]
or
result = 15 and hex = ["f", "F"]
}
/**
* A word boundary, that is, a regular expression term of the form `\b`.
*/

View File

@@ -1470,6 +1470,183 @@ constants/constants.rb:
# 73| getAnOperand/getLeftOperand: [ClassVariableAccess] @@fourty_six
# 73| getAnOperand/getRightOperand: [ConstantReadAccess] FOURTY_SIX
# 73| getScopeExpr: [ConstantReadAccess] Mod3
escape_sequences/escapes.rb:
# 1| [Toplevel] escapes.rb
# 6| getStmt: [StringLiteral] "\'"
# 6| getComponent: [StringTextComponent] \'
# 7| getStmt: [StringLiteral] "\""
# 7| getComponent: [StringTextComponent] \"
# 8| getStmt: [StringLiteral] "\\"
# 8| getComponent: [StringTextComponent] \\
# 9| getStmt: [StringLiteral] "\1"
# 9| getComponent: [StringTextComponent] \1
# 10| getStmt: [StringLiteral] "\\1"
# 10| getComponent: [StringTextComponent] \\1
# 11| getStmt: [StringLiteral] "\141"
# 11| getComponent: [StringTextComponent] \141
# 12| getStmt: [StringLiteral] "\n"
# 12| getComponent: [StringTextComponent] \n
# 15| getStmt: [StringLiteral] "\'"
# 15| getComponent: [StringEscapeSequenceComponent] \'
# 16| getStmt: [StringLiteral] "\""
# 16| getComponent: [StringEscapeSequenceComponent] \"
# 17| getStmt: [StringLiteral] "\\"
# 17| getComponent: [StringEscapeSequenceComponent] \\
# 18| getStmt: [StringLiteral] "\1"
# 18| getComponent: [StringEscapeSequenceComponent] \1
# 19| getStmt: [StringLiteral] "\\1"
# 19| getComponent: [StringEscapeSequenceComponent] \\
# 19| getComponent: [StringTextComponent] 1
# 20| getStmt: [StringLiteral] "\141"
# 20| getComponent: [StringEscapeSequenceComponent] \141
# 21| getStmt: [StringLiteral] "\x6d"
# 21| getComponent: [StringEscapeSequenceComponent] \x6d
# 22| getStmt: [StringLiteral] "\x6E"
# 22| getComponent: [StringEscapeSequenceComponent] \x6E
# 23| getStmt: [StringLiteral] "\X6d"
# 23| getComponent: [StringEscapeSequenceComponent] \X
# 23| getComponent: [StringTextComponent] 6d
# 24| getStmt: [StringLiteral] "\X6E"
# 24| getComponent: [StringEscapeSequenceComponent] \X
# 24| getComponent: [StringTextComponent] 6E
# 25| getStmt: [StringLiteral] "\u203d"
# 25| getComponent: [StringEscapeSequenceComponent] \u203d
# 26| getStmt: [StringLiteral] "\u{62}"
# 26| getComponent: [StringEscapeSequenceComponent] \u{62}
# 27| getStmt: [StringLiteral] "\u{1f60a}"
# 27| getComponent: [StringEscapeSequenceComponent] \u{1f60a}
# 28| getStmt: [StringLiteral] "\a"
# 28| getComponent: [StringEscapeSequenceComponent] \a
# 29| getStmt: [StringLiteral] "\b"
# 29| getComponent: [StringEscapeSequenceComponent] \b
# 30| getStmt: [StringLiteral] "\t"
# 30| getComponent: [StringEscapeSequenceComponent] \t
# 31| getStmt: [StringLiteral] "\n"
# 31| getComponent: [StringEscapeSequenceComponent] \n
# 32| getStmt: [StringLiteral] "\v"
# 32| getComponent: [StringEscapeSequenceComponent] \v
# 33| getStmt: [StringLiteral] "\f"
# 33| getComponent: [StringEscapeSequenceComponent] \f
# 34| getStmt: [StringLiteral] "\r"
# 34| getComponent: [StringEscapeSequenceComponent] \r
# 35| getStmt: [StringLiteral] "\e"
# 35| getComponent: [StringEscapeSequenceComponent] \e
# 36| getStmt: [StringLiteral] "\s"
# 36| getComponent: [StringEscapeSequenceComponent] \s
# 37| getStmt: [StringLiteral] "\c?"
# 37| getComponent: [StringEscapeSequenceComponent] \c
# 37| getComponent: [StringTextComponent] ?
# 38| getStmt: [StringLiteral] "\C-?"
# 38| getComponent: [StringEscapeSequenceComponent] \C
# 38| getComponent: [StringTextComponent] -?
# 43| getStmt: [AssignExpr] ... = ...
# 43| getAnOperand/getLeftOperand: [LocalVariableAccess] a
# 43| getAnOperand/getRightOperand: [StringLiteral] "\\."
# 43| getComponent: [StringEscapeSequenceComponent] \\
# 43| getComponent: [StringTextComponent] .
# 44| getStmt: [StringLiteral] "#{...}"
# 44| getComponent: [StringInterpolationComponent] #{...}
# 44| getStmt: [LocalVariableAccess] a
# 48| getStmt: [RegExpLiteral] /\n/
# 48| getParsed: [RegExpConstant, RegExpEscape] \n
# 48| getComponent: [RegExpEscapeSequenceComponent] \n
# 49| getStmt: [RegExpLiteral] /\p/
# 49| getParsed: [RegExpConstant, RegExpEscape] \p
# 49| getComponent: [RegExpEscapeSequenceComponent] \p
# 50| getStmt: [RegExpLiteral] /\u0061/
# 50| getParsed: [RegExpConstant, RegExpEscape] \u0061
# 50| getComponent: [RegExpEscapeSequenceComponent] \u0061
# 53| getStmt: [AssignExpr] ... = ...
# 53| getAnOperand/getLeftOperand: [LocalVariableAccess] a
# 53| getAnOperand/getRightOperand: [StringLiteral] "\\."
# 53| getComponent: [StringEscapeSequenceComponent] \\
# 53| getComponent: [StringTextComponent] .
# 54| getStmt: [AssignExpr] ... = ...
# 54| getAnOperand/getLeftOperand: [LocalVariableAccess] b
# 54| getAnOperand/getRightOperand: [RegExpLiteral] /\./
# 54| getParsed: [RegExpConstant, RegExpEscape] \.
# 54| getComponent: [RegExpEscapeSequenceComponent] \.
# 55| getStmt: [RegExpLiteral] /#{...}#{...}/
# 55| getParsed: [RegExpSequence] \.\.
# 55| 0: [RegExpConstant, RegExpEscape] \.
# 55| 1: [RegExpConstant, RegExpEscape] \.
# 55| getComponent: [RegExpInterpolationComponent] #{...}
# 55| getStmt: [LocalVariableAccess] a
# 55| getComponent: [RegExpInterpolationComponent] #{...}
# 55| getStmt: [LocalVariableAccess] b
# 58| getStmt: [ArrayLiteral] %w(...)
# 58| getElement: [StringLiteral] "foo \n"
# 58| getComponent: [StringTextComponent] foo
# 58| getComponent: [StringEscapeSequenceComponent] \n
# 58| getElement: [StringLiteral] "bar"
# 58| getComponent: [StringTextComponent] bar
# 61| getStmt: [SymbolLiteral] :"\'"
# 61| getComponent: [StringTextComponent] \'
# 62| getStmt: [SymbolLiteral] :"\""
# 62| getComponent: [StringTextComponent] \"
# 63| getStmt: [SymbolLiteral] :"\\"
# 63| getComponent: [StringTextComponent] \\
# 64| getStmt: [SymbolLiteral] :"\1"
# 64| getComponent: [StringTextComponent] \1
# 65| getStmt: [SymbolLiteral] :"\\1"
# 65| getComponent: [StringTextComponent] \\1
# 66| getStmt: [SymbolLiteral] :"\141"
# 66| getComponent: [StringTextComponent] \141
# 67| getStmt: [SymbolLiteral] :"\n"
# 67| getComponent: [StringTextComponent] \n
# 70| getStmt: [SymbolLiteral] :"\'"
# 70| getComponent: [StringEscapeSequenceComponent] \'
# 71| getStmt: [SymbolLiteral] :"\""
# 71| getComponent: [StringEscapeSequenceComponent] \"
# 72| getStmt: [SymbolLiteral] :"\\"
# 72| getComponent: [StringEscapeSequenceComponent] \\
# 73| getStmt: [SymbolLiteral] :"\1"
# 73| getComponent: [StringEscapeSequenceComponent] \1
# 74| getStmt: [SymbolLiteral] :"\\1"
# 74| getComponent: [StringEscapeSequenceComponent] \\
# 74| getComponent: [StringTextComponent] 1
# 75| getStmt: [SymbolLiteral] :"\141"
# 75| getComponent: [StringEscapeSequenceComponent] \141
# 76| getStmt: [SymbolLiteral] :"\x6d"
# 76| getComponent: [StringEscapeSequenceComponent] \x6d
# 77| getStmt: [SymbolLiteral] :"\x6E"
# 77| getComponent: [StringEscapeSequenceComponent] \x6E
# 78| getStmt: [SymbolLiteral] :"\X6d"
# 78| getComponent: [StringEscapeSequenceComponent] \X
# 78| getComponent: [StringTextComponent] 6d
# 79| getStmt: [SymbolLiteral] :"\X6E"
# 79| getComponent: [StringEscapeSequenceComponent] \X
# 79| getComponent: [StringTextComponent] 6E
# 80| getStmt: [SymbolLiteral] :"\u203d"
# 80| getComponent: [StringEscapeSequenceComponent] \u203d
# 81| getStmt: [SymbolLiteral] :"\u{62}"
# 81| getComponent: [StringEscapeSequenceComponent] \u{62}
# 82| getStmt: [SymbolLiteral] :"\u{1f60a}"
# 82| getComponent: [StringEscapeSequenceComponent] \u{1f60a}
# 83| getStmt: [SymbolLiteral] :"\a"
# 83| getComponent: [StringEscapeSequenceComponent] \a
# 84| getStmt: [SymbolLiteral] :"\b"
# 84| getComponent: [StringEscapeSequenceComponent] \b
# 85| getStmt: [SymbolLiteral] :"\t"
# 85| getComponent: [StringEscapeSequenceComponent] \t
# 86| getStmt: [SymbolLiteral] :"\n"
# 86| getComponent: [StringEscapeSequenceComponent] \n
# 87| getStmt: [SymbolLiteral] :"\v"
# 87| getComponent: [StringEscapeSequenceComponent] \v
# 88| getStmt: [SymbolLiteral] :"\f"
# 88| getComponent: [StringEscapeSequenceComponent] \f
# 89| getStmt: [SymbolLiteral] :"\r"
# 89| getComponent: [StringEscapeSequenceComponent] \r
# 90| getStmt: [SymbolLiteral] :"\e"
# 90| getComponent: [StringEscapeSequenceComponent] \e
# 91| getStmt: [SymbolLiteral] :"\s"
# 91| getComponent: [StringEscapeSequenceComponent] \s
# 92| getStmt: [SymbolLiteral] :"\c?"
# 92| getComponent: [StringEscapeSequenceComponent] \c
# 92| getComponent: [StringTextComponent] ?
# 93| getStmt: [SymbolLiteral] :"\C-?"
# 93| getComponent: [StringEscapeSequenceComponent] \C
# 93| getComponent: [StringTextComponent] -?
literals/literals.rb:
# 1| [Toplevel] literals.rb
# 2| getStmt: [NilLiteral] nil

View File

@@ -304,6 +304,15 @@ constants/constants.rb:
# 20| getComponent: [StringTextComponent] Chuck
# 20| getArgument: [StringLiteral] "Dave"
# 20| getComponent: [StringTextComponent] Dave
escape_sequences/escapes.rb:
# 58| [ArrayLiteral] %w(...)
# 58| getDesugared: [MethodCall] call to []
# 58| getReceiver: [ConstantReadAccess] Array
# 58| getArgument: [StringLiteral] "foo \n"
# 58| getComponent: [StringTextComponent] foo
# 58| getComponent: [StringEscapeSequenceComponent] \n
# 58| getArgument: [StringLiteral] "bar"
# 58| getComponent: [StringTextComponent] bar
literals/literals.rb:
# 88| [HashLiteral] {...}
# 88| getDesugared: [MethodCall] call to []

View File

@@ -345,6 +345,81 @@
| erb/template.html.erb:27:16:27:20 | "foo" | foo |
| erb/template.html.erb:27:23:27:27 | "bar" | bar |
| erb/template.html.erb:27:30:27:34 | "baz" | baz |
| escape_sequences/escapes.rb:6:1:6:4 | "\\'" | ' |
| escape_sequences/escapes.rb:7:1:7:4 | "\\"" | \\" |
| escape_sequences/escapes.rb:8:1:8:4 | "\\\\" | \\ |
| escape_sequences/escapes.rb:9:1:9:4 | "\\1" | \\1 |
| escape_sequences/escapes.rb:10:1:10:5 | "\\\\1" | \\1 |
| escape_sequences/escapes.rb:11:1:11:6 | "\\141" | \\141 |
| escape_sequences/escapes.rb:12:1:12:4 | "\\n" | \\n |
| escape_sequences/escapes.rb:15:1:15:4 | "\\'" | ' |
| escape_sequences/escapes.rb:16:1:16:4 | "\\"" | " |
| escape_sequences/escapes.rb:17:1:17:4 | "\\\\" | \\ |
| escape_sequences/escapes.rb:18:1:18:4 | "\\1" | \u0001 |
| escape_sequences/escapes.rb:19:1:19:5 | "\\\\1" | \\1 |
| escape_sequences/escapes.rb:20:1:20:6 | "\\141" | a |
| escape_sequences/escapes.rb:21:1:21:6 | "\\x6d" | m |
| escape_sequences/escapes.rb:22:1:22:6 | "\\x6E" | n |
| escape_sequences/escapes.rb:23:1:23:6 | "\\X6d" | X6d |
| escape_sequences/escapes.rb:24:1:24:6 | "\\X6E" | X6E |
| escape_sequences/escapes.rb:25:1:25:8 | "\\u203d" | \u203d |
| escape_sequences/escapes.rb:26:1:26:8 | "\\u{62}" | b |
| escape_sequences/escapes.rb:27:1:27:11 | "\\u{1f60a}" | \ud83d\ude0a |
| escape_sequences/escapes.rb:28:1:28:4 | "\\a" | \u0007 |
| escape_sequences/escapes.rb:29:1:29:4 | "\\b" | \u0008 |
| escape_sequences/escapes.rb:30:1:30:4 | "\\t" | \t |
| escape_sequences/escapes.rb:31:1:31:4 | "\\n" | \n |
| escape_sequences/escapes.rb:32:1:32:4 | "\\v" | \u000b |
| escape_sequences/escapes.rb:33:1:33:4 | "\\f" | \u000c |
| escape_sequences/escapes.rb:34:1:34:4 | "\\r" | \r |
| escape_sequences/escapes.rb:35:1:35:4 | "\\e" | \u001b |
| escape_sequences/escapes.rb:36:1:36:4 | "\\s" | |
| escape_sequences/escapes.rb:37:1:37:5 | "\\c?" | c? |
| escape_sequences/escapes.rb:38:1:38:6 | "\\C-?" | C-? |
| escape_sequences/escapes.rb:43:5:43:9 | "\\\\." | \\. |
| escape_sequences/escapes.rb:44:1:44:6 | "#{...}" | \\. |
| escape_sequences/escapes.rb:44:4:44:4 | a | \\. |
| escape_sequences/escapes.rb:48:1:48:4 | /\\n/ | \\n |
| escape_sequences/escapes.rb:49:1:49:4 | /\\p/ | \\p |
| escape_sequences/escapes.rb:50:1:50:8 | /\\u0061/ | \\u0061 |
| escape_sequences/escapes.rb:53:5:53:9 | "\\\\." | \\. |
| escape_sequences/escapes.rb:54:5:54:8 | /\\./ | \\. |
| escape_sequences/escapes.rb:55:1:55:10 | /#{...}#{...}/ | \\.\\. |
| escape_sequences/escapes.rb:55:4:55:4 | a | \\. |
| escape_sequences/escapes.rb:55:8:55:8 | b | \\. |
| escape_sequences/escapes.rb:58:4:58:9 | "foo \\n" | foo\\n |
| escape_sequences/escapes.rb:58:11:58:13 | "bar" | bar |
| escape_sequences/escapes.rb:61:1:61:5 | :"\\'" | :' |
| escape_sequences/escapes.rb:62:1:62:5 | :"\\"" | :\\" |
| escape_sequences/escapes.rb:63:1:63:5 | :"\\\\" | :\\ |
| escape_sequences/escapes.rb:64:1:64:5 | :"\\1" | :\\1 |
| escape_sequences/escapes.rb:65:1:65:6 | :"\\\\1" | :\\1 |
| escape_sequences/escapes.rb:66:1:66:7 | :"\\141" | :\\141 |
| escape_sequences/escapes.rb:67:1:67:5 | :"\\n" | :\\n |
| escape_sequences/escapes.rb:70:1:70:5 | :"\\'" | :' |
| escape_sequences/escapes.rb:71:1:71:5 | :"\\"" | :" |
| escape_sequences/escapes.rb:72:1:72:5 | :"\\\\" | :\\ |
| escape_sequences/escapes.rb:73:1:73:5 | :"\\1" | :\u0001 |
| escape_sequences/escapes.rb:74:1:74:6 | :"\\\\1" | :\\1 |
| escape_sequences/escapes.rb:75:1:75:7 | :"\\141" | :a |
| escape_sequences/escapes.rb:76:1:76:7 | :"\\x6d" | :m |
| escape_sequences/escapes.rb:77:1:77:7 | :"\\x6E" | :n |
| escape_sequences/escapes.rb:78:1:78:7 | :"\\X6d" | :X6d |
| escape_sequences/escapes.rb:79:1:79:7 | :"\\X6E" | :X6E |
| escape_sequences/escapes.rb:80:1:80:9 | :"\\u203d" | :\u203d |
| escape_sequences/escapes.rb:81:1:81:9 | :"\\u{62}" | :b |
| escape_sequences/escapes.rb:82:1:82:12 | :"\\u{1f60a}" | :\ud83d\ude0a |
| escape_sequences/escapes.rb:83:1:83:5 | :"\\a" | :\u0007 |
| escape_sequences/escapes.rb:84:1:84:5 | :"\\b" | :\u0008 |
| escape_sequences/escapes.rb:85:1:85:5 | :"\\t" | :\t |
| escape_sequences/escapes.rb:86:1:86:5 | :"\\n" | :\n |
| escape_sequences/escapes.rb:87:1:87:5 | :"\\v" | :\u000b |
| escape_sequences/escapes.rb:88:1:88:5 | :"\\f" | :\u000c |
| escape_sequences/escapes.rb:89:1:89:5 | :"\\r" | :\r |
| escape_sequences/escapes.rb:90:1:90:5 | :"\\e" | :\u001b |
| escape_sequences/escapes.rb:91:1:91:5 | :"\\s" | : |
| escape_sequences/escapes.rb:92:1:92:6 | :"\\c?" | :c? |
| escape_sequences/escapes.rb:93:1:93:7 | :"\\C-?" | :C-? |
| gems/Gemfile:1:8:1:29 | "https://rubygems.org" | https://rubygems.org |
| gems/Gemfile:3:5:3:13 | "foo_gem" | foo_gem |
| gems/Gemfile:3:16:3:23 | "~> 2.0" | ~> 2.0 |
@@ -396,14 +471,14 @@
| literals/literals.rb:47:1:47:2 | "" | |
| literals/literals.rb:48:1:48:7 | "hello" | hello |
| literals/literals.rb:49:1:49:9 | "goodbye" | goodbye |
| literals/literals.rb:50:1:50:30 | "string with escaped \\" quote" | string with escaped \\" quote |
| literals/literals.rb:50:1:50:30 | "string with escaped \\" quote" | string with escaped " quote |
| literals/literals.rb:51:1:51:21 | "string with " quote" | string with " quote |
| literals/literals.rb:52:1:52:14 | "foo bar baz" | foo bar baz |
| literals/literals.rb:53:1:53:15 | "foo bar baz" | foo bar baz |
| literals/literals.rb:54:1:54:20 | "foo ' bar " baz'" | foo ' bar " baz' |
| literals/literals.rb:55:1:55:20 | "FOO ' BAR " BAZ'" | FOO ' BAR " BAZ' |
| literals/literals.rb:56:1:56:12 | "foo\\ bar" | foo\\ bar |
| literals/literals.rb:57:1:57:12 | "foo\\ bar" | foo\\ bar |
| literals/literals.rb:57:1:57:12 | "foo\\ bar" | foo bar |
| literals/literals.rb:58:1:58:20 | "2 + 2 = #{...}" | 2 + 2 = 4 |
| literals/literals.rb:58:13:58:13 | 2 | 2 |
| literals/literals.rb:58:13:58:17 | ... + ... | 4 |
@@ -578,9 +653,9 @@
| literals/literals.rb:146:28:146:30 | BAR | bar |
| literals/literals.rb:150:1:150:34 | "abcdefghijklmnopqrstuvwxyzabcdef" | abcdefghijklmnopqrstuvwxyzabcdef |
| literals/literals.rb:151:1:151:35 | "foobarfoobarfoobarfoobarfooba..." | foobarfoobarfoobarfoobarfoobarfoo |
| literals/literals.rb:152:1:152:40 | "foobar\\\\foobar\\\\foobar\\\\fooba..." | foobar\\\\foobar\\\\foobar\\\\foobar\\\\foobar |
| literals/literals.rb:152:1:152:40 | "foobar\\\\foobar\\\\foobar\\\\fooba..." | foobar\\foobar\\foobar\\foobar\\foobar |
| literals/literals.rb:155:9:155:13 | <<SQL | \nselect * from table\n |
| literals/literals.rb:162:11:162:16 | <<-BLA | \nsome text\\nand some more\n |
| literals/literals.rb:162:11:162:16 | <<-BLA | \nsome text\nand some more\n |
| literals/literals.rb:167:9:167:19 | <<~SQUIGGLY | \n indented stuff\n |
| literals/literals.rb:180:10:180:19 | <<`SCRIPT` | \n cat file.txt\n |
| literals/literals.rb:184:5:184:6 | 42 | 42 |
@@ -610,7 +685,7 @@
| misc/misc.rb:8:12:8:14 | []= | []= |
| misc/misc.rb:9:7:9:11 | super | super |
| misc/misc.rb:9:13:9:16 | self | self |
| misc/misc.rb:10:7:10:17 | :"\\n#{...}" | :\\nbar |
| misc/misc.rb:10:7:10:17 | :"\\n#{...}" | :\nbar |
| misc/misc.rb:10:13:10:15 | bar | bar |
| misc/misc.rb:10:19:10:24 | :"foo" | :foo |
| modules/classes.rb:11:28:11:31 | :baz | :baz |

View File

@@ -0,0 +1,130 @@
stringEscapeSequenceComponents
| escapes.rb:15:2:15:3 | \\' | \\' | ' |
| escapes.rb:16:2:16:3 | \\" | \\" | " |
| escapes.rb:17:2:17:3 | \\\\ | \\\\ | \\ |
| escapes.rb:18:2:18:3 | \\1 | \\1 | \u0001 |
| escapes.rb:19:2:19:3 | \\\\ | \\\\ | \\ |
| escapes.rb:20:2:20:5 | \\141 | \\141 | a |
| escapes.rb:21:2:21:5 | \\x6d | \\x6d | m |
| escapes.rb:22:2:22:5 | \\x6E | \\x6E | n |
| escapes.rb:23:2:23:3 | \\X | \\X | X |
| escapes.rb:24:2:24:3 | \\X | \\X | X |
| escapes.rb:25:2:25:7 | \\u203d | \\u203d | \u203d |
| escapes.rb:26:2:26:7 | \\u{62} | \\u{62} | b |
| escapes.rb:27:2:27:10 | \\u{1f60a} | \\u{1f60a} | \ud83d\ude0a |
| escapes.rb:28:2:28:3 | \\a | \\a | \u0007 |
| escapes.rb:29:2:29:3 | \\b | \\b | \u0008 |
| escapes.rb:30:2:30:3 | \\t | \\t | \t |
| escapes.rb:31:2:31:3 | \\n | \\n | \n |
| escapes.rb:32:2:32:3 | \\v | \\v | \u000b |
| escapes.rb:33:2:33:3 | \\f | \\f | \u000c |
| escapes.rb:34:2:34:3 | \\r | \\r | \r |
| escapes.rb:35:2:35:3 | \\e | \\e | \u001b |
| escapes.rb:36:2:36:3 | \\s | \\s | |
| escapes.rb:37:2:37:3 | \\c | \\c | c |
| escapes.rb:38:2:38:3 | \\C | \\C | C |
| escapes.rb:43:6:43:7 | \\\\ | \\\\ | \\ |
| escapes.rb:53:6:53:7 | \\\\ | \\\\ | \\ |
| escapes.rb:58:7:58:9 | \\n | \\n | \\n |
| escapes.rb:70:3:70:4 | \\' | \\' | ' |
| escapes.rb:71:3:71:4 | \\" | \\" | " |
| escapes.rb:72:3:72:4 | \\\\ | \\\\ | \\ |
| escapes.rb:73:3:73:4 | \\1 | \\1 | \u0001 |
| escapes.rb:74:3:74:4 | \\\\ | \\\\ | \\ |
| escapes.rb:75:3:75:6 | \\141 | \\141 | a |
| escapes.rb:76:3:76:6 | \\x6d | \\x6d | m |
| escapes.rb:77:3:77:6 | \\x6E | \\x6E | n |
| escapes.rb:78:3:78:4 | \\X | \\X | X |
| escapes.rb:79:3:79:4 | \\X | \\X | X |
| escapes.rb:80:3:80:8 | \\u203d | \\u203d | \u203d |
| escapes.rb:81:3:81:8 | \\u{62} | \\u{62} | b |
| escapes.rb:82:3:82:11 | \\u{1f60a} | \\u{1f60a} | \ud83d\ude0a |
| escapes.rb:83:3:83:4 | \\a | \\a | \u0007 |
| escapes.rb:84:3:84:4 | \\b | \\b | \u0008 |
| escapes.rb:85:3:85:4 | \\t | \\t | \t |
| escapes.rb:86:3:86:4 | \\n | \\n | \n |
| escapes.rb:87:3:87:4 | \\v | \\v | \u000b |
| escapes.rb:88:3:88:4 | \\f | \\f | \u000c |
| escapes.rb:89:3:89:4 | \\r | \\r | \r |
| escapes.rb:90:3:90:4 | \\e | \\e | \u001b |
| escapes.rb:91:3:91:4 | \\s | \\s | |
| escapes.rb:92:3:92:4 | \\c | \\c | c |
| escapes.rb:93:3:93:4 | \\C | \\C | C |
regexpEscapeSequenceComponents
| escapes.rb:48:2:48:3 | \\n | \\n |
| escapes.rb:49:2:49:3 | \\p | \\p |
| escapes.rb:50:2:50:7 | \\u0061 | \\u0061 |
| escapes.rb:54:6:54:7 | \\. | \\. |
stringlikeLiterals
| escapes.rb:6:1:6:4 | "\\'" | ' | string |
| escapes.rb:7:1:7:4 | "\\"" | \\" | string |
| escapes.rb:8:1:8:4 | "\\\\" | \\ | string |
| escapes.rb:9:1:9:4 | "\\1" | \\1 | string |
| escapes.rb:10:1:10:5 | "\\\\1" | \\1 | string |
| escapes.rb:11:1:11:6 | "\\141" | \\141 | string |
| escapes.rb:12:1:12:4 | "\\n" | \\n | string |
| escapes.rb:15:1:15:4 | "\\'" | ' | string |
| escapes.rb:16:1:16:4 | "\\"" | " | string |
| escapes.rb:17:1:17:4 | "\\\\" | \\ | string |
| escapes.rb:18:1:18:4 | "\\1" | \u0001 | string |
| escapes.rb:19:1:19:5 | "\\\\1" | \\1 | string |
| escapes.rb:20:1:20:6 | "\\141" | a | string |
| escapes.rb:21:1:21:6 | "\\x6d" | m | string |
| escapes.rb:22:1:22:6 | "\\x6E" | n | string |
| escapes.rb:23:1:23:6 | "\\X6d" | X6d | string |
| escapes.rb:24:1:24:6 | "\\X6E" | X6E | string |
| escapes.rb:25:1:25:8 | "\\u203d" | \u203d | string |
| escapes.rb:26:1:26:8 | "\\u{62}" | b | string |
| escapes.rb:27:1:27:11 | "\\u{1f60a}" | \ud83d\ude0a | string |
| escapes.rb:28:1:28:4 | "\\a" | \u0007 | string |
| escapes.rb:29:1:29:4 | "\\b" | \u0008 | string |
| escapes.rb:30:1:30:4 | "\\t" | \t | string |
| escapes.rb:31:1:31:4 | "\\n" | \n | string |
| escapes.rb:32:1:32:4 | "\\v" | \u000b | string |
| escapes.rb:33:1:33:4 | "\\f" | \u000c | string |
| escapes.rb:34:1:34:4 | "\\r" | \r | string |
| escapes.rb:35:1:35:4 | "\\e" | \u001b | string |
| escapes.rb:36:1:36:4 | "\\s" | | string |
| escapes.rb:37:1:37:5 | "\\c?" | c? | string |
| escapes.rb:38:1:38:6 | "\\C-?" | C-? | string |
| escapes.rb:43:5:43:9 | "\\\\." | \\. | string |
| escapes.rb:44:1:44:6 | "#{...}" | \\. | string |
| escapes.rb:48:1:48:4 | /\\n/ | \\n | string |
| escapes.rb:49:1:49:4 | /\\p/ | \\p | string |
| escapes.rb:50:1:50:8 | /\\u0061/ | \\u0061 | string |
| escapes.rb:53:5:53:9 | "\\\\." | \\. | string |
| escapes.rb:54:5:54:8 | /\\./ | \\. | string |
| escapes.rb:55:1:55:10 | /#{...}#{...}/ | \\.\\. | string |
| escapes.rb:58:4:58:9 | "foo \\n" | foo\\n | string |
| escapes.rb:58:11:58:13 | "bar" | bar | string |
| escapes.rb:61:1:61:5 | :"\\'" | ' | symbol |
| escapes.rb:62:1:62:5 | :"\\"" | \\" | symbol |
| escapes.rb:63:1:63:5 | :"\\\\" | \\ | symbol |
| escapes.rb:64:1:64:5 | :"\\1" | \\1 | symbol |
| escapes.rb:65:1:65:6 | :"\\\\1" | \\1 | symbol |
| escapes.rb:66:1:66:7 | :"\\141" | \\141 | symbol |
| escapes.rb:67:1:67:5 | :"\\n" | \\n | symbol |
| escapes.rb:70:1:70:5 | :"\\'" | ' | symbol |
| escapes.rb:71:1:71:5 | :"\\"" | " | symbol |
| escapes.rb:72:1:72:5 | :"\\\\" | \\ | symbol |
| escapes.rb:73:1:73:5 | :"\\1" | \u0001 | symbol |
| escapes.rb:74:1:74:6 | :"\\\\1" | \\1 | symbol |
| escapes.rb:75:1:75:7 | :"\\141" | a | symbol |
| escapes.rb:76:1:76:7 | :"\\x6d" | m | symbol |
| escapes.rb:77:1:77:7 | :"\\x6E" | n | symbol |
| escapes.rb:78:1:78:7 | :"\\X6d" | X6d | symbol |
| escapes.rb:79:1:79:7 | :"\\X6E" | X6E | symbol |
| escapes.rb:80:1:80:9 | :"\\u203d" | \u203d | symbol |
| escapes.rb:81:1:81:9 | :"\\u{62}" | b | symbol |
| escapes.rb:82:1:82:12 | :"\\u{1f60a}" | \ud83d\ude0a | symbol |
| escapes.rb:83:1:83:5 | :"\\a" | \u0007 | symbol |
| escapes.rb:84:1:84:5 | :"\\b" | \u0008 | symbol |
| escapes.rb:85:1:85:5 | :"\\t" | \t | symbol |
| escapes.rb:86:1:86:5 | :"\\n" | \n | symbol |
| escapes.rb:87:1:87:5 | :"\\v" | \u000b | symbol |
| escapes.rb:88:1:88:5 | :"\\f" | \u000c | symbol |
| escapes.rb:89:1:89:5 | :"\\r" | \r | symbol |
| escapes.rb:90:1:90:5 | :"\\e" | \u001b | symbol |
| escapes.rb:91:1:91:5 | :"\\s" | | symbol |
| escapes.rb:92:1:92:6 | :"\\c?" | c? | symbol |
| escapes.rb:93:1:93:7 | :"\\C-?" | C-? | symbol |

View File

@@ -0,0 +1,24 @@
import ruby
query predicate stringEscapeSequenceComponents(
StringEscapeSequenceComponent c, string raw, string unescaped
) {
(
unescaped = c.getConstantValue().getString()
or
not exists(c.getConstantValue().getString()) and unescaped = "<none>"
) and
raw = c.getRawText()
}
query predicate regexpEscapeSequenceComponents(RegExpEscapeSequenceComponent c, string stringValue) {
stringValue = c.getConstantValue().getString()
or
not exists(c.getConstantValue().getString()) and stringValue = "<none>"
}
query predicate stringlikeLiterals(StringlikeLiteral l, string value, string kind) {
value = l.getConstantValue().getString() and kind = "string"
or
value = l.getConstantValue().getSymbol() and kind = "symbol"
}

View File

@@ -0,0 +1,93 @@
# Most comments indicate the contents of the string after MRI has parsed the
# escape sequences (i.e. what gets printed by `puts`), and that's what we expect
# `getConstantValue().getString()` to return.
# The only escapes in single-quoted strings are backslash and single-quote.
'\'' # '
'\"' # \"
'\\' # \
'\1' # \1
'\\1' # \1
'\141' # \141
'\n' # \n
# Double-quoted strings
"\'" # '
"\"" # "
"\\" # \
"\1" # <U+0001>
"\\1" # \1
"\141" # a
"\x6d" # m
"\x6E" # n
"\X6d" # X6d
"\X6E" # X6E
"\u203d" # ‽
"\u{62}" # b
"\u{1f60a}" # 😊 <Printed as \ud83d\ude0a by CodeQL>
"\a" # <bell U+0007>
"\b" # <backspace U+0008>
"\t" # <tab U+0009>
"\n" # <newline U+000A>
"\v" # <vertical tab U+000B>
"\f" # <form feed U+000C>
"\r" # <carriage return U+000D>
"\e" # <escape U+001B>
"\s" # <space U+0020>
"\c?" # <delete U+007F> problem: only \c is parsed as part of the escape sequence
"\C-?" # <delete U+007F> problem: only \C is parsed as part of the escape sequence
# TODO: support/test more control characters: \M-..., \cx, \C-x, etc.
# String interpolation
a = "\\." # \.
"#{a}" # \.
# Regexps - escape sequences are handled by the regex parser, so their constant
# value should be interpreted literally and not unescaped as in double-quoted strings
/\n/
/\p/
/\u0061/
# Regexp interpolation
a = "\\." # \.
b = /\./
/#{a}#{b}/ # equivalent to /\.\./
# String arrays
%w[foo \n bar] # should be equivalent to ["foo", "\\n", "bar"], but currently misparsed as ["foo \\n", "bar"]
# Single-quoted symbols. Comments indicate the expected, unescaped string contents.
:'\'' # '
:'\"' # \"
:'\\' # \
:'\1' # \1
:'\\1' # \1
:'\141' # \141
:'\n' # \n
# Double-quoted symbols. Comments indicate the expected, unescaped string contents.
:"\'" # '
:"\"" # "
:"\\" # \
:"\1" # <U+0001>
:"\\1" # \1
:"\141" # a
:"\x6d" # m
:"\x6E" # n
:"\X6d" # X6d
:"\X6E" # X6E
:"\u203d" # ‽
:"\u{62}" # b
:"\u{1f60a}" # 😊 <Printed as \ud83d\ude0a by CodeQL>
:"\a" # <bell U+0007>
:"\b" # <backspace U+0008>
:"\t" # <tab U+0009>
:"\n" # <newline U+000A>
:"\v" # <vertical tab U+000B>
:"\f" # <form feed U+000C>
:"\r" # <carriage return U+000D>
:"\e" # <escape U+001B>
:"\s" # <space U+0020>
:"\c?" # <delete U+007F> problem: only \c is parsed as part of the escape sequence
:"\C-?" # <delete U+007F> problem: only \C is parsed as part of the escape sequence

View File

@@ -27,14 +27,14 @@ allLiterals
| literals.rb:47:1:47:2 | "" | StringLiteral | |
| literals.rb:48:1:48:7 | "hello" | StringLiteral | hello |
| literals.rb:49:1:49:9 | "goodbye" | StringLiteral | goodbye |
| literals.rb:50:1:50:30 | "string with escaped \\" quote" | StringLiteral | string with escaped \\" quote |
| literals.rb:50:1:50:30 | "string with escaped \\" quote" | StringLiteral | string with escaped " quote |
| literals.rb:51:1:51:21 | "string with " quote" | StringLiteral | string with " quote |
| literals.rb:52:1:52:14 | "foo bar baz" | StringLiteral | foo bar baz |
| literals.rb:53:1:53:15 | "foo bar baz" | StringLiteral | foo bar baz |
| literals.rb:54:1:54:20 | "foo ' bar " baz'" | StringLiteral | foo ' bar " baz' |
| literals.rb:55:1:55:20 | "FOO ' BAR " BAZ'" | StringLiteral | FOO ' BAR " BAZ' |
| literals.rb:56:1:56:12 | "foo\\ bar" | StringLiteral | foo\\ bar |
| literals.rb:57:1:57:12 | "foo\\ bar" | StringLiteral | foo\\ bar |
| literals.rb:57:1:57:12 | "foo\\ bar" | StringLiteral | foo bar |
| literals.rb:58:1:58:20 | "2 + 2 = #{...}" | StringLiteral | 2 + 2 = 4 |
| literals.rb:58:13:58:13 | 2 | IntegerLiteral | 2 |
| literals.rb:58:17:58:17 | 2 | IntegerLiteral | 2 |
@@ -209,10 +209,10 @@ allLiterals
| literals.rb:147:1:147:10 | /foo/ | RegExpLiteral | <none> |
| literals.rb:150:1:150:34 | "abcdefghijklmnopqrstuvwxyzabcdef" | StringLiteral | abcdefghijklmnopqrstuvwxyzabcdef |
| literals.rb:151:1:151:35 | "foobarfoobarfoobarfoobarfooba..." | StringLiteral | foobarfoobarfoobarfoobarfoobarfoo |
| literals.rb:152:1:152:40 | "foobar\\\\foobar\\\\foobar\\\\fooba..." | StringLiteral | foobar\\\\foobar\\\\foobar\\\\foobar\\\\foobar |
| literals.rb:152:1:152:40 | "foobar\\\\foobar\\\\foobar\\\\fooba..." | StringLiteral | foobar\\foobar\\foobar\\foobar\\foobar |
| literals.rb:155:9:155:13 | <<SQL | HereDoc | \nselect * from table\n |
| literals.rb:155:16:155:20 | <<SQL | HereDoc | <none> |
| literals.rb:162:11:162:16 | <<-BLA | HereDoc | \nsome text\\nand some more\n |
| literals.rb:162:11:162:16 | <<-BLA | HereDoc | \nsome text\nand some more\n |
| literals.rb:167:9:167:19 | <<~SQUIGGLY | HereDoc | \n indented stuff\n |
| literals.rb:171:9:171:15 | <<"DOC" | HereDoc | <none> |
| literals.rb:176:9:176:15 | <<'DOC' | HereDoc | <none> |
@@ -230,14 +230,14 @@ stringlikeLiterals
| literals.rb:47:1:47:2 | "" | |
| literals.rb:48:1:48:7 | "hello" | hello |
| literals.rb:49:1:49:9 | "goodbye" | goodbye |
| literals.rb:50:1:50:30 | "string with escaped \\" quote" | string with escaped \\" quote |
| literals.rb:50:1:50:30 | "string with escaped \\" quote" | string with escaped " quote |
| literals.rb:51:1:51:21 | "string with " quote" | string with " quote |
| literals.rb:52:1:52:14 | "foo bar baz" | foo bar baz |
| literals.rb:53:1:53:15 | "foo bar baz" | foo bar baz |
| literals.rb:54:1:54:20 | "foo ' bar " baz'" | foo ' bar " baz' |
| literals.rb:55:1:55:20 | "FOO ' BAR " BAZ'" | FOO ' BAR " BAZ' |
| literals.rb:56:1:56:12 | "foo\\ bar" | foo\\ bar |
| literals.rb:57:1:57:12 | "foo\\ bar" | foo\\ bar |
| literals.rb:57:1:57:12 | "foo\\ bar" | foo bar |
| literals.rb:58:1:58:20 | "2 + 2 = #{...}" | 2 + 2 = 4 |
| literals.rb:59:1:59:22 | "3 + 4 = #{...}" | 3 + 4 = 7 |
| literals.rb:60:1:60:20 | "2 + 2 = #{ 2 + 2 }" | 2 + 2 = #{ 2 + 2 } |
@@ -327,10 +327,10 @@ stringlikeLiterals
| literals.rb:147:1:147:10 | /foo/ | <none> |
| literals.rb:150:1:150:34 | "abcdefghijklmnopqrstuvwxyzabcdef" | abcdefghijklmnopqrstuvwxyzabcdef |
| literals.rb:151:1:151:35 | "foobarfoobarfoobarfoobarfooba..." | foobarfoobarfoobarfoobarfoobarfoo |
| literals.rb:152:1:152:40 | "foobar\\\\foobar\\\\foobar\\\\fooba..." | foobar\\\\foobar\\\\foobar\\\\foobar\\\\foobar |
| literals.rb:152:1:152:40 | "foobar\\\\foobar\\\\foobar\\\\fooba..." | foobar\\foobar\\foobar\\foobar\\foobar |
| literals.rb:155:9:155:13 | <<SQL | \nselect * from table\n |
| literals.rb:155:16:155:20 | <<SQL | <none> |
| literals.rb:162:11:162:16 | <<-BLA | \nsome text\\nand some more\n |
| literals.rb:162:11:162:16 | <<-BLA | \nsome text\nand some more\n |
| literals.rb:167:9:167:19 | <<~SQUIGGLY | \n indented stuff\n |
| literals.rb:171:9:171:15 | <<"DOC" | <none> |
| literals.rb:176:9:176:15 | <<'DOC' | <none> |
@@ -344,14 +344,14 @@ stringLiterals
| literals.rb:47:1:47:2 | "" | |
| literals.rb:48:1:48:7 | "hello" | hello |
| literals.rb:49:1:49:9 | "goodbye" | goodbye |
| literals.rb:50:1:50:30 | "string with escaped \\" quote" | string with escaped \\" quote |
| literals.rb:50:1:50:30 | "string with escaped \\" quote" | string with escaped " quote |
| literals.rb:51:1:51:21 | "string with " quote" | string with " quote |
| literals.rb:52:1:52:14 | "foo bar baz" | foo bar baz |
| literals.rb:53:1:53:15 | "foo bar baz" | foo bar baz |
| literals.rb:54:1:54:20 | "foo ' bar " baz'" | foo ' bar " baz' |
| literals.rb:55:1:55:20 | "FOO ' BAR " BAZ'" | FOO ' BAR " BAZ' |
| literals.rb:56:1:56:12 | "foo\\ bar" | foo\\ bar |
| literals.rb:57:1:57:12 | "foo\\ bar" | foo\\ bar |
| literals.rb:57:1:57:12 | "foo\\ bar" | foo bar |
| literals.rb:58:1:58:20 | "2 + 2 = #{...}" | 2 + 2 = 4 |
| literals.rb:59:1:59:22 | "3 + 4 = #{...}" | 3 + 4 = 7 |
| literals.rb:60:1:60:20 | "2 + 2 = #{ 2 + 2 }" | 2 + 2 = #{ 2 + 2 } |
@@ -392,7 +392,7 @@ stringLiterals
| literals.rb:117:22:117:26 | "baz" | baz |
| literals.rb:150:1:150:34 | "abcdefghijklmnopqrstuvwxyzabcdef" | abcdefghijklmnopqrstuvwxyzabcdef |
| literals.rb:151:1:151:35 | "foobarfoobarfoobarfoobarfooba..." | foobarfoobarfoobarfoobarfoobarfoo |
| literals.rb:152:1:152:40 | "foobar\\\\foobar\\\\foobar\\\\fooba..." | foobar\\\\foobar\\\\foobar\\\\foobar\\\\foobar |
| literals.rb:152:1:152:40 | "foobar\\\\foobar\\\\foobar\\\\fooba..." | foobar\\foobar\\foobar\\foobar\\foobar |
regExpLiterals
| literals.rb:136:1:136:2 | // | | |
| literals.rb:137:1:137:5 | /foo/ | foo | |

View File

@@ -17,5 +17,5 @@ alias
| misc.rb:8:1:8:14 | alias ... | old | misc.rb:8:12:8:14 | []= | []= | MethodName |
| misc.rb:9:1:9:16 | alias ... | new | misc.rb:9:7:9:11 | super | super | MethodName |
| misc.rb:9:1:9:16 | alias ... | old | misc.rb:9:13:9:16 | self | self | MethodName |
| misc.rb:10:1:10:24 | alias ... | new | misc.rb:10:7:10:17 | :"\\n#{...}" | \\nbar | MethodName |
| misc.rb:10:1:10:24 | alias ... | new | misc.rb:10:7:10:17 | :"\\n#{...}" | \nbar | MethodName |
| misc.rb:10:1:10:24 | alias ... | old | misc.rb:10:19:10:24 | :"foo" | foo | MethodName |

View File

@@ -95,4 +95,5 @@
| tst.rb:375:11:375:27 | ([[:digit:]]\|\\d)+ | This part of the regular expression may cause exponential backtracking on strings starting with 'X' and containing many repetitions of '0'. |
| tst.rb:378:12:378:18 | (a\|\\w)* | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of 'a'. |
| tst.rb:379:12:379:18 | (a\|\\w)* | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of 'a'. |
| tst.rb:390:66:390:67 | .? | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of '00\\\\'. |
| tst.rb:390:70:390:110 | (?:[a-zA-Z0-9_]\|%[a-fA-F0-9][a-fA-F0-9])+ | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of '0'. |
| tst.rb:390:98:390:108 | [a-fA-F0-9] | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of '0%0'. |