mirror of
https://github.com/github/codeql.git
synced 2025-12-16 16:53:25 +01:00
Merge branch 'main' into js/move-cors-query-from-experimental
This commit is contained in:
@@ -35,7 +35,7 @@ class CustomOptions extends Options {
|
||||
override predicate returnsNull(Call call) { Options.super.returnsNull(call) }
|
||||
|
||||
/**
|
||||
* Holds if a call to this function will never return.
|
||||
* Holds if a call to the function `f` will never return.
|
||||
*
|
||||
* By default, this holds for `exit`, `_exit`, `abort`, `__assert_fail`,
|
||||
* `longjmp`, `error`, `__builtin_unreachable` and any function with a
|
||||
|
||||
4
cpp/ql/lib/change-notes/2025-09-03-rename-api.md
Normal file
4
cpp/ql/lib/change-notes/2025-09-03-rename-api.md
Normal file
@@ -0,0 +1,4 @@
|
||||
---
|
||||
category: deprecated
|
||||
---
|
||||
* The predicate `getAContructorCall` in the class `SslContextClass` has been deprecated. Use `getAConstructorCall` instead.
|
||||
@@ -127,7 +127,7 @@ abstract class CryptographicAlgorithm extends CryptographicArtifact {
|
||||
/**
|
||||
* Normalizes a raw name into a normalized name as found in `CryptoAlgorithmNames.qll`.
|
||||
* Subclassess should override for more api-specific normalization.
|
||||
* By deafult, converts a raw name to upper-case with no hyphen, underscore, hash, or space.
|
||||
* By default, converts a raw name to upper-case with no hyphen, underscore, hash, or space.
|
||||
*/
|
||||
bindingset[s]
|
||||
string normalizeName(string s) {
|
||||
|
||||
@@ -652,14 +652,14 @@ module KeyGeneration {
|
||||
* Trace from EVP_PKEY_CTX* at algorithm sink to keygen,
|
||||
* users can then extrapolatae the matching algorithm from the alg sink to the keygen
|
||||
*/
|
||||
module EVP_PKEY_CTX_Ptr_Source_to_KeyGenOperationWithNoSize implements DataFlow::ConfigSig {
|
||||
module EVP_PKEY_CTX_Ptr_Source_to_KeyGenOperationWithNoSizeConfig implements DataFlow::ConfigSig {
|
||||
predicate isSource(DataFlow::Node source) { isEVP_PKEY_CTX_Source(source, _) }
|
||||
|
||||
predicate isSink(DataFlow::Node sink) { isKeyGen_EVP_PKEY_CTX_Sink(sink, _) }
|
||||
}
|
||||
|
||||
module EVP_PKEY_CTX_Ptr_Source_to_KeyGenOperationWithNoSize_Flow =
|
||||
DataFlow::Global<EVP_PKEY_CTX_Ptr_Source_to_KeyGenOperationWithNoSize>;
|
||||
DataFlow::Global<EVP_PKEY_CTX_Ptr_Source_to_KeyGenOperationWithNoSizeConfig>;
|
||||
|
||||
/**
|
||||
* UNKNOWN key sizes to general purpose key generation functions (i.e., that take in no key size and assume
|
||||
|
||||
@@ -59,7 +59,7 @@ private string privateNormalizeFunctionName(Function f, string algType) {
|
||||
*
|
||||
* The predicate attempts to restrict normalization to what looks like an openssl
|
||||
* library by looking for functions only in an openssl path (see `isPossibleOpenSSLFunction`).
|
||||
* This may give false postive functions if a directory erronously appears to be openssl;
|
||||
* This may give false positive functions if a directory erronously appears to be openssl;
|
||||
* however, we take the stance that if a function
|
||||
* exists strongly mapping to a known function name in a directory such as these,
|
||||
* regardless of whether its actually a part of openSSL or not, we will analyze it as though it were.
|
||||
|
||||
@@ -49,7 +49,7 @@ private string privateNormalizeFunctionName(Function f, string algType) {
|
||||
*
|
||||
* The predicate attempts to restrict normalization to what looks like an openssl
|
||||
* library by looking for functions only in an openssl path (see `isPossibleOpenSSLFunction`).
|
||||
* This may give false postive functions if a directory erronously appears to be openssl;
|
||||
* This may give false positive functions if a directory erronously appears to be openssl;
|
||||
* however, we take the stance that if a function
|
||||
* exists strongly mapping to a known function name in a directory such as these,
|
||||
* regardless of whether its actually a part of openSSL or not, we will analyze it as though it were.
|
||||
|
||||
@@ -31,7 +31,7 @@ predicate knownPassthroughFunction(Function f, int inInd, int outInd) {
|
||||
|
||||
/**
|
||||
* `c` is a call to a function that preserves the algorithm but changes its form.
|
||||
* `onExpr` is the input argument passing through to, `outExpr` is the next expression in a dataflow step associated with `c`
|
||||
* `inExpr` is the input argument passing through to, `outExpr` is the next expression in a dataflow step associated with `c`
|
||||
*/
|
||||
predicate knownPassthoughCall(Call c, Expr inExpr, Expr outExpr) {
|
||||
exists(int inInd, int outInd |
|
||||
|
||||
@@ -298,10 +298,11 @@ private predicate boundFlowStep(Instruction i, NonPhiOperand op, int delta, bool
|
||||
else
|
||||
if strictlyNegative(x)
|
||||
then upper = true and delta = -1
|
||||
else
|
||||
if negative(x)
|
||||
then upper = true and delta = 0
|
||||
else none()
|
||||
else (
|
||||
negative(x) and
|
||||
upper = true and
|
||||
delta = 0
|
||||
)
|
||||
)
|
||||
or
|
||||
exists(Operand x |
|
||||
@@ -321,10 +322,11 @@ private predicate boundFlowStep(Instruction i, NonPhiOperand op, int delta, bool
|
||||
else
|
||||
if strictlyNegative(x)
|
||||
then upper = false and delta = 1
|
||||
else
|
||||
if negative(x)
|
||||
then upper = false and delta = 0
|
||||
else none()
|
||||
else (
|
||||
negative(x) and
|
||||
upper = false and
|
||||
delta = 0
|
||||
)
|
||||
)
|
||||
or
|
||||
i.(RemInstruction).getRightOperand() = op and positive(op) and delta = -1 and upper = true
|
||||
|
||||
@@ -198,7 +198,7 @@ class ConceptIdExpr extends Expr, @concept_id {
|
||||
final Locatable getATemplateArgumentKind() { result = this.getTemplateArgumentKind(_) }
|
||||
|
||||
/**
|
||||
* Gets the `i`th template argument passed to the concept.
|
||||
* Gets template argument at index `index` passed to the concept, if any.
|
||||
*
|
||||
* For example, if:
|
||||
* ```cpp
|
||||
@@ -219,7 +219,7 @@ class ConceptIdExpr extends Expr, @concept_id {
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the kind of the `i`th template argument value passed to the concept.
|
||||
* Gets the kind of the template argument value at index `index` passed to the concept, if any.
|
||||
*
|
||||
* For example, if:
|
||||
* ```cpp
|
||||
|
||||
@@ -223,8 +223,8 @@ class Declaration extends Locatable, @declaration {
|
||||
final Locatable getATemplateArgumentKind() { result = this.getTemplateArgumentKind(_) }
|
||||
|
||||
/**
|
||||
* Gets the `i`th template argument used to instantiate this declaration from a
|
||||
* template.
|
||||
* Gets the template argument at index `index` used to instantiate this declaration from a
|
||||
* template, if any.
|
||||
*
|
||||
* For example:
|
||||
*
|
||||
@@ -245,9 +245,9 @@ class Declaration extends Locatable, @declaration {
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the `i`th template argument value used to instantiate this declaration
|
||||
* from a template. When called on a template, this will return the `i`th template
|
||||
* parameter value if it exists.
|
||||
* Gets the template argument value at index `index` used to instantiate this declaration
|
||||
* from a template. When called on a template, this will return the template
|
||||
* parameter value at index `index` if it exists.
|
||||
*
|
||||
* For example:
|
||||
*
|
||||
|
||||
@@ -877,7 +877,7 @@ class FormatLiteral extends Literal instanceof StringLiteral {
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the char type required by the nth conversion specifier.
|
||||
* Gets the char type required by the `n`th conversion specifier.
|
||||
* - in the base case this is the default for the formatting function
|
||||
* (e.g. `char` for `printf`, `char` or `wchar_t` for `wprintf`).
|
||||
* - the `%C` format character reverses wideness.
|
||||
@@ -922,7 +922,7 @@ class FormatLiteral extends Literal instanceof StringLiteral {
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the string type required by the nth conversion specifier.
|
||||
* Gets the string type required by the `n`th conversion specifier.
|
||||
* - in the base case this is the default for the formatting function
|
||||
* (e.g. `char *` for `printf`, `char *` or `wchar_t *` for `wprintf`).
|
||||
* - the `%S` format character reverses wideness on some platforms.
|
||||
|
||||
@@ -101,7 +101,7 @@ predicate postDominates(ControlFlowNode postDominator, ControlFlowNode node) {
|
||||
*/
|
||||
|
||||
/**
|
||||
* Holds if `dominator` is an immediate dominator of `node` in the control-flow
|
||||
* Holds if `dom` is an immediate dominator of `node` in the control-flow
|
||||
* graph of basic blocks.
|
||||
*/
|
||||
predicate bbIDominates(BasicBlock dom, BasicBlock node) =
|
||||
@@ -117,7 +117,7 @@ private predicate bb_predecessor(BasicBlock succ, BasicBlock pred) { bb_successo
|
||||
private predicate bb_exit(ExitBasicBlock exit) { any() }
|
||||
|
||||
/**
|
||||
* Holds if `postDominator` is an immediate post-dominator of `node` in the control-flow
|
||||
* Holds if `pDom` is an immediate post-dominator of `node` in the control-flow
|
||||
* graph of basic blocks.
|
||||
*/
|
||||
predicate bbIPostDominates(BasicBlock pDom, BasicBlock node) =
|
||||
|
||||
@@ -1042,8 +1042,8 @@ private predicate subEdgeIncludingDestructors(Pos p1, Node n1, Node n2, Pos p2)
|
||||
* - `MicrosoftTryFinallyStmt`: On the edge following the `__finally` block for
|
||||
* the case where an exception was thrown and needs to be propagated.
|
||||
*/
|
||||
DestructorCall getSynthesisedDestructorCallAfterNode(Node n, int i) {
|
||||
synthetic_destructor_call(n, i, result)
|
||||
DestructorCall getSynthesisedDestructorCallAfterNode(Node node, int index) {
|
||||
synthetic_destructor_call(node, index, result)
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -834,8 +834,10 @@ class ContentSet instanceof Content {
|
||||
* For more information, see
|
||||
* [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/).
|
||||
*/
|
||||
predicate hasLocationInfo(string path, int sl, int sc, int el, int ec) {
|
||||
super.hasLocationInfo(path, sl, sc, el, ec)
|
||||
predicate hasLocationInfo(
|
||||
string filepath, int startline, int startcolumn, int endline, int endcolumn
|
||||
) {
|
||||
super.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -2273,8 +2273,10 @@ class ContentSet instanceof Content {
|
||||
* For more information, see
|
||||
* [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/).
|
||||
*/
|
||||
predicate hasLocationInfo(string path, int sl, int sc, int el, int ec) {
|
||||
super.hasLocationInfo(path, sl, sc, el, ec)
|
||||
predicate hasLocationInfo(
|
||||
string filepath, int startline, int startcolumn, int endline, int endcolumn
|
||||
) {
|
||||
super.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -50,7 +50,7 @@ CppType getEllipsisVariablePRValueType() {
|
||||
CppType getEllipsisVariableGLValueType() { result = getTypeForGLValue(any(UnknownType t)) }
|
||||
|
||||
/**
|
||||
* Holds if the function returns a value, as opposed to returning `void`.
|
||||
* Holds if the function `func` returns a value, as opposed to returning `void`.
|
||||
*/
|
||||
predicate hasReturnValue(Function func) { not func.getUnspecifiedType() instanceof VoidType }
|
||||
|
||||
|
||||
@@ -601,7 +601,7 @@ class TranslatedReturnVoidStmt extends TranslatedReturnStmt {
|
||||
* The IR translation of an implicit `return` statement generated by the extractor to handle control
|
||||
* flow that reaches the end of a non-`void`-returning function body. Such control flow
|
||||
* produces undefined behavior in C++ but not in C. However even in C using the return value is
|
||||
* undefined behaviour. We make it return uninitialized memory to get as much flow as possible.
|
||||
* undefined behavior. We make it return uninitialized memory to get as much flow as possible.
|
||||
*/
|
||||
class TranslatedNoValueReturnStmt extends TranslatedReturnStmt, TranslatedVariableInitialization {
|
||||
TranslatedNoValueReturnStmt() {
|
||||
|
||||
@@ -49,7 +49,8 @@ Type getVariableType(Variable v) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if the database contains a `case` label with the specified minimum and maximum value.
|
||||
* Holds if the database contains a `switchCase` label with the specified minimum `minValue`
|
||||
* and maximum `maxValue` value.
|
||||
*/
|
||||
predicate hasCaseEdge(SwitchCase switchCase, string minValue, string maxValue) {
|
||||
minValue = switchCase.getExpr().getFullyConverted().getValue() and
|
||||
|
||||
@@ -371,7 +371,7 @@ class FunctionOutput extends TFunctionOutput {
|
||||
/**
|
||||
* Holds if this is the output value pointed to by a pointer parameter to a function, or the
|
||||
* output value referred to by a reference parameter to a function, where the parameter has
|
||||
* index `index`.
|
||||
* index `i`.
|
||||
*
|
||||
* Example:
|
||||
* ```
|
||||
@@ -389,7 +389,7 @@ class FunctionOutput extends TFunctionOutput {
|
||||
/**
|
||||
* Holds if this is the output value pointed to by a pointer parameter (through `ind` number
|
||||
* of indirections) to a function, or the output value referred to by a reference parameter to
|
||||
* a function, where the parameter has index `index`.
|
||||
* a function, where the parameter has index `i`.
|
||||
*
|
||||
* Example:
|
||||
* ```
|
||||
|
||||
@@ -307,13 +307,12 @@ class SemStoreExpr extends SemUnaryExpr {
|
||||
}
|
||||
|
||||
class SemConditionalExpr extends SemKnownExpr {
|
||||
SemExpr condition;
|
||||
SemExpr trueResult;
|
||||
SemExpr falseResult;
|
||||
|
||||
SemConditionalExpr() {
|
||||
opcode instanceof Opcode::Conditional and
|
||||
Specific::conditionalExpr(this, type, condition, trueResult, falseResult)
|
||||
Specific::conditionalExpr(this, type, any(SemExpr condition), trueResult, falseResult)
|
||||
}
|
||||
|
||||
final SemExpr getBranchExpr(boolean branch) {
|
||||
|
||||
@@ -21,7 +21,9 @@ class FileWrite extends Expr {
|
||||
Expr getDest() { fileWrite(this, _, result) }
|
||||
|
||||
/**
|
||||
* Gets the conversion character for this write, if it exists and is known. For example in the following code the write of `value1` has conversion character `"s"`, whereas the write of `value2` has no conversion specifier.
|
||||
* Gets the conversion character from `source` for this write, if it exists and is known.
|
||||
* For example in the following code the write of `value1` has conversion character `"s"`, whereas
|
||||
* the write of `value2` has no conversion specifier.
|
||||
* ```
|
||||
* fprintf(file, "%s", value1);
|
||||
* stream << value2;
|
||||
|
||||
@@ -191,11 +191,19 @@ module BoostorgAsio {
|
||||
class SslContextClass extends Class {
|
||||
SslContextClass() { this.getQualifiedName() = "boost::asio::ssl::context" }
|
||||
|
||||
ConstructorCall getAContructorCall() {
|
||||
/**
|
||||
* Gets a constructor call, if any.
|
||||
*/
|
||||
ConstructorCall getAConstructorCall() {
|
||||
this.getAConstructor().getACallToThisFunction() = result and
|
||||
not result.getLocation().getFile().toString().matches("%/boost/asio/%") and
|
||||
result.fromSource()
|
||||
}
|
||||
|
||||
/**
|
||||
* DEPRECATED: Use `getAConstructorCall` instead.
|
||||
*/
|
||||
deprecated ConstructorCall getAContructorCall() { result = this.getAConstructorCall() }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -368,7 +376,7 @@ module BoostorgAsio {
|
||||
*/
|
||||
default predicate isSink(DataFlow::Node sink) {
|
||||
exists(ConstructorCall cc, SslContextClass c, Expr e | e = sink.asExpr() |
|
||||
c.getAContructorCall() = cc and
|
||||
c.getAConstructorCall() = cc and
|
||||
cc.getArgument(0) = e
|
||||
)
|
||||
}
|
||||
@@ -468,7 +476,7 @@ module BoostorgAsio {
|
||||
predicate isSource(DataFlow::Node source) {
|
||||
exists(SslContextClass c, ConstructorCall cc |
|
||||
cc = source.asExpr() and
|
||||
c.getAContructorCall() = cc
|
||||
c.getAConstructorCall() = cc
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -164,12 +164,17 @@ predicate valueOccurrenceCount(string value, int n) {
|
||||
n > 20
|
||||
}
|
||||
|
||||
predicate occurenceCount(Literal lit, string value, int n) {
|
||||
predicate occurrenceCount(Literal lit, string value, int n) {
|
||||
valueOccurrenceCount(value, n) and
|
||||
value = lit.getValue() and
|
||||
nonTrivialValue(_, lit)
|
||||
}
|
||||
|
||||
/**
|
||||
* DEPRECATED: Use `occurrenceCount` instead.
|
||||
*/
|
||||
deprecated predicate occurenceCount = occurrenceCount/3;
|
||||
|
||||
/*
|
||||
* Literals repeated frequently
|
||||
*/
|
||||
@@ -178,7 +183,7 @@ predicate check(Literal lit, string value, int n, File f) {
|
||||
// Check that the literal is nontrivial
|
||||
not trivial(lit) and
|
||||
// Check that it is repeated a number of times
|
||||
occurenceCount(lit, value, n) and
|
||||
occurrenceCount(lit, value, n) and
|
||||
n > 20 and
|
||||
f = lit.getFile() and
|
||||
// Exclude generated files
|
||||
|
||||
@@ -128,11 +128,18 @@ abstract class LeapYearFieldAccess extends YearFieldAccess {
|
||||
/**
|
||||
* Holds if the top-level binary operation includes an addition or subtraction operator with an operand specified by `valueToCheck`.
|
||||
*/
|
||||
predicate additionalAdditionOrSubstractionCheckForLeapYear(int valueToCheck) {
|
||||
predicate additionalAdditionOrSubtractionCheckForLeapYear(int valueToCheck) {
|
||||
additionalLogicalCheck(this, "+", valueToCheck) or
|
||||
additionalLogicalCheck(this, "-", valueToCheck)
|
||||
}
|
||||
|
||||
/**
|
||||
* DEPRECATED: Use `additionalAdditionOrSubtractionCheckForLeapYear` instead.
|
||||
*/
|
||||
deprecated predicate additionalAdditionOrSubstractionCheckForLeapYear(int valueToCheck) {
|
||||
this.additionalAdditionOrSubtractionCheckForLeapYear(valueToCheck)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if this object is used on a modulus 4 operation, which would likely indicate the start of a leap year check.
|
||||
*/
|
||||
@@ -180,13 +187,13 @@ class StructTmLeapYearFieldAccess extends LeapYearFieldAccess {
|
||||
this.additionalModulusCheckForLeapYear(100) and
|
||||
// tm_year represents years since 1900
|
||||
(
|
||||
this.additionalAdditionOrSubstractionCheckForLeapYear(1900)
|
||||
this.additionalAdditionOrSubtractionCheckForLeapYear(1900)
|
||||
or
|
||||
// some systems may use 2000 for 2-digit year conversions
|
||||
this.additionalAdditionOrSubstractionCheckForLeapYear(2000)
|
||||
this.additionalAdditionOrSubtractionCheckForLeapYear(2000)
|
||||
or
|
||||
// converting from/to Unix epoch
|
||||
this.additionalAdditionOrSubstractionCheckForLeapYear(1970)
|
||||
this.additionalAdditionOrSubtractionCheckForLeapYear(1970)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,7 +14,7 @@ import cpp
|
||||
import semmle.code.cpp.security.boostorg.asio.protocols
|
||||
|
||||
predicate isSourceImpl(DataFlow::Node source, ConstructorCall cc) {
|
||||
exists(BoostorgAsio::SslContextClass c | c.getAContructorCall() = cc and cc = source.asExpr())
|
||||
exists(BoostorgAsio::SslContextClass c | c.getAConstructorCall() = cc and cc = source.asExpr())
|
||||
}
|
||||
|
||||
predicate isSinkImpl(DataFlow::Node sink, FunctionCall fcSetOptions) {
|
||||
|
||||
@@ -20,12 +20,14 @@ class RangeFunction extends Function {
|
||||
* For more information, see
|
||||
* [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/).
|
||||
*/
|
||||
predicate hasLocationInfo(string path, int sl, int sc, int el, int ec) {
|
||||
super.getLocation().hasLocationInfo(path, sl, sc, _, _) and
|
||||
predicate hasLocationInfo(
|
||||
string filepath, int startline, int startcolumn, int endline, int endcolumn
|
||||
) {
|
||||
super.getLocation().hasLocationInfo(filepath, startline, startcolumn, _, _) and
|
||||
(
|
||||
this.getBlock().getLocation().hasLocationInfo(path, _, _, el, ec)
|
||||
this.getBlock().getLocation().hasLocationInfo(filepath, _, _, endline, endcolumn)
|
||||
or
|
||||
not exists(this.getBlock()) and el = sl + 1 and ec = 1
|
||||
not exists(this.getBlock()) and endline = startline + 1 and endcolumn = 1
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,10 +25,10 @@ import semmle.code.cpp.controlflow.IRGuards as IRGuards
|
||||
predicate outOfBoundsExpr(Expr expr, string kind) {
|
||||
if convertedExprMightOverflowPositively(expr)
|
||||
then kind = "overflow"
|
||||
else
|
||||
if convertedExprMightOverflowNegatively(expr)
|
||||
then kind = "overflow negatively"
|
||||
else none()
|
||||
else (
|
||||
convertedExprMightOverflowNegatively(expr) and
|
||||
kind = "overflow negatively"
|
||||
)
|
||||
}
|
||||
|
||||
predicate isSource(FS::FlowSource source, string sourceType) { sourceType = source.getSourceType() }
|
||||
|
||||
@@ -31,27 +31,28 @@ private predicate hasConditionalInitialization(
|
||||
class ConditionallyInitializedVariable extends LocalVariable {
|
||||
ConditionalInitializationCall call;
|
||||
ConditionalInitializationFunction f;
|
||||
VariableAccess initAccess;
|
||||
Evidence e;
|
||||
|
||||
ConditionallyInitializedVariable() {
|
||||
// Find a call that conditionally initializes this variable
|
||||
hasConditionalInitialization(f, call, this, initAccess, e) and
|
||||
// Ignore cases where the variable is assigned prior to the call
|
||||
not reaches(this.getAnAssignedValue(), initAccess) and
|
||||
// Ignore cases where the variable is assigned field-wise prior to the call.
|
||||
not exists(FieldAccess fa |
|
||||
exists(Assignment a |
|
||||
fa = getAFieldAccess(this) and
|
||||
a.getLValue() = fa
|
||||
exists(VariableAccess initAccess |
|
||||
hasConditionalInitialization(f, call, this, initAccess, e) and
|
||||
// Ignore cases where the variable is assigned prior to the call
|
||||
not reaches(this.getAnAssignedValue(), initAccess) and
|
||||
// Ignore cases where the variable is assigned field-wise prior to the call.
|
||||
not exists(FieldAccess fa |
|
||||
exists(Assignment a |
|
||||
fa = getAFieldAccess(this) and
|
||||
a.getLValue() = fa
|
||||
)
|
||||
|
|
||||
reaches(fa, initAccess)
|
||||
) and
|
||||
// Ignore cases where the variable is assigned by a prior call to an initialization function
|
||||
not exists(Call c |
|
||||
this.getAnAccess() = getAnInitializedArgument(c).(AddressOfExpr).getOperand() and
|
||||
reaches(c, initAccess)
|
||||
)
|
||||
|
|
||||
reaches(fa, initAccess)
|
||||
) and
|
||||
// Ignore cases where the variable is assigned by a prior call to an initialization function
|
||||
not exists(Call c |
|
||||
this.getAnAccess() = getAnInitializedArgument(c).(AddressOfExpr).getOperand() and
|
||||
reaches(c, initAccess)
|
||||
) and
|
||||
/*
|
||||
* Static local variables with constant initializers do not have the initializer expr as part of
|
||||
|
||||
@@ -41,7 +41,7 @@ predicate deleteMayThrow(DeleteOrDeleteArrayExpr deleteExpr) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if the function may throw an exception when called. That is, if the body of the function looks
|
||||
* Holds if the function `f` may throw an exception when called. That is, if the body of the function looks
|
||||
* like it might throw an exception, and the function does not have a `noexcept` or `throw()` specifier.
|
||||
*/
|
||||
predicate functionMayThrow(Function f) {
|
||||
|
||||
5
cpp/ql/src/change-notes/2025-09-03-rename-api.md
Normal file
5
cpp/ql/src/change-notes/2025-09-03-rename-api.md
Normal file
@@ -0,0 +1,5 @@
|
||||
---
|
||||
category: fix
|
||||
---
|
||||
* The predicate `occurenceCount` in the file module `MagicConstants` has been deprecated. Use `occurrenceCount` instead.
|
||||
* The predicate `additionalAdditionOrSubstractionCheckForLeapYear` in the file module `LeapYear` has been deprecated. Use `additionalAdditionOrSubtractionCheckForLeapYear` instead.
|
||||
@@ -13,6 +13,6 @@ where
|
||||
def = definitionOf(e, kind) and
|
||||
// We need to exclude definitions for elements inside template instantiations,
|
||||
// as these often lead to multiple links to definitions from the same source location.
|
||||
// LGTM does not support this behaviour.
|
||||
// LGTM does not support this behavior.
|
||||
not e.isFromTemplateInstantiation(_)
|
||||
select e, def, kind
|
||||
|
||||
@@ -47,7 +47,7 @@ where
|
||||
// for a function parameter
|
||||
unchecked.getTarget() = param and
|
||||
// this function parameter is not overwritten
|
||||
count(param.getAnAssignment()) = 0 and
|
||||
not exists(param.getAnAssignment()) and
|
||||
check.getTarget() = param and
|
||||
// which is once checked
|
||||
candidateResultChecked(check, eqop) and
|
||||
|
||||
@@ -19,16 +19,17 @@ import cpp
|
||||
* Errors when using a variable declaration inside a loop.
|
||||
*/
|
||||
class DangerousWhileLoop extends WhileStmt {
|
||||
Expr exp;
|
||||
Declaration dl;
|
||||
|
||||
DangerousWhileLoop() {
|
||||
this = dl.getParentScope().(BlockStmt).getParent*() and
|
||||
exp = this.getCondition().getAChild*() and
|
||||
not exp instanceof PointerFieldAccess and
|
||||
not exp instanceof ValueFieldAccess and
|
||||
exp.(VariableAccess).getTarget().getName() = dl.getName() and
|
||||
not exp.getParent*() instanceof FunctionCall
|
||||
exists(Expr exp |
|
||||
exp = this.getCondition().getAChild*() and
|
||||
not exp instanceof PointerFieldAccess and
|
||||
not exp instanceof ValueFieldAccess and
|
||||
exp.(VariableAccess).getTarget().getName() = dl.getName() and
|
||||
not exp.getParent*() instanceof FunctionCall
|
||||
)
|
||||
}
|
||||
|
||||
Declaration getDeclaration() { result = dl }
|
||||
|
||||
@@ -46,7 +46,7 @@ predicate exprMayBeString(Expr exp) {
|
||||
)
|
||||
}
|
||||
|
||||
/** Holds if expression is constant or operator call `sizeof`. */
|
||||
/** Holds if expression `exp` is constant or operator call `sizeof`. */
|
||||
predicate argConstOrSizeof(Expr exp) {
|
||||
exp.getValue().toInt() > 1 or
|
||||
exp.(SizeofTypeOperator).getTypeOperand().getSize() > 1
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
import cpp
|
||||
import semmle.code.cpp.commons.Exclusions
|
||||
|
||||
/** Holds if a `fc` function call is available before or after a `chdir` function call. */
|
||||
/** Holds if a `fcp` function call is available before or after a `chdir` function call. */
|
||||
predicate inExistsChdir(FunctionCall fcp) {
|
||||
exists(FunctionCall fctmp |
|
||||
(
|
||||
@@ -29,7 +29,7 @@ predicate inExistsChdir(FunctionCall fcp) {
|
||||
)
|
||||
}
|
||||
|
||||
/** Holds if a `fc` function call is available before or after a function call containing a `chdir` call. */
|
||||
/** Holds if a `fcp` function call is available before or after a function call containing a `chdir` call. */
|
||||
predicate outExistsChdir(FunctionCall fcp) {
|
||||
exists(FunctionCall fctmp |
|
||||
exists(FunctionCall fctmp2 |
|
||||
|
||||
@@ -266,7 +266,7 @@ class LifetimePointerType extends LifetimeIndirectionType {
|
||||
class FullExpr extends Expr {
|
||||
FullExpr() {
|
||||
// A full-expression is not a subexpression
|
||||
not exists(Expr p | this.getParent() = p)
|
||||
not this.getParent() instanceof Expr
|
||||
or
|
||||
// A sub-expression that is an unevaluated operand
|
||||
this.isUnevaluated()
|
||||
|
||||
4
cpp/ql/src/external/DefectFilter.qll
vendored
4
cpp/ql/src/external/DefectFilter.qll
vendored
@@ -5,8 +5,8 @@ import cpp
|
||||
/**
|
||||
* Holds if `id` in the opaque identifier of a result reported by query `queryPath`,
|
||||
* such that `message` is the associated message and the location of the result spans
|
||||
* column `startcolumn` of line `startline` to column `endcolumn` of line `endline`
|
||||
* in file `filepath`.
|
||||
* column `startcol` of line `startline` to column `endcol` of line `endline`
|
||||
* in file `file`.
|
||||
*
|
||||
* For more information, see [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/).
|
||||
*/
|
||||
|
||||
4
cpp/ql/src/external/MetricFilter.qll
vendored
4
cpp/ql/src/external/MetricFilter.qll
vendored
@@ -5,8 +5,8 @@ import cpp
|
||||
/**
|
||||
* Holds if `id` in the opaque identifier of a result reported by query `queryPath`,
|
||||
* such that `value` is the reported metric value and the location of the result spans
|
||||
* column `startcolumn` of line `startline` to column `endcolumn` of line `endline`
|
||||
* in file `filepath`.
|
||||
* column `startcol` of line `startline` to column `endcol` of line `endline`
|
||||
* in file `file`.
|
||||
*
|
||||
* For more information, see [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/).
|
||||
*/
|
||||
|
||||
@@ -28,7 +28,7 @@ where
|
||||
exists(FunctionCall c, int i, Function f |
|
||||
c.getArgument(i) = e and
|
||||
c.getTarget() = f and
|
||||
exists(Parameter p | f.getParameter(i) = p) and // varargs
|
||||
exists(f.getParameter(i)) and // varargs
|
||||
baseElement(e.getType(), cl) and // only interested in arrays with classes
|
||||
not compatible(f.getParameter(i).getUnspecifiedType(), e.getUnspecifiedType())
|
||||
)
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
category: minorAnalysis
|
||||
---
|
||||
* The second argument of the `CreateTemp` function, from the `os` package, is no longer a path-injection sink due to proper sanitization by Go.
|
||||
* The query "Uncontrolled data used in path expression" (`go/path-injection`) now detects sanitizing a path by adding `os.PathSeparator` or `\` to the beginning.
|
||||
@@ -28,7 +28,7 @@ extensions:
|
||||
- ["os", "", False, "ReadDir", "", "", "Argument[0]", "path-injection", "manual"]
|
||||
- ["os", "", False, "ReadFile", "", "", "Argument[0]", "path-injection", "manual"]
|
||||
- ["os", "", False, "MkdirTemp", "", "", "Argument[0..1]", "path-injection", "manual"]
|
||||
- ["os", "", False, "CreateTemp", "", "", "Argument[0..1]", "path-injection", "manual"]
|
||||
- ["os", "", False, "CreateTemp", "", "", "Argument[0]", "path-injection", "manual"]
|
||||
- ["os", "", False, "WriteFile", "", "", "Argument[0]", "path-injection", "manual"]
|
||||
# command-injection
|
||||
- ["os", "", False, "StartProcess", "", "", "Argument[0]", "command-injection", "manual"]
|
||||
|
||||
@@ -87,7 +87,7 @@ module TaintedPath {
|
||||
exists(DataFlow::CallNode cleanCall, StringOps::Concatenation concatNode |
|
||||
cleanCall = any(Function f | f.hasQualifiedName("path/filepath", "Clean")).getACall() and
|
||||
concatNode = cleanCall.getArgument(0) and
|
||||
concatNode.getOperand(0).asExpr().(StringLit).getValue() = "/" and
|
||||
concatNode.getOperand(0).getStringValue().prefix(1) = ["/", "\\"] and
|
||||
this = cleanCall.getResult()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -178,6 +178,6 @@ func fsAccesses() {
|
||||
os.ReadDir(path) // $ fsaccess=path
|
||||
os.ReadFile(path) // $ fsaccess=path
|
||||
os.MkdirTemp(path, part) // $ fsaccess=path fsaccess=part
|
||||
os.CreateTemp(path, part) // $ fsaccess=path fsaccess=part
|
||||
os.CreateTemp(path, part) // $ fsaccess=path
|
||||
os.WriteFile(path, []byte{}, 0600) // $ fsaccess=path
|
||||
}
|
||||
|
||||
@@ -1,25 +1,25 @@
|
||||
#select
|
||||
| TaintedPath.go:17:29:17:40 | tainted_path | TaintedPath.go:14:18:14:22 | selection of URL | TaintedPath.go:17:29:17:40 | tainted_path | This path depends on a $@. | TaintedPath.go:14:18:14:22 | selection of URL | user-provided value |
|
||||
| TaintedPath.go:21:28:21:69 | call to Join | TaintedPath.go:14:18:14:22 | selection of URL | TaintedPath.go:21:28:21:69 | call to Join | This path depends on a $@. | TaintedPath.go:14:18:14:22 | selection of URL | user-provided value |
|
||||
| TaintedPath.go:68:28:68:57 | call to Clean | TaintedPath.go:14:18:14:22 | selection of URL | TaintedPath.go:68:28:68:57 | call to Clean | This path depends on a $@. | TaintedPath.go:14:18:14:22 | selection of URL | user-provided value |
|
||||
| TaintedPath.go:18:29:18:40 | tainted_path | TaintedPath.go:15:18:15:22 | selection of URL | TaintedPath.go:18:29:18:40 | tainted_path | This path depends on a $@. | TaintedPath.go:15:18:15:22 | selection of URL | user-provided value |
|
||||
| TaintedPath.go:22:28:22:69 | call to Join | TaintedPath.go:15:18:15:22 | selection of URL | TaintedPath.go:22:28:22:69 | call to Join | This path depends on a $@. | TaintedPath.go:15:18:15:22 | selection of URL | user-provided value |
|
||||
| TaintedPath.go:74:28:74:57 | call to Clean | TaintedPath.go:15:18:15:22 | selection of URL | TaintedPath.go:74:28:74:57 | call to Clean | This path depends on a $@. | TaintedPath.go:15:18:15:22 | selection of URL | user-provided value |
|
||||
edges
|
||||
| TaintedPath.go:14:18:14:22 | selection of URL | TaintedPath.go:14:18:14:30 | call to Query | provenance | Src:MaD:2 MaD:3 |
|
||||
| TaintedPath.go:14:18:14:30 | call to Query | TaintedPath.go:17:29:17:40 | tainted_path | provenance | Sink:MaD:1 |
|
||||
| TaintedPath.go:14:18:14:30 | call to Query | TaintedPath.go:21:57:21:68 | tainted_path | provenance | |
|
||||
| TaintedPath.go:14:18:14:30 | call to Query | TaintedPath.go:68:39:68:56 | ...+... | provenance | |
|
||||
| TaintedPath.go:21:57:21:68 | tainted_path | TaintedPath.go:21:28:21:69 | call to Join | provenance | FunctionModel Sink:MaD:1 |
|
||||
| TaintedPath.go:68:39:68:56 | ...+... | TaintedPath.go:68:28:68:57 | call to Clean | provenance | MaD:4 Sink:MaD:1 |
|
||||
| TaintedPath.go:15:18:15:22 | selection of URL | TaintedPath.go:15:18:15:30 | call to Query | provenance | Src:MaD:2 MaD:3 |
|
||||
| TaintedPath.go:15:18:15:30 | call to Query | TaintedPath.go:18:29:18:40 | tainted_path | provenance | Sink:MaD:1 |
|
||||
| TaintedPath.go:15:18:15:30 | call to Query | TaintedPath.go:22:57:22:68 | tainted_path | provenance | |
|
||||
| TaintedPath.go:15:18:15:30 | call to Query | TaintedPath.go:74:39:74:56 | ...+... | provenance | |
|
||||
| TaintedPath.go:22:57:22:68 | tainted_path | TaintedPath.go:22:28:22:69 | call to Join | provenance | FunctionModel Sink:MaD:1 |
|
||||
| TaintedPath.go:74:39:74:56 | ...+... | TaintedPath.go:74:28:74:57 | call to Clean | provenance | MaD:4 Sink:MaD:1 |
|
||||
models
|
||||
| 1 | Sink: io/ioutil; ; false; ReadFile; ; ; Argument[0]; path-injection; manual |
|
||||
| 2 | Source: net/http; Request; true; URL; ; ; ; remote; manual |
|
||||
| 3 | Summary: net/url; URL; true; Query; ; ; Argument[receiver]; ReturnValue; taint; manual |
|
||||
| 4 | Summary: path; ; false; Clean; ; ; Argument[0]; ReturnValue; taint; manual |
|
||||
nodes
|
||||
| TaintedPath.go:14:18:14:22 | selection of URL | semmle.label | selection of URL |
|
||||
| TaintedPath.go:14:18:14:30 | call to Query | semmle.label | call to Query |
|
||||
| TaintedPath.go:17:29:17:40 | tainted_path | semmle.label | tainted_path |
|
||||
| TaintedPath.go:21:28:21:69 | call to Join | semmle.label | call to Join |
|
||||
| TaintedPath.go:21:57:21:68 | tainted_path | semmle.label | tainted_path |
|
||||
| TaintedPath.go:68:28:68:57 | call to Clean | semmle.label | call to Clean |
|
||||
| TaintedPath.go:68:39:68:56 | ...+... | semmle.label | ...+... |
|
||||
| TaintedPath.go:15:18:15:22 | selection of URL | semmle.label | selection of URL |
|
||||
| TaintedPath.go:15:18:15:30 | call to Query | semmle.label | call to Query |
|
||||
| TaintedPath.go:18:29:18:40 | tainted_path | semmle.label | tainted_path |
|
||||
| TaintedPath.go:22:28:22:69 | call to Join | semmle.label | call to Join |
|
||||
| TaintedPath.go:22:57:22:68 | tainted_path | semmle.label | tainted_path |
|
||||
| TaintedPath.go:74:28:74:57 | call to Clean | semmle.label | call to Clean |
|
||||
| TaintedPath.go:74:39:74:56 | ...+... | semmle.label | ...+... |
|
||||
subpaths
|
||||
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"io/ioutil"
|
||||
"mime/multipart"
|
||||
"net/http"
|
||||
"os"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
@@ -63,6 +64,11 @@ func handler(w http.ResponseWriter, r *http.Request) {
|
||||
data, _ = ioutil.ReadFile(filepath.Clean("/" + tainted_path))
|
||||
w.Write(data)
|
||||
|
||||
// GOOD: Sanitized by filepath.Clean with a prepended os.PathSeparator forcing interpretation
|
||||
// as an absolute path, so that Clean will throw away any leading `..` components.
|
||||
data, _ = ioutil.ReadFile(filepath.Clean(string(os.PathSeparator) + "hardcoded" + tainted_path))
|
||||
w.Write(data)
|
||||
|
||||
// BAD: Sanitized by path.Clean with a prepended '/' forcing interpretation
|
||||
// as an absolute path, however is not sufficient for Windows paths.
|
||||
data, _ = ioutil.ReadFile(path.Clean("/" + tainted_path))
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,3 @@
|
||||
description: Remove Java 25 compact source files support by removing `isImplicitClass` table
|
||||
compatibility: partial
|
||||
isImplicitClass.rel: delete
|
||||
@@ -0,0 +1,4 @@
|
||||
---
|
||||
category: feature
|
||||
---
|
||||
* Added support for Java 25 compact source files (JEP 512). The new predicate `Class.isImplicit()` identifies classes that are implicitly declared when using compact source files, and the new predicate `CompilationUnit.isCompactSourceFile()` identifies compilation units that contain compact source files.
|
||||
@@ -537,6 +537,10 @@ isLocalClassOrInterface(
|
||||
int parent: @localtypedeclstmt ref
|
||||
);
|
||||
|
||||
isImplicitClass(
|
||||
unique int classid: @classorinterface ref
|
||||
);
|
||||
|
||||
isDefConstr(
|
||||
int constructorid: @constructor ref
|
||||
);
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -33,5 +33,13 @@ class CompilationUnit extends Element, File {
|
||||
*/
|
||||
Module getModule() { cumodule(this, result) }
|
||||
|
||||
/**
|
||||
* Holds if this compilation unit represents a compact source file.
|
||||
* A compact source file contains an implicitly declared top-level class.
|
||||
*/
|
||||
predicate isCompactSourceFile() {
|
||||
exists(Class c | c.getCompilationUnit() = this and c.isImplicit())
|
||||
}
|
||||
|
||||
override string getAPrimaryQlClass() { result = "CompilationUnit" }
|
||||
}
|
||||
|
||||
@@ -848,6 +848,9 @@ class Field extends Member, ExprParent, @field, Variable {
|
||||
override string getAPrimaryQlClass() { result = "Field" }
|
||||
}
|
||||
|
||||
overlay[local]
|
||||
private class DiscardableField extends DiscardableReferableLocatable, @field { }
|
||||
|
||||
/** An instance field. */
|
||||
class InstanceField extends Field {
|
||||
InstanceField() { not this.isStatic() }
|
||||
|
||||
@@ -15,6 +15,7 @@ module;
|
||||
import Member
|
||||
import Modifier
|
||||
import JDK
|
||||
private import semmle.code.java.Overlay
|
||||
|
||||
/**
|
||||
* Holds if reference type `t` is an immediate super-type of `sub`.
|
||||
@@ -699,6 +700,15 @@ class Class extends ClassOrInterface {
|
||||
/** Holds if this class is an anonymous class. */
|
||||
predicate isAnonymous() { isAnonymClass(this.getSourceDeclaration(), _) }
|
||||
|
||||
/** Holds if this class is an implicit class (compact source file). */
|
||||
predicate isImplicit() { isImplicitClass(this.getSourceDeclaration()) }
|
||||
|
||||
/** Holds if this is an auxiliary program element generated by the compiler. */
|
||||
override predicate isCompilerGenerated() {
|
||||
super.isCompilerGenerated() or
|
||||
this.isImplicit()
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets an annotation that applies to this class.
|
||||
*
|
||||
@@ -998,6 +1008,10 @@ class ClassOrInterface extends RefType, @classorinterface {
|
||||
CompanionObject getCompanionObject() { type_companion_object(this, _, result) }
|
||||
}
|
||||
|
||||
overlay[local]
|
||||
private class DiscardableClassOrInterface extends DiscardableReferableLocatable, @classorinterface {
|
||||
}
|
||||
|
||||
private string getAPublicObjectMethodSignature() {
|
||||
exists(Method m |
|
||||
m.getDeclaringType() instanceof TypeObject and
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,2 @@
|
||||
description: Add support for Java 25 compact source files by introducing isImplicitClass table
|
||||
compatibility: full
|
||||
@@ -16,30 +16,6 @@ methodWithDuplicate
|
||||
| AbstractCollection<E> | removeAll | Collection<?> |
|
||||
| AbstractCollection<E> | retainAll | Collection<?> |
|
||||
| AbstractCollection<E> | toArray | T[] |
|
||||
| AbstractCollection<Entry<K,V>> | add | Entry<K,V> |
|
||||
| AbstractCollection<Entry<K,V>> | addAll | Collection<? extends Entry<K,V>> |
|
||||
| AbstractCollection<Entry<K,V>> | contains | Object |
|
||||
| AbstractCollection<Entry<K,V>> | containsAll | Collection<?> |
|
||||
| AbstractCollection<Entry<K,V>> | remove | Object |
|
||||
| AbstractCollection<Entry<K,V>> | removeAll | Collection<?> |
|
||||
| AbstractCollection<Entry<K,V>> | retainAll | Collection<?> |
|
||||
| AbstractCollection<Entry<K,V>> | toArray | T[] |
|
||||
| AbstractCollection<K> | add | K |
|
||||
| AbstractCollection<K> | addAll | Collection<? extends K> |
|
||||
| AbstractCollection<K> | contains | Object |
|
||||
| AbstractCollection<K> | containsAll | Collection<?> |
|
||||
| AbstractCollection<K> | remove | Object |
|
||||
| AbstractCollection<K> | removeAll | Collection<?> |
|
||||
| AbstractCollection<K> | retainAll | Collection<?> |
|
||||
| AbstractCollection<K> | toArray | T[] |
|
||||
| AbstractCollection<Runnable> | add | Runnable |
|
||||
| AbstractCollection<Runnable> | addAll | Collection<? extends Runnable> |
|
||||
| AbstractCollection<Runnable> | contains | Object |
|
||||
| AbstractCollection<Runnable> | containsAll | Collection<?> |
|
||||
| AbstractCollection<Runnable> | remove | Object |
|
||||
| AbstractCollection<Runnable> | removeAll | Collection<?> |
|
||||
| AbstractCollection<Runnable> | retainAll | Collection<?> |
|
||||
| AbstractCollection<Runnable> | toArray | T[] |
|
||||
| AbstractCollection<String> | add | String |
|
||||
| AbstractCollection<String> | addAll | Collection<? extends String> |
|
||||
| AbstractCollection<String> | contains | Object |
|
||||
@@ -56,14 +32,6 @@ methodWithDuplicate
|
||||
| AbstractCollection<T> | removeAll | Collection<?> |
|
||||
| AbstractCollection<T> | retainAll | Collection<?> |
|
||||
| AbstractCollection<T> | toArray | T[] |
|
||||
| AbstractCollection<V> | add | V |
|
||||
| AbstractCollection<V> | addAll | Collection<? extends V> |
|
||||
| AbstractCollection<V> | contains | Object |
|
||||
| AbstractCollection<V> | containsAll | Collection<?> |
|
||||
| AbstractCollection<V> | remove | Object |
|
||||
| AbstractCollection<V> | removeAll | Collection<?> |
|
||||
| AbstractCollection<V> | retainAll | Collection<?> |
|
||||
| AbstractCollection<V> | toArray | T[] |
|
||||
| AbstractList | add | E |
|
||||
| AbstractList | add | int |
|
||||
| AbstractList | addAll | Collection<? extends E> |
|
||||
@@ -103,14 +71,14 @@ methodWithDuplicate
|
||||
| AbstractMap | put | V |
|
||||
| AbstractMap | putAll | Map<? extends K,? extends V> |
|
||||
| AbstractMap | remove | Object |
|
||||
| AbstractMap<Identity,Entry<?>> | containsKey | Object |
|
||||
| AbstractMap<Identity,Entry<?>> | containsValue | Object |
|
||||
| AbstractMap<Identity,Entry<?>> | equals | Object |
|
||||
| AbstractMap<Identity,Entry<?>> | get | Object |
|
||||
| AbstractMap<Identity,Entry<?>> | put | Entry<?> |
|
||||
| AbstractMap<Identity,Entry<?>> | put | Identity |
|
||||
| AbstractMap<Identity,Entry<?>> | putAll | Map<? extends Identity,? extends Entry<?>> |
|
||||
| AbstractMap<Identity,Entry<?>> | remove | Object |
|
||||
| AbstractMap<Identity,Object> | containsKey | Object |
|
||||
| AbstractMap<Identity,Object> | containsValue | Object |
|
||||
| AbstractMap<Identity,Object> | equals | Object |
|
||||
| AbstractMap<Identity,Object> | get | Object |
|
||||
| AbstractMap<Identity,Object> | put | Identity |
|
||||
| AbstractMap<Identity,Object> | put | Object |
|
||||
| AbstractMap<Identity,Object> | putAll | Map<? extends Identity,? extends Object> |
|
||||
| AbstractMap<Identity,Object> | remove | Object |
|
||||
| AbstractMap<K,V> | containsKey | Object |
|
||||
| AbstractMap<K,V> | containsValue | Object |
|
||||
| AbstractMap<K,V> | equals | Object |
|
||||
@@ -179,17 +147,6 @@ methodWithDuplicate
|
||||
| Collection<K> | retainAll | Collection<?> |
|
||||
| Collection<K> | toArray | IntFunction<T[]> |
|
||||
| Collection<K> | toArray | T[] |
|
||||
| Collection<Runnable> | add | Runnable |
|
||||
| Collection<Runnable> | addAll | Collection<? extends Runnable> |
|
||||
| Collection<Runnable> | contains | Object |
|
||||
| Collection<Runnable> | containsAll | Collection<?> |
|
||||
| Collection<Runnable> | equals | Object |
|
||||
| Collection<Runnable> | remove | Object |
|
||||
| Collection<Runnable> | removeAll | Collection<?> |
|
||||
| Collection<Runnable> | removeIf | Predicate<? super Runnable> |
|
||||
| Collection<Runnable> | retainAll | Collection<?> |
|
||||
| Collection<Runnable> | toArray | IntFunction<T[]> |
|
||||
| Collection<Runnable> | toArray | T[] |
|
||||
| Collection<String> | add | String |
|
||||
| Collection<String> | addAll | Collection<? extends String> |
|
||||
| Collection<String> | contains | Object |
|
||||
@@ -332,37 +289,36 @@ methodWithDuplicate
|
||||
| Map | replace | K |
|
||||
| Map | replace | V |
|
||||
| Map | replaceAll | BiFunction<? super K,? super V,? extends V> |
|
||||
| Map<Identity,Entry<?>> | compute | BiFunction<? super Identity,? super Entry<?>,? extends Entry<?>> |
|
||||
| Map<Identity,Entry<?>> | compute | Identity |
|
||||
| Map<Identity,Entry<?>> | computeIfAbsent | Function<? super Identity,? extends Entry<?>> |
|
||||
| Map<Identity,Entry<?>> | computeIfAbsent | Identity |
|
||||
| Map<Identity,Entry<?>> | computeIfPresent | BiFunction<? super Identity,? super Entry<?>,? extends Entry<?>> |
|
||||
| Map<Identity,Entry<?>> | computeIfPresent | Identity |
|
||||
| Map<Identity,Entry<?>> | containsKey | Object |
|
||||
| Map<Identity,Entry<?>> | containsValue | Object |
|
||||
| Map<Identity,Entry<?>> | copyOf | Map<? extends K,? extends V> |
|
||||
| Map<Identity,Entry<?>> | entry | K |
|
||||
| Map<Identity,Entry<?>> | entry | V |
|
||||
| Map<Identity,Entry<?>> | equals | Object |
|
||||
| Map<Identity,Entry<?>> | forEach | BiConsumer<? super Identity,? super Entry<?>> |
|
||||
| Map<Identity,Entry<?>> | get | Object |
|
||||
| Map<Identity,Entry<?>> | getOrDefault | Entry<?> |
|
||||
| Map<Identity,Entry<?>> | getOrDefault | Object |
|
||||
| Map<Identity,Entry<?>> | merge | BiFunction<? super Entry<?>,? super Entry<?>,? extends Entry<?>> |
|
||||
| Map<Identity,Entry<?>> | merge | Entry<?> |
|
||||
| Map<Identity,Entry<?>> | merge | Identity |
|
||||
| Map<Identity,Entry<?>> | of | K |
|
||||
| Map<Identity,Entry<?>> | of | V |
|
||||
| Map<Identity,Entry<?>> | ofEntries | Entry<? extends K,? extends V>[] |
|
||||
| Map<Identity,Entry<?>> | put | Entry<?> |
|
||||
| Map<Identity,Entry<?>> | put | Identity |
|
||||
| Map<Identity,Entry<?>> | putAll | Map<? extends Identity,? extends Entry<?>> |
|
||||
| Map<Identity,Entry<?>> | putIfAbsent | Entry<?> |
|
||||
| Map<Identity,Entry<?>> | putIfAbsent | Identity |
|
||||
| Map<Identity,Entry<?>> | remove | Object |
|
||||
| Map<Identity,Entry<?>> | replace | Entry<?> |
|
||||
| Map<Identity,Entry<?>> | replace | Identity |
|
||||
| Map<Identity,Entry<?>> | replaceAll | BiFunction<? super Identity,? super Entry<?>,? extends Entry<?>> |
|
||||
| Map<Identity,Object> | compute | BiFunction<? super Identity,? super Object,? extends Object> |
|
||||
| Map<Identity,Object> | compute | Identity |
|
||||
| Map<Identity,Object> | computeIfAbsent | Function<? super Identity,? extends Object> |
|
||||
| Map<Identity,Object> | computeIfAbsent | Identity |
|
||||
| Map<Identity,Object> | computeIfPresent | BiFunction<? super Identity,? super Object,? extends Object> |
|
||||
| Map<Identity,Object> | computeIfPresent | Identity |
|
||||
| Map<Identity,Object> | containsKey | Object |
|
||||
| Map<Identity,Object> | containsValue | Object |
|
||||
| Map<Identity,Object> | copyOf | Map<? extends K,? extends V> |
|
||||
| Map<Identity,Object> | entry | K |
|
||||
| Map<Identity,Object> | entry | V |
|
||||
| Map<Identity,Object> | equals | Object |
|
||||
| Map<Identity,Object> | forEach | BiConsumer<? super Identity,? super Object> |
|
||||
| Map<Identity,Object> | get | Object |
|
||||
| Map<Identity,Object> | getOrDefault | Object |
|
||||
| Map<Identity,Object> | merge | BiFunction<? super Object,? super Object,? extends Object> |
|
||||
| Map<Identity,Object> | merge | Identity |
|
||||
| Map<Identity,Object> | merge | Object |
|
||||
| Map<Identity,Object> | of | K |
|
||||
| Map<Identity,Object> | of | V |
|
||||
| Map<Identity,Object> | ofEntries | Entry<? extends K,? extends V>[] |
|
||||
| Map<Identity,Object> | put | Identity |
|
||||
| Map<Identity,Object> | put | Object |
|
||||
| Map<Identity,Object> | putAll | Map<? extends Identity,? extends Object> |
|
||||
| Map<Identity,Object> | putIfAbsent | Identity |
|
||||
| Map<Identity,Object> | putIfAbsent | Object |
|
||||
| Map<Identity,Object> | remove | Object |
|
||||
| Map<Identity,Object> | replace | Identity |
|
||||
| Map<Identity,Object> | replace | Object |
|
||||
| Map<Identity,Object> | replaceAll | BiFunction<? super Identity,? super Object,? extends Object> |
|
||||
| Map<K,V> | compute | BiFunction<? super K,? super V,? extends V> |
|
||||
| Map<K,V> | compute | K |
|
||||
| Map<K,V> | computeIfAbsent | Function<? super K,? extends V> |
|
||||
|
||||
@@ -289,6 +289,7 @@ compGenerated
|
||||
| file://<external>/LongProgression.class:0:0:0:0 | spliterator | Forwarder for a Kotlin class inheriting an interface default method |
|
||||
| file://<external>/LongRange.class:0:0:0:0 | forEach | Forwarder for a Kotlin class inheriting an interface default method |
|
||||
| file://<external>/LongRange.class:0:0:0:0 | spliterator | Forwarder for a Kotlin class inheriting an interface default method |
|
||||
| file://<external>/String.class:0:0:0:0 | getChars | Forwarder for a Kotlin class inheriting an interface default method |
|
||||
| file://<external>/String.class:0:0:0:0 | isEmpty | Forwarder for a Kotlin class inheriting an interface default method |
|
||||
| reflection.kt:7:49:7:54 | new Function2<Ccc,Integer,Double>(...) { ... } | The class around a local function, a lambda, or a function reference |
|
||||
| reflection.kt:10:38:10:42 | new KProperty1<C,Integer>(...) { ... } | The class around a local function, a lambda, or a function reference |
|
||||
|
||||
@@ -16,30 +16,6 @@ methodWithDuplicate
|
||||
| AbstractCollection<E> | removeAll | Collection<?> |
|
||||
| AbstractCollection<E> | retainAll | Collection<?> |
|
||||
| AbstractCollection<E> | toArray | T[] |
|
||||
| AbstractCollection<Entry<K,V>> | add | Entry<K,V> |
|
||||
| AbstractCollection<Entry<K,V>> | addAll | Collection<? extends Entry<K,V>> |
|
||||
| AbstractCollection<Entry<K,V>> | contains | Object |
|
||||
| AbstractCollection<Entry<K,V>> | containsAll | Collection<?> |
|
||||
| AbstractCollection<Entry<K,V>> | remove | Object |
|
||||
| AbstractCollection<Entry<K,V>> | removeAll | Collection<?> |
|
||||
| AbstractCollection<Entry<K,V>> | retainAll | Collection<?> |
|
||||
| AbstractCollection<Entry<K,V>> | toArray | T[] |
|
||||
| AbstractCollection<K> | add | K |
|
||||
| AbstractCollection<K> | addAll | Collection<? extends K> |
|
||||
| AbstractCollection<K> | contains | Object |
|
||||
| AbstractCollection<K> | containsAll | Collection<?> |
|
||||
| AbstractCollection<K> | remove | Object |
|
||||
| AbstractCollection<K> | removeAll | Collection<?> |
|
||||
| AbstractCollection<K> | retainAll | Collection<?> |
|
||||
| AbstractCollection<K> | toArray | T[] |
|
||||
| AbstractCollection<Runnable> | add | Runnable |
|
||||
| AbstractCollection<Runnable> | addAll | Collection<? extends Runnable> |
|
||||
| AbstractCollection<Runnable> | contains | Object |
|
||||
| AbstractCollection<Runnable> | containsAll | Collection<?> |
|
||||
| AbstractCollection<Runnable> | remove | Object |
|
||||
| AbstractCollection<Runnable> | removeAll | Collection<?> |
|
||||
| AbstractCollection<Runnable> | retainAll | Collection<?> |
|
||||
| AbstractCollection<Runnable> | toArray | T[] |
|
||||
| AbstractCollection<String> | add | String |
|
||||
| AbstractCollection<String> | addAll | Collection<? extends String> |
|
||||
| AbstractCollection<String> | contains | Object |
|
||||
@@ -56,14 +32,6 @@ methodWithDuplicate
|
||||
| AbstractCollection<T> | removeAll | Collection<?> |
|
||||
| AbstractCollection<T> | retainAll | Collection<?> |
|
||||
| AbstractCollection<T> | toArray | T[] |
|
||||
| AbstractCollection<V> | add | V |
|
||||
| AbstractCollection<V> | addAll | Collection<? extends V> |
|
||||
| AbstractCollection<V> | contains | Object |
|
||||
| AbstractCollection<V> | containsAll | Collection<?> |
|
||||
| AbstractCollection<V> | remove | Object |
|
||||
| AbstractCollection<V> | removeAll | Collection<?> |
|
||||
| AbstractCollection<V> | retainAll | Collection<?> |
|
||||
| AbstractCollection<V> | toArray | T[] |
|
||||
| AbstractList | add | E |
|
||||
| AbstractList | add | int |
|
||||
| AbstractList | addAll | Collection<? extends E> |
|
||||
@@ -103,14 +71,14 @@ methodWithDuplicate
|
||||
| AbstractMap | put | V |
|
||||
| AbstractMap | putAll | Map<? extends K,? extends V> |
|
||||
| AbstractMap | remove | Object |
|
||||
| AbstractMap<Identity,Entry<?>> | containsKey | Object |
|
||||
| AbstractMap<Identity,Entry<?>> | containsValue | Object |
|
||||
| AbstractMap<Identity,Entry<?>> | equals | Object |
|
||||
| AbstractMap<Identity,Entry<?>> | get | Object |
|
||||
| AbstractMap<Identity,Entry<?>> | put | Entry<?> |
|
||||
| AbstractMap<Identity,Entry<?>> | put | Identity |
|
||||
| AbstractMap<Identity,Entry<?>> | putAll | Map<? extends Identity,? extends Entry<?>> |
|
||||
| AbstractMap<Identity,Entry<?>> | remove | Object |
|
||||
| AbstractMap<Identity,Object> | containsKey | Object |
|
||||
| AbstractMap<Identity,Object> | containsValue | Object |
|
||||
| AbstractMap<Identity,Object> | equals | Object |
|
||||
| AbstractMap<Identity,Object> | get | Object |
|
||||
| AbstractMap<Identity,Object> | put | Identity |
|
||||
| AbstractMap<Identity,Object> | put | Object |
|
||||
| AbstractMap<Identity,Object> | putAll | Map<? extends Identity,? extends Object> |
|
||||
| AbstractMap<Identity,Object> | remove | Object |
|
||||
| AbstractMap<K,V> | containsKey | Object |
|
||||
| AbstractMap<K,V> | containsValue | Object |
|
||||
| AbstractMap<K,V> | equals | Object |
|
||||
@@ -176,16 +144,6 @@ methodWithDuplicate
|
||||
| Collection<K> | retainAll | Collection<?> |
|
||||
| Collection<K> | toArray | IntFunction<T[]> |
|
||||
| Collection<K> | toArray | T[] |
|
||||
| Collection<Runnable> | add | Runnable |
|
||||
| Collection<Runnable> | addAll | Collection<? extends Runnable> |
|
||||
| Collection<Runnable> | contains | Object |
|
||||
| Collection<Runnable> | containsAll | Collection<?> |
|
||||
| Collection<Runnable> | remove | Object |
|
||||
| Collection<Runnable> | removeAll | Collection<?> |
|
||||
| Collection<Runnable> | removeIf | Predicate<? super Runnable> |
|
||||
| Collection<Runnable> | retainAll | Collection<?> |
|
||||
| Collection<Runnable> | toArray | IntFunction<T[]> |
|
||||
| Collection<Runnable> | toArray | T[] |
|
||||
| Collection<String> | add | String |
|
||||
| Collection<String> | addAll | Collection<? extends String> |
|
||||
| Collection<String> | contains | Object |
|
||||
@@ -325,36 +283,35 @@ methodWithDuplicate
|
||||
| Map | replace | K |
|
||||
| Map | replace | V |
|
||||
| Map | replaceAll | BiFunction<? super K,? super V,? extends V> |
|
||||
| Map<Identity,Entry<?>> | compute | BiFunction<? super Identity,? super Entry<?>,? extends Entry<?>> |
|
||||
| Map<Identity,Entry<?>> | compute | Identity |
|
||||
| Map<Identity,Entry<?>> | computeIfAbsent | Function<? super Identity,? extends Entry<?>> |
|
||||
| Map<Identity,Entry<?>> | computeIfAbsent | Identity |
|
||||
| Map<Identity,Entry<?>> | computeIfPresent | BiFunction<? super Identity,? super Entry<?>,? extends Entry<?>> |
|
||||
| Map<Identity,Entry<?>> | computeIfPresent | Identity |
|
||||
| Map<Identity,Entry<?>> | containsKey | Object |
|
||||
| Map<Identity,Entry<?>> | containsValue | Object |
|
||||
| Map<Identity,Entry<?>> | copyOf | Map<? extends K,? extends V> |
|
||||
| Map<Identity,Entry<?>> | entry | K |
|
||||
| Map<Identity,Entry<?>> | entry | V |
|
||||
| Map<Identity,Entry<?>> | forEach | BiConsumer<? super Identity,? super Entry<?>> |
|
||||
| Map<Identity,Entry<?>> | get | Object |
|
||||
| Map<Identity,Entry<?>> | getOrDefault | Entry<?> |
|
||||
| Map<Identity,Entry<?>> | getOrDefault | Object |
|
||||
| Map<Identity,Entry<?>> | merge | BiFunction<? super Entry<?>,? super Entry<?>,? extends Entry<?>> |
|
||||
| Map<Identity,Entry<?>> | merge | Entry<?> |
|
||||
| Map<Identity,Entry<?>> | merge | Identity |
|
||||
| Map<Identity,Entry<?>> | of | K |
|
||||
| Map<Identity,Entry<?>> | of | V |
|
||||
| Map<Identity,Entry<?>> | ofEntries | Entry<? extends K,? extends V>[] |
|
||||
| Map<Identity,Entry<?>> | put | Entry<?> |
|
||||
| Map<Identity,Entry<?>> | put | Identity |
|
||||
| Map<Identity,Entry<?>> | putAll | Map<? extends Identity,? extends Entry<?>> |
|
||||
| Map<Identity,Entry<?>> | putIfAbsent | Entry<?> |
|
||||
| Map<Identity,Entry<?>> | putIfAbsent | Identity |
|
||||
| Map<Identity,Entry<?>> | remove | Object |
|
||||
| Map<Identity,Entry<?>> | replace | Entry<?> |
|
||||
| Map<Identity,Entry<?>> | replace | Identity |
|
||||
| Map<Identity,Entry<?>> | replaceAll | BiFunction<? super Identity,? super Entry<?>,? extends Entry<?>> |
|
||||
| Map<Identity,Object> | compute | BiFunction<? super Identity,? super Object,? extends Object> |
|
||||
| Map<Identity,Object> | compute | Identity |
|
||||
| Map<Identity,Object> | computeIfAbsent | Function<? super Identity,? extends Object> |
|
||||
| Map<Identity,Object> | computeIfAbsent | Identity |
|
||||
| Map<Identity,Object> | computeIfPresent | BiFunction<? super Identity,? super Object,? extends Object> |
|
||||
| Map<Identity,Object> | computeIfPresent | Identity |
|
||||
| Map<Identity,Object> | containsKey | Object |
|
||||
| Map<Identity,Object> | containsValue | Object |
|
||||
| Map<Identity,Object> | copyOf | Map<? extends K,? extends V> |
|
||||
| Map<Identity,Object> | entry | K |
|
||||
| Map<Identity,Object> | entry | V |
|
||||
| Map<Identity,Object> | forEach | BiConsumer<? super Identity,? super Object> |
|
||||
| Map<Identity,Object> | get | Object |
|
||||
| Map<Identity,Object> | getOrDefault | Object |
|
||||
| Map<Identity,Object> | merge | BiFunction<? super Object,? super Object,? extends Object> |
|
||||
| Map<Identity,Object> | merge | Identity |
|
||||
| Map<Identity,Object> | merge | Object |
|
||||
| Map<Identity,Object> | of | K |
|
||||
| Map<Identity,Object> | of | V |
|
||||
| Map<Identity,Object> | ofEntries | Entry<? extends K,? extends V>[] |
|
||||
| Map<Identity,Object> | put | Identity |
|
||||
| Map<Identity,Object> | put | Object |
|
||||
| Map<Identity,Object> | putAll | Map<? extends Identity,? extends Object> |
|
||||
| Map<Identity,Object> | putIfAbsent | Identity |
|
||||
| Map<Identity,Object> | putIfAbsent | Object |
|
||||
| Map<Identity,Object> | remove | Object |
|
||||
| Map<Identity,Object> | replace | Identity |
|
||||
| Map<Identity,Object> | replace | Object |
|
||||
| Map<Identity,Object> | replaceAll | BiFunction<? super Identity,? super Object,? extends Object> |
|
||||
| Map<K,V> | compute | BiFunction<? super K,? super V,? extends V> |
|
||||
| Map<K,V> | compute | K |
|
||||
| Map<K,V> | computeIfAbsent | Function<? super K,? extends V> |
|
||||
|
||||
@@ -329,6 +329,7 @@ compGenerated
|
||||
| file://<external>/SignStyle.class:0:0:0:0 | getEntries | Default property accessor |
|
||||
| file://<external>/StackWalker$ExtendedOption.class:0:0:0:0 | getEntries | Default property accessor |
|
||||
| file://<external>/StackWalker$Option.class:0:0:0:0 | getEntries | Default property accessor |
|
||||
| file://<external>/String.class:0:0:0:0 | getChars | Forwarder for a Kotlin class inheriting an interface default method |
|
||||
| file://<external>/String.class:0:0:0:0 | isEmpty | Forwarder for a Kotlin class inheriting an interface default method |
|
||||
| file://<external>/TextStyle.class:0:0:0:0 | getEntries | Default property accessor |
|
||||
| file://<external>/Thread$State.class:0:0:0:0 | getEntries | Default property accessor |
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
| Test.java:0:0:0:0 | Test | Test.java:1:1:1:1 | Test | Compact source file 'Test' contains implicit class 'Test' |
|
||||
@@ -0,0 +1,9 @@
|
||||
import java
|
||||
|
||||
from CompilationUnit cu, Class c
|
||||
where
|
||||
cu.isCompactSourceFile() and
|
||||
c.getCompilationUnit() = cu and
|
||||
c.isImplicit()
|
||||
select cu, c,
|
||||
"Compact source file '" + cu.getName() + "' contains implicit class '" + c.getName() + "'"
|
||||
@@ -0,0 +1 @@
|
||||
| Test.java:0:0:0:0 | Test |
|
||||
@@ -0,0 +1,5 @@
|
||||
import java
|
||||
|
||||
from CompilationUnit cu
|
||||
where cu.isCompactSourceFile()
|
||||
select cu
|
||||
@@ -0,0 +1,2 @@
|
||||
| Test.java:1:1:1:1 | Test | implicit |
|
||||
| Test.java:25:7:25:16 | NotCompact | not implicit |
|
||||
@@ -0,0 +1,7 @@
|
||||
import java
|
||||
|
||||
from Class c, string res
|
||||
where
|
||||
exists(c.getCompilationUnit().getRelativePath()) and
|
||||
if c.isImplicit() then res = "implicit" else res = "not implicit"
|
||||
select c, res
|
||||
@@ -0,0 +1,7 @@
|
||||
| Test.java:1:1:1:1 | <clinit> | in compact source |
|
||||
| Test.java:1:1:1:1 | <obinit> | in compact source |
|
||||
| Test.java:5:6:5:9 | main | in compact source |
|
||||
| Test.java:11:6:11:16 | processData | in compact source |
|
||||
| Test.java:16:14:16:31 | updatePrivateField | in compact source |
|
||||
| Test.java:21:13:21:28 | testStaticAccess | in compact source |
|
||||
| Test.java:27:10:27:25 | methodNotCompact | NOT in compact source |
|
||||
@@ -0,0 +1,8 @@
|
||||
import java
|
||||
|
||||
from Method m, Class c, string res
|
||||
where
|
||||
c = m.getDeclaringType() and
|
||||
exists(c.getCompilationUnit().getRelativePath()) and
|
||||
if c.isImplicit() then res = "in compact source" else res = "NOT in compact source"
|
||||
select m, res
|
||||
@@ -0,0 +1,45 @@
|
||||
Test.java:
|
||||
# 0| [CompilationUnit] Test
|
||||
# 1| 1: [Class] Test
|
||||
# 1| 4: [FieldDeclaration] int instanceField;
|
||||
# 1| -1: [TypeAccess] int
|
||||
# 1| 0: [IntegerLiteral] 10
|
||||
# 2| 5: [FieldDeclaration] int STATIC_CONSTANT;
|
||||
# 2| -1: [TypeAccess] int
|
||||
# 2| 0: [IntegerLiteral] 42
|
||||
# 3| 6: [FieldDeclaration] String privateField;
|
||||
# 3| -1: [TypeAccess] String
|
||||
# 3| 0: [StringLiteral] "data"
|
||||
# 5| 7: [Method] main
|
||||
# 5| 3: [TypeAccess] void
|
||||
# 5| 5: [BlockStmt] { ... }
|
||||
# 6| 0: [ExprStmt] <Expr>;
|
||||
# 6| 0: [MethodCall] processData(...)
|
||||
# 7| 1: [ExprStmt] <Expr>;
|
||||
# 7| 0: [MethodCall] testStaticAccess(...)
|
||||
# 11| 8: [Method] processData
|
||||
# 11| 3: [TypeAccess] void
|
||||
# 11| 5: [BlockStmt] { ... }
|
||||
# 12| 0: [ExprStmt] <Expr>;
|
||||
# 12| 0: [PostIncExpr] ...++
|
||||
# 12| 0: [VarAccess] instanceField
|
||||
# 13| 1: [ExprStmt] <Expr>;
|
||||
# 13| 0: [MethodCall] updatePrivateField(...)
|
||||
# 16| 9: [Method] updatePrivateField
|
||||
# 16| 3: [TypeAccess] void
|
||||
# 16| 5: [BlockStmt] { ... }
|
||||
# 17| 0: [ExprStmt] <Expr>;
|
||||
# 17| 0: [AssignExpr] ...=...
|
||||
# 17| 0: [VarAccess] privateField
|
||||
# 17| 1: [StringLiteral] "updated"
|
||||
# 21| 10: [Method] testStaticAccess
|
||||
# 21| 3: [TypeAccess] void
|
||||
# 21| 5: [BlockStmt] { ... }
|
||||
# 22| 0: [ExprStmt] <Expr>;
|
||||
# 22| 0: [MethodCall] println(...)
|
||||
# 22| -1: [TypeAccess] IO
|
||||
# 22| 0: [StringLiteral] "Static access test"
|
||||
# 25| 11: [Class] NotCompact
|
||||
# 27| 2: [Method] methodNotCompact
|
||||
# 27| 3: [TypeAccess] void
|
||||
# 27| 5: [BlockStmt] { ... }
|
||||
@@ -0,0 +1 @@
|
||||
semmle/code/java/PrintAst.ql
|
||||
29
java/ql/test/library-tests/compact-source-files/Test.java
Normal file
29
java/ql/test/library-tests/compact-source-files/Test.java
Normal file
@@ -0,0 +1,29 @@
|
||||
int instanceField = 10;
|
||||
static final int STATIC_CONSTANT = 42;
|
||||
private String privateField = "data";
|
||||
|
||||
void main() {
|
||||
processData();
|
||||
testStaticAccess();
|
||||
}
|
||||
|
||||
// Test instance methods
|
||||
void processData() {
|
||||
instanceField++;
|
||||
updatePrivateField();
|
||||
}
|
||||
|
||||
private void updatePrivateField() {
|
||||
privateField = "updated";
|
||||
}
|
||||
|
||||
// Test static method access
|
||||
static void testStaticAccess() {
|
||||
IO.println("Static access test");
|
||||
}
|
||||
|
||||
class NotCompact {
|
||||
//Test explict class
|
||||
void methodNotCompact() {
|
||||
}
|
||||
}
|
||||
1
java/ql/test/library-tests/compact-source-files/options
Normal file
1
java/ql/test/library-tests/compact-source-files/options
Normal file
@@ -0,0 +1 @@
|
||||
//semmle-extractor-options: --javac-args --release 25 --enable-preview
|
||||
@@ -0,0 +1,95 @@
|
||||
class A {
|
||||
A(String msg) {
|
||||
System.out.println("A: " + msg);
|
||||
}
|
||||
}
|
||||
|
||||
class B extends A {
|
||||
B(String input) {
|
||||
var msg = input.trim().toUpperCase();
|
||||
super(msg);
|
||||
}
|
||||
}
|
||||
|
||||
class C {
|
||||
private final int x;
|
||||
|
||||
C(int x) {
|
||||
if (x < 0) throw new IllegalArgumentException();
|
||||
super();
|
||||
this.x = x;
|
||||
}
|
||||
}
|
||||
|
||||
record R(String name, int score) {
|
||||
public R(String name) {
|
||||
var score = name.length();
|
||||
this(name, score);
|
||||
}
|
||||
}
|
||||
|
||||
class Outer {
|
||||
private final String prefix = "outer";
|
||||
|
||||
class Inner {
|
||||
private String full;
|
||||
|
||||
Inner(String suffix) {
|
||||
var combined = prefix + "_" + suffix;
|
||||
super();
|
||||
this.full = combined;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class D {
|
||||
private final String value;
|
||||
private final int length;
|
||||
|
||||
D(String input) {
|
||||
var processed = input.toLowerCase();
|
||||
value = processed;
|
||||
this.length = processed.length();
|
||||
super();
|
||||
}
|
||||
}
|
||||
|
||||
class E extends A {
|
||||
private boolean isValid;
|
||||
private String processed;
|
||||
|
||||
E(String data) {
|
||||
var temp = data != null ? data.trim() : "";
|
||||
this.processed = temp;
|
||||
isValid = !temp.isEmpty();
|
||||
super(temp);
|
||||
}
|
||||
}
|
||||
|
||||
class F {
|
||||
private int x;
|
||||
private final int y;
|
||||
private int sum;
|
||||
|
||||
F(int a, int b) {
|
||||
x = a;
|
||||
this.y = b;
|
||||
this.sum = a + b;
|
||||
super();
|
||||
}
|
||||
}
|
||||
|
||||
class G {
|
||||
private String instance_val;
|
||||
|
||||
{
|
||||
instance_val = "instance";
|
||||
}
|
||||
|
||||
G(String input) {
|
||||
var tmp = input != null ? input : "default";
|
||||
var string = tmp + "_initialized";
|
||||
super();
|
||||
this.instance_val = string;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
| FlexibleConstructors.java:31:7:31:11 | <Expr>; | 1 | <obinit> | Instance initializer call at index 1 |
|
||||
| FlexibleConstructors.java:89:5:89:5 | <Expr>; | 3 | <obinit> | Instance initializer call at index 3 |
|
||||
@@ -0,0 +1,8 @@
|
||||
import java
|
||||
|
||||
from MethodCall call, Method m
|
||||
where
|
||||
call.getMethod() = m and
|
||||
m.getName() = "<obinit>"
|
||||
select call.getEnclosingStmt(), call.getEnclosingStmt().getIndex(), call.getMethod().getName(),
|
||||
"Instance initializer call at index " + call.getEnclosingStmt().getIndex()
|
||||
@@ -0,0 +1,125 @@
|
||||
| FlexibleConstructors.java:1:7:1:7 | A | 0 | class A { |
|
||||
| FlexibleConstructors.java:1:7:1:7 | A | 1 | A(String msg) { |
|
||||
| FlexibleConstructors.java:1:7:1:7 | A | 2 | super(); |
|
||||
| FlexibleConstructors.java:1:7:1:7 | A | 3 | System.out.println("A: " + msg); |
|
||||
| FlexibleConstructors.java:1:7:1:7 | A | 4 | } |
|
||||
| FlexibleConstructors.java:1:7:1:7 | A | 5 | } |
|
||||
| FlexibleConstructors.java:7:7:7:7 | B | 0 | class B { |
|
||||
| FlexibleConstructors.java:7:7:7:7 | B | 1 | B(String input) { |
|
||||
| FlexibleConstructors.java:7:7:7:7 | B | 2 | var msg = input.trim().toUpperCase(); |
|
||||
| FlexibleConstructors.java:7:7:7:7 | B | 3 | super(msg); |
|
||||
| FlexibleConstructors.java:7:7:7:7 | B | 4 | } |
|
||||
| FlexibleConstructors.java:7:7:7:7 | B | 5 | } |
|
||||
| FlexibleConstructors.java:14:7:14:7 | C | 0 | class C { |
|
||||
| FlexibleConstructors.java:14:7:14:7 | C | 1 | private final int x; |
|
||||
| FlexibleConstructors.java:14:7:14:7 | C | 2 | |
|
||||
| FlexibleConstructors.java:14:7:14:7 | C | 3 | C(int x) { |
|
||||
| FlexibleConstructors.java:14:7:14:7 | C | 4 | if (x < 0) |
|
||||
| FlexibleConstructors.java:14:7:14:7 | C | 5 | throw new IllegalArgumentException(); |
|
||||
| FlexibleConstructors.java:14:7:14:7 | C | 6 | super(); |
|
||||
| FlexibleConstructors.java:14:7:14:7 | C | 7 | this.x = x; |
|
||||
| FlexibleConstructors.java:14:7:14:7 | C | 8 | } |
|
||||
| FlexibleConstructors.java:14:7:14:7 | C | 9 | } |
|
||||
| FlexibleConstructors.java:24:8:24:8 | R | 0 | final class R { |
|
||||
| FlexibleConstructors.java:24:8:24:8 | R | 1 | public final boolean equals(Object p0) { <missing body> } |
|
||||
| FlexibleConstructors.java:24:8:24:8 | R | 2 | |
|
||||
| FlexibleConstructors.java:24:8:24:8 | R | 3 | public final int hashCode() { <missing body> } |
|
||||
| FlexibleConstructors.java:24:8:24:8 | R | 4 | |
|
||||
| FlexibleConstructors.java:24:8:24:8 | R | 5 | public String name() { <missing body> } |
|
||||
| FlexibleConstructors.java:24:8:24:8 | R | 6 | |
|
||||
| FlexibleConstructors.java:24:8:24:8 | R | 7 | public int score() { <missing body> } |
|
||||
| FlexibleConstructors.java:24:8:24:8 | R | 8 | |
|
||||
| FlexibleConstructors.java:24:8:24:8 | R | 9 | public final String toString() { <missing body> } |
|
||||
| FlexibleConstructors.java:24:8:24:8 | R | 10 | |
|
||||
| FlexibleConstructors.java:24:8:24:8 | R | 11 | R(String name, int score) { |
|
||||
| FlexibleConstructors.java:24:8:24:8 | R | 12 | super(); |
|
||||
| FlexibleConstructors.java:24:8:24:8 | R | 13 | this.name = name; |
|
||||
| FlexibleConstructors.java:24:8:24:8 | R | 14 | this.score = score; |
|
||||
| FlexibleConstructors.java:24:8:24:8 | R | 15 | } |
|
||||
| FlexibleConstructors.java:24:8:24:8 | R | 16 | |
|
||||
| FlexibleConstructors.java:24:8:24:8 | R | 17 | private final String name; |
|
||||
| FlexibleConstructors.java:24:8:24:8 | R | 18 | |
|
||||
| FlexibleConstructors.java:24:8:24:8 | R | 19 | private final int score; |
|
||||
| FlexibleConstructors.java:24:8:24:8 | R | 20 | |
|
||||
| FlexibleConstructors.java:24:8:24:8 | R | 21 | public R(String name) { |
|
||||
| FlexibleConstructors.java:24:8:24:8 | R | 22 | var score = name.length(); |
|
||||
| FlexibleConstructors.java:24:8:24:8 | R | 23 | this(name, score); |
|
||||
| FlexibleConstructors.java:24:8:24:8 | R | 24 | } |
|
||||
| FlexibleConstructors.java:24:8:24:8 | R | 25 | } |
|
||||
| FlexibleConstructors.java:31:7:31:11 | Outer | 0 | class Outer { |
|
||||
| FlexibleConstructors.java:31:7:31:11 | Outer | 1 | private void <obinit>() { |
|
||||
| FlexibleConstructors.java:31:7:31:11 | Outer | 2 | prefix = "outer"; |
|
||||
| FlexibleConstructors.java:31:7:31:11 | Outer | 3 | } |
|
||||
| FlexibleConstructors.java:31:7:31:11 | Outer | 4 | |
|
||||
| FlexibleConstructors.java:31:7:31:11 | Outer | 5 | Outer() { |
|
||||
| FlexibleConstructors.java:31:7:31:11 | Outer | 6 | super(); |
|
||||
| FlexibleConstructors.java:31:7:31:11 | Outer | 7 | <obinit>(); |
|
||||
| FlexibleConstructors.java:31:7:31:11 | Outer | 8 | } |
|
||||
| FlexibleConstructors.java:31:7:31:11 | Outer | 9 | |
|
||||
| FlexibleConstructors.java:31:7:31:11 | Outer | 10 | private final String prefix; |
|
||||
| FlexibleConstructors.java:31:7:31:11 | Outer | 11 | |
|
||||
| FlexibleConstructors.java:31:7:31:11 | Outer | 12 | class Inner { |
|
||||
| FlexibleConstructors.java:31:7:31:11 | Outer | 13 | private String full; |
|
||||
| FlexibleConstructors.java:31:7:31:11 | Outer | 14 | |
|
||||
| FlexibleConstructors.java:31:7:31:11 | Outer | 15 | Inner(String suffix) { |
|
||||
| FlexibleConstructors.java:31:7:31:11 | Outer | 16 | var combined = prefix + "_" + suffix; |
|
||||
| FlexibleConstructors.java:31:7:31:11 | Outer | 17 | super(); |
|
||||
| FlexibleConstructors.java:31:7:31:11 | Outer | 18 | this.full = combined; |
|
||||
| FlexibleConstructors.java:31:7:31:11 | Outer | 19 | } |
|
||||
| FlexibleConstructors.java:31:7:31:11 | Outer | 20 | } |
|
||||
| FlexibleConstructors.java:31:7:31:11 | Outer | 21 | } |
|
||||
| FlexibleConstructors.java:45:7:45:7 | D | 0 | class D { |
|
||||
| FlexibleConstructors.java:45:7:45:7 | D | 1 | private final String value; |
|
||||
| FlexibleConstructors.java:45:7:45:7 | D | 2 | |
|
||||
| FlexibleConstructors.java:45:7:45:7 | D | 3 | private final int length; |
|
||||
| FlexibleConstructors.java:45:7:45:7 | D | 4 | |
|
||||
| FlexibleConstructors.java:45:7:45:7 | D | 5 | D(String input) { |
|
||||
| FlexibleConstructors.java:45:7:45:7 | D | 6 | var processed = input.toLowerCase(); |
|
||||
| FlexibleConstructors.java:45:7:45:7 | D | 7 | value = processed; |
|
||||
| FlexibleConstructors.java:45:7:45:7 | D | 8 | this.length = processed.length(); |
|
||||
| FlexibleConstructors.java:45:7:45:7 | D | 9 | super(); |
|
||||
| FlexibleConstructors.java:45:7:45:7 | D | 10 | } |
|
||||
| FlexibleConstructors.java:45:7:45:7 | D | 11 | } |
|
||||
| FlexibleConstructors.java:57:7:57:7 | E | 0 | class E { |
|
||||
| FlexibleConstructors.java:57:7:57:7 | E | 1 | private boolean isValid; |
|
||||
| FlexibleConstructors.java:57:7:57:7 | E | 2 | |
|
||||
| FlexibleConstructors.java:57:7:57:7 | E | 3 | private String processed; |
|
||||
| FlexibleConstructors.java:57:7:57:7 | E | 4 | |
|
||||
| FlexibleConstructors.java:57:7:57:7 | E | 5 | E(String data) { |
|
||||
| FlexibleConstructors.java:57:7:57:7 | E | 6 | var temp = data != null ? data.trim() : ""; |
|
||||
| FlexibleConstructors.java:57:7:57:7 | E | 7 | this.processed = temp; |
|
||||
| FlexibleConstructors.java:57:7:57:7 | E | 8 | isValid = !temp.isEmpty(); |
|
||||
| FlexibleConstructors.java:57:7:57:7 | E | 9 | super(temp); |
|
||||
| FlexibleConstructors.java:57:7:57:7 | E | 10 | } |
|
||||
| FlexibleConstructors.java:57:7:57:7 | E | 11 | } |
|
||||
| FlexibleConstructors.java:69:7:69:7 | F | 0 | class F { |
|
||||
| FlexibleConstructors.java:69:7:69:7 | F | 1 | private int x; |
|
||||
| FlexibleConstructors.java:69:7:69:7 | F | 2 | |
|
||||
| FlexibleConstructors.java:69:7:69:7 | F | 3 | private final int y; |
|
||||
| FlexibleConstructors.java:69:7:69:7 | F | 4 | |
|
||||
| FlexibleConstructors.java:69:7:69:7 | F | 5 | private int sum; |
|
||||
| FlexibleConstructors.java:69:7:69:7 | F | 6 | |
|
||||
| FlexibleConstructors.java:69:7:69:7 | F | 7 | F(int a, int b) { |
|
||||
| FlexibleConstructors.java:69:7:69:7 | F | 8 | x = a; |
|
||||
| FlexibleConstructors.java:69:7:69:7 | F | 9 | this.y = b; |
|
||||
| FlexibleConstructors.java:69:7:69:7 | F | 10 | this.sum = a + b; |
|
||||
| FlexibleConstructors.java:69:7:69:7 | F | 11 | super(); |
|
||||
| FlexibleConstructors.java:69:7:69:7 | F | 12 | } |
|
||||
| FlexibleConstructors.java:69:7:69:7 | F | 13 | } |
|
||||
| FlexibleConstructors.java:82:7:82:7 | G | 0 | class G { |
|
||||
| FlexibleConstructors.java:82:7:82:7 | G | 1 | private void <obinit>() { |
|
||||
| FlexibleConstructors.java:82:7:82:7 | G | 2 | { |
|
||||
| FlexibleConstructors.java:82:7:82:7 | G | 3 | instance_val = "instance"; |
|
||||
| FlexibleConstructors.java:82:7:82:7 | G | 4 | } |
|
||||
| FlexibleConstructors.java:82:7:82:7 | G | 5 | } |
|
||||
| FlexibleConstructors.java:82:7:82:7 | G | 6 | |
|
||||
| FlexibleConstructors.java:82:7:82:7 | G | 7 | private String instance_val; |
|
||||
| FlexibleConstructors.java:82:7:82:7 | G | 8 | |
|
||||
| FlexibleConstructors.java:82:7:82:7 | G | 9 | G(String input) { |
|
||||
| FlexibleConstructors.java:82:7:82:7 | G | 10 | var tmp = input != null ? input : "default"; |
|
||||
| FlexibleConstructors.java:82:7:82:7 | G | 11 | var string = tmp + "_initialized"; |
|
||||
| FlexibleConstructors.java:82:7:82:7 | G | 12 | super(); |
|
||||
| FlexibleConstructors.java:82:7:82:7 | G | 13 | <obinit>(); |
|
||||
| FlexibleConstructors.java:82:7:82:7 | G | 14 | this.instance_val = string; |
|
||||
| FlexibleConstructors.java:82:7:82:7 | G | 15 | } |
|
||||
| FlexibleConstructors.java:82:7:82:7 | G | 16 | } |
|
||||
@@ -0,0 +1,5 @@
|
||||
import semmle.code.java.PrettyPrintAst
|
||||
|
||||
from ClassOrInterface cori, string s, int line
|
||||
where pp(cori, s, line) and cori.fromSource()
|
||||
select cori, line, s
|
||||
@@ -0,0 +1,213 @@
|
||||
FlexibleConstructors.java:
|
||||
# 0| [CompilationUnit] FlexibleConstructors
|
||||
# 1| 1: [Class] A
|
||||
# 2| 1: [Constructor] A
|
||||
#-----| 4: (Parameters)
|
||||
# 2| 0: [Parameter] msg
|
||||
# 2| 0: [TypeAccess] String
|
||||
# 2| 5: [BlockStmt] { ... }
|
||||
# 3| 1: [ExprStmt] <Expr>;
|
||||
# 3| 0: [MethodCall] println(...)
|
||||
# 3| -1: [VarAccess] System.out
|
||||
# 3| -1: [TypeAccess] System
|
||||
# 3| 0: [AddExpr] ... + ...
|
||||
# 3| 0: [StringLiteral] "A: "
|
||||
# 3| 1: [VarAccess] msg
|
||||
# 7| 2: [Class] B
|
||||
#-----| -1: (Base Types)
|
||||
# 7| -1: [TypeAccess] A
|
||||
# 8| 1: [Constructor] B
|
||||
#-----| 4: (Parameters)
|
||||
# 8| 0: [Parameter] input
|
||||
# 8| 0: [TypeAccess] String
|
||||
# 8| 5: [BlockStmt] { ... }
|
||||
# 9| 0: [LocalVariableDeclStmt] var ...;
|
||||
# 9| 1: [LocalVariableDeclExpr] msg
|
||||
# 9| 0: [MethodCall] toUpperCase(...)
|
||||
# 9| -1: [MethodCall] trim(...)
|
||||
# 9| -1: [VarAccess] input
|
||||
# 10| 1: [SuperConstructorInvocationStmt] super(...)
|
||||
# 10| 0: [VarAccess] msg
|
||||
# 14| 3: [Class] C
|
||||
# 15| 1: [FieldDeclaration] int x;
|
||||
# 15| -1: [TypeAccess] int
|
||||
# 17| 2: [Constructor] C
|
||||
#-----| 4: (Parameters)
|
||||
# 17| 0: [Parameter] x
|
||||
# 17| 0: [TypeAccess] int
|
||||
# 17| 5: [BlockStmt] { ... }
|
||||
# 18| 0: [IfStmt] if (...)
|
||||
# 18| 0: [LTExpr] ... < ...
|
||||
# 18| 0: [VarAccess] x
|
||||
# 18| 1: [IntegerLiteral] 0
|
||||
# 18| 1: [ThrowStmt] throw ...
|
||||
# 18| 0: [ClassInstanceExpr] new IllegalArgumentException(...)
|
||||
# 18| -3: [TypeAccess] IllegalArgumentException
|
||||
# 19| 1: [SuperConstructorInvocationStmt] super(...)
|
||||
# 20| 2: [ExprStmt] <Expr>;
|
||||
# 20| 0: [AssignExpr] ...=...
|
||||
# 20| 0: [VarAccess] this.x
|
||||
# 20| -1: [ThisAccess] this
|
||||
# 20| 1: [VarAccess] x
|
||||
# 24| 4: [Class] R
|
||||
# 24| 2: [FieldDeclaration] String name;
|
||||
# 24| 3: [FieldDeclaration] int score;
|
||||
# 25| 4: [Constructor] R
|
||||
#-----| 4: (Parameters)
|
||||
# 25| 0: [Parameter] name
|
||||
# 25| 0: [TypeAccess] String
|
||||
# 25| 5: [BlockStmt] { ... }
|
||||
# 26| 0: [LocalVariableDeclStmt] var ...;
|
||||
# 26| 1: [LocalVariableDeclExpr] score
|
||||
# 26| 0: [MethodCall] length(...)
|
||||
# 26| -1: [VarAccess] name
|
||||
# 27| 1: [ThisConstructorInvocationStmt] this(...)
|
||||
# 27| 0: [VarAccess] name
|
||||
# 27| 1: [VarAccess] score
|
||||
# 31| 5: [Class] Outer
|
||||
# 32| 3: [FieldDeclaration] String prefix;
|
||||
# 32| -1: [TypeAccess] String
|
||||
# 32| 0: [StringLiteral] "outer"
|
||||
# 34| 4: [Class] Inner
|
||||
# 35| 1: [FieldDeclaration] String full;
|
||||
# 35| -1: [TypeAccess] String
|
||||
# 37| 2: [Constructor] Inner
|
||||
#-----| 4: (Parameters)
|
||||
# 37| 0: [Parameter] suffix
|
||||
# 37| 0: [TypeAccess] String
|
||||
# 37| 5: [BlockStmt] { ... }
|
||||
# 38| 0: [LocalVariableDeclStmt] var ...;
|
||||
# 38| 1: [LocalVariableDeclExpr] combined
|
||||
# 38| 0: [AddExpr] ... + ...
|
||||
# 38| 0: [AddExpr] ... + ...
|
||||
# 38| 0: [VarAccess] prefix
|
||||
# 38| 1: [StringLiteral] "_"
|
||||
# 38| 1: [VarAccess] suffix
|
||||
# 39| 1: [SuperConstructorInvocationStmt] super(...)
|
||||
# 40| 2: [ExprStmt] <Expr>;
|
||||
# 40| 0: [AssignExpr] ...=...
|
||||
# 40| 0: [VarAccess] this.full
|
||||
# 40| -1: [ThisAccess] this
|
||||
# 40| 1: [VarAccess] combined
|
||||
# 45| 6: [Class] D
|
||||
# 46| 1: [FieldDeclaration] String value;
|
||||
# 46| -1: [TypeAccess] String
|
||||
# 47| 2: [FieldDeclaration] int length;
|
||||
# 47| -1: [TypeAccess] int
|
||||
# 49| 3: [Constructor] D
|
||||
#-----| 4: (Parameters)
|
||||
# 49| 0: [Parameter] input
|
||||
# 49| 0: [TypeAccess] String
|
||||
# 49| 5: [BlockStmt] { ... }
|
||||
# 50| 0: [LocalVariableDeclStmt] var ...;
|
||||
# 50| 1: [LocalVariableDeclExpr] processed
|
||||
# 50| 0: [MethodCall] toLowerCase(...)
|
||||
# 50| -1: [VarAccess] input
|
||||
# 51| 1: [ExprStmt] <Expr>;
|
||||
# 51| 0: [AssignExpr] ...=...
|
||||
# 51| 0: [VarAccess] value
|
||||
# 51| 1: [VarAccess] processed
|
||||
# 52| 2: [ExprStmt] <Expr>;
|
||||
# 52| 0: [AssignExpr] ...=...
|
||||
# 52| 0: [VarAccess] this.length
|
||||
# 52| -1: [ThisAccess] this
|
||||
# 52| 1: [MethodCall] length(...)
|
||||
# 52| -1: [VarAccess] processed
|
||||
# 53| 3: [SuperConstructorInvocationStmt] super(...)
|
||||
# 57| 7: [Class] E
|
||||
#-----| -1: (Base Types)
|
||||
# 57| -1: [TypeAccess] A
|
||||
# 58| 1: [FieldDeclaration] boolean isValid;
|
||||
# 58| -1: [TypeAccess] boolean
|
||||
# 59| 2: [FieldDeclaration] String processed;
|
||||
# 59| -1: [TypeAccess] String
|
||||
# 61| 3: [Constructor] E
|
||||
#-----| 4: (Parameters)
|
||||
# 61| 0: [Parameter] data
|
||||
# 61| 0: [TypeAccess] String
|
||||
# 61| 5: [BlockStmt] { ... }
|
||||
# 62| 0: [LocalVariableDeclStmt] var ...;
|
||||
# 62| 1: [LocalVariableDeclExpr] temp
|
||||
# 62| 0: [ConditionalExpr] ...?...:...
|
||||
# 62| 0: [NEExpr] ... != ...
|
||||
# 62| 0: [VarAccess] data
|
||||
# 62| 1: [NullLiteral] null
|
||||
# 62| 1: [MethodCall] trim(...)
|
||||
# 62| -1: [VarAccess] data
|
||||
# 62| 2: [StringLiteral] ""
|
||||
# 63| 1: [ExprStmt] <Expr>;
|
||||
# 63| 0: [AssignExpr] ...=...
|
||||
# 63| 0: [VarAccess] this.processed
|
||||
# 63| -1: [ThisAccess] this
|
||||
# 63| 1: [VarAccess] temp
|
||||
# 64| 2: [ExprStmt] <Expr>;
|
||||
# 64| 0: [AssignExpr] ...=...
|
||||
# 64| 0: [VarAccess] isValid
|
||||
# 64| 1: [LogNotExpr] !...
|
||||
# 64| 0: [MethodCall] isEmpty(...)
|
||||
# 64| -1: [VarAccess] temp
|
||||
# 65| 3: [SuperConstructorInvocationStmt] super(...)
|
||||
# 65| 0: [VarAccess] temp
|
||||
# 69| 8: [Class] F
|
||||
# 70| 1: [FieldDeclaration] int x;
|
||||
# 70| -1: [TypeAccess] int
|
||||
# 71| 2: [FieldDeclaration] int y;
|
||||
# 71| -1: [TypeAccess] int
|
||||
# 72| 3: [FieldDeclaration] int sum;
|
||||
# 72| -1: [TypeAccess] int
|
||||
# 74| 4: [Constructor] F
|
||||
#-----| 4: (Parameters)
|
||||
# 74| 0: [Parameter] a
|
||||
# 74| 0: [TypeAccess] int
|
||||
# 74| 1: [Parameter] b
|
||||
# 74| 0: [TypeAccess] int
|
||||
# 74| 5: [BlockStmt] { ... }
|
||||
# 75| 0: [ExprStmt] <Expr>;
|
||||
# 75| 0: [AssignExpr] ...=...
|
||||
# 75| 0: [VarAccess] x
|
||||
# 75| 1: [VarAccess] a
|
||||
# 76| 1: [ExprStmt] <Expr>;
|
||||
# 76| 0: [AssignExpr] ...=...
|
||||
# 76| 0: [VarAccess] this.y
|
||||
# 76| -1: [ThisAccess] this
|
||||
# 76| 1: [VarAccess] b
|
||||
# 77| 2: [ExprStmt] <Expr>;
|
||||
# 77| 0: [AssignExpr] ...=...
|
||||
# 77| 0: [VarAccess] this.sum
|
||||
# 77| -1: [ThisAccess] this
|
||||
# 77| 1: [AddExpr] ... + ...
|
||||
# 77| 0: [VarAccess] a
|
||||
# 77| 1: [VarAccess] b
|
||||
# 78| 3: [SuperConstructorInvocationStmt] super(...)
|
||||
# 82| 9: [Class] G
|
||||
# 83| 2: [FieldDeclaration] String instance_val;
|
||||
# 83| -1: [TypeAccess] String
|
||||
# 85| 3: [BlockStmt] { ... }
|
||||
# 86| 0: [ExprStmt] <Expr>;
|
||||
# 86| 0: [AssignExpr] ...=...
|
||||
# 86| 0: [VarAccess] instance_val
|
||||
# 86| 1: [StringLiteral] "instance"
|
||||
# 89| 4: [Constructor] G
|
||||
#-----| 4: (Parameters)
|
||||
# 89| 0: [Parameter] input
|
||||
# 89| 0: [TypeAccess] String
|
||||
# 89| 5: [BlockStmt] { ... }
|
||||
# 90| 0: [LocalVariableDeclStmt] var ...;
|
||||
# 90| 1: [LocalVariableDeclExpr] tmp
|
||||
# 90| 0: [ConditionalExpr] ...?...:...
|
||||
# 90| 0: [NEExpr] ... != ...
|
||||
# 90| 0: [VarAccess] input
|
||||
# 90| 1: [NullLiteral] null
|
||||
# 90| 1: [VarAccess] input
|
||||
# 90| 2: [StringLiteral] "default"
|
||||
# 91| 1: [LocalVariableDeclStmt] var ...;
|
||||
# 91| 1: [LocalVariableDeclExpr] string
|
||||
# 91| 0: [AddExpr] ... + ...
|
||||
# 91| 0: [VarAccess] tmp
|
||||
# 91| 1: [StringLiteral] "_initialized"
|
||||
# 92| 2: [SuperConstructorInvocationStmt] super(...)
|
||||
# 93| 4: [ExprStmt] <Expr>;
|
||||
# 93| 0: [AssignExpr] ...=...
|
||||
# 93| 0: [VarAccess] this.instance_val
|
||||
# 93| -1: [ThisAccess] this
|
||||
# 93| 1: [VarAccess] string
|
||||
@@ -0,0 +1 @@
|
||||
semmle/code/java/PrintAst.ql
|
||||
@@ -0,0 +1,7 @@
|
||||
| FlexibleConstructors.java:10:15:10:17 | msg | FlexibleConstructors.java:10:9:10:19 | super(...) | predecessor of explicit super() |
|
||||
| FlexibleConstructors.java:18:13:18:17 | ... < ... | FlexibleConstructors.java:19:9:19:16 | super(...) | predecessor of explicit super() |
|
||||
| FlexibleConstructors.java:38:17:38:48 | combined | FlexibleConstructors.java:39:13:39:20 | super(...) | predecessor of explicit super() |
|
||||
| FlexibleConstructors.java:52:9:52:40 | ...=... | FlexibleConstructors.java:53:9:53:16 | super(...) | predecessor of explicit super() |
|
||||
| FlexibleConstructors.java:65:15:65:18 | temp | FlexibleConstructors.java:65:9:65:20 | super(...) | predecessor of explicit super() |
|
||||
| FlexibleConstructors.java:77:9:77:24 | ...=... | FlexibleConstructors.java:78:9:78:16 | super(...) | predecessor of explicit super() |
|
||||
| FlexibleConstructors.java:91:13:91:41 | string | FlexibleConstructors.java:92:9:92:16 | super(...) | predecessor of explicit super() |
|
||||
@@ -0,0 +1,11 @@
|
||||
import java
|
||||
|
||||
from ControlFlowNode pred, ControlFlowNode supNode, SuperConstructorInvocationStmt sc
|
||||
where
|
||||
supNode.asStmt() = sc and
|
||||
pred.getASuccessor() = supNode and
|
||||
pred != supNode and
|
||||
not pred.asStmt() instanceof BlockStmt and
|
||||
exists(sc.getEnclosingCallable().getFile().getRelativePath()) and
|
||||
sc.getLocation().getEndColumn() > sc.getLocation().getStartColumn()
|
||||
select pred, sc, "predecessor of explicit super()"
|
||||
1
java/ql/test/library-tests/flexible-constructors/options
Normal file
1
java/ql/test/library-tests/flexible-constructors/options
Normal file
@@ -0,0 +1 @@
|
||||
//semmle-extractor-options: --javac-args --release 25 --enable-preview
|
||||
@@ -17,10 +17,10 @@ private import semmle.javascript.dataflow.internal.DataFlowPrivate
|
||||
*
|
||||
* - The relevant call sites cannot be matched by the access path syntax, and require the full power of CodeQL.
|
||||
* For example, complex overloading patterns might require more local reasoning at the call site.
|
||||
* - The input/output behaviour cannot be described statically in the access path syntax, but the relevant access paths
|
||||
* - The input/output behavior cannot be described statically in the access path syntax, but the relevant access paths
|
||||
* can be generated dynamically in CodeQL, based on the usages found in the codebase.
|
||||
*
|
||||
* Subclasses should bind `this` to a unique identifier for the function being modelled. There is no special
|
||||
* Subclasses should bind `this` to a unique identifier for the function being modeled. There is no special
|
||||
* interpreation of the `this` value, it should just not clash with the `this`-value used by other classes.
|
||||
*
|
||||
* For example, this models flow through calls such as `require("my-library").myFunction()`:
|
||||
|
||||
@@ -386,34 +386,35 @@ module MakeStateBarrierGuard<
|
||||
*/
|
||||
private class BarrierGuardFunction extends FinalFunction {
|
||||
DataFlow::ParameterNode sanitizedParameter;
|
||||
BarrierGuard guard;
|
||||
boolean guardOutcome;
|
||||
FlowState state;
|
||||
int paramIndex;
|
||||
|
||||
BarrierGuardFunction() {
|
||||
barrierGuardIsRelevant(guard) and
|
||||
exists(Expr e |
|
||||
exists(Expr returnExpr |
|
||||
returnExpr = guard.asExpr()
|
||||
or
|
||||
// ad hoc support for conjunctions:
|
||||
getALogicalAndParent(guard) = returnExpr and guardOutcome = true
|
||||
or
|
||||
// ad hoc support for disjunctions:
|
||||
getALogicalOrParent(guard) = returnExpr and guardOutcome = false
|
||||
|
|
||||
exists(SsaExplicitDefinition ssa |
|
||||
ssa.getDef().getSource() = returnExpr and
|
||||
ssa.getVariable().getAUse() = this.getAReturnedExpr()
|
||||
)
|
||||
or
|
||||
returnExpr = this.getAReturnedExpr()
|
||||
exists(BarrierGuard guard |
|
||||
barrierGuardIsRelevant(guard) and
|
||||
exists(Expr e |
|
||||
exists(Expr returnExpr |
|
||||
returnExpr = guard.asExpr()
|
||||
or
|
||||
// ad hoc support for conjunctions:
|
||||
getALogicalAndParent(guard) = returnExpr and guardOutcome = true
|
||||
or
|
||||
// ad hoc support for disjunctions:
|
||||
getALogicalOrParent(guard) = returnExpr and guardOutcome = false
|
||||
|
|
||||
exists(SsaExplicitDefinition ssa |
|
||||
ssa.getDef().getSource() = returnExpr and
|
||||
ssa.getVariable().getAUse() = this.getAReturnedExpr()
|
||||
)
|
||||
or
|
||||
returnExpr = this.getAReturnedExpr()
|
||||
) and
|
||||
sanitizedParameter.flowsToExpr(e) and
|
||||
barrierGuardBlocksExpr(guard, guardOutcome, e, state)
|
||||
) and
|
||||
sanitizedParameter.flowsToExpr(e) and
|
||||
barrierGuardBlocksExpr(guard, guardOutcome, e, state)
|
||||
) and
|
||||
sanitizedParameter.getParameter() = this.getParameter(paramIndex)
|
||||
sanitizedParameter.getParameter() = this.getParameter(paramIndex)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -674,7 +674,7 @@ predicate neverSkipInPathGraph(Node node) {
|
||||
// Include the return-value expression
|
||||
node.asExpr() = any(Function f).getAReturnedExpr()
|
||||
or
|
||||
// Include calls (which may have been modelled as steps)
|
||||
// Include calls (which may have been modeled as steps)
|
||||
node.asExpr() instanceof InvokeExpr
|
||||
or
|
||||
// Include references to a variable
|
||||
@@ -1103,7 +1103,7 @@ private predicate legacyBarrier(DataFlow::Node node) {
|
||||
pragma[nomagic]
|
||||
private predicate isBlockedLegacyNode(Node node) {
|
||||
// Ignore captured variable nodes for those variables that are handled by the captured-variable library.
|
||||
// Note that some variables, such as top-level variables, are still modelled with these nodes (which will result in jump steps).
|
||||
// Note that some variables, such as top-level variables, are still modeled with these nodes (which will result in jump steps).
|
||||
exists(LocalVariable variable |
|
||||
node = TCapturedVariableNode(variable) and
|
||||
variable = any(VariableCaptureConfig::CapturedVariable v).asLocalVariable()
|
||||
|
||||
@@ -170,7 +170,7 @@ module VariableCaptureConfig implements InputSig<js::Location, js::Cfg::BasicBlo
|
||||
|
||||
predicate hasCfgNode(js::Cfg::BasicBlock bb, int i) { none() } // Overridden in subclass
|
||||
|
||||
// note: langauge-specific
|
||||
// note: language-specific
|
||||
js::DataFlow::Node getSource() { none() } // Overridden in subclass
|
||||
}
|
||||
|
||||
|
||||
@@ -141,16 +141,17 @@ module Babel {
|
||||
*/
|
||||
deprecated private class BabelRootTransformedPathExpr extends PathExpr, Expr {
|
||||
RootImportConfig plugin;
|
||||
string prefix;
|
||||
string mappedPrefix;
|
||||
string suffix;
|
||||
|
||||
BabelRootTransformedPathExpr() {
|
||||
this instanceof PathExpr and
|
||||
plugin.appliesTo(this.getTopLevel()) and
|
||||
prefix = this.getStringValue().regexpCapture("(.)/(.*)", 1) and
|
||||
suffix = this.getStringValue().regexpCapture("(.)/(.*)", 2) and
|
||||
mappedPrefix = plugin.getRoot(prefix)
|
||||
exists(string prefix |
|
||||
prefix = this.getStringValue().regexpCapture("(.)/(.*)", 1) and
|
||||
mappedPrefix = plugin.getRoot(prefix)
|
||||
)
|
||||
}
|
||||
|
||||
/** Gets the configuration that applies to this path. */
|
||||
|
||||
@@ -35,7 +35,7 @@ class Location = JS::Location;
|
||||
* Type names have form `package.type` or just `package` if referring to the package export
|
||||
* object. If `package` contains a `.` character it must be enclosed in single quotes, such as `'package'.type`.
|
||||
*
|
||||
* A type name of form `(package)` may also be used when refering to the package export object.
|
||||
* A type name of form `(package)` may also be used when referring to the package export object.
|
||||
* We allow this syntax as an alternative to the above, so models generated based on `EndpointNaming` look more consistent.
|
||||
* However, access paths are deliberately not parsed here, as we can not handle aliasing at this stage.
|
||||
* The model generator must explicitly generate the step between `(package)` and `(package).foo`, for example.
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/**
|
||||
* Contains a summary for relevant methods on arrays.
|
||||
*
|
||||
* Note that some of Array methods are modelled in `AmbiguousCoreMethods.qll`, and `toString` is special-cased elsewhere.
|
||||
* Note that some of Array methods are modeled in `AmbiguousCoreMethods.qll`, and `toString` is special-cased elsewhere.
|
||||
*/
|
||||
|
||||
private import javascript
|
||||
@@ -60,7 +60,7 @@ private predicate isForLoopVariable(Variable v) {
|
||||
|
||||
private predicate isLikelyArrayIndex(Expr e) {
|
||||
// Require that 'e' is of type number and refers to a for-loop variable.
|
||||
// TODO: This is here to mirror the old behaviour. Experiment with turning the 'and' into an 'or'.
|
||||
// TODO: This is here to mirror the old behavior. Experiment with turning the 'and' into an 'or'.
|
||||
TTNumber() = unique(InferredType type | type = e.flow().analyze().getAType()) and
|
||||
isForLoopVariable(e.(VarAccess).getVariable())
|
||||
or
|
||||
@@ -114,7 +114,7 @@ class ArrayConstructorSummary extends SummarizedCallable {
|
||||
/**
|
||||
* A call to `join` with a separator argument.
|
||||
*
|
||||
* Calls without separators are modelled in `StringConcatenation.qll`.
|
||||
* Calls without separators are modeled in `StringConcatenation.qll`.
|
||||
*/
|
||||
class Join extends SummarizedCallable {
|
||||
Join() { this = "Array#join" }
|
||||
|
||||
@@ -8,7 +8,7 @@ private import semmle.javascript.dataflow.internal.AdditionalFlowInternal
|
||||
private import semmle.javascript.dataflow.internal.DataFlowPrivate
|
||||
|
||||
/**
|
||||
* Steps modelling flow in an `async` function.
|
||||
* Steps modeling flow in an `async` function.
|
||||
*
|
||||
* Note about promise-coercion and flattening:
|
||||
* - `await` preserves non-promise values, e.g. `await "foo"` is just `"foo"`.
|
||||
|
||||
@@ -7,7 +7,7 @@ private import semmle.javascript.dataflow.internal.DataFlowNode
|
||||
private import semmle.javascript.dataflow.internal.AdditionalFlowInternal
|
||||
|
||||
/**
|
||||
* Steps modelling flow out of a generator function:
|
||||
* Steps modeling flow out of a generator function:
|
||||
* ```js
|
||||
* function* foo() {
|
||||
* yield x; // store 'x' in the return value's IteratorElement
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Contains flow summaries and steps modelling flow through iterators.
|
||||
* Contains flow summaries and steps modeling flow through iterators.
|
||||
*/
|
||||
|
||||
private import javascript
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Contains flow summaries and steps modelling flow through `Map` objects.
|
||||
* Contains flow summaries and steps modeling flow through `Map` objects.
|
||||
*/
|
||||
|
||||
private import javascript
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Contains flow summaries and steps modelling flow through `Promise` objects.
|
||||
* Contains flow summaries and steps modeling flow through `Promise` objects.
|
||||
*/
|
||||
|
||||
private import javascript
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Contains flow summaries and steps modelling flow through `Set` objects.
|
||||
* Contains flow summaries and steps modeling flow through `Set` objects.
|
||||
*/
|
||||
|
||||
private import javascript
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Contains flow summaries and steps modelling flow through string methods.
|
||||
* Contains flow summaries and steps modeling flow through string methods.
|
||||
*/
|
||||
|
||||
private import javascript
|
||||
@@ -73,7 +73,7 @@ class StringSplit extends SummarizedCallable {
|
||||
* These are of special significance when tracking a tainted URL suffix, such as `window.location.href`,
|
||||
* because the first element of the resulting array should not be considered tainted.
|
||||
*
|
||||
* This summary defaults to the same behaviour as the general `.split()` case, but it contains optional steps
|
||||
* This summary defaults to the same behavior as the general `.split()` case, but it contains optional steps
|
||||
* and barriers named `tainted-url-suffix` that should be activated when tracking a tainted URL suffix.
|
||||
*/
|
||||
class StringSplitHashOrQuestionMark extends SummarizedCallable {
|
||||
|
||||
@@ -76,7 +76,7 @@ module TaintedUrlSuffix {
|
||||
//
|
||||
// x [tainted-url-suffix] --> x.split('#') [array element 1] [taint]
|
||||
//
|
||||
// Technically we should also preverse tainted-url-suffix when entering the first array element of such
|
||||
// Technically we should also preserve tainted-url-suffix when entering the first array element of such
|
||||
// a split, but this mostly leads to FPs since we currently don't track if the taint has been through URI-decoding.
|
||||
// (The query/fragment parts are often URI-decoded in practice, but not the other URL parts are not)
|
||||
state1.isTaintedUrlSuffix() and
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
|
||||
import javascript
|
||||
import RemotePropertyInjectionCustomizations::RemotePropertyInjection
|
||||
private import semmle.javascript.DynamicPropertyAccess
|
||||
|
||||
/**
|
||||
* A taint-tracking configuration for reasoning about remote property injection.
|
||||
@@ -24,6 +25,10 @@ module RemotePropertyInjectionConfig implements DataFlow::ConfigSig {
|
||||
node = StringConcatenation::getRoot(any(ConstantString str).flow())
|
||||
}
|
||||
|
||||
predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) {
|
||||
node1 = node2.(EnumeratedPropName).getSourceObject()
|
||||
}
|
||||
|
||||
predicate observeDiffInformedIncrementalMode() { any() }
|
||||
}
|
||||
|
||||
|
||||
@@ -46,9 +46,7 @@ string getKind(MemberDeclaration m) {
|
||||
* A call-signature that originates from a MethodSignature in the AST.
|
||||
*/
|
||||
private class MethodCallSig extends Function {
|
||||
private MethodSignature signature;
|
||||
|
||||
MethodCallSig() { this = signature.getBody() }
|
||||
MethodCallSig() { this = any(MethodSignature signature).getBody() }
|
||||
|
||||
int getNumOptionalParameter() {
|
||||
result = count(Parameter p | p = this.getParameter(_) and p.isDeclaredOptional())
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user