mirror of
https://github.com/github/codeql.git
synced 2026-05-25 00:27:09 +02:00
Compare commits
1 Commits
28-strsafe
...
criemen/cs
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1a98dbf55e |
@@ -31,11 +31,6 @@ abstract class MustFlowConfiguration extends string {
|
||||
*/
|
||||
abstract predicate isSink(Operand sink);
|
||||
|
||||
/**
|
||||
* Holds if data flow through `instr` is prohibited.
|
||||
*/
|
||||
predicate isBarrier(Instruction instr) { none() }
|
||||
|
||||
/**
|
||||
* Holds if the additional flow step from `node1` to `node2` must be taken
|
||||
* into account in the analysis.
|
||||
@@ -53,21 +48,18 @@ abstract class MustFlowConfiguration extends string {
|
||||
*/
|
||||
final predicate hasFlowPath(MustFlowPathNode source, MustFlowPathSink sink) {
|
||||
this.isSource(source.getInstruction()) and
|
||||
source.getASuccessor*() = sink
|
||||
source.getASuccessor+() = sink
|
||||
}
|
||||
}
|
||||
|
||||
/** Holds if `node` flows from a source. */
|
||||
pragma[nomagic]
|
||||
private predicate flowsFromSource(Instruction node, MustFlowConfiguration config) {
|
||||
not config.isBarrier(node) and
|
||||
(
|
||||
config.isSource(node)
|
||||
or
|
||||
exists(Instruction mid |
|
||||
step(mid, node, config) and
|
||||
flowsFromSource(mid, pragma[only_bind_into](config))
|
||||
)
|
||||
config.isSource(node)
|
||||
or
|
||||
exists(Instruction mid |
|
||||
step(mid, node, config) and
|
||||
flowsFromSource(mid, pragma[only_bind_into](config))
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -147,32 +147,19 @@ private class SnprintfImpl extends Snprintf {
|
||||
|
||||
/**
|
||||
* The Microsoft `StringCchPrintf` function and variants.
|
||||
* See: https://learn.microsoft.com/en-us/windows/win32/api/strsafe/
|
||||
* and
|
||||
* https://learn.microsoft.com/en-us/previous-versions/windows/embedded/ms860435(v=msdn.10)
|
||||
*/
|
||||
private class StringCchPrintf extends FormattingFunction {
|
||||
StringCchPrintf() {
|
||||
this instanceof TopLevelFunction and
|
||||
exists(string baseName |
|
||||
baseName in [
|
||||
"StringCchPrintf", //StringCchPrintf(pszDest, cchDest, pszFormat, …)
|
||||
"StringCchPrintfEx", //StringCchPrintfEx(pszDest,cchDest, ppszDestEnd, pcchRemaining, dwFlags, pszFormat, ...);
|
||||
"StringCchPrintf_l", //StringCchPrintf_l(pszDest, cbDest, pszFormat, locale, …)
|
||||
"StringCchPrintf_lEx", //StringCchPrintf_lEx(pszDest, cchDest, ppszDestEnd, pcchRemaining, dwFlags, pszFormat, locale, …)
|
||||
"StringCbPrintf", //StringCbPrintf(pszDest, cbDest, pszFormat, …)
|
||||
"StringCbPrintfEx", //StringCbPrintfEx(pszDest, cbDest, ppszDestEnd, pcbRemaining, dwFlags, pszFormat, …)
|
||||
"StringCbPrintf_l", //StringCbPrintf_l(pszDest, cbDest, pszFormat, locale, …)
|
||||
"StringCbPrintf_lEx" //StringCbPrintf_lEx(pszDest, cbDest, ppszDestEnd, pcbRemaining, dwFlags, pszFormat, locale, …)
|
||||
]
|
||||
|
|
||||
this.hasGlobalName(baseName + ["", "A", "W"])
|
||||
) and
|
||||
this.hasGlobalName([
|
||||
"StringCchPrintf", "StringCchPrintfEx", "StringCchPrintf_l", "StringCchPrintf_lEx",
|
||||
"StringCbPrintf", "StringCbPrintfEx", "StringCbPrintf_l", "StringCbPrintf_lEx"
|
||||
]) and
|
||||
not exists(this.getDefinition().getFile().getRelativePath())
|
||||
}
|
||||
|
||||
override int getFormatParameterIndex() {
|
||||
if this.getName().matches("%Ex" + ["", "A", "W"]) then result = 5 else result = 2
|
||||
if this.getName().matches("%Ex") then result = 5 else result = 2
|
||||
}
|
||||
|
||||
override int getOutputParameterIndex(boolean isStream) { result = 0 and isStream = false }
|
||||
|
||||
@@ -12,6 +12,9 @@ class SemBasicBlock extends Specific::BasicBlock {
|
||||
/** Holds if this block (transitively) dominates `otherblock`. */
|
||||
final predicate bbDominates(SemBasicBlock otherBlock) { Specific::bbDominates(this, otherBlock) }
|
||||
|
||||
/** Holds if this block has dominance information. */
|
||||
final predicate hasDominanceInformation() { Specific::hasDominanceInformation(this) }
|
||||
|
||||
/** Gets an expression that is evaluated in this basic block. */
|
||||
final SemExpr getAnExpr() { result.getBasicBlock() = this }
|
||||
|
||||
|
||||
@@ -122,6 +122,8 @@ module SemanticExprConfig {
|
||||
dominator.dominates(dominated)
|
||||
}
|
||||
|
||||
predicate hasDominanceInformation(BasicBlock block) { any() }
|
||||
|
||||
private predicate id(Cpp::Locatable x, Cpp::Locatable y) { x = y }
|
||||
|
||||
private predicate idOf(Cpp::Locatable x, int y) = equivalenceRelation(id/2)(x, y)
|
||||
@@ -130,7 +132,17 @@ module SemanticExprConfig {
|
||||
|
||||
newtype TSsaVariable =
|
||||
TSsaInstruction(IR::Instruction instr) { instr.hasMemoryResult() } or
|
||||
TSsaOperand(IR::Operand op) { op.isDefinitionInexact() }
|
||||
TSsaOperand(IR::Operand op) { op.isDefinitionInexact() } or
|
||||
TSsaPointerArithmeticGuard(ValueNumber instr) {
|
||||
exists(Guard g, IR::Operand use |
|
||||
use = instr.getAUse() and use.getIRType() instanceof IR::IRAddressType
|
||||
|
|
||||
g.comparesLt(use, _, _, _, _) or
|
||||
g.comparesLt(_, use, _, _, _) or
|
||||
g.comparesEq(use, _, _, _, _) or
|
||||
g.comparesEq(_, use, _, _, _)
|
||||
)
|
||||
}
|
||||
|
||||
class SsaVariable extends TSsaVariable {
|
||||
string toString() { none() }
|
||||
@@ -139,6 +151,8 @@ module SemanticExprConfig {
|
||||
|
||||
IR::Instruction asInstruction() { none() }
|
||||
|
||||
ValueNumber asPointerArithGuard() { none() }
|
||||
|
||||
IR::Operand asOperand() { none() }
|
||||
}
|
||||
|
||||
@@ -154,6 +168,18 @@ module SemanticExprConfig {
|
||||
final override IR::Instruction asInstruction() { result = instr }
|
||||
}
|
||||
|
||||
class SsaPointerArithmeticGuard extends SsaVariable, TSsaPointerArithmeticGuard {
|
||||
ValueNumber vn;
|
||||
|
||||
SsaPointerArithmeticGuard() { this = TSsaPointerArithmeticGuard(vn) }
|
||||
|
||||
final override string toString() { result = vn.toString() }
|
||||
|
||||
final override Location getLocation() { result = vn.getLocation() }
|
||||
|
||||
final override ValueNumber asPointerArithGuard() { result = vn }
|
||||
}
|
||||
|
||||
class SsaOperand extends SsaVariable, TSsaOperand {
|
||||
IR::Operand op;
|
||||
|
||||
@@ -186,7 +212,11 @@ module SemanticExprConfig {
|
||||
)
|
||||
}
|
||||
|
||||
Expr getAUse(SsaVariable v) { result.(IR::LoadInstruction).getSourceValue() = v.asInstruction() }
|
||||
Expr getAUse(SsaVariable v) {
|
||||
result.(IR::LoadInstruction).getSourceValue() = v.asInstruction()
|
||||
or
|
||||
result = v.asPointerArithGuard().getAnInstruction()
|
||||
}
|
||||
|
||||
SemType getSsaVariableType(SsaVariable v) {
|
||||
result = getSemanticType(v.asInstruction().getResultIRType())
|
||||
@@ -225,7 +255,10 @@ module SemanticExprConfig {
|
||||
final override Location getLocation() { result = block.getLocation() }
|
||||
|
||||
final override predicate hasRead(SsaVariable v) {
|
||||
exists(IR::Operand operand | operand.getDef() = v.asInstruction() |
|
||||
exists(IR::Operand operand |
|
||||
operand.getDef() = v.asInstruction() or
|
||||
operand.getDef() = v.asPointerArithGuard().getAnInstruction()
|
||||
|
|
||||
not operand instanceof IR::PhiInputOperand and
|
||||
operand.getUse().getBlock() = block
|
||||
)
|
||||
@@ -243,7 +276,10 @@ module SemanticExprConfig {
|
||||
final override Location getLocation() { result = succ.getLocation() }
|
||||
|
||||
final override predicate hasRead(SsaVariable v) {
|
||||
exists(IR::PhiInputOperand operand | operand.getDef() = v.asInstruction() |
|
||||
exists(IR::PhiInputOperand operand |
|
||||
operand.getDef() = v.asInstruction() or
|
||||
operand.getDef() = v.asPointerArithGuard().getAnInstruction()
|
||||
|
|
||||
operand.getPredecessorBlock() = pred and
|
||||
operand.getUse().getBlock() = succ
|
||||
)
|
||||
|
||||
@@ -35,4 +35,32 @@ predicate semImplies_v2(SemGuard g1, boolean b1, SemGuard g2, boolean b2) {
|
||||
Specific::implies_v2(g1, b1, g2, b2)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `guard` directly controls the position `controlled` with the
|
||||
* value `testIsTrue`.
|
||||
*/
|
||||
pragma[nomagic]
|
||||
predicate semGuardDirectlyControlsSsaRead(
|
||||
SemGuard guard, SemSsaReadPosition controlled, boolean testIsTrue
|
||||
) {
|
||||
guard.directlyControls(controlled.(SemSsaReadPositionBlock).getBlock(), testIsTrue)
|
||||
or
|
||||
exists(SemSsaReadPositionPhiInputEdge controlledEdge | controlledEdge = controlled |
|
||||
guard.directlyControls(controlledEdge.getOrigBlock(), testIsTrue) or
|
||||
guard.hasBranchEdge(controlledEdge.getOrigBlock(), controlledEdge.getPhiBlock(), testIsTrue)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `guard` controls the position `controlled` with the value `testIsTrue`.
|
||||
*/
|
||||
predicate semGuardControlsSsaRead(SemGuard guard, SemSsaReadPosition controlled, boolean testIsTrue) {
|
||||
semGuardDirectlyControlsSsaRead(guard, controlled, testIsTrue)
|
||||
or
|
||||
exists(SemGuard guard0, boolean testIsTrue0 |
|
||||
semImplies_v2(guard0, testIsTrue0, guard, testIsTrue) and
|
||||
semGuardControlsSsaRead(guard0, controlled, testIsTrue0)
|
||||
)
|
||||
}
|
||||
|
||||
SemGuard semGetComparisonGuard(SemRelationalExpr e) { result = Specific::comparisonGuard(e) }
|
||||
|
||||
@@ -63,3 +63,36 @@ class SemSsaReadPositionBlock extends SemSsaReadPosition {
|
||||
|
||||
SemExpr getAnExpr() { result = this.getBlock().getAnExpr() }
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `inp` is an input to `phi` along a back edge.
|
||||
*/
|
||||
predicate semBackEdge(SemSsaPhiNode phi, SemSsaVariable inp, SemSsaReadPositionPhiInputEdge edge) {
|
||||
edge.phiInput(phi, inp) and
|
||||
// Conservatively assume that every edge is a back edge if we don't have dominance information.
|
||||
(
|
||||
phi.getBasicBlock().bbDominates(edge.getOrigBlock()) or
|
||||
irreducibleSccEdge(edge.getOrigBlock(), phi.getBasicBlock()) or
|
||||
not edge.getOrigBlock().hasDominanceInformation()
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if the edge from b1 to b2 is part of a multiple-entry cycle in an irreducible control flow
|
||||
* graph.
|
||||
*
|
||||
* An ireducible control flow graph is one where the usual dominance-based back edge detection does
|
||||
* not work, because there is a cycle with multiple entry points, meaning there are
|
||||
* mutually-reachable basic blocks where neither dominates the other. For such a graph, we first
|
||||
* remove all detectable back-edges using the normal condition that the predecessor block is
|
||||
* dominated by the successor block, then mark all edges in a cycle in the resulting graph as back
|
||||
* edges.
|
||||
*/
|
||||
private predicate irreducibleSccEdge(SemBasicBlock b1, SemBasicBlock b2) {
|
||||
trimmedEdge(b1, b2) and trimmedEdge+(b2, b1)
|
||||
}
|
||||
|
||||
private predicate trimmedEdge(SemBasicBlock pred, SemBasicBlock succ) {
|
||||
pred.getASuccessor() = succ and
|
||||
not succ.bbDominates(pred)
|
||||
}
|
||||
|
||||
@@ -72,12 +72,14 @@ module Sem implements Semantic {
|
||||
|
||||
class BasicBlock = SemBasicBlock;
|
||||
|
||||
BasicBlock getABasicBlockSuccessor(BasicBlock bb) { result = bb.getASuccessor() }
|
||||
|
||||
class Guard = SemGuard;
|
||||
|
||||
predicate implies_v2 = semImplies_v2/4;
|
||||
|
||||
predicate guardDirectlyControlsSsaRead = semGuardDirectlyControlsSsaRead/3;
|
||||
|
||||
predicate guardControlsSsaRead = semGuardControlsSsaRead/3;
|
||||
|
||||
class Type = SemType;
|
||||
|
||||
class IntegerType = SemIntegerType;
|
||||
@@ -98,6 +100,8 @@ module Sem implements Semantic {
|
||||
|
||||
class SsaReadPositionBlock = SemSsaReadPositionBlock;
|
||||
|
||||
predicate backEdge = semBackEdge/3;
|
||||
|
||||
predicate conversionCannotOverflow(Type fromType, Type toType) {
|
||||
SemanticType::conversionCannotOverflow(fromType, toType)
|
||||
}
|
||||
|
||||
@@ -294,7 +294,7 @@ module SignAnalysis<DeltaSig D, UtilSig<Sem, D> Utils> {
|
||||
) {
|
||||
exists(boolean testIsTrue, SemRelationalExpr comp |
|
||||
pos.hasReadOfVar(v) and
|
||||
guardControlsSsaRead(semGetComparisonGuard(comp), pos, testIsTrue) and
|
||||
semGuardControlsSsaRead(semGetComparisonGuard(comp), pos, testIsTrue) and
|
||||
not unknownSign(lowerbound)
|
||||
|
|
||||
testIsTrue = true and
|
||||
@@ -318,7 +318,7 @@ module SignAnalysis<DeltaSig D, UtilSig<Sem, D> Utils> {
|
||||
) {
|
||||
exists(boolean testIsTrue, SemRelationalExpr comp |
|
||||
pos.hasReadOfVar(v) and
|
||||
guardControlsSsaRead(semGetComparisonGuard(comp), pos, testIsTrue) and
|
||||
semGuardControlsSsaRead(semGetComparisonGuard(comp), pos, testIsTrue) and
|
||||
not unknownSign(upperbound)
|
||||
|
|
||||
testIsTrue = true and
|
||||
@@ -343,7 +343,7 @@ module SignAnalysis<DeltaSig D, UtilSig<Sem, D> Utils> {
|
||||
private predicate eqBound(SemExpr eqbound, SemSsaVariable v, SemSsaReadPosition pos, boolean isEq) {
|
||||
exists(SemGuard guard, boolean testIsTrue, boolean polarity, SemExpr e |
|
||||
pos.hasReadOfVar(pragma[only_bind_into](v)) and
|
||||
guardControlsSsaRead(guard, pragma[only_bind_into](pos), testIsTrue) and
|
||||
semGuardControlsSsaRead(guard, pragma[only_bind_into](pos), testIsTrue) and
|
||||
e = ssaRead(pragma[only_bind_into](v), D::fromInt(0)) and
|
||||
guard.isEquality(eqbound, e, polarity) and
|
||||
isEq = polarity.booleanXor(testIsTrue).booleanNot() and
|
||||
|
||||
@@ -13,8 +13,7 @@
|
||||
*/
|
||||
|
||||
import cpp
|
||||
import semmle.code.cpp.ir.IR
|
||||
import semmle.code.cpp.ir.dataflow.MustFlow
|
||||
import semmle.code.cpp.controlflow.StackVariableReachability
|
||||
|
||||
/**
|
||||
* Auxiliary predicate: Types that don't require initialization
|
||||
@@ -34,6 +33,31 @@ predicate allocatedType(Type t) {
|
||||
allocatedType(t.getUnspecifiedType())
|
||||
}
|
||||
|
||||
/**
|
||||
* A declaration of a local variable that leaves the
|
||||
* variable uninitialized.
|
||||
*/
|
||||
DeclStmt declWithNoInit(LocalVariable v) {
|
||||
result.getADeclaration() = v and
|
||||
not exists(v.getInitializer()) and
|
||||
/* The type of the variable is not stack-allocated. */
|
||||
exists(Type t | t = v.getType() | not allocatedType(t))
|
||||
}
|
||||
|
||||
class UninitialisedLocalReachability extends StackVariableReachability {
|
||||
UninitialisedLocalReachability() { this = "UninitialisedLocal" }
|
||||
|
||||
override predicate isSource(ControlFlowNode node, StackVariable v) { node = declWithNoInit(v) }
|
||||
|
||||
override predicate isSink(ControlFlowNode node, StackVariable v) { useOfVarActual(v, node) }
|
||||
|
||||
override predicate isBarrier(ControlFlowNode node, StackVariable v) {
|
||||
// only report the _first_ possibly uninitialized use
|
||||
useOfVarActual(v, node) or
|
||||
definitionBarrier(v, node)
|
||||
}
|
||||
}
|
||||
|
||||
pragma[noinline]
|
||||
predicate containsInlineAssembly(Function f) { exists(AsmStmt s | s.getEnclosingFunction() = f) }
|
||||
|
||||
@@ -58,33 +82,8 @@ VariableAccess commonException() {
|
||||
containsInlineAssembly(result.getEnclosingFunction())
|
||||
}
|
||||
|
||||
predicate isSinkImpl(Instruction sink, VariableAccess va) {
|
||||
exists(LoadInstruction load |
|
||||
va = load.getUnconvertedResultExpression() and
|
||||
not va = commonException() and
|
||||
sink = load.getSourceValue()
|
||||
)
|
||||
}
|
||||
|
||||
class MustFlow extends MustFlowConfiguration {
|
||||
MustFlow() { this = "MustFlow" }
|
||||
|
||||
override predicate isSource(Instruction source) {
|
||||
source instanceof UninitializedInstruction and
|
||||
exists(Type t | t = source.getResultType() | not allocatedType(t))
|
||||
}
|
||||
|
||||
override predicate isSink(Operand sink) { isSinkImpl(sink.getDef(), _) }
|
||||
|
||||
override predicate allowInterproceduralFlow() { none() }
|
||||
|
||||
override predicate isBarrier(Instruction instr) { instr instanceof ChiInstruction }
|
||||
}
|
||||
|
||||
from
|
||||
VariableAccess va, LocalVariable v, MustFlow conf, MustFlowPathNode source, MustFlowPathNode sink
|
||||
from UninitialisedLocalReachability r, LocalVariable v, VariableAccess va
|
||||
where
|
||||
conf.hasFlowPath(source, sink) and
|
||||
isSinkImpl(sink.getInstruction(), va) and
|
||||
v = va.getTarget()
|
||||
r.reaches(_, v, va) and
|
||||
not va = commonException()
|
||||
select va, "The variable $@ may not be initialized at this access.", v, v.getName()
|
||||
|
||||
@@ -1,4 +0,0 @@
|
||||
---
|
||||
category: minorAnalysis
|
||||
---
|
||||
* The `cpp/uninitialized-local` query has been improved to produce fewer false positives.
|
||||
@@ -1,4 +0,0 @@
|
||||
---
|
||||
category: minorAnalysis
|
||||
---
|
||||
* Added models for the `sprintf` variants from the `StrSafe.h` header.
|
||||
@@ -22,6 +22,10 @@ edges
|
||||
| test.cpp:52:19:52:37 | call to malloc | test.cpp:53:12:53:23 | ... + ... |
|
||||
| test.cpp:53:12:53:23 | ... + ... | test.cpp:51:33:51:35 | end |
|
||||
| test.cpp:60:34:60:37 | mk_array output argument | test.cpp:67:9:67:14 | ... = ... |
|
||||
| test.cpp:194:15:194:33 | call to malloc | test.cpp:195:17:195:23 | ... + ... |
|
||||
| test.cpp:195:17:195:23 | ... + ... | test.cpp:195:17:195:23 | ... + ... |
|
||||
| test.cpp:195:17:195:23 | ... + ... | test.cpp:201:5:201:19 | ... = ... |
|
||||
| test.cpp:195:17:195:23 | ... + ... | test.cpp:201:5:201:19 | ... = ... |
|
||||
| test.cpp:205:15:205:33 | call to malloc | test.cpp:206:17:206:23 | ... + ... |
|
||||
| test.cpp:206:17:206:23 | ... + ... | test.cpp:206:17:206:23 | ... + ... |
|
||||
| test.cpp:206:17:206:23 | ... + ... | test.cpp:213:5:213:13 | ... = ... |
|
||||
@@ -121,6 +125,10 @@ nodes
|
||||
| test.cpp:53:12:53:23 | ... + ... | semmle.label | ... + ... |
|
||||
| test.cpp:60:34:60:37 | mk_array output argument | semmle.label | mk_array output argument |
|
||||
| test.cpp:67:9:67:14 | ... = ... | semmle.label | ... = ... |
|
||||
| test.cpp:194:15:194:33 | call to malloc | semmle.label | call to malloc |
|
||||
| test.cpp:195:17:195:23 | ... + ... | semmle.label | ... + ... |
|
||||
| test.cpp:195:17:195:23 | ... + ... | semmle.label | ... + ... |
|
||||
| test.cpp:201:5:201:19 | ... = ... | semmle.label | ... = ... |
|
||||
| test.cpp:205:15:205:33 | call to malloc | semmle.label | call to malloc |
|
||||
| test.cpp:206:17:206:23 | ... + ... | semmle.label | ... + ... |
|
||||
| test.cpp:206:17:206:23 | ... + ... | semmle.label | ... + ... |
|
||||
@@ -206,6 +214,7 @@ subpaths
|
||||
| test.cpp:30:14:30:15 | * ... | test.cpp:28:15:28:37 | call to malloc | test.cpp:30:14:30:15 | * ... | This read might be out of bounds, as the pointer might be equal to $@ + $@. | test.cpp:28:15:28:37 | call to malloc | call to malloc | test.cpp:29:20:29:27 | ... + ... | ... + ... |
|
||||
| test.cpp:32:14:32:21 | * ... | test.cpp:28:15:28:37 | call to malloc | test.cpp:32:14:32:21 | * ... | This read might be out of bounds, as the pointer might be equal to $@ + $@ + 1. | test.cpp:28:15:28:37 | call to malloc | call to malloc | test.cpp:29:20:29:27 | ... + ... | ... + ... |
|
||||
| test.cpp:67:9:67:14 | ... = ... | test.cpp:52:19:52:37 | call to malloc | test.cpp:67:9:67:14 | ... = ... | This write might be out of bounds, as the pointer might be equal to $@ + $@. | test.cpp:52:19:52:37 | call to malloc | call to malloc | test.cpp:53:20:53:23 | size | size |
|
||||
| test.cpp:201:5:201:19 | ... = ... | test.cpp:194:15:194:33 | call to malloc | test.cpp:201:5:201:19 | ... = ... | This write might be out of bounds, as the pointer might be equal to $@ + $@. | test.cpp:194:15:194:33 | call to malloc | call to malloc | test.cpp:195:21:195:23 | len | len |
|
||||
| test.cpp:213:5:213:13 | ... = ... | test.cpp:205:15:205:33 | call to malloc | test.cpp:213:5:213:13 | ... = ... | This write might be out of bounds, as the pointer might be equal to $@ + $@. | test.cpp:205:15:205:33 | call to malloc | call to malloc | test.cpp:206:21:206:23 | len | len |
|
||||
| test.cpp:264:13:264:14 | * ... | test.cpp:260:13:260:24 | new[] | test.cpp:264:13:264:14 | * ... | This read might be out of bounds, as the pointer might be equal to $@ + $@. | test.cpp:260:13:260:24 | new[] | new[] | test.cpp:261:19:261:21 | len | len |
|
||||
| test.cpp:274:5:274:10 | ... = ... | test.cpp:270:13:270:24 | new[] | test.cpp:274:5:274:10 | ... = ... | This write might be out of bounds, as the pointer might be equal to $@ + $@. | test.cpp:270:13:270:24 | new[] | new[] | test.cpp:271:19:271:21 | len | len |
|
||||
|
||||
@@ -198,7 +198,7 @@ void test12(unsigned len, unsigned index) {
|
||||
return;
|
||||
}
|
||||
|
||||
p[index] = '\0'; // $ MISSING: deref=L195->L201 // BAD [NOT DETECTED]
|
||||
p[index] = '\0'; // $ deref=L195->L201 // BAD
|
||||
}
|
||||
|
||||
void test13(unsigned len, unsigned index) {
|
||||
|
||||
@@ -1,7 +1,14 @@
|
||||
| test.cpp:12:6:12:8 | foo | The variable $@ may not be initialized at this access. | test.cpp:11:6:11:8 | foo | foo |
|
||||
| test.cpp:30:6:30:8 | foo | The variable $@ may not be initialized at this access. | test.cpp:26:6:26:8 | foo | foo |
|
||||
| test.cpp:46:6:46:8 | foo | The variable $@ may not be initialized at this access. | test.cpp:42:6:42:8 | foo | foo |
|
||||
| test.cpp:55:7:55:9 | foo | The variable $@ may not be initialized at this access. | test.cpp:50:6:50:8 | foo | foo |
|
||||
| test.cpp:67:7:67:9 | foo | The variable $@ may not be initialized at this access. | test.cpp:61:6:61:8 | foo | foo |
|
||||
| test.cpp:92:6:92:8 | foo | The variable $@ may not be initialized at this access. | test.cpp:82:6:82:8 | foo | foo |
|
||||
| test.cpp:113:6:113:8 | foo | The variable $@ may not be initialized at this access. | test.cpp:111:6:111:8 | foo | foo |
|
||||
| test.cpp:132:9:132:9 | j | The variable $@ may not be initialized at this access. | test.cpp:126:6:126:6 | j | j |
|
||||
| test.cpp:219:3:219:3 | x | The variable $@ may not be initialized at this access. | test.cpp:218:7:218:7 | x | x |
|
||||
| test.cpp:243:13:243:13 | i | The variable $@ may not be initialized at this access. | test.cpp:241:6:241:6 | i | i |
|
||||
| test.cpp:329:9:329:11 | val | The variable $@ may not be initialized at this access. | test.cpp:321:6:321:8 | val | val |
|
||||
| test.cpp:336:10:336:10 | a | The variable $@ may not be initialized at this access. | test.cpp:333:7:333:7 | a | a |
|
||||
| test.cpp:369:10:369:10 | a | The variable $@ may not be initialized at this access. | test.cpp:358:7:358:7 | a | a |
|
||||
| test.cpp:378:9:378:11 | val | The variable $@ may not be initialized at this access. | test.cpp:359:6:359:8 | val | val |
|
||||
|
||||
@@ -27,7 +27,7 @@ void test4(bool b) {
|
||||
if (b) {
|
||||
foo = 1;
|
||||
}
|
||||
use(foo); // BAD [NOT DETECTED]
|
||||
use(foo); // BAD
|
||||
}
|
||||
|
||||
void test5() {
|
||||
@@ -43,7 +43,7 @@ void test5(int count) {
|
||||
for (int i = 0; i < count; i++) {
|
||||
foo = i;
|
||||
}
|
||||
use(foo); // BAD [NOT DETECTED]
|
||||
use(foo); // BAD
|
||||
}
|
||||
|
||||
void test6(bool b) {
|
||||
@@ -52,7 +52,7 @@ void test6(bool b) {
|
||||
foo = 42;
|
||||
}
|
||||
if (b) {
|
||||
use(foo); // GOOD
|
||||
use(foo); // GOOD (REPORTED, FP)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -64,7 +64,7 @@ void test7(bool b) {
|
||||
set = true;
|
||||
}
|
||||
if (set) {
|
||||
use(foo); // GOOD
|
||||
use(foo); // GOOD (REPORTED, FP)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -89,7 +89,7 @@ void test9(int count) {
|
||||
if (!set) {
|
||||
foo = 42;
|
||||
}
|
||||
use(foo); // GOOD
|
||||
use(foo); // GOOD (REPORTED, FP)
|
||||
}
|
||||
|
||||
void test10() {
|
||||
@@ -129,7 +129,7 @@ int absWrong(int i) {
|
||||
} else if (i < 0) {
|
||||
j = -i;
|
||||
}
|
||||
return j; // wrong: j may not be initialized before use [NOT DETECTED]
|
||||
return j; // wrong: j may not be initialized before use
|
||||
}
|
||||
|
||||
// Example from qhelp
|
||||
@@ -326,7 +326,7 @@ int test28() {
|
||||
a = false;
|
||||
c = false;
|
||||
}
|
||||
return val; // GOOD
|
||||
return val; // GOOD [FALSE POSITIVE]
|
||||
}
|
||||
|
||||
int test29() {
|
||||
@@ -472,64 +472,4 @@ void test44() {
|
||||
int y = 1;
|
||||
|
||||
void(x + y); // BAD
|
||||
}
|
||||
|
||||
enum class State { StateA, StateB, StateC };
|
||||
|
||||
int exhaustive_switch(State s) {
|
||||
int y;
|
||||
switch(s) {
|
||||
case State::StateA:
|
||||
y = 1;
|
||||
break;
|
||||
case State::StateB:
|
||||
y = 2;
|
||||
break;
|
||||
case State::StateC:
|
||||
y = 3;
|
||||
break;
|
||||
}
|
||||
return y; // GOOD (y is always initialized)
|
||||
}
|
||||
|
||||
int exhaustive_switch_2(State s) {
|
||||
int y;
|
||||
switch(s) {
|
||||
case State::StateA:
|
||||
y = 1;
|
||||
break;
|
||||
default:
|
||||
y = 2;
|
||||
break;
|
||||
}
|
||||
return y; // GOOD (y is always initialized)
|
||||
}
|
||||
|
||||
int non_exhaustive_switch(State s) {
|
||||
int y;
|
||||
switch(s) {
|
||||
case State::StateA:
|
||||
y = 1;
|
||||
break;
|
||||
case State::StateB:
|
||||
y = 2;
|
||||
break;
|
||||
}
|
||||
return y; // BAD [NOT DETECTED] (y is not initialized when s = StateC)
|
||||
}
|
||||
|
||||
int non_exhaustive_switch_2(State s) {
|
||||
int y;
|
||||
switch(s) {
|
||||
case State::StateA:
|
||||
y = 1;
|
||||
break;
|
||||
case State::StateB:
|
||||
y = 2;
|
||||
break;
|
||||
}
|
||||
if(s != State::StateC) {
|
||||
return y; // GOOD (y is not initialized when s = StateC, but if s = StateC we won't reach this point)
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -82,8 +82,8 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
|
||||
? new[] { options.SolutionFile }
|
||||
: allNonBinaryFiles.SelectFileNamesByExtension(".sln");
|
||||
var dllPaths = options.DllDirs.Count == 0
|
||||
? allFiles.SelectFileNamesByExtension(".dll").ToHashSet()
|
||||
: options.DllDirs.Select(Path.GetFullPath).ToHashSet();
|
||||
? allFiles.SelectFileNamesByExtension(".dll").ToList()
|
||||
: options.DllDirs.Select(Path.GetFullPath).ToList();
|
||||
|
||||
if (options.UseNuGet)
|
||||
{
|
||||
@@ -107,7 +107,7 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
|
||||
.RequiredPaths
|
||||
.Select(d => Path.Combine(packageDirectory.DirInfo.FullName, d))
|
||||
.ToList();
|
||||
dllPaths.UnionWith(paths);
|
||||
dllPaths.AddRange(paths);
|
||||
|
||||
LogAllUnusedPackages(dependencies);
|
||||
DownloadMissingPackages(allNonBinaryFiles, dllPaths);
|
||||
@@ -205,7 +205,7 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
|
||||
}
|
||||
}
|
||||
|
||||
private void AddNetFrameworkDlls(ISet<string> dllPaths)
|
||||
private void AddNetFrameworkDlls(List<string> dllPaths)
|
||||
{
|
||||
// Multiple dotnet framework packages could be present.
|
||||
// The order of the packages is important, we're adding the first one that is present in the nuget cache.
|
||||
@@ -218,19 +218,13 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
|
||||
};
|
||||
|
||||
var frameworkPath = packagesInPrioOrder
|
||||
.Select((s, index) => (Index: index, Path: GetPackageDirectory(s)))
|
||||
.FirstOrDefault(pair => pair.Path is not null);
|
||||
.Select(GetPackageDirectory)
|
||||
.FirstOrDefault(dir => dir is not null);
|
||||
|
||||
if (frameworkPath.Path is not null)
|
||||
if (frameworkPath is not null)
|
||||
{
|
||||
dllPaths.Add(frameworkPath.Path);
|
||||
progressMonitor.LogInfo($"Found .NET Core/Framework DLLs in NuGet packages at {frameworkPath.Path}. Not adding installation directory.");
|
||||
|
||||
for (var i = frameworkPath.Index + 1; i < packagesInPrioOrder.Length; i++)
|
||||
{
|
||||
RemoveNugetPackageReference(packagesInPrioOrder[i], dllPaths);
|
||||
}
|
||||
|
||||
dllPaths.Add(frameworkPath);
|
||||
progressMonitor.LogInfo("Found .NET Core/Framework DLLs in NuGet packages. Not adding installation directory.");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -255,29 +249,7 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
|
||||
dllPaths.Add(runtimeLocation);
|
||||
}
|
||||
|
||||
private void RemoveNugetPackageReference(string packagePrefix, ISet<string> dllPaths)
|
||||
{
|
||||
if (!options.UseNuGet)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var packageFolder = packageDirectory.DirInfo.FullName.ToLowerInvariant();
|
||||
if (packageFolder == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var packagePathPrefix = Path.Combine(packageFolder, packagePrefix.ToLowerInvariant());
|
||||
var toRemove = dllPaths.Where(s => s.ToLowerInvariant().StartsWith(packagePathPrefix));
|
||||
foreach (var path in toRemove)
|
||||
{
|
||||
dllPaths.Remove(path);
|
||||
progressMonitor.RemovedReference(path);
|
||||
}
|
||||
}
|
||||
|
||||
private void AddAspNetCoreFrameworkDlls(ISet<string> dllPaths)
|
||||
private void AddAspNetCoreFrameworkDlls(List<string> dllPaths)
|
||||
{
|
||||
if (!fileContent.IsNewProjectStructureUsed || !fileContent.UseAspNetCoreDlls)
|
||||
{
|
||||
@@ -297,7 +269,7 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
|
||||
}
|
||||
}
|
||||
|
||||
private void AddMicrosoftWindowsDesktopDlls(ISet<string> dllPaths)
|
||||
private void AddMicrosoftWindowsDesktopDlls(List<string> dllPaths)
|
||||
{
|
||||
if (GetPackageDirectory("microsoft.windowsdesktop.app.ref") is string windowsDesktopApp)
|
||||
{
|
||||
@@ -656,7 +628,7 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
|
||||
assets = assetFiles;
|
||||
}
|
||||
|
||||
private void DownloadMissingPackages(List<FileInfo> allFiles, ISet<string> dllPaths)
|
||||
private void DownloadMissingPackages(List<FileInfo> allFiles, List<string> dllPaths)
|
||||
{
|
||||
var nugetConfigs = allFiles.SelectFileNamesByName("nuget.config").ToArray();
|
||||
string? nugetConfig = null;
|
||||
|
||||
@@ -91,7 +91,7 @@ namespace Semmle.Extraction.CSharp.Entities
|
||||
// The current argument is not named
|
||||
// so the previous ones were also not named
|
||||
// so the child index matches the parameter index.
|
||||
isParamsParameter = Symbol.AttributeConstructor?.Parameters[childIndex].IsParams == true;
|
||||
isParamsParameter = Symbol?.AttributeConstructor?.Parameters[childIndex].IsParams == true;
|
||||
argSyntax = ctorArguments[childIndex];
|
||||
}
|
||||
|
||||
|
||||
@@ -22,7 +22,7 @@ namespace Semmle.Extraction.CSharp.Entities
|
||||
Position.Span.Start.Line + 1, Position.Span.Start.Character + 1,
|
||||
Position.Span.End.Line + 1, Position.Span.End.Character);
|
||||
|
||||
var mapped = Symbol.GetMappedLineSpan();
|
||||
var mapped = Symbol!.GetMappedLineSpan();
|
||||
if (mapped.HasMappedPath && mapped.IsValid)
|
||||
{
|
||||
var mappedLoc = Create(Context, Location.Create(mapped.Path, default, mapped.Span));
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.IO;
|
||||
using Microsoft.CodeAnalysis;
|
||||
|
||||
@@ -31,7 +30,6 @@ namespace Semmle.Extraction
|
||||
/// <typeparam name="TSymbol">The type of the symbol.</typeparam>
|
||||
public abstract class CachedEntity<TSymbol> : CachedEntity where TSymbol : notnull
|
||||
{
|
||||
[NotNull]
|
||||
public TSymbol Symbol { get; }
|
||||
|
||||
protected CachedEntity(Context context, TSymbol symbol) : base(context)
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net7.0</TargetFramework>
|
||||
<Nullable>enable</Nullable>
|
||||
|
||||
<IsPackable>false</IsPackable>
|
||||
</PropertyGroup>
|
||||
|
||||
@@ -13,9 +14,4 @@
|
||||
<PackageReference Include="coverlet.collector" Version="3.2.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<Target Name="DeleteBinObjFolders" BeforeTargets="Clean">
|
||||
<RemoveDir Directories=".\bin" />
|
||||
<RemoveDir Directories=".\obj" />
|
||||
<RemoveDir Directories=".\myout" />
|
||||
</Target>
|
||||
</Project>
|
||||
|
||||
@@ -8,8 +8,3 @@ check_diagnostics()
|
||||
# Explicitly build and then run tests.
|
||||
run_codeql_database_create(['dotnet clean', 'rm -rf test-db', 'dotnet build -o myout', 'dotnet test myout/dotnet_test.dll'], test_db="test2-db", lang="csharp")
|
||||
check_diagnostics(test_db="test2-db")
|
||||
|
||||
thisDir = os.path.abspath(os.getcwd())
|
||||
# Explicit build and then run tests using the absolute path.
|
||||
run_codeql_database_create(['dotnet clean', 'rm -rf test2-db', 'dotnet build -o myout', f'dotnet test {thisDir}/myout/dotnet_test.dll'], test_db="test3-db", lang="csharp")
|
||||
check_diagnostics(test_db="test3-db")
|
||||
@@ -1,163 +0,0 @@
|
||||
| /microsoft.netcore.app.ref/7.0.2/ref/net7.0/Microsoft.CSharp.dll |
|
||||
| /microsoft.netcore.app.ref/7.0.2/ref/net7.0/Microsoft.VisualBasic.Core.dll |
|
||||
| /microsoft.netcore.app.ref/7.0.2/ref/net7.0/Microsoft.VisualBasic.dll |
|
||||
| /microsoft.netcore.app.ref/7.0.2/ref/net7.0/Microsoft.Win32.Primitives.dll |
|
||||
| /microsoft.netcore.app.ref/7.0.2/ref/net7.0/Microsoft.Win32.Registry.dll |
|
||||
| /microsoft.netcore.app.ref/7.0.2/ref/net7.0/System.AppContext.dll |
|
||||
| /microsoft.netcore.app.ref/7.0.2/ref/net7.0/System.Buffers.dll |
|
||||
| /microsoft.netcore.app.ref/7.0.2/ref/net7.0/System.Collections.Concurrent.dll |
|
||||
| /microsoft.netcore.app.ref/7.0.2/ref/net7.0/System.Collections.Immutable.dll |
|
||||
| /microsoft.netcore.app.ref/7.0.2/ref/net7.0/System.Collections.NonGeneric.dll |
|
||||
| /microsoft.netcore.app.ref/7.0.2/ref/net7.0/System.Collections.Specialized.dll |
|
||||
| /microsoft.netcore.app.ref/7.0.2/ref/net7.0/System.Collections.dll |
|
||||
| /microsoft.netcore.app.ref/7.0.2/ref/net7.0/System.ComponentModel.Annotations.dll |
|
||||
| /microsoft.netcore.app.ref/7.0.2/ref/net7.0/System.ComponentModel.DataAnnotations.dll |
|
||||
| /microsoft.netcore.app.ref/7.0.2/ref/net7.0/System.ComponentModel.EventBasedAsync.dll |
|
||||
| /microsoft.netcore.app.ref/7.0.2/ref/net7.0/System.ComponentModel.Primitives.dll |
|
||||
| /microsoft.netcore.app.ref/7.0.2/ref/net7.0/System.ComponentModel.TypeConverter.dll |
|
||||
| /microsoft.netcore.app.ref/7.0.2/ref/net7.0/System.ComponentModel.dll |
|
||||
| /microsoft.netcore.app.ref/7.0.2/ref/net7.0/System.Configuration.dll |
|
||||
| /microsoft.netcore.app.ref/7.0.2/ref/net7.0/System.Console.dll |
|
||||
| /microsoft.netcore.app.ref/7.0.2/ref/net7.0/System.Core.dll |
|
||||
| /microsoft.netcore.app.ref/7.0.2/ref/net7.0/System.Data.Common.dll |
|
||||
| /microsoft.netcore.app.ref/7.0.2/ref/net7.0/System.Data.DataSetExtensions.dll |
|
||||
| /microsoft.netcore.app.ref/7.0.2/ref/net7.0/System.Data.dll |
|
||||
| /microsoft.netcore.app.ref/7.0.2/ref/net7.0/System.Diagnostics.Contracts.dll |
|
||||
| /microsoft.netcore.app.ref/7.0.2/ref/net7.0/System.Diagnostics.Debug.dll |
|
||||
| /microsoft.netcore.app.ref/7.0.2/ref/net7.0/System.Diagnostics.DiagnosticSource.dll |
|
||||
| /microsoft.netcore.app.ref/7.0.2/ref/net7.0/System.Diagnostics.FileVersionInfo.dll |
|
||||
| /microsoft.netcore.app.ref/7.0.2/ref/net7.0/System.Diagnostics.Process.dll |
|
||||
| /microsoft.netcore.app.ref/7.0.2/ref/net7.0/System.Diagnostics.StackTrace.dll |
|
||||
| /microsoft.netcore.app.ref/7.0.2/ref/net7.0/System.Diagnostics.TextWriterTraceListener.dll |
|
||||
| /microsoft.netcore.app.ref/7.0.2/ref/net7.0/System.Diagnostics.Tools.dll |
|
||||
| /microsoft.netcore.app.ref/7.0.2/ref/net7.0/System.Diagnostics.TraceSource.dll |
|
||||
| /microsoft.netcore.app.ref/7.0.2/ref/net7.0/System.Diagnostics.Tracing.dll |
|
||||
| /microsoft.netcore.app.ref/7.0.2/ref/net7.0/System.Drawing.Primitives.dll |
|
||||
| /microsoft.netcore.app.ref/7.0.2/ref/net7.0/System.Drawing.dll |
|
||||
| /microsoft.netcore.app.ref/7.0.2/ref/net7.0/System.Dynamic.Runtime.dll |
|
||||
| /microsoft.netcore.app.ref/7.0.2/ref/net7.0/System.Formats.Asn1.dll |
|
||||
| /microsoft.netcore.app.ref/7.0.2/ref/net7.0/System.Formats.Tar.dll |
|
||||
| /microsoft.netcore.app.ref/7.0.2/ref/net7.0/System.Globalization.Calendars.dll |
|
||||
| /microsoft.netcore.app.ref/7.0.2/ref/net7.0/System.Globalization.Extensions.dll |
|
||||
| /microsoft.netcore.app.ref/7.0.2/ref/net7.0/System.Globalization.dll |
|
||||
| /microsoft.netcore.app.ref/7.0.2/ref/net7.0/System.IO.Compression.Brotli.dll |
|
||||
| /microsoft.netcore.app.ref/7.0.2/ref/net7.0/System.IO.Compression.FileSystem.dll |
|
||||
| /microsoft.netcore.app.ref/7.0.2/ref/net7.0/System.IO.Compression.ZipFile.dll |
|
||||
| /microsoft.netcore.app.ref/7.0.2/ref/net7.0/System.IO.Compression.dll |
|
||||
| /microsoft.netcore.app.ref/7.0.2/ref/net7.0/System.IO.FileSystem.AccessControl.dll |
|
||||
| /microsoft.netcore.app.ref/7.0.2/ref/net7.0/System.IO.FileSystem.DriveInfo.dll |
|
||||
| /microsoft.netcore.app.ref/7.0.2/ref/net7.0/System.IO.FileSystem.Primitives.dll |
|
||||
| /microsoft.netcore.app.ref/7.0.2/ref/net7.0/System.IO.FileSystem.Watcher.dll |
|
||||
| /microsoft.netcore.app.ref/7.0.2/ref/net7.0/System.IO.FileSystem.dll |
|
||||
| /microsoft.netcore.app.ref/7.0.2/ref/net7.0/System.IO.IsolatedStorage.dll |
|
||||
| /microsoft.netcore.app.ref/7.0.2/ref/net7.0/System.IO.MemoryMappedFiles.dll |
|
||||
| /microsoft.netcore.app.ref/7.0.2/ref/net7.0/System.IO.Pipes.AccessControl.dll |
|
||||
| /microsoft.netcore.app.ref/7.0.2/ref/net7.0/System.IO.Pipes.dll |
|
||||
| /microsoft.netcore.app.ref/7.0.2/ref/net7.0/System.IO.UnmanagedMemoryStream.dll |
|
||||
| /microsoft.netcore.app.ref/7.0.2/ref/net7.0/System.IO.dll |
|
||||
| /microsoft.netcore.app.ref/7.0.2/ref/net7.0/System.Linq.Expressions.dll |
|
||||
| /microsoft.netcore.app.ref/7.0.2/ref/net7.0/System.Linq.Parallel.dll |
|
||||
| /microsoft.netcore.app.ref/7.0.2/ref/net7.0/System.Linq.Queryable.dll |
|
||||
| /microsoft.netcore.app.ref/7.0.2/ref/net7.0/System.Linq.dll |
|
||||
| /microsoft.netcore.app.ref/7.0.2/ref/net7.0/System.Memory.dll |
|
||||
| /microsoft.netcore.app.ref/7.0.2/ref/net7.0/System.Net.Http.Json.dll |
|
||||
| /microsoft.netcore.app.ref/7.0.2/ref/net7.0/System.Net.Http.dll |
|
||||
| /microsoft.netcore.app.ref/7.0.2/ref/net7.0/System.Net.HttpListener.dll |
|
||||
| /microsoft.netcore.app.ref/7.0.2/ref/net7.0/System.Net.Mail.dll |
|
||||
| /microsoft.netcore.app.ref/7.0.2/ref/net7.0/System.Net.NameResolution.dll |
|
||||
| /microsoft.netcore.app.ref/7.0.2/ref/net7.0/System.Net.NetworkInformation.dll |
|
||||
| /microsoft.netcore.app.ref/7.0.2/ref/net7.0/System.Net.Ping.dll |
|
||||
| /microsoft.netcore.app.ref/7.0.2/ref/net7.0/System.Net.Primitives.dll |
|
||||
| /microsoft.netcore.app.ref/7.0.2/ref/net7.0/System.Net.Quic.dll |
|
||||
| /microsoft.netcore.app.ref/7.0.2/ref/net7.0/System.Net.Requests.dll |
|
||||
| /microsoft.netcore.app.ref/7.0.2/ref/net7.0/System.Net.Security.dll |
|
||||
| /microsoft.netcore.app.ref/7.0.2/ref/net7.0/System.Net.ServicePoint.dll |
|
||||
| /microsoft.netcore.app.ref/7.0.2/ref/net7.0/System.Net.Sockets.dll |
|
||||
| /microsoft.netcore.app.ref/7.0.2/ref/net7.0/System.Net.WebClient.dll |
|
||||
| /microsoft.netcore.app.ref/7.0.2/ref/net7.0/System.Net.WebHeaderCollection.dll |
|
||||
| /microsoft.netcore.app.ref/7.0.2/ref/net7.0/System.Net.WebProxy.dll |
|
||||
| /microsoft.netcore.app.ref/7.0.2/ref/net7.0/System.Net.WebSockets.Client.dll |
|
||||
| /microsoft.netcore.app.ref/7.0.2/ref/net7.0/System.Net.WebSockets.dll |
|
||||
| /microsoft.netcore.app.ref/7.0.2/ref/net7.0/System.Net.dll |
|
||||
| /microsoft.netcore.app.ref/7.0.2/ref/net7.0/System.Numerics.Vectors.dll |
|
||||
| /microsoft.netcore.app.ref/7.0.2/ref/net7.0/System.Numerics.dll |
|
||||
| /microsoft.netcore.app.ref/7.0.2/ref/net7.0/System.ObjectModel.dll |
|
||||
| /microsoft.netcore.app.ref/7.0.2/ref/net7.0/System.Reflection.DispatchProxy.dll |
|
||||
| /microsoft.netcore.app.ref/7.0.2/ref/net7.0/System.Reflection.Emit.ILGeneration.dll |
|
||||
| /microsoft.netcore.app.ref/7.0.2/ref/net7.0/System.Reflection.Emit.Lightweight.dll |
|
||||
| /microsoft.netcore.app.ref/7.0.2/ref/net7.0/System.Reflection.Emit.dll |
|
||||
| /microsoft.netcore.app.ref/7.0.2/ref/net7.0/System.Reflection.Extensions.dll |
|
||||
| /microsoft.netcore.app.ref/7.0.2/ref/net7.0/System.Reflection.Metadata.dll |
|
||||
| /microsoft.netcore.app.ref/7.0.2/ref/net7.0/System.Reflection.Primitives.dll |
|
||||
| /microsoft.netcore.app.ref/7.0.2/ref/net7.0/System.Reflection.TypeExtensions.dll |
|
||||
| /microsoft.netcore.app.ref/7.0.2/ref/net7.0/System.Reflection.dll |
|
||||
| /microsoft.netcore.app.ref/7.0.2/ref/net7.0/System.Resources.Reader.dll |
|
||||
| /microsoft.netcore.app.ref/7.0.2/ref/net7.0/System.Resources.ResourceManager.dll |
|
||||
| /microsoft.netcore.app.ref/7.0.2/ref/net7.0/System.Resources.Writer.dll |
|
||||
| /microsoft.netcore.app.ref/7.0.2/ref/net7.0/System.Runtime.CompilerServices.Unsafe.dll |
|
||||
| /microsoft.netcore.app.ref/7.0.2/ref/net7.0/System.Runtime.CompilerServices.VisualC.dll |
|
||||
| /microsoft.netcore.app.ref/7.0.2/ref/net7.0/System.Runtime.Extensions.dll |
|
||||
| /microsoft.netcore.app.ref/7.0.2/ref/net7.0/System.Runtime.Handles.dll |
|
||||
| /microsoft.netcore.app.ref/7.0.2/ref/net7.0/System.Runtime.InteropServices.JavaScript.dll |
|
||||
| /microsoft.netcore.app.ref/7.0.2/ref/net7.0/System.Runtime.InteropServices.RuntimeInformation.dll |
|
||||
| /microsoft.netcore.app.ref/7.0.2/ref/net7.0/System.Runtime.InteropServices.dll |
|
||||
| /microsoft.netcore.app.ref/7.0.2/ref/net7.0/System.Runtime.Intrinsics.dll |
|
||||
| /microsoft.netcore.app.ref/7.0.2/ref/net7.0/System.Runtime.Loader.dll |
|
||||
| /microsoft.netcore.app.ref/7.0.2/ref/net7.0/System.Runtime.Numerics.dll |
|
||||
| /microsoft.netcore.app.ref/7.0.2/ref/net7.0/System.Runtime.Serialization.Formatters.dll |
|
||||
| /microsoft.netcore.app.ref/7.0.2/ref/net7.0/System.Runtime.Serialization.Json.dll |
|
||||
| /microsoft.netcore.app.ref/7.0.2/ref/net7.0/System.Runtime.Serialization.Primitives.dll |
|
||||
| /microsoft.netcore.app.ref/7.0.2/ref/net7.0/System.Runtime.Serialization.Xml.dll |
|
||||
| /microsoft.netcore.app.ref/7.0.2/ref/net7.0/System.Runtime.Serialization.dll |
|
||||
| /microsoft.netcore.app.ref/7.0.2/ref/net7.0/System.Runtime.dll |
|
||||
| /microsoft.netcore.app.ref/7.0.2/ref/net7.0/System.Security.AccessControl.dll |
|
||||
| /microsoft.netcore.app.ref/7.0.2/ref/net7.0/System.Security.Claims.dll |
|
||||
| /microsoft.netcore.app.ref/7.0.2/ref/net7.0/System.Security.Cryptography.Algorithms.dll |
|
||||
| /microsoft.netcore.app.ref/7.0.2/ref/net7.0/System.Security.Cryptography.Cng.dll |
|
||||
| /microsoft.netcore.app.ref/7.0.2/ref/net7.0/System.Security.Cryptography.Csp.dll |
|
||||
| /microsoft.netcore.app.ref/7.0.2/ref/net7.0/System.Security.Cryptography.Encoding.dll |
|
||||
| /microsoft.netcore.app.ref/7.0.2/ref/net7.0/System.Security.Cryptography.OpenSsl.dll |
|
||||
| /microsoft.netcore.app.ref/7.0.2/ref/net7.0/System.Security.Cryptography.Primitives.dll |
|
||||
| /microsoft.netcore.app.ref/7.0.2/ref/net7.0/System.Security.Cryptography.X509Certificates.dll |
|
||||
| /microsoft.netcore.app.ref/7.0.2/ref/net7.0/System.Security.Cryptography.dll |
|
||||
| /microsoft.netcore.app.ref/7.0.2/ref/net7.0/System.Security.Principal.Windows.dll |
|
||||
| /microsoft.netcore.app.ref/7.0.2/ref/net7.0/System.Security.Principal.dll |
|
||||
| /microsoft.netcore.app.ref/7.0.2/ref/net7.0/System.Security.SecureString.dll |
|
||||
| /microsoft.netcore.app.ref/7.0.2/ref/net7.0/System.Security.dll |
|
||||
| /microsoft.netcore.app.ref/7.0.2/ref/net7.0/System.ServiceModel.Web.dll |
|
||||
| /microsoft.netcore.app.ref/7.0.2/ref/net7.0/System.ServiceProcess.dll |
|
||||
| /microsoft.netcore.app.ref/7.0.2/ref/net7.0/System.Text.Encoding.CodePages.dll |
|
||||
| /microsoft.netcore.app.ref/7.0.2/ref/net7.0/System.Text.Encoding.Extensions.dll |
|
||||
| /microsoft.netcore.app.ref/7.0.2/ref/net7.0/System.Text.Encoding.dll |
|
||||
| /microsoft.netcore.app.ref/7.0.2/ref/net7.0/System.Text.Encodings.Web.dll |
|
||||
| /microsoft.netcore.app.ref/7.0.2/ref/net7.0/System.Text.Json.dll |
|
||||
| /microsoft.netcore.app.ref/7.0.2/ref/net7.0/System.Text.RegularExpressions.dll |
|
||||
| /microsoft.netcore.app.ref/7.0.2/ref/net7.0/System.Threading.Channels.dll |
|
||||
| /microsoft.netcore.app.ref/7.0.2/ref/net7.0/System.Threading.Overlapped.dll |
|
||||
| /microsoft.netcore.app.ref/7.0.2/ref/net7.0/System.Threading.Tasks.Dataflow.dll |
|
||||
| /microsoft.netcore.app.ref/7.0.2/ref/net7.0/System.Threading.Tasks.Extensions.dll |
|
||||
| /microsoft.netcore.app.ref/7.0.2/ref/net7.0/System.Threading.Tasks.Parallel.dll |
|
||||
| /microsoft.netcore.app.ref/7.0.2/ref/net7.0/System.Threading.Tasks.dll |
|
||||
| /microsoft.netcore.app.ref/7.0.2/ref/net7.0/System.Threading.Thread.dll |
|
||||
| /microsoft.netcore.app.ref/7.0.2/ref/net7.0/System.Threading.ThreadPool.dll |
|
||||
| /microsoft.netcore.app.ref/7.0.2/ref/net7.0/System.Threading.Timer.dll |
|
||||
| /microsoft.netcore.app.ref/7.0.2/ref/net7.0/System.Threading.dll |
|
||||
| /microsoft.netcore.app.ref/7.0.2/ref/net7.0/System.Transactions.Local.dll |
|
||||
| /microsoft.netcore.app.ref/7.0.2/ref/net7.0/System.Transactions.dll |
|
||||
| /microsoft.netcore.app.ref/7.0.2/ref/net7.0/System.ValueTuple.dll |
|
||||
| /microsoft.netcore.app.ref/7.0.2/ref/net7.0/System.Web.HttpUtility.dll |
|
||||
| /microsoft.netcore.app.ref/7.0.2/ref/net7.0/System.Web.dll |
|
||||
| /microsoft.netcore.app.ref/7.0.2/ref/net7.0/System.Windows.dll |
|
||||
| /microsoft.netcore.app.ref/7.0.2/ref/net7.0/System.Xml.Linq.dll |
|
||||
| /microsoft.netcore.app.ref/7.0.2/ref/net7.0/System.Xml.ReaderWriter.dll |
|
||||
| /microsoft.netcore.app.ref/7.0.2/ref/net7.0/System.Xml.Serialization.dll |
|
||||
| /microsoft.netcore.app.ref/7.0.2/ref/net7.0/System.Xml.XDocument.dll |
|
||||
| /microsoft.netcore.app.ref/7.0.2/ref/net7.0/System.Xml.XPath.XDocument.dll |
|
||||
| /microsoft.netcore.app.ref/7.0.2/ref/net7.0/System.Xml.XPath.dll |
|
||||
| /microsoft.netcore.app.ref/7.0.2/ref/net7.0/System.Xml.XmlDocument.dll |
|
||||
| /microsoft.netcore.app.ref/7.0.2/ref/net7.0/System.Xml.XmlSerializer.dll |
|
||||
| /microsoft.netcore.app.ref/7.0.2/ref/net7.0/System.Xml.dll |
|
||||
| /microsoft.netcore.app.ref/7.0.2/ref/net7.0/System.dll |
|
||||
| /microsoft.netcore.app.ref/7.0.2/ref/net7.0/WindowsBase.dll |
|
||||
| /microsoft.netcore.app.ref/7.0.2/ref/net7.0/mscorlib.dll |
|
||||
| /microsoft.netcore.app.ref/7.0.2/ref/net7.0/netstandard.dll |
|
||||
@@ -1,15 +0,0 @@
|
||||
import csharp
|
||||
|
||||
private string getPath(Assembly a) {
|
||||
not a.getCompilation().getOutputAssembly() = a and
|
||||
exists(string s | s = a.getFile().getAbsolutePath() |
|
||||
result =
|
||||
s.substring(s.indexOf("GitHub/packages/") + "GitHub/packages/".length() + 16, s.length())
|
||||
or
|
||||
result = s and
|
||||
not exists(s.indexOf("GitHub/packages/"))
|
||||
)
|
||||
}
|
||||
|
||||
from Assembly a
|
||||
select getPath(a)
|
||||
@@ -1 +0,0 @@
|
||||
var dummy = "dummy";
|
||||
@@ -1,10 +0,0 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net48</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
</Project>
|
||||
@@ -1,10 +0,0 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net7.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
</Project>
|
||||
@@ -1,3 +0,0 @@
|
||||
from create_database_utils import *
|
||||
|
||||
run_codeql_database_create([], lang="csharp", extra_args=["--extractor-option=buildless=true", "--extractor-option=cil=false"])
|
||||
@@ -80,15 +80,16 @@ function RegisterExtractorPack(id)
|
||||
end
|
||||
end
|
||||
|
||||
-- for `dotnet test`, we should not append `-p:UseSharedCompilation=false` to the command line
|
||||
-- if an `exe` or `dll` is passed as an argument as the call is forwarded to vstest.
|
||||
if testMatch and (arg:match('%.exe$') or arg:match('%.dll')) then
|
||||
match = false
|
||||
break
|
||||
end
|
||||
|
||||
-- we have found a sub-command, ignore all strings that look like sub-command names from now on
|
||||
inSubCommandPosition = false
|
||||
end
|
||||
-- for `dotnet test`, we should not append `-p:UseSharedCompilation=false` to the command line
|
||||
-- if an `exe` or `dll` is passed as an argument as the call is forwarded to vstest.
|
||||
if testMatch and (arg:match('%.exe$') or arg:match('%.dll')) then
|
||||
match = false
|
||||
break
|
||||
end
|
||||
-- if we see a separator to `dotnet run`, inject just prior to the existing separator
|
||||
if arg == '--' then
|
||||
dotnetRunNeedsSeparator = false
|
||||
|
||||
@@ -39,7 +39,7 @@ Changing the labels of query history items
|
||||
|
||||
The query history **Format** setting controls how the extension lists queries in the query history. By default, each item has a label with the following format::
|
||||
|
||||
%q on %d - %s %r [%t]
|
||||
%q on %d - %s, %r result count [%t]
|
||||
|
||||
- ``%q`` is the query name
|
||||
- ``%d`` is the database name
|
||||
@@ -107,19 +107,6 @@ You can also edit the items shown in the Variant Analysis Repositories panel by
|
||||
|
||||
You can change the items shown in the panel or add new items by directly editing this file.
|
||||
|
||||
Configuring settings for adding databases
|
||||
------------------------------------------------
|
||||
|
||||
To automatically add database source folders to your workspace, you can enable the **Adding Databases > Add Database Source to Workspace** setting.
|
||||
|
||||
This setting is disabled by default. You may want to enable the setting if you regularly browse the source code of databases, for example to view the abstract syntax tree of the code. For more information, see ":ref:`Exploring the structure of your source code <exploring-the-structure-of-your-source-code>`."
|
||||
|
||||
.. pull-quote:: Note
|
||||
|
||||
If you are in a single-folder workspace, adding database source folders will cause the workspace to reload as a multi-root workspace. This may cause query history and database lists to be reset.
|
||||
|
||||
Before enabling this setting, we recommend that you save your workspace as a multi-root workspace. For more information, see "`Multi-root Workspaces <https://code.visualstudio.com/docs/editor/multi-root-workspaces>`__" in the Visual Studio Code help.
|
||||
|
||||
Configuring settings for testing queries locally
|
||||
------------------------------------------------
|
||||
|
||||
|
||||
@@ -18,26 +18,20 @@ CodeQL for Visual Studio Code contains an AST viewer. The viewer consists of a g
|
||||
Viewing the abstract syntax tree of a source file
|
||||
--------------------------------------------------
|
||||
|
||||
1. Open the CodeQL Databases view and right-click the database that you want to explore. Click **Add Database Source to Workspace**.
|
||||
|
||||
.. image:: ../images/codeql-for-visual-studio-code/add-database-source-to-workspace.png
|
||||
:width: 350
|
||||
:alt: Add database source to workspace
|
||||
|
||||
2. Navigate to a CodeQL database's source file in the File Explorer.
|
||||
1. Open a source file from a CodeQL database. For example, you can navigate to a source file in the File Explorer.
|
||||
|
||||
.. image:: ../images/codeql-for-visual-studio-code/open-source-file.png
|
||||
:width: 350
|
||||
:alt: Open a source file
|
||||
|
||||
3. Run **CodeQL: View AST** from the Command Palette. This runs a CodeQL query (usually called ``printAST.ql``) over the active file, which may take a few seconds.
|
||||
2. Run **CodeQL: View AST** from the Command Palette. This runs a CodeQL query (usually called ``printAST.ql``) over the active file, which may take a few seconds.
|
||||
|
||||
.. pull-quote:: Note
|
||||
|
||||
If you don't have an appropriate ``printAST.ql`` query in your workspace, the **CodeQL: View AST** command won't work. To fix this, you can update your copy of the `CodeQL <https://github.com/github/codeql>`__ repository from ``main``. If you do this, you may need to upgrade your databases. Also, query caches may be discarded and your next query runs could be slower.
|
||||
|
||||
4. Once the query has run, the AST viewer displays the structure of the source file.
|
||||
5. To see the nested structure, click the arrows and expand the nodes.
|
||||
3. Once the query has run, the AST viewer displays the structure of the source file.
|
||||
4. To see the nested structure, click the arrows and expand the nodes.
|
||||
|
||||
.. image:: ../images/codeql-for-visual-studio-code/explore-ast.png
|
||||
:alt: Explore the AST
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 73 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 80 KiB After Width: | Height: | Size: 82 KiB |
@@ -47,7 +47,7 @@ endif
|
||||
qhelp-to-markdown:
|
||||
scripts/qhelp-to-markdown.sh ql/src "$(QHELP_OUT_DIR)"
|
||||
|
||||
tools: tools-codeql tools/tokenizer.jar
|
||||
tools: $(addsuffix $(EXE),$(addprefix tools/bin/,$(BINARIES))) tools/tokenizer.jar
|
||||
|
||||
.PHONY: $(addsuffix $(EXE),$(addprefix tools/bin/,$(BINARIES)))
|
||||
$(addsuffix $(EXE),$(addprefix tools/bin/,$(BINARIES))):
|
||||
@@ -67,10 +67,7 @@ tools-osx64: $(addprefix tools/osx64/,$(BINARIES))
|
||||
|
||||
.PHONY: $(addprefix tools/osx64/,$(BINARIES))
|
||||
$(addprefix tools/osx64/,$(BINARIES)):
|
||||
GOOS=darwin GOARCH=amd64 go build -C extractor -mod=vendor -o ../$@.amd64 ./cli/$(@F)
|
||||
GOOS=darwin GOARCH=arm64 go build -C extractor -mod=vendor -o ../$@.arm64 ./cli/$(@F)
|
||||
lipo -create $@.amd64 $@.arm64 -output $@
|
||||
rm $@.amd64 $@.arm64
|
||||
GOOS=darwin GOARCH=amd64 go build -C extractor -mod=vendor -o ../$@ ./cli/$(@F)
|
||||
|
||||
tools-win64: $(addsuffix .exe,$(addprefix tools/win64/,$(BINARIES)))
|
||||
|
||||
|
||||
@@ -211,11 +211,7 @@ module Sem implements Semantic {
|
||||
|
||||
class BasicBlock = J::BasicBlock;
|
||||
|
||||
BasicBlock getABasicBlockSuccessor(BasicBlock bb) { result = bb.getABBSuccessor() }
|
||||
|
||||
final private class FinalGuard = GL::Guard;
|
||||
|
||||
class Guard extends FinalGuard {
|
||||
class Guard extends GL::Guard {
|
||||
Expr asExpr() { result = this }
|
||||
}
|
||||
|
||||
@@ -223,6 +219,14 @@ module Sem implements Semantic {
|
||||
GL::implies_v2(g1, b1, g2, b2)
|
||||
}
|
||||
|
||||
predicate guardDirectlyControlsSsaRead(Guard guard, SsaReadPosition controlled, boolean testIsTrue) {
|
||||
RU::guardDirectlyControlsSsaRead(guard, controlled, testIsTrue)
|
||||
}
|
||||
|
||||
predicate guardControlsSsaRead(Guard guard, SsaReadPosition controlled, boolean testIsTrue) {
|
||||
RU::guardControlsSsaRead(guard, controlled, testIsTrue)
|
||||
}
|
||||
|
||||
class Type = J::Type;
|
||||
|
||||
class IntegerType extends J::IntegralType {
|
||||
@@ -257,10 +261,6 @@ module Sem implements Semantic {
|
||||
|
||||
class SsaReadPositionPhiInputEdge extends SsaReadPosition instanceof SsaReadPos::SsaReadPositionPhiInputEdge
|
||||
{
|
||||
BasicBlock getOrigBlock() { result = super.getOrigBlock() }
|
||||
|
||||
BasicBlock getPhiBlock() { result = super.getPhiBlock() }
|
||||
|
||||
predicate phiInput(SsaPhiNode phi, SsaVariable inp) { super.phiInput(phi, inp) }
|
||||
}
|
||||
|
||||
@@ -268,6 +268,10 @@ module Sem implements Semantic {
|
||||
BasicBlock getBlock() { result = super.getBlock() }
|
||||
}
|
||||
|
||||
predicate backEdge(SsaPhiNode phi, SsaVariable inp, SsaReadPositionPhiInputEdge edge) {
|
||||
RU::backEdge(phi, inp, edge)
|
||||
}
|
||||
|
||||
predicate conversionCannotOverflow = safeCast/2;
|
||||
}
|
||||
|
||||
|
||||
@@ -7,18 +7,6 @@ private import SSA
|
||||
private import semmle.code.java.controlflow.internal.GuardsLogic
|
||||
private import semmle.code.java.dataflow.internal.rangeanalysis.SsaReadPositionCommon
|
||||
private import semmle.code.java.Constants
|
||||
private import semmle.code.java.dataflow.RangeAnalysis
|
||||
private import codeql.rangeanalysis.internal.RangeUtils
|
||||
|
||||
private module U = MakeUtils<Sem, IntDelta>;
|
||||
|
||||
private predicate backEdge = U::backEdge/3;
|
||||
|
||||
predicate ssaRead = U::ssaRead/2;
|
||||
|
||||
predicate guardDirectlyControlsSsaRead = U::guardDirectlyControlsSsaRead/3;
|
||||
|
||||
predicate guardControlsSsaRead = U::guardControlsSsaRead/3;
|
||||
|
||||
/**
|
||||
* Holds if `v` is an input to `phi` that is not along a back edge, and the
|
||||
@@ -157,6 +145,79 @@ class ConstantStringExpr extends Expr {
|
||||
string getStringValue() { constantStringExpr(this, result) }
|
||||
}
|
||||
|
||||
bindingset[f]
|
||||
private predicate okInt(float f) { -2.pow(31) <= f and f <= 2.pow(31) - 1 }
|
||||
|
||||
/**
|
||||
* Gets an expression that equals `v - d`.
|
||||
*/
|
||||
Expr ssaRead(SsaVariable v, int delta) {
|
||||
result = v.getAUse() and delta = 0
|
||||
or
|
||||
exists(int d1, ConstantIntegerExpr c |
|
||||
result.(AddExpr).hasOperands(ssaRead(v, d1), c) and
|
||||
delta = d1 - c.getIntValue() and
|
||||
okInt(d1.(float) - c.getIntValue().(float))
|
||||
)
|
||||
or
|
||||
exists(SubExpr sub, int d1, ConstantIntegerExpr c |
|
||||
result = sub and
|
||||
sub.getLeftOperand() = ssaRead(v, d1) and
|
||||
sub.getRightOperand() = c and
|
||||
delta = d1 + c.getIntValue() and
|
||||
okInt(d1.(float) + c.getIntValue().(float))
|
||||
)
|
||||
or
|
||||
v.(SsaExplicitUpdate).getDefiningExpr().(PreIncExpr) = result and delta = 0
|
||||
or
|
||||
v.(SsaExplicitUpdate).getDefiningExpr().(PreDecExpr) = result and delta = 0
|
||||
or
|
||||
v.(SsaExplicitUpdate).getDefiningExpr().(PostIncExpr) = result and delta = 1 // x++ === ++x - 1
|
||||
or
|
||||
v.(SsaExplicitUpdate).getDefiningExpr().(PostDecExpr) = result and delta = -1 // x-- === --x + 1
|
||||
or
|
||||
v.(SsaExplicitUpdate).getDefiningExpr().(Assignment) = result and delta = 0
|
||||
or
|
||||
result.(AssignExpr).getSource() = ssaRead(v, delta)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `inp` is an input to `phi` along a back edge.
|
||||
*/
|
||||
predicate backEdge(SsaPhiNode phi, SsaVariable inp, SsaReadPositionPhiInputEdge edge) {
|
||||
edge.phiInput(phi, inp) and
|
||||
// Conservatively assume that every edge is a back edge if we don't have dominance information.
|
||||
(
|
||||
phi.getBasicBlock().bbDominates(edge.getOrigBlock()) or
|
||||
not hasDominanceInformation(edge.getOrigBlock())
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `guard` directly controls the position `controlled` with the
|
||||
* value `testIsTrue`.
|
||||
*/
|
||||
predicate guardDirectlyControlsSsaRead(Guard guard, SsaReadPosition controlled, boolean testIsTrue) {
|
||||
guard.directlyControls(controlled.(SsaReadPositionBlock).getBlock(), testIsTrue)
|
||||
or
|
||||
exists(SsaReadPositionPhiInputEdge controlledEdge | controlledEdge = controlled |
|
||||
guard.directlyControls(controlledEdge.getOrigBlock(), testIsTrue) or
|
||||
guard.hasBranchEdge(controlledEdge.getOrigBlock(), controlledEdge.getPhiBlock(), testIsTrue)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `guard` controls the position `controlled` with the value `testIsTrue`.
|
||||
*/
|
||||
predicate guardControlsSsaRead(Guard guard, SsaReadPosition controlled, boolean testIsTrue) {
|
||||
guardDirectlyControlsSsaRead(guard, controlled, testIsTrue)
|
||||
or
|
||||
exists(Guard guard0, boolean testIsTrue0 |
|
||||
implies_v2(guard0, testIsTrue0, guard, testIsTrue) and
|
||||
guardControlsSsaRead(guard0, controlled, testIsTrue0)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a condition that tests whether `v` equals `e + delta`.
|
||||
*
|
||||
|
||||
@@ -1,10 +0,0 @@
|
||||
/** Provides definitions for working with the JMS library. */
|
||||
|
||||
import java
|
||||
|
||||
/** The method `ObjectMessage.getObject`. */
|
||||
class ObjectMessageGetObjectMethod extends Method {
|
||||
ObjectMessageGetObjectMethod() {
|
||||
this.hasQualifiedName(["javax", "jakarta"] + ".jms", "ObjectMessage", "getObject")
|
||||
}
|
||||
}
|
||||
@@ -4,7 +4,6 @@
|
||||
|
||||
import semmle.code.java.dataflow.FlowSources
|
||||
private import semmle.code.java.dataflow.TaintTracking2
|
||||
private import semmle.code.java.dispatch.VirtualDispatch
|
||||
private import semmle.code.java.frameworks.Kryo
|
||||
private import semmle.code.java.frameworks.XStream
|
||||
private import semmle.code.java.frameworks.SnakeYaml
|
||||
@@ -16,7 +15,6 @@ private import semmle.code.java.frameworks.HessianBurlap
|
||||
private import semmle.code.java.frameworks.Castor
|
||||
private import semmle.code.java.frameworks.Jackson
|
||||
private import semmle.code.java.frameworks.Jabsorb
|
||||
private import semmle.code.java.frameworks.Jms
|
||||
private import semmle.code.java.frameworks.JoddJson
|
||||
private import semmle.code.java.frameworks.Flexjson
|
||||
private import semmle.code.java.frameworks.google.Gson
|
||||
@@ -226,11 +224,6 @@ predicate unsafeDeserialization(MethodCall ma, Expr sink) {
|
||||
m instanceof GsonDeserializeMethod and
|
||||
sink = ma.getArgument(0) and
|
||||
UnsafeTypeFlow::flowToExpr(ma.getArgument(1))
|
||||
or
|
||||
m.getASourceOverriddenMethod*() instanceof ObjectMessageGetObjectMethod and
|
||||
sink = ma.getQualifier().getUnderlyingExpr() and
|
||||
// If we can see an implementation, we trust dataflow to find a path to the other sinks instead
|
||||
not exists(viableCallable(ma))
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@ may have unforeseen effects, such as the execution of arbitrary code.
|
||||
<p>
|
||||
There are many different serialization frameworks. This query currently
|
||||
supports Kryo, XmlDecoder, XStream, SnakeYaml, JYaml, JsonIO, YAMLBeans, HessianBurlap, Castor, Burlap,
|
||||
Jackson, Jabsorb, Jodd JSON, Flexjson, Gson, JMS, and Java IO serialization through
|
||||
Jackson, Jabsorb, Jodd JSON, Flexjson, Gson and Java IO serialization through
|
||||
<code>ObjectInputStream</code>/<code>ObjectOutputStream</code>.
|
||||
</p>
|
||||
</overview>
|
||||
@@ -74,12 +74,6 @@ Recommendations specific to particular frameworks supported by this query:
|
||||
<li><b>Recommendation</b>: Do not use with untrusted user input.</li>
|
||||
</ul>
|
||||
<p></p>
|
||||
<p><b>ObjectMesssage</b> - <code>Java EE/Jakarta EE</code></p>
|
||||
<ul>
|
||||
<li><b>Secure by Default</b>: Depends on the JMS implementation.</li>
|
||||
<li><b>Recommendation</b>: Do not use with untrusted user input.</li>
|
||||
</ul>
|
||||
<p></p>
|
||||
</recommendation>
|
||||
|
||||
<example>
|
||||
@@ -164,10 +158,6 @@ RCE in Flexjson:
|
||||
Android Intent deserialization vulnerabilities with GSON parser:
|
||||
<a href="https://blog.oversecured.com/Exploiting-memory-corruption-vulnerabilities-on-Android/#insecure-use-of-json-parsers">Insecure use of JSON parsers</a>.
|
||||
</li>
|
||||
<li>
|
||||
Research by Matthias Kaiser:
|
||||
<a href="https://www.blackhat.com/docs/us-16/materials/us-16-Kaiser-Pwning-Your-Java-Messaging-With-Deserialization-Vulnerabilities.pdf">Pwning Your Java Messaging With Deserialization Vulnerabilities</a>.
|
||||
</li>
|
||||
</references>
|
||||
|
||||
</qhelp>
|
||||
|
||||
@@ -1,4 +0,0 @@
|
||||
---
|
||||
category: minorAnalysis
|
||||
---
|
||||
* The query `java/unsafe-deserialization` has been improved to detect insecure calls to `ObjectMessage.getObject` in JMS.
|
||||
@@ -1,9 +0,0 @@
|
||||
import javax.jms.Message;
|
||||
import javax.jms.MessageListener;
|
||||
import javax.jms.ObjectMessage;
|
||||
|
||||
public class ObjectMessageTest implements MessageListener {
|
||||
public void onMessage(Message message) {
|
||||
((ObjectMessage) message).getObject(); // $ unsafeDeserialization
|
||||
}
|
||||
}
|
||||
@@ -1 +1 @@
|
||||
//semmle-extractor-options: --javac-args -cp ${testdir}/../../../stubs/snakeyaml-1.21:${testdir}/../../../stubs/xstream-1.4.10:${testdir}/../../../stubs/kryo-4.0.2:${testdir}/../../../stubs/jsr311-api-1.1.1:${testdir}/../../../stubs/fastjson-1.2.74:${testdir}/../../../stubs/springframework-5.3.8:${testdir}/../../../stubs/servlet-api-2.4:${testdir}/../../../stubs/jyaml-1.3:${testdir}/../../../stubs/json-io-4.10.0:${testdir}/../../../stubs/yamlbeans-1.09:${testdir}/../../../stubs/hessian-4.0.38:${testdir}/../../../stubs/castor-1.4.1:${testdir}/../../../stubs/jackson-databind-2.12:${testdir}/../../../stubs/jackson-core-2.12:${testdir}/../../../stubs/jabsorb-1.3.2:${testdir}/../../../stubs/json-java-20210307:${testdir}/../../../stubs/joddjson-6.0.3:${testdir}/../../../stubs/flexjson-2.1:${testdir}/../../../stubs/gson-2.8.6:${testdir}/../../../stubs/google-android-9.0.0:${testdir}/../../../stubs/serialkiller-4.0.0:${testdir}/../../../stubs/jms-api-1
|
||||
//semmle-extractor-options: --javac-args -cp ${testdir}/../../../stubs/snakeyaml-1.21:${testdir}/../../../stubs/xstream-1.4.10:${testdir}/../../../stubs/kryo-4.0.2:${testdir}/../../../stubs/jsr311-api-1.1.1:${testdir}/../../../stubs/fastjson-1.2.74:${testdir}/../../../stubs/springframework-5.3.8:${testdir}/../../../stubs/servlet-api-2.4:${testdir}/../../../stubs/jyaml-1.3:${testdir}/../../../stubs/json-io-4.10.0:${testdir}/../../../stubs/yamlbeans-1.09:${testdir}/../../../stubs/hessian-4.0.38:${testdir}/../../../stubs/castor-1.4.1:${testdir}/../../../stubs/jackson-databind-2.12:${testdir}/../../../stubs/jackson-core-2.12:${testdir}/../../../stubs/jabsorb-1.3.2:${testdir}/../../../stubs/json-java-20210307:${testdir}/../../../stubs/joddjson-6.0.3:${testdir}/../../../stubs/flexjson-2.1:${testdir}/../../../stubs/gson-2.8.6:${testdir}/../../../stubs/google-android-9.0.0:${testdir}/../../../stubs/serialkiller-4.0.0
|
||||
|
||||
@@ -892,15 +892,10 @@ protected DependencyInstallationResult preparePackagesAndDependencies(Set<Path>
|
||||
// For named packages, find the main file.
|
||||
String name = packageJson.getName();
|
||||
if (name != null) {
|
||||
Path entryPoint = null;
|
||||
try {
|
||||
entryPoint = guessPackageMainFile(path, packageJson, FileType.TYPESCRIPT.getExtensions());
|
||||
if (entryPoint == null) {
|
||||
// Try a TypeScript-recognized JS extension instead
|
||||
entryPoint = guessPackageMainFile(path, packageJson, Arrays.asList(".js", ".jsx"));
|
||||
}
|
||||
} catch (InvalidPathException ignore) {
|
||||
// can happen if the `main:` field is invalid. E.g. on Windows a path like `dist/*.js` will crash.
|
||||
Path entryPoint = guessPackageMainFile(path, packageJson, FileType.TYPESCRIPT.getExtensions());
|
||||
if (entryPoint == null) {
|
||||
// Try a TypeScript-recognized JS extension instead
|
||||
entryPoint = guessPackageMainFile(path, packageJson, Arrays.asList(".js", ".jsx"));
|
||||
}
|
||||
if (entryPoint != null) {
|
||||
System.out.println(relativePath + ": Main file set to " + sourceRoot.relativize(entryPoint));
|
||||
|
||||
@@ -51,7 +51,6 @@ private module AsmCrypto {
|
||||
private class Apply extends CryptographicOperation::Range instanceof DataFlow::CallNode {
|
||||
DataFlow::Node input;
|
||||
CryptographicAlgorithm algorithm; // non-functional
|
||||
DataFlow::PropRead algorithmSelection;
|
||||
private string algorithmName;
|
||||
private string methodName;
|
||||
|
||||
@@ -69,14 +68,11 @@ private module AsmCrypto {
|
||||
exists(DataFlow::SourceNode asmCrypto |
|
||||
asmCrypto = DataFlow::globalVarRef("asmCrypto") and
|
||||
algorithm.matchesName(algorithmName) and
|
||||
algorithmSelection = asmCrypto.getAPropertyRead(algorithmName) and
|
||||
this = algorithmSelection.getAMemberCall(methodName) and
|
||||
this = asmCrypto.getAPropertyRead(algorithmName).getAMemberCall(methodName) and
|
||||
input = this.getArgument(0)
|
||||
)
|
||||
}
|
||||
|
||||
override DataFlow::Node getInitialization() { result = algorithmSelection }
|
||||
|
||||
override DataFlow::Node getAnInput() { result = input }
|
||||
|
||||
override CryptographicAlgorithm getAlgorithm() { result = algorithm }
|
||||
@@ -107,7 +103,6 @@ private module BrowserIdCrypto {
|
||||
|
||||
private class Apply extends CryptographicOperation::Range instanceof DataFlow::MethodCallNode {
|
||||
CryptographicAlgorithm algorithm; // non-functional
|
||||
DataFlow::CallNode keygen;
|
||||
|
||||
Apply() {
|
||||
/*
|
||||
@@ -127,7 +122,8 @@ private module BrowserIdCrypto {
|
||||
*/
|
||||
|
||||
exists(
|
||||
DataFlow::SourceNode mod, DataFlow::Node algorithmNameNode, DataFlow::FunctionNode callback
|
||||
DataFlow::SourceNode mod, DataFlow::Node algorithmNameNode, DataFlow::CallNode keygen,
|
||||
DataFlow::FunctionNode callback
|
||||
|
|
||||
mod = DataFlow::moduleImport("browserid-crypto") and
|
||||
keygen = mod.getAMemberCall("generateKeypair") and
|
||||
@@ -138,8 +134,6 @@ private module BrowserIdCrypto {
|
||||
)
|
||||
}
|
||||
|
||||
override DataFlow::Node getInitialization() { result = keygen }
|
||||
|
||||
override DataFlow::Node getAnInput() { result = super.getArgument(0) }
|
||||
|
||||
override CryptographicAlgorithm getAlgorithm() { result = algorithm }
|
||||
@@ -245,8 +239,6 @@ private module NodeJSCrypto {
|
||||
|
||||
Apply() { this = instantiation.getAMethodCall(any(string m | m = "update" or m = "write")) }
|
||||
|
||||
override DataFlow::Node getInitialization() { result = instantiation }
|
||||
|
||||
override DataFlow::Node getAnInput() { result = super.getArgument(0) }
|
||||
|
||||
override CryptographicAlgorithm getAlgorithm() { result = instantiation.getAlgorithm() }
|
||||
@@ -332,9 +324,7 @@ private module CryptoJS {
|
||||
)
|
||||
}
|
||||
|
||||
private API::CallNode getEncryptionApplication(
|
||||
API::Node input, API::Node algorithmNode, CryptographicAlgorithm algorithm
|
||||
) {
|
||||
private API::CallNode getEncryptionApplication(API::Node input, CryptographicAlgorithm algorithm) {
|
||||
/*
|
||||
* ```
|
||||
* var CryptoJS = require("crypto-js");
|
||||
@@ -348,14 +338,11 @@ private module CryptoJS {
|
||||
* Also matches where `CryptoJS.<algorithmName>` has been replaced by `require("crypto-js/<algorithmName>")`
|
||||
*/
|
||||
|
||||
algorithmNode = getAlgorithmNode(algorithm) and
|
||||
result = algorithmNode.getMember("encrypt").getACall() and
|
||||
result = getAlgorithmNode(algorithm).getMember("encrypt").getACall() and
|
||||
input = result.getParameter(0)
|
||||
}
|
||||
|
||||
private API::CallNode getDirectApplication(
|
||||
API::Node input, API::Node algorithmNode, CryptographicAlgorithm algorithm
|
||||
) {
|
||||
private API::CallNode getDirectApplication(API::Node input, CryptographicAlgorithm algorithm) {
|
||||
/*
|
||||
* ```
|
||||
* var CryptoJS = require("crypto-js");
|
||||
@@ -370,8 +357,7 @@ private module CryptoJS {
|
||||
* Also matches where `CryptoJS.<algorithmName>` has been replaced by `require("crypto-js/<algorithmName>")`
|
||||
*/
|
||||
|
||||
algorithmNode = getAlgorithmNode(algorithm) and
|
||||
result = algorithmNode.getACall() and
|
||||
result = getAlgorithmNode(algorithm).getACall() and
|
||||
input = result.getParameter(0)
|
||||
}
|
||||
|
||||
@@ -403,23 +389,18 @@ private module CryptoJS {
|
||||
private class Apply extends CryptographicOperation::Range instanceof API::CallNode {
|
||||
API::Node input;
|
||||
CryptographicAlgorithm algorithm; // non-functional
|
||||
DataFlow::Node instantiation;
|
||||
|
||||
Apply() {
|
||||
exists(API::Node algorithmNode |
|
||||
this = getEncryptionApplication(input, algorithmNode, algorithm)
|
||||
or
|
||||
this = getDirectApplication(input, algorithmNode, algorithm)
|
||||
|
|
||||
instantiation = algorithmNode.asSource()
|
||||
)
|
||||
this = getEncryptionApplication(input, algorithm)
|
||||
or
|
||||
this = getUpdatedApplication(input, instantiation) and
|
||||
algorithm = instantiation.(InstantiatedAlgorithm).getAlgorithm()
|
||||
this = getDirectApplication(input, algorithm)
|
||||
or
|
||||
exists(InstantiatedAlgorithm instantiation |
|
||||
this = getUpdatedApplication(input, instantiation) and
|
||||
algorithm = instantiation.getAlgorithm()
|
||||
)
|
||||
}
|
||||
|
||||
override DataFlow::Node getInitialization() { result = instantiation }
|
||||
|
||||
override DataFlow::Node getAnInput() { result = input.asSink() }
|
||||
|
||||
override CryptographicAlgorithm getAlgorithm() { result = algorithm }
|
||||
@@ -523,8 +504,6 @@ private module TweetNaCl {
|
||||
)
|
||||
}
|
||||
|
||||
override DataFlow::Node getInitialization() { result = this }
|
||||
|
||||
override DataFlow::Node getAnInput() { result = input }
|
||||
|
||||
override CryptographicAlgorithm getAlgorithm() { result = algorithm }
|
||||
@@ -560,7 +539,6 @@ private module HashJs {
|
||||
private class Apply extends CryptographicOperation::Range instanceof DataFlow::CallNode {
|
||||
DataFlow::Node input;
|
||||
CryptographicAlgorithm algorithm; // non-functional
|
||||
DataFlow::CallNode init;
|
||||
|
||||
Apply() {
|
||||
/*
|
||||
@@ -576,13 +554,10 @@ private module HashJs {
|
||||
* Also matches where `hash.<algorithmName>()` has been replaced by a more specific require a la `require("hash.js/lib/hash/sha/512")`
|
||||
*/
|
||||
|
||||
init = getAlgorithmNode(algorithm) and
|
||||
this = init.getAMemberCall("update") and
|
||||
this = getAlgorithmNode(algorithm).getAMemberCall("update") and
|
||||
input = super.getArgument(0)
|
||||
}
|
||||
|
||||
override DataFlow::Node getInitialization() { result = init }
|
||||
|
||||
override DataFlow::Node getAnInput() { result = input }
|
||||
|
||||
override CryptographicAlgorithm getAlgorithm() { result = algorithm }
|
||||
@@ -678,8 +653,6 @@ private module Forge {
|
||||
algorithm = cipher.getAlgorithm()
|
||||
}
|
||||
|
||||
override DataFlow::Node getInitialization() { result = cipher }
|
||||
|
||||
override DataFlow::Node getAnInput() { result = input }
|
||||
|
||||
override CryptographicAlgorithm getAlgorithm() { result = algorithm }
|
||||
@@ -742,8 +715,6 @@ private module Md5 {
|
||||
super.getArgument(0) = input
|
||||
}
|
||||
|
||||
override DataFlow::Node getInitialization() { result = this }
|
||||
|
||||
override DataFlow::Node getAnInput() { result = input }
|
||||
|
||||
override CryptographicAlgorithm getAlgorithm() { result = algorithm }
|
||||
@@ -760,18 +731,17 @@ private module Bcrypt {
|
||||
private class Apply extends CryptographicOperation::Range instanceof DataFlow::CallNode {
|
||||
DataFlow::Node input;
|
||||
CryptographicAlgorithm algorithm;
|
||||
API::Node init;
|
||||
|
||||
Apply() {
|
||||
// `require("bcrypt").hash(password);` with minor naming variations
|
||||
algorithm.matchesName("BCRYPT") and
|
||||
init = API::moduleImport(["bcrypt", "bcryptjs", "bcrypt-nodejs"]) and
|
||||
this = init.getMember(["hash", "hashSync"]).getACall() and
|
||||
this =
|
||||
API::moduleImport(["bcrypt", "bcryptjs", "bcrypt-nodejs"])
|
||||
.getMember(["hash", "hashSync"])
|
||||
.getACall() and
|
||||
super.getArgument(0) = input
|
||||
}
|
||||
|
||||
override DataFlow::Node getInitialization() { result = init.asSource() }
|
||||
|
||||
override DataFlow::Node getAnInput() { result = input }
|
||||
|
||||
override CryptographicAlgorithm getAlgorithm() { result = algorithm }
|
||||
@@ -799,8 +769,6 @@ private module Hasha {
|
||||
)
|
||||
}
|
||||
|
||||
override DataFlow::Node getInitialization() { result = this }
|
||||
|
||||
override DataFlow::Node getAnInput() { result = input }
|
||||
|
||||
override CryptographicAlgorithm getAlgorithm() { result = algorithm }
|
||||
|
||||
@@ -40,9 +40,6 @@ module Cryptography {
|
||||
/** Gets the algorithm used, if it matches a known `CryptographicAlgorithm`. */
|
||||
CryptographicAlgorithm getAlgorithm() { result = super.getAlgorithm() }
|
||||
|
||||
/** Gets the data-flow node where the cryptographic algorithm used in this operation is configured. */
|
||||
DataFlow::Node getInitialization() { result = super.getInitialization() }
|
||||
|
||||
/** Gets an input the algorithm is used on, for example the plain text input to be encrypted. */
|
||||
DataFlow::Node getAnInput() { result = super.getAnInput() }
|
||||
|
||||
@@ -68,9 +65,6 @@ module Cryptography {
|
||||
* extend `CryptographicOperation` instead.
|
||||
*/
|
||||
abstract class Range extends DataFlow::Node {
|
||||
/** Gets the data-flow node where the cryptographic algorithm used in this operation is configured. */
|
||||
abstract DataFlow::Node getInitialization();
|
||||
|
||||
/** Gets the algorithm used, if it matches a known `CryptographicAlgorithm`. */
|
||||
abstract CryptographicAlgorithm getAlgorithm();
|
||||
|
||||
|
||||
@@ -19,10 +19,7 @@ module BrokenCryptoAlgorithm {
|
||||
/**
|
||||
* A data flow sink for sensitive information in broken or weak cryptographic algorithms.
|
||||
*/
|
||||
abstract class Sink extends DataFlow::Node {
|
||||
/** Gets the data-flow node where the cryptographic algorithm used in this operation is configured. */
|
||||
abstract DataFlow::Node getInitialization();
|
||||
}
|
||||
abstract class Sink extends DataFlow::Node { }
|
||||
|
||||
/**
|
||||
* A sanitizer for sensitive information in broken or weak cryptographic algorithms.
|
||||
@@ -41,17 +38,15 @@ module BrokenCryptoAlgorithm {
|
||||
* An expression used by a broken or weak cryptographic algorithm.
|
||||
*/
|
||||
class WeakCryptographicOperationSink extends Sink {
|
||||
CryptographicOperation application;
|
||||
|
||||
WeakCryptographicOperationSink() {
|
||||
(
|
||||
application.getAlgorithm().isWeak()
|
||||
or
|
||||
application.getBlockMode().isWeak()
|
||||
) and
|
||||
this = application.getAnInput()
|
||||
exists(CryptographicOperation application |
|
||||
(
|
||||
application.getAlgorithm().isWeak()
|
||||
or
|
||||
application.getBlockMode().isWeak()
|
||||
) and
|
||||
this = application.getAnInput()
|
||||
)
|
||||
}
|
||||
|
||||
override DataFlow::Node getInitialization() { result = application.getInitialization() }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,14 +16,9 @@ import semmle.javascript.security.dataflow.BrokenCryptoAlgorithmQuery
|
||||
import semmle.javascript.security.SensitiveActions
|
||||
import DataFlow::PathGraph
|
||||
|
||||
from
|
||||
Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink, Source sourceNode,
|
||||
Sink sinkNode
|
||||
from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink
|
||||
where
|
||||
cfg.hasFlowPath(source, sink) and
|
||||
sourceNode = source.getNode() and
|
||||
sinkNode = sink.getNode() and
|
||||
not sourceNode instanceof CleartextPasswordExpr // flagged by js/insufficient-password-hash
|
||||
select sinkNode, source, sink, "$@ depends on $@.", sinkNode.getInitialization(),
|
||||
"A broken or weak cryptographic algorithm", sourceNode,
|
||||
"sensitive data from " + sourceNode.describe()
|
||||
not source.getNode() instanceof CleartextPasswordExpr // flagged by js/insufficient-password-hash
|
||||
select sink.getNode(), source, sink, "A broken or weak cryptographic algorithm depends on $@.",
|
||||
source.getNode(), "sensitive data from " + source.getNode().(Source).describe()
|
||||
|
||||
@@ -26,8 +26,8 @@ edges
|
||||
| tst.js:19:17:19:24 | password | tst.js:19:17:19:24 | password |
|
||||
| tst.js:22:21:22:30 | secretText | tst.js:22:21:22:30 | secretText |
|
||||
#select
|
||||
| tst.js:11:17:11:26 | secretText | tst.js:3:18:3:24 | trusted | tst.js:11:17:11:26 | secretText | $@ depends on $@. | tst.js:5:19:5:49 | crypto. ... ', key) | A broken or weak cryptographic algorithm | tst.js:3:18:3:24 | trusted | sensitive data from an access to trusted |
|
||||
| tst.js:11:17:11:26 | secretText | tst.js:11:17:11:26 | secretText | tst.js:11:17:11:26 | secretText | $@ depends on $@. | tst.js:5:19:5:49 | crypto. ... ', key) | A broken or weak cryptographic algorithm | tst.js:11:17:11:26 | secretText | sensitive data from an access to secretText |
|
||||
| tst.js:17:17:17:25 | o.trusted | tst.js:17:17:17:25 | o.trusted | tst.js:17:17:17:25 | o.trusted | $@ depends on $@. | tst.js:5:19:5:49 | crypto. ... ', key) | A broken or weak cryptographic algorithm | tst.js:17:17:17:25 | o.trusted | sensitive data from an access to trusted |
|
||||
| tst.js:22:21:22:30 | secretText | tst.js:3:18:3:24 | trusted | tst.js:22:21:22:30 | secretText | $@ depends on $@. | tst.js:21:22:21:60 | crypto. ... ', key) | A broken or weak cryptographic algorithm | tst.js:3:18:3:24 | trusted | sensitive data from an access to trusted |
|
||||
| tst.js:22:21:22:30 | secretText | tst.js:22:21:22:30 | secretText | tst.js:22:21:22:30 | secretText | $@ depends on $@. | tst.js:21:22:21:60 | crypto. ... ', key) | A broken or weak cryptographic algorithm | tst.js:22:21:22:30 | secretText | sensitive data from an access to secretText |
|
||||
| tst.js:11:17:11:26 | secretText | tst.js:3:18:3:24 | trusted | tst.js:11:17:11:26 | secretText | A broken or weak cryptographic algorithm depends on $@. | tst.js:3:18:3:24 | trusted | sensitive data from an access to trusted |
|
||||
| tst.js:11:17:11:26 | secretText | tst.js:11:17:11:26 | secretText | tst.js:11:17:11:26 | secretText | A broken or weak cryptographic algorithm depends on $@. | tst.js:11:17:11:26 | secretText | sensitive data from an access to secretText |
|
||||
| tst.js:17:17:17:25 | o.trusted | tst.js:17:17:17:25 | o.trusted | tst.js:17:17:17:25 | o.trusted | A broken or weak cryptographic algorithm depends on $@. | tst.js:17:17:17:25 | o.trusted | sensitive data from an access to trusted |
|
||||
| tst.js:22:21:22:30 | secretText | tst.js:3:18:3:24 | trusted | tst.js:22:21:22:30 | secretText | A broken or weak cryptographic algorithm depends on $@. | tst.js:3:18:3:24 | trusted | sensitive data from an access to trusted |
|
||||
| tst.js:22:21:22:30 | secretText | tst.js:22:21:22:30 | secretText | tst.js:22:21:22:30 | secretText | A broken or weak cryptographic algorithm depends on $@. | tst.js:22:21:22:30 | secretText | sensitive data from an access to secretText |
|
||||
|
||||
@@ -1352,10 +1352,7 @@ abstract class DataFlowCall extends TDataFlowCall {
|
||||
abstract ControlFlowNode getNode();
|
||||
|
||||
/** Gets the enclosing callable of this call. */
|
||||
DataFlowCallable getEnclosingCallable() { result = getCallableScope(this.getScope()) }
|
||||
|
||||
/** Gets the scope of this node, if any. */
|
||||
abstract Scope getScope();
|
||||
abstract DataFlowCallable getEnclosingCallable();
|
||||
|
||||
/** Gets the location of this dataflow call. */
|
||||
abstract Location getLocation();
|
||||
@@ -1403,7 +1400,7 @@ class NormalCall extends ExtractedDataFlowCall, TNormalCall {
|
||||
|
||||
override ControlFlowNode getNode() { result = call }
|
||||
|
||||
override Scope getScope() { result = call.getScope() }
|
||||
override DataFlowCallable getEnclosingCallable() { result.getScope() = call.getScope() }
|
||||
|
||||
override DataFlowCallable getCallable() { result.(DataFlowFunction).getScope() = target }
|
||||
|
||||
@@ -1453,7 +1450,7 @@ class PotentialLibraryCall extends ExtractedDataFlowCall, TPotentialLibraryCall
|
||||
|
||||
override ControlFlowNode getNode() { result = call }
|
||||
|
||||
override Scope getScope() { result = call.getScope() }
|
||||
override DataFlowCallable getEnclosingCallable() { result.getScope() = call.getScope() }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1477,8 +1474,6 @@ class SummaryCall extends DataFlowCall, TSummaryCall {
|
||||
|
||||
override DataFlowCallable getEnclosingCallable() { result.asLibraryCallable() = c }
|
||||
|
||||
override Scope getScope() { none() }
|
||||
|
||||
override DataFlowCallable getCallable() { none() }
|
||||
|
||||
override ArgumentNode getArgument(ArgumentPosition apos) { none() }
|
||||
|
||||
@@ -1044,11 +1044,3 @@ class ContentApprox = Unit;
|
||||
/** Gets an approximated value for content `c`. */
|
||||
pragma[inline]
|
||||
ContentApprox getContentApprox(Content c) { any() }
|
||||
|
||||
/** Helper for `.getEnclosingCallable`. */
|
||||
DataFlowCallable getCallableScope(Scope s) {
|
||||
result.getScope() = s
|
||||
or
|
||||
not exists(DataFlowCallable c | c.getScope() = s) and
|
||||
result = getCallableScope(s.getEnclosingScope())
|
||||
}
|
||||
|
||||
@@ -117,6 +117,14 @@ newtype TNode =
|
||||
exists(ParameterPosition ppos | ppos.isKeyword(_) | exists(callable.getParameter(ppos)))
|
||||
}
|
||||
|
||||
/** Helper for `Node::getEnclosingCallable`. */
|
||||
private DataFlowCallable getCallableScope(Scope s) {
|
||||
result.getScope() = s
|
||||
or
|
||||
not exists(DataFlowCallable c | c.getScope() = s) and
|
||||
result = getCallableScope(s.getEnclosingScope())
|
||||
}
|
||||
|
||||
private import semmle.python.internal.CachedStages
|
||||
|
||||
/**
|
||||
|
||||
@@ -128,8 +128,6 @@ private module CryptodomeModel {
|
||||
this = newCall.getReturn().getMember(methodName).getACall()
|
||||
}
|
||||
|
||||
override DataFlow::Node getInitialization() { result = newCall }
|
||||
|
||||
override Cryptography::CryptographicAlgorithm getAlgorithm() { result.matchesName(cipherName) }
|
||||
|
||||
override DataFlow::Node getAnInput() {
|
||||
@@ -183,23 +181,21 @@ private module CryptodomeModel {
|
||||
class CryptodomeGenericSignatureOperation extends Cryptography::CryptographicOperation::Range,
|
||||
DataFlow::CallCfgNode
|
||||
{
|
||||
API::CallNode newCall;
|
||||
string methodName;
|
||||
string signatureName;
|
||||
|
||||
CryptodomeGenericSignatureOperation() {
|
||||
methodName in ["sign", "verify"] and
|
||||
newCall =
|
||||
this =
|
||||
API::moduleImport(["Crypto", "Cryptodome"])
|
||||
.getMember("Signature")
|
||||
.getMember(signatureName)
|
||||
.getMember("new")
|
||||
.getACall() and
|
||||
this = newCall.getReturn().getMember(methodName).getACall()
|
||||
.getReturn()
|
||||
.getMember(methodName)
|
||||
.getACall()
|
||||
}
|
||||
|
||||
override DataFlow::Node getInitialization() { result = newCall }
|
||||
|
||||
override Cryptography::CryptographicAlgorithm getAlgorithm() {
|
||||
result.matchesName(signatureName)
|
||||
}
|
||||
@@ -225,23 +221,19 @@ private module CryptodomeModel {
|
||||
class CryptodomeGenericHashOperation extends Cryptography::CryptographicOperation::Range,
|
||||
DataFlow::CallCfgNode
|
||||
{
|
||||
API::CallNode newCall;
|
||||
string hashName;
|
||||
|
||||
CryptodomeGenericHashOperation() {
|
||||
exists(API::Node hashModule |
|
||||
hashModule =
|
||||
API::moduleImport(["Crypto", "Cryptodome"]).getMember("Hash").getMember(hashName) and
|
||||
newCall = hashModule.getMember("new").getACall()
|
||||
API::moduleImport(["Crypto", "Cryptodome"]).getMember("Hash").getMember(hashName)
|
||||
|
|
||||
this = newCall
|
||||
this = hashModule.getMember("new").getACall()
|
||||
or
|
||||
this = newCall.getReturn().getMember("update").getACall()
|
||||
this = hashModule.getMember("new").getReturn().getMember("update").getACall()
|
||||
)
|
||||
}
|
||||
|
||||
override DataFlow::Node getInitialization() { result = newCall }
|
||||
|
||||
override Cryptography::CryptographicAlgorithm getAlgorithm() { result.matchesName(hashName) }
|
||||
|
||||
override DataFlow::Node getAnInput() { result in [this.getArg(0), this.getArgByName("data")] }
|
||||
|
||||
@@ -209,18 +209,18 @@ private module CryptographyModel {
|
||||
class CryptographyGenericCipherOperation extends Cryptography::CryptographicOperation::Range,
|
||||
DataFlow::MethodCallNode
|
||||
{
|
||||
API::CallNode init;
|
||||
string algorithmName;
|
||||
string modeName;
|
||||
|
||||
CryptographyGenericCipherOperation() {
|
||||
init =
|
||||
cipherInstance(algorithmName, modeName).getMember(["decryptor", "encryptor"]).getACall() and
|
||||
this = init.getReturn().getMember(["update", "update_into"]).getACall()
|
||||
this =
|
||||
cipherInstance(algorithmName, modeName)
|
||||
.getMember(["decryptor", "encryptor"])
|
||||
.getReturn()
|
||||
.getMember(["update", "update_into"])
|
||||
.getACall()
|
||||
}
|
||||
|
||||
override DataFlow::Node getInitialization() { result = init }
|
||||
|
||||
override Cryptography::CryptographicAlgorithm getAlgorithm() {
|
||||
result.matchesName(algorithmName)
|
||||
}
|
||||
@@ -247,17 +247,19 @@ private module CryptographyModel {
|
||||
}
|
||||
|
||||
/** Gets a reference to a Hash instance using algorithm with `algorithmName`. */
|
||||
private API::CallNode hashInstance(string algorithmName) {
|
||||
result =
|
||||
API::moduleImport("cryptography")
|
||||
.getMember("hazmat")
|
||||
.getMember("primitives")
|
||||
.getMember("hashes")
|
||||
.getMember("Hash")
|
||||
.getACall() and
|
||||
algorithmClassRef(algorithmName).getReturn().getAValueReachableFromSource() in [
|
||||
result.getArg(0), result.getArgByName("algorithm")
|
||||
]
|
||||
private API::Node hashInstance(string algorithmName) {
|
||||
exists(API::CallNode call | result = call.getReturn() |
|
||||
call =
|
||||
API::moduleImport("cryptography")
|
||||
.getMember("hazmat")
|
||||
.getMember("primitives")
|
||||
.getMember("hashes")
|
||||
.getMember("Hash")
|
||||
.getACall() and
|
||||
algorithmClassRef(algorithmName).getReturn().getAValueReachableFromSource() in [
|
||||
call.getArg(0), call.getArgByName("algorithm")
|
||||
]
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -266,16 +268,12 @@ private module CryptographyModel {
|
||||
class CryptographyGenericHashOperation extends Cryptography::CryptographicOperation::Range,
|
||||
DataFlow::MethodCallNode
|
||||
{
|
||||
API::CallNode init;
|
||||
string algorithmName;
|
||||
|
||||
CryptographyGenericHashOperation() {
|
||||
init = hashInstance(algorithmName) and
|
||||
this = init.getReturn().getMember("update").getACall()
|
||||
this = hashInstance(algorithmName).getMember("update").getACall()
|
||||
}
|
||||
|
||||
override DataFlow::Node getInitialization() { result = init }
|
||||
|
||||
override Cryptography::CryptographicAlgorithm getAlgorithm() {
|
||||
result.matchesName(algorithmName)
|
||||
}
|
||||
|
||||
@@ -37,8 +37,6 @@ private module Rsa {
|
||||
class RsaEncryptCall extends Cryptography::CryptographicOperation::Range, DataFlow::CallCfgNode {
|
||||
RsaEncryptCall() { this = API::moduleImport("rsa").getMember("encrypt").getACall() }
|
||||
|
||||
override DataFlow::Node getInitialization() { result = this }
|
||||
|
||||
override Cryptography::CryptographicAlgorithm getAlgorithm() { result.getName() = "RSA" }
|
||||
|
||||
override DataFlow::Node getAnInput() {
|
||||
@@ -56,8 +54,6 @@ private module Rsa {
|
||||
class RsaDecryptCall extends Cryptography::CryptographicOperation::Range, DataFlow::CallCfgNode {
|
||||
RsaDecryptCall() { this = API::moduleImport("rsa").getMember("decrypt").getACall() }
|
||||
|
||||
override DataFlow::Node getInitialization() { result = this }
|
||||
|
||||
override Cryptography::CryptographicAlgorithm getAlgorithm() { result.getName() = "RSA" }
|
||||
|
||||
override DataFlow::Node getAnInput() { result in [this.getArg(0), this.getArgByName("crypto")] }
|
||||
@@ -73,8 +69,6 @@ private module Rsa {
|
||||
class RsaSignCall extends Cryptography::CryptographicOperation::Range, DataFlow::CallCfgNode {
|
||||
RsaSignCall() { this = API::moduleImport("rsa").getMember("sign").getACall() }
|
||||
|
||||
override DataFlow::Node getInitialization() { result = this }
|
||||
|
||||
override Cryptography::CryptographicAlgorithm getAlgorithm() {
|
||||
// signature part
|
||||
result.getName() = "RSA"
|
||||
@@ -102,8 +96,6 @@ private module Rsa {
|
||||
class RsaVerifyCall extends Cryptography::CryptographicOperation::Range, DataFlow::CallCfgNode {
|
||||
RsaVerifyCall() { this = API::moduleImport("rsa").getMember("verify").getACall() }
|
||||
|
||||
override DataFlow::Node getInitialization() { result = this }
|
||||
|
||||
override Cryptography::CryptographicAlgorithm getAlgorithm() {
|
||||
// note that technically there is also a hashing operation going on but we don't
|
||||
// know what algorithm is used up front, since it is encoded in the signature
|
||||
@@ -129,8 +121,6 @@ private module Rsa {
|
||||
{
|
||||
RsaComputeHashCall() { this = API::moduleImport("rsa").getMember("compute_hash").getACall() }
|
||||
|
||||
override DataFlow::Node getInitialization() { result = this }
|
||||
|
||||
override Cryptography::CryptographicAlgorithm getAlgorithm() {
|
||||
exists(StrConst str, DataFlow::Node hashNameArg |
|
||||
hashNameArg in [this.getArg(1), this.getArgByName("method_name")] and
|
||||
@@ -154,8 +144,6 @@ private module Rsa {
|
||||
class RsaSignHashCall extends Cryptography::CryptographicOperation::Range, DataFlow::CallCfgNode {
|
||||
RsaSignHashCall() { this = API::moduleImport("rsa").getMember("sign_hash").getACall() }
|
||||
|
||||
override DataFlow::Node getInitialization() { result = this }
|
||||
|
||||
override Cryptography::CryptographicAlgorithm getAlgorithm() { result.getName() = "RSA" }
|
||||
|
||||
override DataFlow::Node getAnInput() {
|
||||
|
||||
@@ -2747,8 +2747,6 @@ private module StdlibPrivate {
|
||||
exists(this.getParameter(1, "data"))
|
||||
}
|
||||
|
||||
override DataFlow::Node getInitialization() { result = this }
|
||||
|
||||
override Cryptography::CryptographicAlgorithm getAlgorithm() { result.matchesName(hashName) }
|
||||
|
||||
override DataFlow::Node getAnInput() { result = this.getParameter(1, "data").asSink() }
|
||||
@@ -2760,16 +2758,12 @@ private module StdlibPrivate {
|
||||
* A hashing operation by using the `update` method on the result of calling the `hashlib.new` function.
|
||||
*/
|
||||
class HashlibNewUpdateCall extends Cryptography::CryptographicOperation::Range, API::CallNode {
|
||||
API::CallNode init;
|
||||
string hashName;
|
||||
|
||||
HashlibNewUpdateCall() {
|
||||
init = hashlibNewCall(hashName) and
|
||||
this = init.getReturn().getMember("update").getACall()
|
||||
this = hashlibNewCall(hashName).getReturn().getMember("update").getACall()
|
||||
}
|
||||
|
||||
override DataFlow::Node getInitialization() { result = init }
|
||||
|
||||
override Cryptography::CryptographicAlgorithm getAlgorithm() { result.matchesName(hashName) }
|
||||
|
||||
override DataFlow::Node getAnInput() { result = this.getArg(0) }
|
||||
@@ -2808,14 +2802,7 @@ private module StdlibPrivate {
|
||||
* (such as `hashlib.md5`), by calling its' `update` method.
|
||||
*/
|
||||
class HashlibHashClassUpdateCall extends HashlibGenericHashOperation {
|
||||
API::CallNode init;
|
||||
|
||||
HashlibHashClassUpdateCall() {
|
||||
init = hashClass.getACall() and
|
||||
this = hashClass.getReturn().getMember("update").getACall()
|
||||
}
|
||||
|
||||
override DataFlow::Node getInitialization() { result = init }
|
||||
HashlibHashClassUpdateCall() { this = hashClass.getReturn().getMember("update").getACall() }
|
||||
|
||||
override DataFlow::Node getAnInput() { result = this.getArg(0) }
|
||||
}
|
||||
@@ -2832,8 +2819,6 @@ private module StdlibPrivate {
|
||||
exists([this.getArg(0), this.getArgByName("string")])
|
||||
}
|
||||
|
||||
override DataFlow::Node getInitialization() { result = this }
|
||||
|
||||
override DataFlow::Node getAnInput() {
|
||||
result = this.getArg(0)
|
||||
or
|
||||
@@ -2880,8 +2865,6 @@ private module StdlibPrivate {
|
||||
exists(this.getParameter(1, "msg").asSink())
|
||||
}
|
||||
|
||||
override DataFlow::Node getInitialization() { result = this }
|
||||
|
||||
override API::Node getDigestArg() { result = digestArg }
|
||||
|
||||
override DataFlow::Node getAnInput() { result = this.getParameter(1, "msg").asSink() }
|
||||
@@ -2893,16 +2876,12 @@ private module StdlibPrivate {
|
||||
* See https://docs.python.org/3.11/library/hmac.html#hmac.HMAC.update
|
||||
*/
|
||||
class HmacUpdateCall extends HmacCryptographicOperation {
|
||||
API::CallNode init;
|
||||
API::Node digestArg;
|
||||
|
||||
HmacUpdateCall() {
|
||||
init = getHmacConstructorCall(digestArg) and
|
||||
this = init.getReturn().getMember("update").getACall()
|
||||
this = getHmacConstructorCall(digestArg).getReturn().getMember("update").getACall()
|
||||
}
|
||||
|
||||
override DataFlow::Node getInitialization() { result = init }
|
||||
|
||||
override API::Node getDigestArg() { result = digestArg }
|
||||
|
||||
override DataFlow::Node getAnInput() { result = this.getParameter(0, "msg").asSink() }
|
||||
@@ -2916,8 +2895,6 @@ private module StdlibPrivate {
|
||||
class HmacDigestCall extends HmacCryptographicOperation {
|
||||
HmacDigestCall() { this = API::moduleImport("hmac").getMember("digest").getACall() }
|
||||
|
||||
override DataFlow::Node getInitialization() { result = this }
|
||||
|
||||
override API::Node getDigestArg() { result = this.getParameter(2, "digest") }
|
||||
|
||||
override DataFlow::Node getAnInput() { result = this.getParameter(1, "msg").asSink() }
|
||||
|
||||
@@ -40,9 +40,6 @@ module Cryptography {
|
||||
/** Gets the algorithm used, if it matches a known `CryptographicAlgorithm`. */
|
||||
CryptographicAlgorithm getAlgorithm() { result = super.getAlgorithm() }
|
||||
|
||||
/** Gets the data-flow node where the cryptographic algorithm used in this operation is configured. */
|
||||
DataFlow::Node getInitialization() { result = super.getInitialization() }
|
||||
|
||||
/** Gets an input the algorithm is used on, for example the plain text input to be encrypted. */
|
||||
DataFlow::Node getAnInput() { result = super.getAnInput() }
|
||||
|
||||
@@ -68,9 +65,6 @@ module Cryptography {
|
||||
* extend `CryptographicOperation` instead.
|
||||
*/
|
||||
abstract class Range extends DataFlow::Node {
|
||||
/** Gets the data-flow node where the cryptographic algorithm used in this operation is configured. */
|
||||
abstract DataFlow::Node getInitialization();
|
||||
|
||||
/** Gets the algorithm used, if it matches a known `CryptographicAlgorithm`. */
|
||||
abstract CryptographicAlgorithm getAlgorithm();
|
||||
|
||||
|
||||
@@ -13,15 +13,18 @@
|
||||
import python
|
||||
import semmle.python.Concepts
|
||||
|
||||
from Cryptography::CryptographicOperation operation, string msgPrefix
|
||||
from
|
||||
Cryptography::CryptographicOperation operation, Cryptography::CryptographicAlgorithm algorithm,
|
||||
string msgPrefix
|
||||
where
|
||||
algorithm = operation.getAlgorithm() and
|
||||
// `Cryptography::HashingAlgorithm` and `Cryptography::PasswordHashingAlgorithm` are
|
||||
// handled by `py/weak-sensitive-data-hashing`
|
||||
exists(Cryptography::EncryptionAlgorithm algorithm | algorithm = operation.getAlgorithm() |
|
||||
algorithm instanceof Cryptography::EncryptionAlgorithm and
|
||||
(
|
||||
algorithm.isWeak() and
|
||||
msgPrefix = "The cryptographic algorithm " + algorithm.getName()
|
||||
msgPrefix = "The cryptographic algorithm " + operation.getAlgorithm().getName()
|
||||
)
|
||||
or
|
||||
operation.getBlockMode().isWeak() and msgPrefix = "The block mode " + operation.getBlockMode()
|
||||
select operation, "$@ is broken or weak, and should not be used.", operation.getInitialization(),
|
||||
msgPrefix
|
||||
select operation, msgPrefix + " is broken or weak, and should not be used."
|
||||
|
||||
@@ -1,5 +1,9 @@
|
||||
uniqueEnclosingCallable
|
||||
uniqueCallEnclosingCallable
|
||||
| new_cls_param.py:14:6:14:16 | classmethod() | Call should have one enclosing callable but has 0. |
|
||||
| test.py:21:6:21:17 | staticmethod() | Call should have one enclosing callable but has 0. |
|
||||
| test.py:25:6:25:16 | classmethod() | Call should have one enclosing callable but has 0. |
|
||||
| test.py:29:6:29:16 | classmethod() | Call should have one enclosing callable but has 0. |
|
||||
uniqueType
|
||||
uniqueNodeLocation
|
||||
missingLocation
|
||||
|
||||
@@ -1,25 +0,0 @@
|
||||
# Originally we had module and functions as `DataFlowCallable``, and any call inside a
|
||||
# class scope would not have a result for getEnclosingCallable. Since this was only a
|
||||
# consistency error for calls, originally we added a new `DataFlowClassScope` only for
|
||||
# those classes that had a call in their scope. That's why all the class definitions in
|
||||
# this test do a call to the dummy function `func`.
|
||||
#
|
||||
# Note: this was shortsighted, since most DataFlow::Node use `getCallableScope` helper
|
||||
# to define their .getEnclosingCallable(), which picks the first DataFlowCallable to
|
||||
# contain the node. (so for some classes that would be DataFlowClassScope, and for some
|
||||
# it would be the module/function containing the class definition)
|
||||
|
||||
def func(*args, **kwargs):
|
||||
print("func()")
|
||||
|
||||
class Cls:
|
||||
func()
|
||||
class Inner:
|
||||
func()
|
||||
|
||||
def other_func():
|
||||
class Cls2:
|
||||
func()
|
||||
return Cls2
|
||||
|
||||
x = other_func()
|
||||
@@ -1,5 +1,7 @@
|
||||
uniqueEnclosingCallable
|
||||
uniqueCallEnclosingCallable
|
||||
| datamodel.py:71:6:71:16 | classmethod() | Call should have one enclosing callable but has 0. |
|
||||
| datamodel.py:76:6:76:17 | staticmethod() | Call should have one enclosing callable but has 0. |
|
||||
uniqueType
|
||||
uniqueNodeLocation
|
||||
missingLocation
|
||||
|
||||
@@ -1,5 +1,11 @@
|
||||
uniqueEnclosingCallable
|
||||
uniqueCallEnclosingCallable
|
||||
| test_collections.py:39:17:39:38 | Lambda() | Call should have one enclosing callable but has 0. |
|
||||
| test_collections.py:39:17:39:38 | Lambda() | Call should have one enclosing callable but has 0. |
|
||||
| test_collections.py:45:19:45:24 | mod() | Call should have one enclosing callable but has 0. |
|
||||
| test_collections.py:45:19:45:24 | mod() | Call should have one enclosing callable but has 0. |
|
||||
| test_collections.py:52:13:52:24 | mod_local() | Call should have one enclosing callable but has 0. |
|
||||
| test_collections.py:52:13:52:24 | mod_local() | Call should have one enclosing callable but has 0. |
|
||||
uniqueType
|
||||
uniqueNodeLocation
|
||||
missingLocation
|
||||
|
||||
@@ -1,5 +1,36 @@
|
||||
uniqueEnclosingCallable
|
||||
uniqueCallEnclosingCallable
|
||||
| code/bound_method_arg.py:5:6:5:16 | classmethod() | Call should have one enclosing callable but has 0. |
|
||||
| code/callable_as_argument.py:37:6:37:17 | staticmethod() | Call should have one enclosing callable but has 0. |
|
||||
| code/callable_as_argument.py:49:10:49:21 | staticmethod() | Call should have one enclosing callable but has 0. |
|
||||
| code/class_construction.py:13:6:13:16 | classmethod() | Call should have one enclosing callable but has 0. |
|
||||
| code/class_properties.py:9:6:9:13 | property() | Call should have one enclosing callable but has 0. |
|
||||
| code/class_properties.py:11:9:11:32 | print() | Call should have one enclosing callable but has 0. |
|
||||
| code/class_properties.py:14:6:14:15 | Attribute() | Call should have one enclosing callable but has 0. |
|
||||
| code/class_properties.py:19:6:19:16 | Attribute() | Call should have one enclosing callable but has 0. |
|
||||
| code/class_properties.py:36:12:36:62 | property() | Call should have one enclosing callable but has 0. |
|
||||
| code/class_properties.py:38:6:38:13 | property() | Call should have one enclosing callable but has 0. |
|
||||
| code/class_properties.py:40:9:40:38 | print() | Call should have one enclosing callable but has 0. |
|
||||
| code/class_subclass.py:10:6:10:17 | staticmethod() | Call should have one enclosing callable but has 0. |
|
||||
| code/class_subclass.py:14:6:14:16 | classmethod() | Call should have one enclosing callable but has 0. |
|
||||
| code/class_subclass.py:104:6:104:17 | staticmethod() | Call should have one enclosing callable but has 0. |
|
||||
| code/class_subclass.py:108:6:108:16 | classmethod() | Call should have one enclosing callable but has 0. |
|
||||
| code/class_subclass.py:112:6:112:17 | staticmethod() | Call should have one enclosing callable but has 0. |
|
||||
| code/class_subclass.py:116:6:116:16 | classmethod() | Call should have one enclosing callable but has 0. |
|
||||
| code/class_subclass.py:120:6:120:16 | classmethod() | Call should have one enclosing callable but has 0. |
|
||||
| code/class_subclass.py:149:6:149:17 | staticmethod() | Call should have one enclosing callable but has 0. |
|
||||
| code/class_subclass.py:153:6:153:16 | classmethod() | Call should have one enclosing callable but has 0. |
|
||||
| code/class_super.py:13:6:13:16 | classmethod() | Call should have one enclosing callable but has 0. |
|
||||
| code/class_super.py:28:6:28:17 | staticmethod() | Call should have one enclosing callable but has 0. |
|
||||
| code/class_super.py:36:6:36:16 | classmethod() | Call should have one enclosing callable but has 0. |
|
||||
| code/class_super.py:40:6:40:16 | classmethod() | Call should have one enclosing callable but has 0. |
|
||||
| code/func_defined_outside_class.py:17:18:17:41 | staticmethod() | Call should have one enclosing callable but has 0. |
|
||||
| code/func_defined_outside_class.py:18:18:18:40 | classmethod() | Call should have one enclosing callable but has 0. |
|
||||
| code/func_defined_outside_class.py:38:11:38:21 | _gen() | Call should have one enclosing callable but has 0. |
|
||||
| code/func_defined_outside_class.py:39:11:39:21 | _gen() | Call should have one enclosing callable but has 0. |
|
||||
| code/nested_class.py:3:10:3:21 | staticmethod() | Call should have one enclosing callable but has 0. |
|
||||
| code/nested_class.py:7:10:7:21 | staticmethod() | Call should have one enclosing callable but has 0. |
|
||||
| code/self_passing.py:60:6:60:16 | classmethod() | Call should have one enclosing callable but has 0. |
|
||||
uniqueType
|
||||
uniqueNodeLocation
|
||||
missingLocation
|
||||
|
||||
@@ -1,5 +1,9 @@
|
||||
uniqueEnclosingCallable
|
||||
uniqueCallEnclosingCallable
|
||||
| test_captured.py:7:22:7:25 | p() | Call should have one enclosing callable but has 0. |
|
||||
| test_captured.py:7:22:7:25 | p() | Call should have one enclosing callable but has 0. |
|
||||
| test_captured.py:14:26:14:30 | pp() | Call should have one enclosing callable but has 0. |
|
||||
| test_captured.py:14:26:14:30 | pp() | Call should have one enclosing callable but has 0. |
|
||||
uniqueType
|
||||
uniqueNodeLocation
|
||||
missingLocation
|
||||
|
||||
@@ -1,5 +1,40 @@
|
||||
uniqueEnclosingCallable
|
||||
uniqueCallEnclosingCallable
|
||||
| testapp/orm_form_test.py:7:12:7:43 | Attribute() | Call should have one enclosing callable but has 0. |
|
||||
| testapp/orm_inheritance.py:30:13:30:44 | Attribute() | Call should have one enclosing callable but has 0. |
|
||||
| testapp/orm_inheritance.py:34:25:34:56 | Attribute() | Call should have one enclosing callable but has 0. |
|
||||
| testapp/orm_inheritance.py:35:33:35:64 | Attribute() | Call should have one enclosing callable but has 0. |
|
||||
| testapp/orm_inheritance.py:39:21:39:52 | Attribute() | Call should have one enclosing callable but has 0. |
|
||||
| testapp/orm_inheritance.py:40:33:40:64 | Attribute() | Call should have one enclosing callable but has 0. |
|
||||
| testapp/orm_inheritance.py:118:13:118:44 | Attribute() | Call should have one enclosing callable but has 0. |
|
||||
| testapp/orm_inheritance.py:122:25:122:56 | Attribute() | Call should have one enclosing callable but has 0. |
|
||||
| testapp/orm_inheritance.py:123:33:123:64 | Attribute() | Call should have one enclosing callable but has 0. |
|
||||
| testapp/orm_inheritance.py:127:21:127:52 | Attribute() | Call should have one enclosing callable but has 0. |
|
||||
| testapp/orm_inheritance.py:128:33:128:64 | Attribute() | Call should have one enclosing callable but has 0. |
|
||||
| testapp/orm_security_tests.py:16:12:16:43 | Attribute() | Call should have one enclosing callable but has 0. |
|
||||
| testapp/orm_security_tests.py:17:11:17:31 | Attribute() | Call should have one enclosing callable but has 0. |
|
||||
| testapp/orm_security_tests.py:93:12:93:65 | Attribute() | Call should have one enclosing callable but has 0. |
|
||||
| testapp/orm_security_tests.py:112:12:112:65 | Attribute() | Call should have one enclosing callable but has 0. |
|
||||
| testapp/orm_tests.py:29:12:29:43 | Attribute() | Call should have one enclosing callable but has 0. |
|
||||
| testapp/orm_tests.py:43:12:43:43 | Attribute() | Call should have one enclosing callable but has 0. |
|
||||
| testapp/orm_tests.py:59:12:59:61 | Attribute() | Call should have one enclosing callable but has 0. |
|
||||
| testapp/orm_tests.py:74:12:74:43 | Attribute() | Call should have one enclosing callable but has 0. |
|
||||
| testapp/orm_tests.py:90:12:90:43 | Attribute() | Call should have one enclosing callable but has 0. |
|
||||
| testapp/orm_tests.py:111:12:111:43 | Attribute() | Call should have one enclosing callable but has 0. |
|
||||
| testapp/orm_tests.py:127:12:127:43 | Attribute() | Call should have one enclosing callable but has 0. |
|
||||
| testapp/orm_tests.py:128:13:128:44 | Attribute() | Call should have one enclosing callable but has 0. |
|
||||
| testapp/orm_tests.py:145:12:145:43 | Attribute() | Call should have one enclosing callable but has 0. |
|
||||
| testapp/orm_tests.py:146:13:146:44 | Attribute() | Call should have one enclosing callable but has 0. |
|
||||
| testapp/orm_tests.py:162:12:162:43 | Attribute() | Call should have one enclosing callable but has 0. |
|
||||
| testapp/orm_tests.py:178:12:178:43 | Attribute() | Call should have one enclosing callable but has 0. |
|
||||
| testapp/orm_tests.py:181:12:181:64 | Attribute() | Call should have one enclosing callable but has 0. |
|
||||
| testapp/orm_tests.py:207:12:207:43 | Attribute() | Call should have one enclosing callable but has 0. |
|
||||
| testapp/orm_tests.py:208:12:208:70 | Attribute() | Call should have one enclosing callable but has 0. |
|
||||
| testapp/orm_tests.py:234:12:234:43 | Attribute() | Call should have one enclosing callable but has 0. |
|
||||
| testapp/orm_tests.py:235:12:235:95 | Attribute() | Call should have one enclosing callable but has 0. |
|
||||
| testapp/orm_tests.py:256:12:256:43 | Attribute() | Call should have one enclosing callable but has 0. |
|
||||
| testapp/orm_tests.py:274:12:274:43 | Attribute() | Call should have one enclosing callable but has 0. |
|
||||
| testapp/orm_tests.py:295:12:295:43 | Attribute() | Call should have one enclosing callable but has 0. |
|
||||
uniqueType
|
||||
uniqueNodeLocation
|
||||
missingLocation
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
| test_cryptodome.py:11:13:11:42 | ControlFlowNode for Attribute() | $@ is broken or weak, and should not be used. | test_cryptodome.py:10:10:10:22 | ControlFlowNode for Attribute() | The cryptographic algorithm ARC4 |
|
||||
| test_cryptodome.py:16:13:16:42 | ControlFlowNode for Attribute() | $@ is broken or weak, and should not be used. | test_cryptodome.py:15:10:15:35 | ControlFlowNode for Attribute() | The block mode ECB |
|
||||
| test_cryptography.py:13:13:13:44 | ControlFlowNode for Attribute() | $@ is broken or weak, and should not be used. | test_cryptography.py:12:13:12:30 | ControlFlowNode for Attribute() | The cryptographic algorithm ARC4 |
|
||||
| test_cryptography.py:22:13:22:58 | ControlFlowNode for Attribute() | $@ is broken or weak, and should not be used. | test_cryptography.py:21:13:21:30 | ControlFlowNode for Attribute() | The block mode ECB |
|
||||
| test_cryptodome.py:11:13:11:42 | ControlFlowNode for Attribute() | The cryptographic algorithm ARC4 is broken or weak, and should not be used. |
|
||||
| test_cryptodome.py:16:13:16:42 | ControlFlowNode for Attribute() | The block mode ECB is broken or weak, and should not be used. |
|
||||
| test_cryptography.py:13:13:13:44 | ControlFlowNode for Attribute() | The cryptographic algorithm ARC4 is broken or weak, and should not be used. |
|
||||
| test_cryptography.py:22:13:22:58 | ControlFlowNode for Attribute() | The block mode ECB is broken or weak, and should not be used. |
|
||||
|
||||
@@ -18,21 +18,15 @@ private API::Node digest(Cryptography::HashingAlgorithm algo) {
|
||||
private class DigestCall extends Cryptography::CryptographicOperation::Range instanceof DataFlow::CallNode
|
||||
{
|
||||
Cryptography::HashingAlgorithm algo;
|
||||
API::Node digestNode;
|
||||
|
||||
DigestCall() {
|
||||
digestNode = digest(algo) and
|
||||
(
|
||||
this = digestNode.getAMethodCall(["hexdigest", "base64digest", "bubblebabble"])
|
||||
or
|
||||
this = digestNode.getAMethodCall("file") // it's directly hashing the contents of a file, but that's close enough for us.
|
||||
or
|
||||
this = digestNode.getInstance().getAMethodCall(["digest", "update", "<<"])
|
||||
)
|
||||
this = digest(algo).getAMethodCall(["hexdigest", "base64digest", "bubblebabble"])
|
||||
or
|
||||
this = digest(algo).getAMethodCall("file") // it's directly hashing the contents of a file, but that's close enough for us.
|
||||
or
|
||||
this = digest(algo).getInstance().getAMethodCall(["digest", "update", "<<"])
|
||||
}
|
||||
|
||||
override DataFlow::Node getInitialization() { result = digestNode.asSource() }
|
||||
|
||||
override Cryptography::HashingAlgorithm getAlgorithm() { result = algo }
|
||||
|
||||
override DataFlow::Node getAnInput() { result = super.getArgument(0) }
|
||||
|
||||
@@ -40,9 +40,6 @@ module Cryptography {
|
||||
/** Gets the algorithm used, if it matches a known `CryptographicAlgorithm`. */
|
||||
CryptographicAlgorithm getAlgorithm() { result = super.getAlgorithm() }
|
||||
|
||||
/** Gets the data-flow node where the cryptographic algorithm used in this operation is configured. */
|
||||
DataFlow::Node getInitialization() { result = super.getInitialization() }
|
||||
|
||||
/** Gets an input the algorithm is used on, for example the plain text input to be encrypted. */
|
||||
DataFlow::Node getAnInput() { result = super.getAnInput() }
|
||||
|
||||
@@ -68,9 +65,6 @@ module Cryptography {
|
||||
* extend `CryptographicOperation` instead.
|
||||
*/
|
||||
abstract class Range extends DataFlow::Node {
|
||||
/** Gets the data-flow node where the cryptographic algorithm used in this operation is configured. */
|
||||
abstract DataFlow::Node getInitialization();
|
||||
|
||||
/** Gets the algorithm used, if it matches a known `CryptographicAlgorithm`. */
|
||||
abstract CryptographicAlgorithm getAlgorithm();
|
||||
|
||||
|
||||
@@ -569,8 +569,6 @@ private class CipherOperation extends Cryptography::CryptographicOperation::Rang
|
||||
this.getMethodName() = "update"
|
||||
}
|
||||
|
||||
override DataFlow::Node getInitialization() { result = cipherNode }
|
||||
|
||||
override Cryptography::EncryptionAlgorithm getAlgorithm() {
|
||||
result = cipherNode.getCipher().getAlgorithm()
|
||||
}
|
||||
@@ -593,21 +591,21 @@ private module Digest {
|
||||
private class DigestCall extends Cryptography::CryptographicOperation::Range instanceof DataFlow::CallNode
|
||||
{
|
||||
Cryptography::HashingAlgorithm algo;
|
||||
API::MethodAccessNode call;
|
||||
|
||||
DigestCall() {
|
||||
call = API::getTopLevelMember("OpenSSL").getMember("Digest").getMethod("new") and
|
||||
this = call.getReturn().getAMethodCall(["digest", "update", "<<"]) and
|
||||
algo.matchesName(call.asCall()
|
||||
.getArgument(0)
|
||||
.asExpr()
|
||||
.getExpr()
|
||||
.getConstantValue()
|
||||
.getString())
|
||||
exists(API::MethodAccessNode call |
|
||||
call = API::getTopLevelMember("OpenSSL").getMember("Digest").getMethod("new")
|
||||
|
|
||||
this = call.getReturn().getAMethodCall(["digest", "update", "<<"]) and
|
||||
algo.matchesName(call.asCall()
|
||||
.getArgument(0)
|
||||
.asExpr()
|
||||
.getExpr()
|
||||
.getConstantValue()
|
||||
.getString())
|
||||
)
|
||||
}
|
||||
|
||||
override DataFlow::Node getInitialization() { result = call.asCall() }
|
||||
|
||||
override Cryptography::HashingAlgorithm getAlgorithm() { result = algo }
|
||||
|
||||
override DataFlow::Node getAnInput() { result = super.getArgument(0) }
|
||||
@@ -619,16 +617,12 @@ private module Digest {
|
||||
private class DigestCallDirect extends Cryptography::CryptographicOperation::Range instanceof DataFlow::CallNode
|
||||
{
|
||||
Cryptography::HashingAlgorithm algo;
|
||||
API::Node digestNode;
|
||||
|
||||
DigestCallDirect() {
|
||||
digestNode = API::getTopLevelMember("OpenSSL").getMember("Digest") and
|
||||
this = digestNode.getMethod("digest").asCall() and
|
||||
this = API::getTopLevelMember("OpenSSL").getMember("Digest").getMethod("digest").asCall() and
|
||||
algo.matchesName(this.getArgument(0).asExpr().getExpr().getConstantValue().getString())
|
||||
}
|
||||
|
||||
override DataFlow::Node getInitialization() { result = digestNode.asSource() }
|
||||
|
||||
override Cryptography::HashingAlgorithm getAlgorithm() { result = algo }
|
||||
|
||||
override DataFlow::Node getAnInput() { result = super.getArgument(1) }
|
||||
|
||||
@@ -23,5 +23,4 @@ where
|
||||
)
|
||||
or
|
||||
operation.getBlockMode().isWeak() and msgPrefix = "The block mode " + operation.getBlockMode()
|
||||
select operation, "$@ is broken or weak, and should not be used.", operation.getInitialization(),
|
||||
msgPrefix
|
||||
select operation, msgPrefix + " is broken or weak, and should not be used."
|
||||
|
||||
@@ -1,19 +1,19 @@
|
||||
| broken_crypto.rb:4:8:4:34 | call to new | $@ is broken or weak, and should not be used. | broken_crypto.rb:4:8:4:34 | call to new | The cryptographic algorithm DES |
|
||||
| broken_crypto.rb:8:1:8:18 | call to update | $@ is broken or weak, and should not be used. | broken_crypto.rb:8:1:8:4 | weak | The cryptographic algorithm DES |
|
||||
| broken_crypto.rb:12:8:12:43 | call to new | $@ is broken or weak, and should not be used. | broken_crypto.rb:12:8:12:43 | call to new | The block mode ECB |
|
||||
| broken_crypto.rb:16:1:16:18 | call to update | $@ is broken or weak, and should not be used. | broken_crypto.rb:16:1:16:4 | weak | The block mode ECB |
|
||||
| broken_crypto.rb:28:1:28:35 | call to new | $@ is broken or weak, and should not be used. | broken_crypto.rb:28:1:28:35 | call to new | The block mode ECB |
|
||||
| broken_crypto.rb:37:1:37:33 | call to new | $@ is broken or weak, and should not be used. | broken_crypto.rb:37:1:37:33 | call to new | The block mode ECB |
|
||||
| broken_crypto.rb:42:1:42:33 | call to new | $@ is broken or weak, and should not be used. | broken_crypto.rb:42:1:42:33 | call to new | The block mode ECB |
|
||||
| broken_crypto.rb:47:1:47:33 | call to new | $@ is broken or weak, and should not be used. | broken_crypto.rb:47:1:47:33 | call to new | The block mode ECB |
|
||||
| broken_crypto.rb:52:1:52:29 | call to new | $@ is broken or weak, and should not be used. | broken_crypto.rb:52:1:52:29 | call to new | The block mode ECB |
|
||||
| broken_crypto.rb:57:1:57:32 | call to new | $@ is broken or weak, and should not be used. | broken_crypto.rb:57:1:57:32 | call to new | The block mode ECB |
|
||||
| broken_crypto.rb:60:1:60:24 | call to new | $@ is broken or weak, and should not be used. | broken_crypto.rb:60:1:60:24 | call to new | The cryptographic algorithm DES |
|
||||
| broken_crypto.rb:62:1:62:30 | call to new | $@ is broken or weak, and should not be used. | broken_crypto.rb:62:1:62:30 | call to new | The cryptographic algorithm DES |
|
||||
| broken_crypto.rb:67:1:67:31 | call to new | $@ is broken or weak, and should not be used. | broken_crypto.rb:67:1:67:31 | call to new | The block mode ECB |
|
||||
| broken_crypto.rb:70:1:70:24 | call to new | $@ is broken or weak, and should not be used. | broken_crypto.rb:70:1:70:24 | call to new | The cryptographic algorithm RC2 |
|
||||
| broken_crypto.rb:72:1:72:30 | call to new | $@ is broken or weak, and should not be used. | broken_crypto.rb:72:1:72:30 | call to new | The block mode ECB |
|
||||
| broken_crypto.rb:72:1:72:30 | call to new | $@ is broken or weak, and should not be used. | broken_crypto.rb:72:1:72:30 | call to new | The cryptographic algorithm RC2 |
|
||||
| broken_crypto.rb:75:1:75:24 | call to new | $@ is broken or weak, and should not be used. | broken_crypto.rb:75:1:75:24 | call to new | The cryptographic algorithm RC4 |
|
||||
| broken_crypto.rb:77:1:77:29 | call to new | $@ is broken or weak, and should not be used. | broken_crypto.rb:77:1:77:29 | call to new | The cryptographic algorithm RC4 |
|
||||
| broken_crypto.rb:79:1:79:35 | call to new | $@ is broken or weak, and should not be used. | broken_crypto.rb:79:1:79:35 | call to new | The cryptographic algorithm RC4 |
|
||||
| broken_crypto.rb:4:8:4:34 | call to new | The cryptographic algorithm DES is broken or weak, and should not be used. |
|
||||
| broken_crypto.rb:8:1:8:18 | call to update | The cryptographic algorithm DES is broken or weak, and should not be used. |
|
||||
| broken_crypto.rb:12:8:12:43 | call to new | The block mode ECB is broken or weak, and should not be used. |
|
||||
| broken_crypto.rb:16:1:16:18 | call to update | The block mode ECB is broken or weak, and should not be used. |
|
||||
| broken_crypto.rb:28:1:28:35 | call to new | The block mode ECB is broken or weak, and should not be used. |
|
||||
| broken_crypto.rb:37:1:37:33 | call to new | The block mode ECB is broken or weak, and should not be used. |
|
||||
| broken_crypto.rb:42:1:42:33 | call to new | The block mode ECB is broken or weak, and should not be used. |
|
||||
| broken_crypto.rb:47:1:47:33 | call to new | The block mode ECB is broken or weak, and should not be used. |
|
||||
| broken_crypto.rb:52:1:52:29 | call to new | The block mode ECB is broken or weak, and should not be used. |
|
||||
| broken_crypto.rb:57:1:57:32 | call to new | The block mode ECB is broken or weak, and should not be used. |
|
||||
| broken_crypto.rb:60:1:60:24 | call to new | The cryptographic algorithm DES is broken or weak, and should not be used. |
|
||||
| broken_crypto.rb:62:1:62:30 | call to new | The cryptographic algorithm DES is broken or weak, and should not be used. |
|
||||
| broken_crypto.rb:67:1:67:31 | call to new | The block mode ECB is broken or weak, and should not be used. |
|
||||
| broken_crypto.rb:70:1:70:24 | call to new | The cryptographic algorithm RC2 is broken or weak, and should not be used. |
|
||||
| broken_crypto.rb:72:1:72:30 | call to new | The block mode ECB is broken or weak, and should not be used. |
|
||||
| broken_crypto.rb:72:1:72:30 | call to new | The cryptographic algorithm RC2 is broken or weak, and should not be used. |
|
||||
| broken_crypto.rb:75:1:75:24 | call to new | The cryptographic algorithm RC4 is broken or weak, and should not be used. |
|
||||
| broken_crypto.rb:77:1:77:29 | call to new | The cryptographic algorithm RC4 is broken or weak, and should not be used. |
|
||||
| broken_crypto.rb:79:1:79:35 | call to new | The cryptographic algorithm RC4 is broken or weak, and should not be used. |
|
||||
|
||||
@@ -17,8 +17,6 @@ module ModulusAnalysis<
|
||||
LocationSig Location, Semantic Sem, DeltaSig D, BoundSig<Location, Sem, D> Bounds,
|
||||
UtilSig<Sem, D> U>
|
||||
{
|
||||
private import internal.RangeUtils::MakeUtils<Sem, D>
|
||||
|
||||
bindingset[pos, v]
|
||||
pragma[inline_late]
|
||||
private predicate hasReadOfVarInlineLate(Sem::SsaReadPosition pos, Sem::SsaVariable v) {
|
||||
@@ -37,7 +35,7 @@ module ModulusAnalysis<
|
||||
exists(Sem::Guard guard, boolean testIsTrue |
|
||||
hasReadOfVarInlineLate(pos, v) and
|
||||
guard = U::semEqFlowCond(v, e, D::fromInt(delta), true, testIsTrue) and
|
||||
guardDirectlyControlsSsaRead(guard, pos, testIsTrue)
|
||||
Sem::guardDirectlyControlsSsaRead(guard, pos, testIsTrue)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -109,7 +107,7 @@ module ModulusAnalysis<
|
||||
exists(Sem::Guard guard, boolean testIsTrue |
|
||||
pos.hasReadOfVar(v) and
|
||||
guard = moduloCheck(v, val, mod, testIsTrue) and
|
||||
guardControlsSsaRead(guard, pos, testIsTrue)
|
||||
Sem::guardControlsSsaRead(guard, pos, testIsTrue)
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -142,13 +142,7 @@ signature module Semantic {
|
||||
Expr getBranchExpr(boolean branch);
|
||||
}
|
||||
|
||||
class BasicBlock {
|
||||
/** Holds if this block (transitively) dominates `otherblock`. */
|
||||
predicate bbDominates(BasicBlock otherBlock);
|
||||
}
|
||||
|
||||
/** Gets an immediate successor of basic block `bb`, if any. */
|
||||
BasicBlock getABasicBlockSuccessor(BasicBlock bb);
|
||||
class BasicBlock;
|
||||
|
||||
class Guard {
|
||||
string toString();
|
||||
@@ -160,12 +154,14 @@ signature module Semantic {
|
||||
predicate directlyControls(BasicBlock controlled, boolean branch);
|
||||
|
||||
predicate isEquality(Expr e1, Expr e2, boolean polarity);
|
||||
|
||||
predicate hasBranchEdge(BasicBlock bb1, BasicBlock bb2, boolean branch);
|
||||
}
|
||||
|
||||
predicate implies_v2(Guard g1, boolean b1, Guard g2, boolean b2);
|
||||
|
||||
predicate guardDirectlyControlsSsaRead(Guard guard, SsaReadPosition controlled, boolean testIsTrue);
|
||||
|
||||
predicate guardControlsSsaRead(Guard guard, SsaReadPosition controlled, boolean testIsTrue);
|
||||
|
||||
class Type;
|
||||
|
||||
class IntegerType extends Type {
|
||||
@@ -180,8 +176,6 @@ signature module Semantic {
|
||||
|
||||
class SsaVariable {
|
||||
Expr getAUse();
|
||||
|
||||
BasicBlock getBasicBlock();
|
||||
}
|
||||
|
||||
class SsaPhiNode extends SsaVariable;
|
||||
@@ -195,10 +189,6 @@ signature module Semantic {
|
||||
}
|
||||
|
||||
class SsaReadPositionPhiInputEdge extends SsaReadPosition {
|
||||
BasicBlock getOrigBlock();
|
||||
|
||||
BasicBlock getPhiBlock();
|
||||
|
||||
predicate phiInput(SsaPhiNode phi, SsaVariable inp);
|
||||
}
|
||||
|
||||
@@ -206,6 +196,8 @@ signature module Semantic {
|
||||
BasicBlock getBlock();
|
||||
}
|
||||
|
||||
predicate backEdge(SsaPhiNode phi, SsaVariable inp, SsaReadPositionPhiInputEdge edge);
|
||||
|
||||
predicate conversionCannotOverflow(Type fromType, Type toType);
|
||||
}
|
||||
|
||||
@@ -699,7 +691,7 @@ module RangeStage<
|
||||
exists(Sem::Guard guard, boolean testIsTrue |
|
||||
pos.hasReadOfVar(v) and
|
||||
guard = boundFlowCond(v, e, delta, upper, testIsTrue) and
|
||||
guardDirectlyControlsSsaRead(guard, pos, testIsTrue) and
|
||||
Sem::guardDirectlyControlsSsaRead(guard, pos, testIsTrue) and
|
||||
reason = TSemCondReason(guard)
|
||||
)
|
||||
}
|
||||
@@ -712,7 +704,7 @@ module RangeStage<
|
||||
exists(Sem::Guard guard, boolean testIsTrue |
|
||||
pos.hasReadOfVar(v) and
|
||||
guard = semEqFlowCond(v, e, delta, false, testIsTrue) and
|
||||
guardDirectlyControlsSsaRead(guard, pos, testIsTrue) and
|
||||
Sem::guardDirectlyControlsSsaRead(guard, pos, testIsTrue) and
|
||||
reason = TSemCondReason(guard)
|
||||
)
|
||||
}
|
||||
@@ -936,7 +928,7 @@ module RangeStage<
|
||||
origdelta = D::fromFloat(0) and
|
||||
reason = TSemNoReason()
|
||||
|
|
||||
if backEdge(phi, inp, edge)
|
||||
if Sem::backEdge(phi, inp, edge)
|
||||
then
|
||||
fromBackEdge = true and
|
||||
(
|
||||
|
||||
@@ -34,63 +34,4 @@ module MakeUtils<Semantic Lang, DeltaSig D> {
|
||||
or
|
||||
result.(Lang::CopyValueExpr).getOperand() = ssaRead(v, delta)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `guard` directly controls the position `controlled` with the
|
||||
* value `testIsTrue`.
|
||||
*/
|
||||
pragma[nomagic]
|
||||
predicate guardDirectlyControlsSsaRead(Lang::Guard guard, Lang::SsaReadPosition controlled, boolean testIsTrue) {
|
||||
guard.directlyControls(controlled.(Lang::SsaReadPositionBlock).getBlock(), testIsTrue)
|
||||
or
|
||||
exists(Lang::SsaReadPositionPhiInputEdge controlledEdge | controlledEdge = controlled |
|
||||
guard.directlyControls(controlledEdge.getOrigBlock(), testIsTrue) or
|
||||
guard.hasBranchEdge(controlledEdge.getOrigBlock(), controlledEdge.getPhiBlock(), testIsTrue)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `guard` controls the position `controlled` with the value `testIsTrue`.
|
||||
*/
|
||||
predicate guardControlsSsaRead(Lang::Guard guard, Lang::SsaReadPosition controlled, boolean testIsTrue) {
|
||||
guardDirectlyControlsSsaRead(guard, controlled, testIsTrue)
|
||||
or
|
||||
exists(Lang::Guard guard0, boolean testIsTrue0 |
|
||||
Lang::implies_v2(guard0, testIsTrue0, guard, testIsTrue) and
|
||||
guardControlsSsaRead(guard0, controlled, testIsTrue0)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `inp` is an input to `phi` along a back edge.
|
||||
*/
|
||||
predicate backEdge(
|
||||
Lang::SsaPhiNode phi, Lang::SsaVariable inp, Lang::SsaReadPositionPhiInputEdge edge
|
||||
) {
|
||||
edge.phiInput(phi, inp) and
|
||||
(
|
||||
phi.getBasicBlock().bbDominates(edge.getOrigBlock()) or
|
||||
irreducibleSccEdge(edge.getOrigBlock(), phi.getBasicBlock())
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if the edge from b1 to b2 is part of a multiple-entry cycle in an irreducible control flow
|
||||
* graph. Or if the edge is part of a cycle in unreachable code.
|
||||
*
|
||||
* An irreducible control flow graph is one where the usual dominance-based back edge detection does
|
||||
* not work, because there is a cycle with multiple entry points, meaning there are
|
||||
* mutually-reachable basic blocks where neither dominates the other. For such a graph, we first
|
||||
* remove all detectable back-edges using the normal condition that the predecessor block is
|
||||
* dominated by the successor block, then mark all edges in a cycle in the resulting graph as back
|
||||
* edges.
|
||||
*/
|
||||
private predicate irreducibleSccEdge(Lang::BasicBlock b1, Lang::BasicBlock b2) {
|
||||
trimmedEdge(b1, b2) and trimmedEdge+(b2, b1)
|
||||
}
|
||||
|
||||
private predicate trimmedEdge(Lang::BasicBlock pred, Lang::BasicBlock succ) {
|
||||
Lang::getABasicBlockSuccessor(pred) = succ and
|
||||
not succ.bbDominates(pred)
|
||||
}
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,13 +0,0 @@
|
||||
// Converts SingleValueStmtExprs into UnspecifiedElements
|
||||
class Element extends @element {
|
||||
string toString() { none() }
|
||||
}
|
||||
|
||||
from Element e, string property, string error
|
||||
where
|
||||
single_value_stmt_exprs(e, _) and
|
||||
property = "" and
|
||||
error = "Removed SingleValueStmtExpr during the database downgrade"
|
||||
or
|
||||
unspecified_elements(e, property, error)
|
||||
select e, property, error
|
||||
@@ -1,5 +0,0 @@
|
||||
description: Removing SingleValueStmtExpr
|
||||
compatibility: partial
|
||||
|
||||
unspecified_elements.rel: run unspecified_elements.ql
|
||||
single_value_stmt_exprs.rel: delete
|
||||
@@ -205,7 +205,7 @@ MAP(swift::Expr, ExprTag)
|
||||
MAP(swift::CopyExpr, void) // TODO (introduced in 5.9)
|
||||
MAP(swift::ConsumeExpr, void) // TODO (introduced in 5.9)
|
||||
MAP(swift::MaterializePackExpr, void) // TODO (introduced in 5.9)
|
||||
MAP(swift::SingleValueStmtExpr, SingleValueStmtExprTag)
|
||||
MAP(swift::SingleValueStmtExpr, void) // TODO (introduced in 5.9)
|
||||
#endif
|
||||
|
||||
MAP(swift::Decl, DeclTag)
|
||||
|
||||
@@ -636,11 +636,4 @@ codeql::RegexLiteralExpr ExprTranslator::translateRegexLiteralExpr(
|
||||
return entry;
|
||||
}
|
||||
|
||||
codeql::SingleValueStmtExpr ExprTranslator::translateSingleValueStmtExpr(
|
||||
const swift::SingleValueStmtExpr& expr) {
|
||||
auto entry = createExprEntry(expr);
|
||||
entry.stmt = dispatcher.fetchLabel(expr.getStmt());
|
||||
return entry;
|
||||
}
|
||||
|
||||
} // namespace codeql
|
||||
|
||||
@@ -119,7 +119,6 @@ class ExprTranslator : public AstTranslatorBase<ExprTranslator> {
|
||||
codeql::AppliedPropertyWrapperExpr translateAppliedPropertyWrapperExpr(
|
||||
const swift::AppliedPropertyWrapperExpr& expr);
|
||||
codeql::RegexLiteralExpr translateRegexLiteralExpr(const swift::RegexLiteralExpr& expr);
|
||||
codeql::SingleValueStmtExpr translateSingleValueStmtExpr(const swift::SingleValueStmtExpr& expr);
|
||||
|
||||
private:
|
||||
void fillClosureExpr(const swift::AbstractClosureExpr& expr, codeql::ClosureExpr& entry);
|
||||
|
||||
15
swift/ql/.generated.list
generated
15
swift/ql/.generated.list
generated
@@ -193,8 +193,6 @@ lib/codeql/swift/elements/expr/RegexLiteralExprConstructor.qll 7bf1bdba26d38e839
|
||||
lib/codeql/swift/elements/expr/SelfApplyExpr.qll 986b3ff9833aac59facecea185517c006264c5011191b4c7f31317a20926467a f0349628f9ead822783e09e56e0721f939bfb7f59c8661e6155b5a7d113c26f3
|
||||
lib/codeql/swift/elements/expr/SequenceExpr.qll 813360eff6a312e39c7b6c49928477679a3f32314badf3383bf6204690a280e4 3b2d06ac54746033a90319463243f2d0f17265c7f1573cbfedbdca3fb7063fd2
|
||||
lib/codeql/swift/elements/expr/SequenceExprConstructor.qll 5a15ede013bb017a85092aff35dd2f4f1fb025e0e4e9002ac6e65b8e27c27a0b 05d6c0e2fa80bbd088b67c039520fe74ef4aa7c946f75c86207af125e7e2e6b4
|
||||
lib/codeql/swift/elements/expr/SingleValueStmtExpr.qll 9eb08ce070e3a48ed1ff11e884492c27daeae2613377d4e20a08abba917fe068 d0b293c68f5562ff27ff6bb894723e3965348530fe4924b1e492a78a9f2911d7
|
||||
lib/codeql/swift/elements/expr/SingleValueStmtExprConstructor.qll 578ff8a344c6e5d1b5d2aae9f7ca0c8205e4aab42cd1f73d00720d7c34a9c407 68c78198f1c280cb1566299b747da2b359fa9d4273e4f167693986af41450b3c
|
||||
lib/codeql/swift/elements/expr/StringLiteralExprConstructor.qll 49de92f9566459609f4a05b7bf9b776e3a420a7316151e1d3d4ec4c5471dcffb 4a7474d3782b74a098afe48599faee2c35c88c1c7a47d4b94f79d39921cd4a1f
|
||||
lib/codeql/swift/elements/expr/StringToPointerExpr.qll c30a9f184de3f395183751a826c59e5e3605560f738315cead3bf89a49cfe23c 6f6710f7ac709102b0f3240dcd779baf5da00d2e7a547d19291600bc405c5a54
|
||||
lib/codeql/swift/elements/expr/StringToPointerExprConstructor.qll 138dd290fff168d00af79f78d9d39a1940c2a1654afd0ec02e36be86cebef970 66f7385721789915b6d5311665b89feff9469707fab630a6dcbf742980857fd9
|
||||
@@ -362,7 +360,7 @@ lib/codeql/swift/elements/type/UnresolvedTypeConstructor.qll 76c34ca055a017a0fa7
|
||||
lib/codeql/swift/elements/type/VariadicSequenceTypeConstructor.qll 0d1d2328a3b5e503a883e7e6d7efd0ca5e7f2633abead9e4c94a9f98ed3cb223 69bff81c1b9413949eacb9298d2efb718ea808e68364569a1090c9878c4af856
|
||||
lib/codeql/swift/elements/type/WeakStorageType.qll 7c07739cfc1459f068f24fef74838428128054adf611504d22532e4a156073e7 9c968414d7cc8d672f3754bced5d4f83f43a6d7872d0d263d79ff60483e1f996
|
||||
lib/codeql/swift/elements/type/WeakStorageTypeConstructor.qll d88b031ef44d6de14b3ddcff2eb47b53dbd11550c37250ff2edb42e5d21ec3e9 26d855c33492cf7a118e439f7baeed0e5425cfaf058b1dcc007eca7ed765c897
|
||||
lib/codeql/swift/elements.qll 08d1b17dc7cd5f438b1fc606098b027051e0f3cc1adde2c22c2e5bb83f7cf66f 08d1b17dc7cd5f438b1fc606098b027051e0f3cc1adde2c22c2e5bb83f7cf66f
|
||||
lib/codeql/swift/elements.qll 3df0060edd2b2030f4e4d7d5518afe0073d798474d9b1d6185d833bec63ca8bd 3df0060edd2b2030f4e4d7d5518afe0073d798474d9b1d6185d833bec63ca8bd
|
||||
lib/codeql/swift/generated/AstNode.qll 02ca56d82801f942ae6265c6079d92ccafdf6b532f6bcebd98a04029ddf696e4 6216fda240e45bd4302fa0cf0f08f5f945418b144659264cdda84622b0420aa2
|
||||
lib/codeql/swift/generated/AvailabilityInfo.qll 1e38e7f52ccbcecd4dd088eae15c482d87911682dabb426332cc0e207fc6bf2f 7c6640530cdbece90d4172e8d6cfd119656860da08bb61ed4ef3a6757723994f
|
||||
lib/codeql/swift/generated/AvailabilitySpec.qll fb1255f91bb5e41ad4e9c675a2efbc50d0fb366ea2de68ab7eebd177b0795309 144e0c2e7d6c62ecee43325f7f26dcf437881edf0b75cc1bc898c6c4b61fdeaf
|
||||
@@ -378,12 +376,12 @@ lib/codeql/swift/generated/KeyPathComponent.qll c79c7bc04fc1426992ab472eedc1a20a
|
||||
lib/codeql/swift/generated/Locatable.qll be20967d48a34cdba126fe298606e0adc11697831f097acba9c52a0b7ce9983e 8aa01bc376614abbc3209e25785c72f86c9b4e94bb5f471a4a0677fedaec4f61
|
||||
lib/codeql/swift/generated/Location.qll c5793987e77812059a28254dadee29bfe9b38153c0399fbb1bf6a2f5c237fdab 6e6d8802b021e36bbaad81845657769dd48a798ea33080ada05e9818a20b38f7
|
||||
lib/codeql/swift/generated/OtherAvailabilitySpec.qll 0e26a203b26ff0581b7396b0c6d1606feec5cc32477f676585cdec4911af91c5 0e26a203b26ff0581b7396b0c6d1606feec5cc32477f676585cdec4911af91c5
|
||||
lib/codeql/swift/generated/ParentChild.qll 235b7536d6c6b027871a1308463352e4486e2e66ed179e737bf1ac35944c2aa9 9e0d24028afd81836e8fee80cf679f39b18526c95a375b4acb2f1db0508200bf
|
||||
lib/codeql/swift/generated/ParentChild.qll 680cbaa7cad7b8c33b7cf3b60aba7013facdbc5601b5076a6f38560fd284f2e8 af472eeaca6bd32848cb2de647ff015053f9fb7c54c1eca18f91fcc6ea8ad7b7
|
||||
lib/codeql/swift/generated/PlatformVersionAvailabilitySpec.qll f82d9ca416fe8bd59b5531b65b1c74c9f317b3297a6101544a11339a1cffce38 7f5c6d3309e66c134107afe55bae76dfc9a72cb7cdd6d4c3706b6b34cee09fa0
|
||||
lib/codeql/swift/generated/PureSynthConstructors.qll 173c0dd59396a1de26fe870e3bc2766c46de689da2a4d8807cb62023bbce1a98 173c0dd59396a1de26fe870e3bc2766c46de689da2a4d8807cb62023bbce1a98
|
||||
lib/codeql/swift/generated/Raw.qll 00582f74242803b3aac75448945443ed0578954c5620fb143cc6074b48616e6d b25e950dbc171c6a0cf086593e89daf177dcf24a314a4280b2cb63d24b5526ee
|
||||
lib/codeql/swift/generated/Synth.qll 0e299d5d910589d82be11fc503640d425ea20478b8a5802347fbc575075dd53c dc87a4f03bb1ead4ef6676e6fd1b53b38b9ec6904b5113f24eb7a778f089490a
|
||||
lib/codeql/swift/generated/SynthConstructors.qll e6533af43a95a90e6e07add5720c83f436aa2a24c445080ba5e8cbc6417b973f e6533af43a95a90e6e07add5720c83f436aa2a24c445080ba5e8cbc6417b973f
|
||||
lib/codeql/swift/generated/Raw.qll 59a847c009d682dfceb72f33bb54d6cf6da589e59a386450bb5fba310a4170e7 ed02d96d3bfc998a105b8f34e6a92d966e6c3db5c581872a53ac5db6904e5fab
|
||||
lib/codeql/swift/generated/Synth.qll 551fdf7e4b53f9ee1314d1bb42c2638cf82f45bfa1f40a635dfa7b6072e4418c 9ab178464700a19951fc5285acacda4913addee81515d8e072b3d7055935a814
|
||||
lib/codeql/swift/generated/SynthConstructors.qll 2f801bd8b0db829b0253cd459ed3253c1fdfc55dce68ebc53e7fec138ef0aca4 2f801bd8b0db829b0253cd459ed3253c1fdfc55dce68ebc53e7fec138ef0aca4
|
||||
lib/codeql/swift/generated/UnknownFile.qll 0fcf9beb8de79440bcdfff4bb6ab3dd139bd273e6c32754e05e6a632651e85f6 0fcf9beb8de79440bcdfff4bb6ab3dd139bd273e6c32754e05e6a632651e85f6
|
||||
lib/codeql/swift/generated/UnknownLocation.qll e50efefa02a0ec1ff635a00951b5924602fc8cab57e5756e4a039382c69d3882 e50efefa02a0ec1ff635a00951b5924602fc8cab57e5756e4a039382c69d3882
|
||||
lib/codeql/swift/generated/UnspecifiedElement.qll bfe0dfb0a34fe8f7501710809cdfb82dc423bece9f3bcd23ebfb0e3ecb7aadf7 cdf7553ba0324a7670f6a275ff99bad96498f7363234f829533a27b6e97892f4
|
||||
@@ -533,7 +531,6 @@ lib/codeql/swift/generated/expr/RebindSelfInInitializerExpr.qll 66d4cbf211cae63a
|
||||
lib/codeql/swift/generated/expr/RegexLiteralExpr.qll a11eb6f6ce7cebb35ab9ff51eae85f272980140814d7e6bded454069457a1312 bdb4bb65c9f4e187cf743ed13c0213bb7e55db9cc3adeae2169df5e32b003940
|
||||
lib/codeql/swift/generated/expr/SelfApplyExpr.qll c0815a4d6d4f08bd0c7bc170fa817ebcb2328c937c8ef16391fb0da71aff17ae 0979f035e8d4b54e93f17163a4df3c2aa65f23d56c491fa72376887e3e5c10ac
|
||||
lib/codeql/swift/generated/expr/SequenceExpr.qll 62301b2e4c76de4820c6deef0ee95c8b328ed14ba8eac70aa10cc8fb0f3c5ace feb960c796ea517abc9587bd76f7ae9aabfd9a6b0984fe2d8380e803b002eede
|
||||
lib/codeql/swift/generated/expr/SingleValueStmtExpr.qll 4c802cdd67b05e6ce6f59a71a2d8f727fb59a01acba1017b025e0979e32bb5c3 d220e60089a4ca1e464e933bd0d2b06d815fa796e5b9f5a970d4fbf3a4fde565
|
||||
lib/codeql/swift/generated/expr/StringLiteralExpr.qll f420c5cd51a223b6f98177147967266e0094a5718ba2d57ae2d3acbb64bbb4b6 30d6dab2a93fd95e652a700902c4d106fecfce13880c2ece565de29f2504bedf
|
||||
lib/codeql/swift/generated/expr/StringToPointerExpr.qll ef69b570aa90697d438f5787a86797955b4b2f985960b5859a7bd13b9ecb9cd3 ef69b570aa90697d438f5787a86797955b4b2f985960b5859a7bd13b9ecb9cd3
|
||||
lib/codeql/swift/generated/expr/SubscriptExpr.qll 8a2bf1f0ded1888546791e0e59b969267f0352223e2abeb38e91dfa2144a38ae 009566ef61689d14844730235b0e0c31ee01e95e2002cf7272cbabc97539dce9
|
||||
@@ -835,8 +832,6 @@ test/extractor-tests/generated/expr/PropertyWrapperValuePlaceholderExpr/Property
|
||||
test/extractor-tests/generated/expr/PropertyWrapperValuePlaceholderExpr/PropertyWrapperValuePlaceholderExpr_getWrappedValue.ql 208153f062b04bec13a860b64ea51c1d531597140d81a6d4598294dc9f8649a2 dfaea19e1075c02dfc0366fac8fd2edfae8dde06308730eb462c54be5b571129
|
||||
test/extractor-tests/generated/expr/RebindSelfInInitializerExpr/MISSING_SOURCE.txt 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7
|
||||
test/extractor-tests/generated/expr/RegexLiteralExpr/MISSING_SOURCE.txt 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7
|
||||
test/extractor-tests/generated/expr/SingleValueStmtExpr/SingleValueStmtExpr.ql efbfaf798a86c5a7d8053a22f61249208db31edcdaf750f2671057ad2f376806 d3256d2315d5bd5420b40a4be9522752bb57897807ea3853a7a4c61e9a05e478
|
||||
test/extractor-tests/generated/expr/SingleValueStmtExpr/SingleValueStmtExpr_getType.ql bfbeb24e57078b1bbaae331a6f3e8d13d0efbdca2228dbbca53b86d5e287efd8 864351b87f7981825e148a479e997936c653a4581e8a893eaed96ddeed891eab
|
||||
test/extractor-tests/generated/expr/StringLiteralExpr/MISSING_SOURCE.txt 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7
|
||||
test/extractor-tests/generated/expr/SubscriptExpr/MISSING_SOURCE.txt 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7
|
||||
test/extractor-tests/generated/expr/SuperRefExpr/MISSING_SOURCE.txt 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7
|
||||
|
||||
5
swift/ql/.gitattributes
generated
vendored
5
swift/ql/.gitattributes
generated
vendored
@@ -195,8 +195,6 @@
|
||||
/lib/codeql/swift/elements/expr/SelfApplyExpr.qll linguist-generated
|
||||
/lib/codeql/swift/elements/expr/SequenceExpr.qll linguist-generated
|
||||
/lib/codeql/swift/elements/expr/SequenceExprConstructor.qll linguist-generated
|
||||
/lib/codeql/swift/elements/expr/SingleValueStmtExpr.qll linguist-generated
|
||||
/lib/codeql/swift/elements/expr/SingleValueStmtExprConstructor.qll linguist-generated
|
||||
/lib/codeql/swift/elements/expr/StringLiteralExprConstructor.qll linguist-generated
|
||||
/lib/codeql/swift/elements/expr/StringToPointerExpr.qll linguist-generated
|
||||
/lib/codeql/swift/elements/expr/StringToPointerExprConstructor.qll linguist-generated
|
||||
@@ -535,7 +533,6 @@
|
||||
/lib/codeql/swift/generated/expr/RegexLiteralExpr.qll linguist-generated
|
||||
/lib/codeql/swift/generated/expr/SelfApplyExpr.qll linguist-generated
|
||||
/lib/codeql/swift/generated/expr/SequenceExpr.qll linguist-generated
|
||||
/lib/codeql/swift/generated/expr/SingleValueStmtExpr.qll linguist-generated
|
||||
/lib/codeql/swift/generated/expr/StringLiteralExpr.qll linguist-generated
|
||||
/lib/codeql/swift/generated/expr/StringToPointerExpr.qll linguist-generated
|
||||
/lib/codeql/swift/generated/expr/SubscriptExpr.qll linguist-generated
|
||||
@@ -837,8 +834,6 @@
|
||||
/test/extractor-tests/generated/expr/PropertyWrapperValuePlaceholderExpr/PropertyWrapperValuePlaceholderExpr_getWrappedValue.ql linguist-generated
|
||||
/test/extractor-tests/generated/expr/RebindSelfInInitializerExpr/MISSING_SOURCE.txt linguist-generated
|
||||
/test/extractor-tests/generated/expr/RegexLiteralExpr/MISSING_SOURCE.txt linguist-generated
|
||||
/test/extractor-tests/generated/expr/SingleValueStmtExpr/SingleValueStmtExpr.ql linguist-generated
|
||||
/test/extractor-tests/generated/expr/SingleValueStmtExpr/SingleValueStmtExpr_getType.ql linguist-generated
|
||||
/test/extractor-tests/generated/expr/StringLiteralExpr/MISSING_SOURCE.txt linguist-generated
|
||||
/test/extractor-tests/generated/expr/SubscriptExpr/MISSING_SOURCE.txt linguist-generated
|
||||
/test/extractor-tests/generated/expr/SuperRefExpr/MISSING_SOURCE.txt linguist-generated
|
||||
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
category: minorAnalysis
|
||||
---
|
||||
|
||||
* Fixed a bug where some flow sinks at field accesses were not being correctly identified.
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
category: majorAnalysis
|
||||
---
|
||||
* Added Swift 5.9.1 support
|
||||
* New AST node is extracted: `SingleValueStmtExpr`
|
||||
@@ -1417,15 +1417,6 @@ module Exprs {
|
||||
}
|
||||
}
|
||||
|
||||
/** Control-flow for a `SingleValueStmtExpr`. See the QLDoc for `SingleValueStmtExpr` for the semantics of a `SingleValueStmtExpr`. */
|
||||
private class SingleValueStmtExprTree extends AstStandardPostOrderTree {
|
||||
override SingleValueStmtExpr ast;
|
||||
|
||||
final override ControlFlowElement getChildElement(int i) {
|
||||
i = 0 and result.asAstNode() = ast.getStmt()
|
||||
}
|
||||
}
|
||||
|
||||
private class OpaqueValueExprTree extends AstLeafTree {
|
||||
override OpaqueValueExpr ast;
|
||||
}
|
||||
|
||||
@@ -32,12 +32,8 @@ predicate defaultImplicitTaintRead(DataFlow::Node node, DataFlow::ContentSet cs)
|
||||
// So when the node is a `PostUpdateNode` we allow any sequence of implicit read steps of an appropriate
|
||||
// type to make sure we arrive at the sink with an empty access path.
|
||||
exists(NominalTypeDecl d, Decl cx |
|
||||
node.(DataFlow::PostUpdateNode)
|
||||
.getPreUpdateNode()
|
||||
.asExpr()
|
||||
.getType()
|
||||
.getUnderlyingType()
|
||||
.getABaseType*() = d.getType() and
|
||||
node.(DataFlow::PostUpdateNode).getPreUpdateNode().asExpr().getType().getUnderlyingType() =
|
||||
d.getType().getABaseType*() and
|
||||
cx.asNominalTypeDecl() = d and
|
||||
cs.getAReadContent().(DataFlow::Content::FieldContent).getField() = cx.getAMember()
|
||||
)
|
||||
|
||||
1
swift/ql/lib/codeql/swift/elements.qll
generated
1
swift/ql/lib/codeql/swift/elements.qll
generated
@@ -160,7 +160,6 @@ import codeql.swift.elements.expr.ProtocolMetatypeToObjectExpr
|
||||
import codeql.swift.elements.expr.RebindSelfInInitializerExpr
|
||||
import codeql.swift.elements.expr.RegexLiteralExpr
|
||||
import codeql.swift.elements.expr.SequenceExpr
|
||||
import codeql.swift.elements.expr.SingleValueStmtExpr
|
||||
import codeql.swift.elements.expr.StringLiteralExpr
|
||||
import codeql.swift.elements.expr.StringToPointerExpr
|
||||
import codeql.swift.elements.expr.SubscriptExpr
|
||||
|
||||
@@ -1,4 +0,0 @@
|
||||
// generated by codegen/codegen.py, remove this comment if you wish to edit this file
|
||||
private import codeql.swift.generated.expr.SingleValueStmtExpr
|
||||
|
||||
class SingleValueStmtExpr extends Generated::SingleValueStmtExpr { }
|
||||
@@ -1,4 +0,0 @@
|
||||
// generated by codegen/codegen.py, remove this comment if you wish to edit this file
|
||||
private import codeql.swift.generated.Raw
|
||||
|
||||
predicate constructSingleValueStmtExpr(Raw::SingleValueStmtExpr id) { any() }
|
||||
20
swift/ql/lib/codeql/swift/generated/ParentChild.qll
generated
20
swift/ql/lib/codeql/swift/generated/ParentChild.qll
generated
@@ -1745,24 +1745,6 @@ private module Impl {
|
||||
)
|
||||
}
|
||||
|
||||
private Element getImmediateChildOfSingleValueStmtExpr(
|
||||
SingleValueStmtExpr e, int index, string partialPredicateCall
|
||||
) {
|
||||
exists(int b, int bExpr, int n, int nStmt |
|
||||
b = 0 and
|
||||
bExpr = b + 1 + max(int i | i = -1 or exists(getImmediateChildOfExpr(e, i, _)) | i) and
|
||||
n = bExpr and
|
||||
nStmt = n + 1 and
|
||||
(
|
||||
none()
|
||||
or
|
||||
result = getImmediateChildOfExpr(e, index - b, partialPredicateCall)
|
||||
or
|
||||
index = n and result = e.getStmt() and partialPredicateCall = "Stmt()"
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
private Element getImmediateChildOfSuperRefExpr(
|
||||
SuperRefExpr e, int index, string partialPredicateCall
|
||||
) {
|
||||
@@ -4995,8 +4977,6 @@ private module Impl {
|
||||
or
|
||||
result = getImmediateChildOfSequenceExpr(e, index, partialAccessor)
|
||||
or
|
||||
result = getImmediateChildOfSingleValueStmtExpr(e, index, partialAccessor)
|
||||
or
|
||||
result = getImmediateChildOfSuperRefExpr(e, index, partialAccessor)
|
||||
or
|
||||
result = getImmediateChildOfTapExpr(e, index, partialAccessor)
|
||||
|
||||
13
swift/ql/lib/codeql/swift/generated/Raw.qll
generated
13
swift/ql/lib/codeql/swift/generated/Raw.qll
generated
@@ -1571,19 +1571,6 @@ module Raw {
|
||||
Expr getElement(int index) { sequence_expr_elements(this, index, result) }
|
||||
}
|
||||
|
||||
/**
|
||||
* INTERNAL: Do not use.
|
||||
* An expression that wraps a statement which produces a single value.
|
||||
*/
|
||||
class SingleValueStmtExpr extends @single_value_stmt_expr, Expr {
|
||||
override string toString() { result = "SingleValueStmtExpr" }
|
||||
|
||||
/**
|
||||
* Gets the statement of this single value statement expression.
|
||||
*/
|
||||
Stmt getStmt() { single_value_stmt_exprs(this, result) }
|
||||
}
|
||||
|
||||
/**
|
||||
* INTERNAL: Do not use.
|
||||
*/
|
||||
|
||||
30
swift/ql/lib/codeql/swift/generated/Synth.qll
generated
30
swift/ql/lib/codeql/swift/generated/Synth.qll
generated
@@ -579,10 +579,6 @@ module Synth {
|
||||
* INTERNAL: Do not use.
|
||||
*/
|
||||
TSequenceExpr(Raw::SequenceExpr id) { constructSequenceExpr(id) } or
|
||||
/**
|
||||
* INTERNAL: Do not use.
|
||||
*/
|
||||
TSingleValueStmtExpr(Raw::SingleValueStmtExpr id) { constructSingleValueStmtExpr(id) } or
|
||||
/**
|
||||
* INTERNAL: Do not use.
|
||||
*/
|
||||
@@ -1176,8 +1172,8 @@ module Synth {
|
||||
TOneWayExpr or TOpaqueValueExpr or TOpenExistentialExpr or TOptionalEvaluationExpr or
|
||||
TOtherInitializerRefExpr or TOverloadedDeclRefExpr or
|
||||
TPropertyWrapperValuePlaceholderExpr or TRebindSelfInInitializerExpr or TSequenceExpr or
|
||||
TSingleValueStmtExpr or TSuperRefExpr or TTapExpr or TTupleElementExpr or TTupleExpr or
|
||||
TTypeExpr or TUnresolvedDeclRefExpr or TUnresolvedDotExpr or TUnresolvedMemberExpr or
|
||||
TSuperRefExpr or TTapExpr or TTupleElementExpr or TTupleExpr or TTypeExpr or
|
||||
TUnresolvedDeclRefExpr or TUnresolvedDotExpr or TUnresolvedMemberExpr or
|
||||
TUnresolvedPatternExpr or TUnresolvedSpecializeExpr or TVarargExpansionExpr;
|
||||
|
||||
/**
|
||||
@@ -2377,15 +2373,6 @@ module Synth {
|
||||
cached
|
||||
TSequenceExpr convertSequenceExprFromRaw(Raw::Element e) { result = TSequenceExpr(e) }
|
||||
|
||||
/**
|
||||
* INTERNAL: Do not use.
|
||||
* Converts a raw element to a synthesized `TSingleValueStmtExpr`, if possible.
|
||||
*/
|
||||
cached
|
||||
TSingleValueStmtExpr convertSingleValueStmtExprFromRaw(Raw::Element e) {
|
||||
result = TSingleValueStmtExpr(e)
|
||||
}
|
||||
|
||||
/**
|
||||
* INTERNAL: Do not use.
|
||||
* Converts a raw element to a synthesized `TStringLiteralExpr`, if possible.
|
||||
@@ -3669,8 +3656,6 @@ module Synth {
|
||||
or
|
||||
result = convertSequenceExprFromRaw(e)
|
||||
or
|
||||
result = convertSingleValueStmtExprFromRaw(e)
|
||||
or
|
||||
result = convertSuperRefExprFromRaw(e)
|
||||
or
|
||||
result = convertTapExprFromRaw(e)
|
||||
@@ -5193,15 +5178,6 @@ module Synth {
|
||||
cached
|
||||
Raw::Element convertSequenceExprToRaw(TSequenceExpr e) { e = TSequenceExpr(result) }
|
||||
|
||||
/**
|
||||
* INTERNAL: Do not use.
|
||||
* Converts a synthesized `TSingleValueStmtExpr` to a raw DB element, if possible.
|
||||
*/
|
||||
cached
|
||||
Raw::Element convertSingleValueStmtExprToRaw(TSingleValueStmtExpr e) {
|
||||
e = TSingleValueStmtExpr(result)
|
||||
}
|
||||
|
||||
/**
|
||||
* INTERNAL: Do not use.
|
||||
* Converts a synthesized `TStringLiteralExpr` to a raw DB element, if possible.
|
||||
@@ -6485,8 +6461,6 @@ module Synth {
|
||||
or
|
||||
result = convertSequenceExprToRaw(e)
|
||||
or
|
||||
result = convertSingleValueStmtExprToRaw(e)
|
||||
or
|
||||
result = convertSuperRefExprToRaw(e)
|
||||
or
|
||||
result = convertTapExprToRaw(e)
|
||||
|
||||
@@ -127,7 +127,6 @@ import codeql.swift.elements.expr.ProtocolMetatypeToObjectExprConstructor
|
||||
import codeql.swift.elements.expr.RebindSelfInInitializerExprConstructor
|
||||
import codeql.swift.elements.expr.RegexLiteralExprConstructor
|
||||
import codeql.swift.elements.expr.SequenceExprConstructor
|
||||
import codeql.swift.elements.expr.SingleValueStmtExprConstructor
|
||||
import codeql.swift.elements.expr.StringLiteralExprConstructor
|
||||
import codeql.swift.elements.expr.StringToPointerExprConstructor
|
||||
import codeql.swift.elements.expr.SubscriptExprConstructor
|
||||
|
||||
@@ -1,24 +0,0 @@
|
||||
// generated by codegen/codegen.py
|
||||
private import codeql.swift.generated.Synth
|
||||
private import codeql.swift.generated.Raw
|
||||
import codeql.swift.elements.expr.Expr
|
||||
import codeql.swift.elements.stmt.Stmt
|
||||
|
||||
module Generated {
|
||||
/**
|
||||
* An expression that wraps a statement which produces a single value.
|
||||
*/
|
||||
class SingleValueStmtExpr extends Synth::TSingleValueStmtExpr, Expr {
|
||||
override string getAPrimaryQlClass() { result = "SingleValueStmtExpr" }
|
||||
|
||||
/**
|
||||
* Gets the statement of this single value statement expression.
|
||||
*/
|
||||
Stmt getStmt() {
|
||||
result =
|
||||
Synth::convertStmtFromRaw(Synth::convertSingleValueStmtExprToRaw(this)
|
||||
.(Raw::SingleValueStmtExpr)
|
||||
.getStmt())
|
||||
}
|
||||
}
|
||||
}
|
||||
6
swift/ql/lib/swift.dbscheme
generated
6
swift/ql/lib/swift.dbscheme
generated
@@ -764,7 +764,6 @@ arguments( //dir=expr
|
||||
| @property_wrapper_value_placeholder_expr
|
||||
| @rebind_self_in_initializer_expr
|
||||
| @sequence_expr
|
||||
| @single_value_stmt_expr
|
||||
| @super_ref_expr
|
||||
| @tap_expr
|
||||
| @tuple_element_expr
|
||||
@@ -1144,11 +1143,6 @@ sequence_expr_elements( //dir=expr
|
||||
int element: @expr_or_none ref
|
||||
);
|
||||
|
||||
single_value_stmt_exprs( //dir=expr
|
||||
unique int id: @single_value_stmt_expr,
|
||||
int stmt: @stmt_or_none ref
|
||||
);
|
||||
|
||||
super_ref_exprs( //dir=expr
|
||||
unique int id: @super_ref_expr,
|
||||
int self: @var_decl_or_none ref
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,2 +0,0 @@
|
||||
description: Added SingleValueStmtExpr
|
||||
compatibility: full
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
category: newQuery
|
||||
---
|
||||
|
||||
* Added new query "System command built from user-controlled sources" (`swift/command-line-injection`) for Swift. This query detects system commands built from user-controlled sources without sufficient validation. The query was previously [contributed to the 'experimental' directory by @maikypedia](https://github.com/github/codeql/pull/13726) but will now run by default for all code scanning users.
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user