The idea behind optional results is that there may be instances where
each line of source code has many results and you don't want to annotate
all of them, but you still want to ensure that any annotations you do
have are correct.
This change makes that possible by exposing a new predicate
`hasOptionalResult`, which has the same signature as `hasResult`.
Results produced by `hasOptionalResult` will be matched against any
annotations, but the lack of a matching annotation will not cause a
failure.
We will use this in the inline tests for the API edge getASubclass,
because for each API path that uses getASubclass there is always a
shorter path that does not use it, and thus we can't use the normal
shortest-path matching approach that works for other API Graph tests.
Create a set of classes for components of regex literals,
separate from those of string literals. This allows us to special-case
components of free-spacing regexes (ones with the /x flag) to not have a
`getValueText()`.
This in turn is useful because our regex parser can't handle free-spacing
regexes, so excluding them ensures that we don't generate erroneous
ReDoS alerts.
Module#const_get takes a single string argument and interprets it as the
name of a constant. It then looks up the constant and returns its value.
Object.const_get("Math::PI")
# => 3.141592653589793
By itself, this method is not as dangerous as e.g. eval, but if the
value returned is a class that is then instantiated, this can allow an
attacker to instantiate arbitrary Ruby classes.
As a result, I think it's safe to say that any remote input flowing into
this call is a potential vulnerability. A real-world example of this is
https://github.com/advisories/GHSA-52p9-v744-mwjj.
When calculating `StringlikeLiteral.getValueText`, include results from
interpolations where we can determine their string value. For example:
b = "b" # local variable
D = "d" # constant
"a#{b}c" # getValueText() = "abc"
"a#{b}c{D}" # getValueText() = "abcd"
/#a#{b}c{D}/ # getValueText() = "abcd"