Merge branch 'main' into js/move-cors-query-from-experimental

This commit is contained in:
Napalys Klicius
2025-09-05 12:11:09 +02:00
committed by GitHub
106 changed files with 14432 additions and 8745 deletions

View File

@@ -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

View File

@@ -0,0 +1,4 @@
---
category: deprecated
---
* The predicate `getAContructorCall` in the class `SslContextClass` has been deprecated. Use `getAConstructorCall` instead.

View File

@@ -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) {

View File

@@ -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

View File

@@ -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.

View File

@@ -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.

View File

@@ -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 |

View File

@@ -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

View File

@@ -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

View File

@@ -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:
*

View File

@@ -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.

View File

@@ -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) =

View File

@@ -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)
}
/**

View File

@@ -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)
}
}

View File

@@ -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)
}
}

View File

@@ -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 }

View File

@@ -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() {

View File

@@ -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

View File

@@ -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:
* ```

View File

@@ -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) {

View File

@@ -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;

View File

@@ -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
)
}

View File

@@ -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

View File

@@ -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)
)
}
}

View File

@@ -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) {

View File

@@ -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
)
}
}

View File

@@ -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() }

View File

@@ -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

View File

@@ -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) {

View 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.

View File

@@ -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

View File

@@ -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

View File

@@ -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 }

View File

@@ -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

View File

@@ -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 |

View File

@@ -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()

View File

@@ -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/).
*/

View File

@@ -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/).
*/

View File

@@ -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())
)

View File

@@ -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.

View File

@@ -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"]

View File

@@ -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()
)
}

View File

@@ -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
}

View File

@@ -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

View File

@@ -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

View File

@@ -0,0 +1,3 @@
description: Remove Java 25 compact source files support by removing `isImplicitClass` table
compatibility: partial
isImplicitClass.rel: delete

View File

@@ -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.

View File

@@ -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

View File

@@ -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" }
}

View File

@@ -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() }

View File

@@ -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

View File

@@ -0,0 +1,2 @@
description: Add support for Java 25 compact source files by introducing isImplicitClass table
compatibility: full

View File

@@ -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> |

View File

@@ -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 |

View File

@@ -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> |

View File

@@ -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 |

View File

@@ -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' |

View File

@@ -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() + "'"

View File

@@ -0,0 +1 @@
| Test.java:0:0:0:0 | Test |

View File

@@ -0,0 +1,5 @@
import java
from CompilationUnit cu
where cu.isCompactSourceFile()
select cu

View File

@@ -0,0 +1,2 @@
| Test.java:1:1:1:1 | Test | implicit |
| Test.java:25:7:25:16 | NotCompact | not implicit |

View File

@@ -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

View File

@@ -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 |

View File

@@ -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

View File

@@ -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] { ... }

View File

@@ -0,0 +1 @@
semmle/code/java/PrintAst.ql

View 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() {
}
}

View File

@@ -0,0 +1 @@
//semmle-extractor-options: --javac-args --release 25 --enable-preview

View File

@@ -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;
}
}

View File

@@ -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 |

View File

@@ -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()

View File

@@ -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 | } |

View File

@@ -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

View File

@@ -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

View File

@@ -0,0 +1 @@
semmle/code/java/PrintAst.ql

View File

@@ -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() |

View File

@@ -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()"

View File

@@ -0,0 +1 @@
//semmle-extractor-options: --javac-args --release 25 --enable-preview

View File

@@ -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()`:

View File

@@ -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)
)
}
/**

View File

@@ -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()

View File

@@ -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
}

View File

@@ -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. */

View File

@@ -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.

View File

@@ -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" }

View File

@@ -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"`.

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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 {

View File

@@ -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

View File

@@ -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() }
}

View File

@@ -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