mirror of
https://github.com/github/codeql.git
synced 2026-05-01 19:55:15 +02:00
Ruby: interpret string escape sequences in getConstantValue()
This commit is contained in:
97
ruby/ql/lib/codeql/NumberUtils.qll
Normal file
97
ruby/ql/lib/codeql/NumberUtils.qll
Normal 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)
|
||||
}
|
||||
@@ -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()) }
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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`.
|
||||
*/
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 []
|
||||
|
||||
@@ -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 |
|
||||
|
||||
@@ -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 |
|
||||
@@ -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"
|
||||
}
|
||||
93
ruby/ql/test/library-tests/ast/escape_sequences/escapes.rb
Normal file
93
ruby/ql/test/library-tests/ast/escape_sequences/escapes.rb
Normal 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
|
||||
@@ -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 | |
|
||||
|
||||
@@ -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 |
|
||||
|
||||
@@ -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'. |
|
||||
|
||||
Reference in New Issue
Block a user