mirror of
https://github.com/github/codeql.git
synced 2026-05-27 09:31:30 +02:00
Compare commits
140 Commits
criemen/mo
...
mbg/csharp
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2bce3879db | ||
|
|
a126e1dfae | ||
|
|
ebc4aaa3db | ||
|
|
373eb0a57e | ||
|
|
adde95d7a1 | ||
|
|
098812b073 | ||
|
|
ca334021ad | ||
|
|
69ab389d9f | ||
|
|
30f0b8ab2b | ||
|
|
75f42f4614 | ||
|
|
0c1fb8c881 | ||
|
|
4f9303eb02 | ||
|
|
2c23dacca1 | ||
|
|
a5e7ef424e | ||
|
|
84e58b77aa | ||
|
|
3092640115 | ||
|
|
143e1680bd | ||
|
|
de83929a60 | ||
|
|
d7c97d9d92 | ||
|
|
30925da7d9 | ||
|
|
f1001374fd | ||
|
|
25d3af9236 | ||
|
|
1f3f1b5ec4 | ||
|
|
947b094387 | ||
|
|
009d58034f | ||
|
|
5c0fb2030d | ||
|
|
2eb67549e6 | ||
|
|
afe318edbe | ||
|
|
71ef98584d | ||
|
|
6bba191407 | ||
|
|
df144f3a1e | ||
|
|
a46dc55e84 | ||
|
|
14268f3c63 | ||
|
|
408ba517e5 | ||
|
|
4d4ca6b948 | ||
|
|
d443354651 | ||
|
|
57f6859ddc | ||
|
|
5f087f0084 | ||
|
|
f66f7ce8d7 | ||
|
|
f22979f4b6 | ||
|
|
46e6e72593 | ||
|
|
92c18960c5 | ||
|
|
e349891cff | ||
|
|
e02c32f3d4 | ||
|
|
0f1dc9b2d9 | ||
|
|
ae6c95ff95 | ||
|
|
bae7e10e46 | ||
|
|
ec63099c54 | ||
|
|
2b8b5cf1b8 | ||
|
|
6730f57d5c | ||
|
|
118d50236f | ||
|
|
a46a7fadb2 | ||
|
|
7a001f4905 | ||
|
|
803ed20962 | ||
|
|
4256fbf11a | ||
|
|
f3dd002ba9 | ||
|
|
f9e9ae91f7 | ||
|
|
23419ee634 | ||
|
|
b8f0f85840 | ||
|
|
69453aa144 | ||
|
|
55f5b26ba6 | ||
|
|
721bde1ce8 | ||
|
|
2e9d548083 | ||
|
|
83d1fc33e1 | ||
|
|
14e51627c5 | ||
|
|
52540b42fc | ||
|
|
6bd7047e41 | ||
|
|
57f1f5b829 | ||
|
|
bff93c4484 | ||
|
|
0342b3eba2 | ||
|
|
d28e7920b3 | ||
|
|
331ca61be9 | ||
|
|
559b965e74 | ||
|
|
6299b844f8 | ||
|
|
4385b316c0 | ||
|
|
b1dc6099ff | ||
|
|
15099b3db0 | ||
|
|
8334c6db91 | ||
|
|
1c75e5b2a6 | ||
|
|
1623bba18a | ||
|
|
475d8da342 | ||
|
|
ae09499905 | ||
|
|
c950e26b3e | ||
|
|
f75c062949 | ||
|
|
f22d87b7c7 | ||
|
|
e11a68803e | ||
|
|
45faed057c | ||
|
|
f1b67ade9b | ||
|
|
f9ae7c5454 | ||
|
|
296dee90dd | ||
|
|
967bbbc1a7 | ||
|
|
c8779d0d0b | ||
|
|
28160e418c | ||
|
|
ed349f7d6b | ||
|
|
fa569dcef4 | ||
|
|
040d971588 | ||
|
|
e95bfc816e | ||
|
|
44935cef63 | ||
|
|
190050f577 | ||
|
|
458baeff32 | ||
|
|
5a451e964d | ||
|
|
b157d73c10 | ||
|
|
985d1990eb | ||
|
|
463096e4be | ||
|
|
892beeab6d | ||
|
|
9ec2f9204b | ||
|
|
c73e6f1fa8 | ||
|
|
9aafbfce13 | ||
|
|
cc6268339b | ||
|
|
834b07e6ad | ||
|
|
031f453af8 | ||
|
|
002f2a0985 | ||
|
|
d21e27c717 | ||
|
|
30e4822fb7 | ||
|
|
ed9a0ea155 | ||
|
|
5fc8a00487 | ||
|
|
b3feb4d7e9 | ||
|
|
9b0ad8295e | ||
|
|
9d5cf0b331 | ||
|
|
5433907c33 | ||
|
|
5bee44dcfe | ||
|
|
6568332e3d | ||
|
|
6c50c2bfe6 | ||
|
|
e8eff78799 | ||
|
|
ad756d59c8 | ||
|
|
315bdc2b48 | ||
|
|
637c52d10a | ||
|
|
92b13c4259 | ||
|
|
3d8a7e0ee3 | ||
|
|
225c96ec9f | ||
|
|
37361d9f79 | ||
|
|
5385cc3aaa | ||
|
|
9087259b1b | ||
|
|
968127eaa3 | ||
|
|
a0e2e1ef21 | ||
|
|
1fe565a46f | ||
|
|
76e56cdac7 | ||
|
|
ad2631202d | ||
|
|
6c8cc79b4d | ||
|
|
1a51c015b4 |
@@ -0,0 +1,4 @@
|
||||
---
|
||||
category: minorAnalysis
|
||||
---
|
||||
* The "Returning stack-allocated memory" (`cpp/return-stack-allocated-memory`) query now also detects returning stack-allocated memory allocated by calls to `alloca`, `strdupa`, and `strndupa`.
|
||||
@@ -27,16 +27,26 @@ class ReturnStackAllocatedMemoryConfig extends MustFlowConfiguration {
|
||||
ReturnStackAllocatedMemoryConfig() { this = "ReturnStackAllocatedMemoryConfig" }
|
||||
|
||||
override predicate isSource(Instruction source) {
|
||||
// Holds if `source` is a node that represents the use of a stack variable
|
||||
exists(VariableAddressInstruction var, Function func |
|
||||
var = source and
|
||||
func = source.getEnclosingFunction() and
|
||||
var.getAstVariable() instanceof StackVariable and
|
||||
// Pointer-to-member types aren't properly handled in the dbscheme.
|
||||
not var.getResultType() instanceof PointerToMemberType and
|
||||
exists(Function func |
|
||||
// Rule out FPs caused by extraction errors.
|
||||
not any(ErrorExpr e).getEnclosingFunction() = func and
|
||||
not intentionallyReturnsStackPointer(func)
|
||||
not intentionallyReturnsStackPointer(func) and
|
||||
func = source.getEnclosingFunction()
|
||||
|
|
||||
// `source` is an instruction that represents the use of a stack variable
|
||||
exists(VariableAddressInstruction var |
|
||||
var = source and
|
||||
var.getAstVariable() instanceof StackVariable and
|
||||
// Pointer-to-member types aren't properly handled in the dbscheme.
|
||||
not var.getResultType() instanceof PointerToMemberType
|
||||
)
|
||||
or
|
||||
// `source` is an instruction that represents the return value of a
|
||||
// function that is known to return stack-allocated memory.
|
||||
exists(Call call |
|
||||
call.getTarget().hasGlobalName(["alloca", "strdupa", "strndupa", "_alloca", "_malloca"]) and
|
||||
source.getUnconvertedResultExpression() = call
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -85,10 +95,10 @@ class ReturnStackAllocatedMemoryConfig extends MustFlowConfiguration {
|
||||
}
|
||||
|
||||
from
|
||||
MustFlowPathNode source, MustFlowPathNode sink, VariableAddressInstruction var,
|
||||
MustFlowPathNode source, MustFlowPathNode sink, Instruction instr,
|
||||
ReturnStackAllocatedMemoryConfig conf
|
||||
where
|
||||
conf.hasFlowPath(pragma[only_bind_into](source), pragma[only_bind_into](sink)) and
|
||||
source.getInstruction() = var
|
||||
source.getInstruction() = instr
|
||||
select sink.getInstruction(), source, sink, "May return stack-allocated memory from $@.",
|
||||
var.getAst(), var.getAst().toString()
|
||||
instr.getAst(), instr.getAst().toString()
|
||||
|
||||
@@ -14,25 +14,47 @@
|
||||
|
||||
import cpp
|
||||
import semmle.code.cpp.security.Security
|
||||
import semmle.code.cpp.ir.dataflow.internal.DefaultTaintTrackingImpl
|
||||
import TaintedWithPath
|
||||
import semmle.code.cpp.security.FlowSources
|
||||
import semmle.code.cpp.ir.dataflow.TaintTracking
|
||||
import semmle.code.cpp.ir.IR
|
||||
import Flow::PathGraph
|
||||
|
||||
predicate isProcessOperationExplanation(Expr arg, string processOperation) {
|
||||
predicate isProcessOperationExplanation(DataFlow::Node arg, string processOperation) {
|
||||
exists(int processOperationArg, FunctionCall call |
|
||||
isProcessOperationArgument(processOperation, processOperationArg) and
|
||||
call.getTarget().getName() = processOperation and
|
||||
call.getArgument(processOperationArg) = arg
|
||||
call.getArgument(processOperationArg) = [arg.asExpr(), arg.asIndirectExpr()]
|
||||
)
|
||||
}
|
||||
|
||||
class Configuration extends TaintTrackingConfiguration {
|
||||
override predicate isSink(Element arg) { isProcessOperationExplanation(arg, _) }
|
||||
predicate isSource(FlowSource source, string sourceType) {
|
||||
not source instanceof DataFlow::ExprNode and
|
||||
sourceType = source.getSourceType()
|
||||
}
|
||||
|
||||
from string processOperation, Expr arg, Expr source, PathNode sourceNode, PathNode sinkNode
|
||||
module Config implements DataFlow::ConfigSig {
|
||||
predicate isSource(DataFlow::Node node) { isSource(node, _) }
|
||||
|
||||
predicate isSink(DataFlow::Node node) { isProcessOperationExplanation(node, _) }
|
||||
|
||||
predicate isBarrier(DataFlow::Node node) {
|
||||
isSink(node) and node.asExpr().getUnspecifiedType() instanceof ArithmeticType
|
||||
or
|
||||
node.asInstruction().(StoreInstruction).getResultType() instanceof ArithmeticType
|
||||
}
|
||||
}
|
||||
|
||||
module Flow = TaintTracking::Global<Config>;
|
||||
|
||||
from
|
||||
string processOperation, string sourceType, DataFlow::Node source, DataFlow::Node sink,
|
||||
Flow::PathNode sourceNode, Flow::PathNode sinkNode
|
||||
where
|
||||
isProcessOperationExplanation(arg, processOperation) and
|
||||
taintedWithPath(source, arg, sourceNode, sinkNode)
|
||||
select arg, sourceNode, sinkNode,
|
||||
source = sourceNode.getNode() and
|
||||
sink = sinkNode.getNode() and
|
||||
isSource(source, sourceType) and
|
||||
isProcessOperationExplanation(sink, processOperation) and
|
||||
Flow::flowPath(sourceNode, sinkNode)
|
||||
select sink, sourceNode, sinkNode,
|
||||
"The value of this argument may come from $@ and is being passed to " + processOperation + ".",
|
||||
source, source.toString()
|
||||
source, sourceType
|
||||
|
||||
@@ -52,16 +52,17 @@ predicate isUnboundedWrite(BufferWrite bw) {
|
||||
* Holds if `e` is a source buffer going into an unbounded write `bw` or a
|
||||
* qualifier of (a qualifier of ...) such a source.
|
||||
*/
|
||||
predicate unboundedWriteSource(Expr e, BufferWrite bw) {
|
||||
isUnboundedWrite(bw) and e = bw.getASource()
|
||||
predicate unboundedWriteSource(Expr e, BufferWrite bw, boolean qualifier) {
|
||||
isUnboundedWrite(bw) and e = bw.getASource() and qualifier = false
|
||||
or
|
||||
exists(FieldAccess fa | unboundedWriteSource(fa, bw) and e = fa.getQualifier())
|
||||
exists(FieldAccess fa | unboundedWriteSource(fa, bw, _) and e = fa.getQualifier()) and
|
||||
qualifier = true
|
||||
}
|
||||
|
||||
predicate isSource(FS::FlowSource source, string sourceType) { source.getSourceType() = sourceType }
|
||||
|
||||
predicate isSink(DataFlow::Node sink, BufferWrite bw) {
|
||||
unboundedWriteSource(sink.asIndirectExpr(), bw)
|
||||
predicate isSink(DataFlow::Node sink, BufferWrite bw, boolean qualifier) {
|
||||
unboundedWriteSource(sink.asIndirectExpr(), bw, qualifier)
|
||||
or
|
||||
// `gets` and `scanf` reads from stdin so there's no real input.
|
||||
// The `BufferWrite` library models this as the call itself being
|
||||
@@ -69,7 +70,7 @@ predicate isSink(DataFlow::Node sink, BufferWrite bw) {
|
||||
// the sink so that we report a path where source = sink (because
|
||||
// the same output argument is also included in `isSource`).
|
||||
bw.getASource() = bw and
|
||||
unboundedWriteSource(sink.asDefiningArgument(), bw)
|
||||
unboundedWriteSource(sink.asDefiningArgument(), bw, qualifier)
|
||||
}
|
||||
|
||||
predicate lessThanOrEqual(IRGuardCondition g, Expr e, boolean branch) {
|
||||
@@ -84,9 +85,9 @@ predicate lessThanOrEqual(IRGuardCondition g, Expr e, boolean branch) {
|
||||
module Config implements DataFlow::ConfigSig {
|
||||
predicate isSource(DataFlow::Node source) { isSource(source, _) }
|
||||
|
||||
predicate isSink(DataFlow::Node sink) { isSink(sink, _) }
|
||||
predicate isSink(DataFlow::Node sink) { isSink(sink, _, _) }
|
||||
|
||||
predicate isBarrierOut(DataFlow::Node node) { isSink(node) }
|
||||
predicate isBarrierOut(DataFlow::Node node) { isSink(node, _, false) }
|
||||
|
||||
predicate isBarrier(DataFlow::Node node) {
|
||||
// Block flow if the node is guarded by any <, <= or = operations.
|
||||
@@ -116,7 +117,7 @@ from BufferWrite bw, Flow::PathNode source, Flow::PathNode sink, string sourceTy
|
||||
where
|
||||
Flow::flowPath(source, sink) and
|
||||
isSource(source.getNode(), sourceType) and
|
||||
isSink(sink.getNode(), bw)
|
||||
isSink(sink.getNode(), bw, _)
|
||||
select bw, source, sink,
|
||||
"This '" + bw.getBWDesc() + "' with input from $@ may overflow the destination.",
|
||||
source.getNode(), sourceType
|
||||
|
||||
@@ -1,24 +0,0 @@
|
||||
#include <stdio.h>
|
||||
|
||||
char *copy;
|
||||
|
||||
void copyArgv(char **argv) {
|
||||
copy = argv[1];
|
||||
}
|
||||
|
||||
void printWrapper(char *str) {
|
||||
printf(str);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
copyArgv(argv);
|
||||
|
||||
// This should be avoided
|
||||
printf(copy);
|
||||
|
||||
// This should be avoided too, because it has the same effect
|
||||
printWrapper(copy);
|
||||
|
||||
// This is fine
|
||||
printf("%s", copy);
|
||||
}
|
||||
@@ -1,36 +0,0 @@
|
||||
<!DOCTYPE qhelp PUBLIC
|
||||
"-//Semmle//qhelp//EN"
|
||||
"qhelp.dtd">
|
||||
<qhelp>
|
||||
<overview>
|
||||
<p>The program uses input from the user, propagated via a global variable, as a format string for <code>printf</code> style functions.
|
||||
This can lead to buffer overflows or data representation problems. An attacker can exploit this weakness to crash the program,
|
||||
disclose information or even execute arbitrary code.</p>
|
||||
|
||||
<p>This rule only identifies inputs from the user that are transferred through global variables before being used in <code>printf</code> style functions.
|
||||
Analyzing the flow of data through global variables is more prone to errors and so this rule may identify some examples of code where
|
||||
the input is not really from the user. For example, when a global variable is set in two places, one that comes from the user and one that does not.
|
||||
In this case we would mark all usages of the global variable as input from the user, but the input from the user may always came after the call to the
|
||||
<code>printf</code> style functions.</p>
|
||||
|
||||
<p>The results of this rule should be considered alongside the related rule "Uncontrolled format string" which tracks the flow of the
|
||||
values input by a user, excluding global variables, until the values are used as the format argument for a <code>printf</code> like function call.</p>
|
||||
|
||||
</overview>
|
||||
<recommendation>
|
||||
<p>Use constant expressions as the format strings. If you need to print a value from the user, use <code>printf("%s", value_from_user)</code>.</p>
|
||||
|
||||
</recommendation>
|
||||
<example>
|
||||
<sample src="UncontrolledFormatStringThroughGlobalVar.c" />
|
||||
|
||||
</example>
|
||||
<references>
|
||||
|
||||
<li>CERT C Coding
|
||||
Standard: <a href="https://www.securecoding.cert.org/confluence/display/c/FIO30-C.+Exclude+user+input+from+format+strings">FIO30-C. Exclude
|
||||
user input from format strings</a>.</li>
|
||||
|
||||
|
||||
</references>
|
||||
</qhelp>
|
||||
@@ -1,40 +0,0 @@
|
||||
/**
|
||||
* @name Uncontrolled format string (through global variable)
|
||||
* @description Using externally-controlled format strings in
|
||||
* printf-style functions can lead to buffer overflows
|
||||
* or data representation problems.
|
||||
* @kind path-problem
|
||||
* @problem.severity warning
|
||||
* @security-severity 9.3
|
||||
* @precision high
|
||||
* @id cpp/tainted-format-string-through-global
|
||||
* @tags reliability
|
||||
* security
|
||||
* external/cwe/cwe-134
|
||||
*/
|
||||
|
||||
import cpp
|
||||
import semmle.code.cpp.security.FunctionWithWrappers
|
||||
import semmle.code.cpp.security.Security
|
||||
import semmle.code.cpp.ir.dataflow.internal.DefaultTaintTrackingImpl
|
||||
import TaintedWithPath
|
||||
|
||||
class Configuration extends TaintTrackingConfiguration {
|
||||
override predicate isSink(Element tainted) {
|
||||
exists(PrintfLikeFunction printf | printf.outermostWrapperFunctionCall(tainted, _))
|
||||
}
|
||||
|
||||
override predicate taintThroughGlobals() { any() }
|
||||
}
|
||||
|
||||
from
|
||||
PrintfLikeFunction printf, Expr arg, PathNode sourceNode, PathNode sinkNode,
|
||||
string printfFunction, Expr userValue, string cause
|
||||
where
|
||||
printf.outermostWrapperFunctionCall(arg, printfFunction) and
|
||||
not taintedWithoutGlobals(arg) and
|
||||
taintedWithPath(userValue, arg, sourceNode, sinkNode) and
|
||||
isUserInput(userValue, cause)
|
||||
select arg, sourceNode, sinkNode,
|
||||
"The value of this argument may come from $@ and is being used as a formatting argument to " +
|
||||
printfFunction + ".", userValue, cause
|
||||
@@ -14,10 +14,13 @@
|
||||
|
||||
import cpp
|
||||
import semmle.code.cpp.security.Overflow
|
||||
import semmle.code.cpp.security.Security
|
||||
import semmle.code.cpp.ir.dataflow.internal.DefaultTaintTrackingImpl
|
||||
import TaintedWithPath
|
||||
import semmle.code.cpp.dataflow.new.TaintTracking
|
||||
import semmle.code.cpp.dataflow.new.DataFlow
|
||||
import semmle.code.cpp.ir.IR
|
||||
import semmle.code.cpp.controlflow.IRGuards as IRGuards
|
||||
import semmle.code.cpp.security.FlowSources as FS
|
||||
import Bounded
|
||||
import Flow::PathGraph
|
||||
|
||||
bindingset[op]
|
||||
predicate missingGuard(Operation op, Expr e, string effect) {
|
||||
@@ -28,28 +31,90 @@ predicate missingGuard(Operation op, Expr e, string effect) {
|
||||
not e instanceof VariableAccess and effect = "overflow"
|
||||
}
|
||||
|
||||
class Configuration extends TaintTrackingConfiguration {
|
||||
override predicate isSink(Element e) {
|
||||
exists(Operation op |
|
||||
missingGuard(op, e, _) and
|
||||
op.getAnOperand() = e
|
||||
|
|
||||
op instanceof UnaryArithmeticOperation or
|
||||
op instanceof BinaryArithmeticOperation or
|
||||
op instanceof AssignArithmeticOperation
|
||||
)
|
||||
}
|
||||
predicate isSource(FS::FlowSource source, string sourceType) { sourceType = source.getSourceType() }
|
||||
|
||||
override predicate isBarrier(Expr e) {
|
||||
super.isBarrier(e) or bounded(e) or e.getUnspecifiedType().(IntegralType).getSize() <= 1
|
||||
predicate isSink(DataFlow::Node sink, Operation op, Expr e) {
|
||||
e = sink.asExpr() and
|
||||
missingGuard(op, e, _) and
|
||||
op.getAnOperand() = e and
|
||||
(
|
||||
op instanceof UnaryArithmeticOperation or
|
||||
op instanceof BinaryArithmeticOperation or
|
||||
op instanceof AssignArithmeticOperation
|
||||
)
|
||||
}
|
||||
|
||||
predicate hasUpperBoundsCheck(Variable var) {
|
||||
exists(RelationalOperation oper, VariableAccess access |
|
||||
oper.getAnOperand() = access and
|
||||
access.getTarget() = var and
|
||||
// Comparing to 0 is not an upper bound check
|
||||
not oper.getAnOperand().getValue() = "0"
|
||||
)
|
||||
}
|
||||
|
||||
predicate constantInstruction(Instruction instr) {
|
||||
instr instanceof ConstantInstruction or
|
||||
constantInstruction(instr.(UnaryInstruction).getUnary())
|
||||
}
|
||||
|
||||
predicate readsVariable(LoadInstruction load, Variable var) {
|
||||
load.getSourceAddress().(VariableAddressInstruction).getAstVariable() = var
|
||||
}
|
||||
|
||||
predicate nodeIsBarrierEqualityCandidate(DataFlow::Node node, Operand access, Variable checkedVar) {
|
||||
exists(Instruction instr | instr = node.asInstruction() |
|
||||
readsVariable(instr, checkedVar) and
|
||||
any(IRGuards::IRGuardCondition guard).ensuresEq(access, _, _, instr.getBlock(), true)
|
||||
)
|
||||
}
|
||||
|
||||
module Config implements DataFlow::ConfigSig {
|
||||
predicate isSource(DataFlow::Node source) { isSource(source, _) }
|
||||
|
||||
predicate isSink(DataFlow::Node sink) { isSink(sink, _, _) }
|
||||
|
||||
predicate isBarrier(DataFlow::Node node) {
|
||||
exists(StoreInstruction store | store = node.asInstruction() |
|
||||
// Block flow to "likely small expressions"
|
||||
bounded(store.getSourceValue().getUnconvertedResultExpression())
|
||||
or
|
||||
// Block flow to "small types"
|
||||
store.getResultType().getUnspecifiedType().(IntegralType).getSize() <= 1
|
||||
)
|
||||
or
|
||||
// Block flow if there's an upper bound check of the variable anywhere in the program
|
||||
exists(Variable checkedVar, Instruction instr | instr = node.asInstruction() |
|
||||
readsVariable(instr, checkedVar) and
|
||||
hasUpperBoundsCheck(checkedVar)
|
||||
)
|
||||
or
|
||||
// Block flow if the node is guarded by an equality check
|
||||
exists(Variable checkedVar, Operand access |
|
||||
nodeIsBarrierEqualityCandidate(node, access, checkedVar) and
|
||||
readsVariable(access.getDef(), checkedVar)
|
||||
)
|
||||
or
|
||||
// Block flow to any binary instruction whose operands are both non-constants.
|
||||
exists(BinaryInstruction iTo |
|
||||
iTo = node.asInstruction() and
|
||||
not constantInstruction(iTo.getLeft()) and
|
||||
not constantInstruction(iTo.getRight()) and
|
||||
// propagate taint from either the pointer or the offset, regardless of constantness
|
||||
not iTo instanceof PointerArithmeticInstruction
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
from Expr origin, Expr e, string effect, PathNode sourceNode, PathNode sinkNode, Operation op
|
||||
module Flow = TaintTracking::Global<Config>;
|
||||
|
||||
from
|
||||
Expr e, string effect, Flow::PathNode source, Flow::PathNode sink, Operation op, string sourceType
|
||||
where
|
||||
taintedWithPath(origin, e, sourceNode, sinkNode) and
|
||||
op.getAnOperand() = e and
|
||||
Flow::flowPath(source, sink) and
|
||||
isSource(source.getNode(), sourceType) and
|
||||
isSink(sink.getNode(), op, e) and
|
||||
missingGuard(op, e, effect)
|
||||
select e, sourceNode, sinkNode,
|
||||
select e, source, sink,
|
||||
"$@ flows to an operand of an arithmetic expression, potentially causing an " + effect + ".",
|
||||
origin, "User-provided value"
|
||||
source, sourceType
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
* @description The total number of lines of C/C++ code across all files, including system headers, libraries, and auto-generated files. This is a useful metric of the size of a database. For all files that were seen during the build, this query counts the lines of code, excluding whitespace or comments.
|
||||
* @kind metric
|
||||
* @tags summary
|
||||
* telemetry
|
||||
*/
|
||||
|
||||
import cpp
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
---
|
||||
category: breaking
|
||||
---
|
||||
* The `cpp/tainted-format-string-through-global` query has been deleted. This does not lead to a loss of relevant alerts, as the query duplicated a subset of the alerts from `cpp/tainted-format-string`.
|
||||
@@ -43,6 +43,11 @@ edges
|
||||
| test.cpp:189:16:189:16 | p | test.cpp:189:16:189:16 | (reference to) |
|
||||
| test.cpp:190:10:190:13 | (reference dereference) | test.cpp:190:10:190:13 | (reference to) |
|
||||
| test.cpp:190:10:190:13 | pRef | test.cpp:190:10:190:13 | (reference dereference) |
|
||||
| test.cpp:237:12:237:17 | call to alloca | test.cpp:237:12:237:17 | call to alloca |
|
||||
| test.cpp:237:12:237:17 | call to alloca | test.cpp:238:9:238:9 | p |
|
||||
| test.cpp:249:13:249:20 | call to strndupa | test.cpp:249:13:249:20 | call to strndupa |
|
||||
| test.cpp:249:13:249:20 | call to strndupa | test.cpp:250:9:250:10 | s2 |
|
||||
| test.cpp:250:9:250:10 | s2 | test.cpp:250:9:250:10 | (void *)... |
|
||||
nodes
|
||||
| test.cpp:17:9:17:11 | & ... | semmle.label | & ... |
|
||||
| test.cpp:17:10:17:11 | mc | semmle.label | mc |
|
||||
@@ -101,6 +106,14 @@ nodes
|
||||
| test.cpp:190:10:190:13 | (reference dereference) | semmle.label | (reference dereference) |
|
||||
| test.cpp:190:10:190:13 | (reference to) | semmle.label | (reference to) |
|
||||
| test.cpp:190:10:190:13 | pRef | semmle.label | pRef |
|
||||
| test.cpp:237:12:237:17 | call to alloca | semmle.label | call to alloca |
|
||||
| test.cpp:237:12:237:17 | call to alloca | semmle.label | call to alloca |
|
||||
| test.cpp:238:9:238:9 | p | semmle.label | p |
|
||||
| test.cpp:245:9:245:15 | call to strdupa | semmle.label | call to strdupa |
|
||||
| test.cpp:249:13:249:20 | call to strndupa | semmle.label | call to strndupa |
|
||||
| test.cpp:249:13:249:20 | call to strndupa | semmle.label | call to strndupa |
|
||||
| test.cpp:250:9:250:10 | (void *)... | semmle.label | (void *)... |
|
||||
| test.cpp:250:9:250:10 | s2 | semmle.label | s2 |
|
||||
#select
|
||||
| test.cpp:17:9:17:11 | CopyValue: & ... | test.cpp:17:10:17:11 | mc | test.cpp:17:9:17:11 | & ... | May return stack-allocated memory from $@. | test.cpp:17:10:17:11 | mc | mc |
|
||||
| test.cpp:25:9:25:11 | Load: ptr | test.cpp:23:18:23:19 | mc | test.cpp:25:9:25:11 | ptr | May return stack-allocated memory from $@. | test.cpp:23:18:23:19 | mc | mc |
|
||||
@@ -115,3 +128,6 @@ nodes
|
||||
| test.cpp:177:10:177:23 | Convert: (void *)... | test.cpp:176:25:176:34 | localArray | test.cpp:177:10:177:23 | (void *)... | May return stack-allocated memory from $@. | test.cpp:176:25:176:34 | localArray | localArray |
|
||||
| test.cpp:183:10:183:19 | CopyValue: (reference to) | test.cpp:182:21:182:27 | myLocal | test.cpp:183:10:183:19 | (reference to) | May return stack-allocated memory from $@. | test.cpp:182:21:182:27 | myLocal | myLocal |
|
||||
| test.cpp:190:10:190:13 | CopyValue: (reference to) | test.cpp:189:16:189:16 | p | test.cpp:190:10:190:13 | (reference to) | May return stack-allocated memory from $@. | test.cpp:189:16:189:16 | p | p |
|
||||
| test.cpp:238:9:238:9 | Load: p | test.cpp:237:12:237:17 | call to alloca | test.cpp:238:9:238:9 | p | May return stack-allocated memory from $@. | test.cpp:237:12:237:17 | call to alloca | call to alloca |
|
||||
| test.cpp:245:9:245:15 | Call: call to strdupa | test.cpp:245:9:245:15 | call to strdupa | test.cpp:245:9:245:15 | call to strdupa | May return stack-allocated memory from $@. | test.cpp:245:9:245:15 | call to strdupa | call to strdupa |
|
||||
| test.cpp:250:9:250:10 | Convert: (void *)... | test.cpp:249:13:249:20 | call to strndupa | test.cpp:250:9:250:10 | (void *)... | May return stack-allocated memory from $@. | test.cpp:249:13:249:20 | call to strndupa | call to strndupa |
|
||||
|
||||
@@ -229,4 +229,23 @@ int* id(int* px) {
|
||||
void f() {
|
||||
int x;
|
||||
int* px = id(&x); // GOOD
|
||||
}
|
||||
|
||||
void *alloca(size_t);
|
||||
|
||||
void* test_alloca() {
|
||||
void* p = alloca(10);
|
||||
return p; // BAD
|
||||
}
|
||||
|
||||
char *strdupa(const char *);
|
||||
char *strndupa(const char *, size_t);
|
||||
|
||||
char* test_strdupa(const char* s) {
|
||||
return strdupa(s); // BAD
|
||||
}
|
||||
|
||||
void* test_strndupa(const char* s, size_t size) {
|
||||
char* s2 = strndupa(s, size);
|
||||
return s2; // BAD
|
||||
}
|
||||
@@ -1,23 +1,12 @@
|
||||
edges
|
||||
| test.cpp:37:73:37:76 | data | test.cpp:43:32:43:35 | data |
|
||||
| test.cpp:37:73:37:76 | data | test.cpp:43:32:43:35 | data |
|
||||
| test.cpp:37:73:37:76 | data indirection | test.cpp:43:32:43:35 | data |
|
||||
| test.cpp:37:73:37:76 | data indirection | test.cpp:43:32:43:35 | data |
|
||||
| test.cpp:64:30:64:35 | call to getenv | test.cpp:73:24:73:27 | data |
|
||||
| test.cpp:64:30:64:35 | call to getenv | test.cpp:73:24:73:27 | data |
|
||||
| test.cpp:64:30:64:35 | call to getenv | test.cpp:73:24:73:27 | data indirection |
|
||||
| test.cpp:64:30:64:35 | call to getenv | test.cpp:73:24:73:27 | data indirection |
|
||||
| test.cpp:73:24:73:27 | data | test.cpp:37:73:37:76 | data |
|
||||
| test.cpp:37:73:37:76 | data indirection | test.cpp:43:32:43:35 | data indirection |
|
||||
| test.cpp:64:30:64:35 | call to getenv indirection | test.cpp:73:24:73:27 | data indirection |
|
||||
| test.cpp:73:24:73:27 | data indirection | test.cpp:37:73:37:76 | data indirection |
|
||||
subpaths
|
||||
nodes
|
||||
| test.cpp:37:73:37:76 | data | semmle.label | data |
|
||||
| test.cpp:37:73:37:76 | data indirection | semmle.label | data indirection |
|
||||
| test.cpp:43:32:43:35 | data | semmle.label | data |
|
||||
| test.cpp:43:32:43:35 | data | semmle.label | data |
|
||||
| test.cpp:64:30:64:35 | call to getenv | semmle.label | call to getenv |
|
||||
| test.cpp:64:30:64:35 | call to getenv | semmle.label | call to getenv |
|
||||
| test.cpp:73:24:73:27 | data | semmle.label | data |
|
||||
| test.cpp:43:32:43:35 | data indirection | semmle.label | data indirection |
|
||||
| test.cpp:64:30:64:35 | call to getenv indirection | semmle.label | call to getenv indirection |
|
||||
| test.cpp:73:24:73:27 | data indirection | semmle.label | data indirection |
|
||||
subpaths
|
||||
#select
|
||||
| test.cpp:43:32:43:35 | data | test.cpp:64:30:64:35 | call to getenv | test.cpp:43:32:43:35 | data | The value of this argument may come from $@ and is being passed to LoadLibraryA. | test.cpp:64:30:64:35 | call to getenv | call to getenv |
|
||||
| test.cpp:43:32:43:35 | data indirection | test.cpp:64:30:64:35 | call to getenv indirection | test.cpp:43:32:43:35 | data indirection | The value of this argument may come from $@ and is being passed to LoadLibraryA. | test.cpp:64:30:64:35 | call to getenv indirection | an environment variable |
|
||||
|
||||
@@ -1,112 +1,48 @@
|
||||
edges
|
||||
| test.cpp:24:30:24:36 | command | test.cpp:26:10:26:16 | command |
|
||||
| test.cpp:24:30:24:36 | command | test.cpp:26:10:26:16 | command |
|
||||
| test.cpp:29:30:29:36 | command | test.cpp:31:10:31:16 | command |
|
||||
| test.cpp:29:30:29:36 | command | test.cpp:31:10:31:16 | command |
|
||||
| test.cpp:42:18:42:23 | call to getenv | test.cpp:24:30:24:36 | command |
|
||||
| test.cpp:42:18:42:34 | call to getenv | test.cpp:24:30:24:36 | command |
|
||||
| test.cpp:43:18:43:23 | call to getenv | test.cpp:29:30:29:36 | command |
|
||||
| test.cpp:43:18:43:34 | call to getenv | test.cpp:29:30:29:36 | command |
|
||||
| test.cpp:56:12:56:17 | buffer | test.cpp:62:10:62:15 | buffer |
|
||||
| test.cpp:56:12:56:17 | buffer | test.cpp:62:10:62:15 | buffer |
|
||||
| test.cpp:56:12:56:17 | buffer | test.cpp:62:10:62:15 | buffer |
|
||||
| test.cpp:56:12:56:17 | buffer | test.cpp:62:10:62:15 | buffer |
|
||||
| test.cpp:56:12:56:17 | buffer | test.cpp:63:10:63:13 | data |
|
||||
| test.cpp:56:12:56:17 | buffer | test.cpp:63:10:63:13 | data |
|
||||
| test.cpp:56:12:56:17 | buffer | test.cpp:63:10:63:13 | data |
|
||||
| test.cpp:56:12:56:17 | buffer | test.cpp:63:10:63:13 | data |
|
||||
| test.cpp:56:12:56:17 | buffer | test.cpp:64:10:64:16 | dataref |
|
||||
| test.cpp:56:12:56:17 | buffer | test.cpp:64:10:64:16 | dataref |
|
||||
| test.cpp:56:12:56:17 | buffer | test.cpp:64:10:64:16 | dataref |
|
||||
| test.cpp:56:12:56:17 | buffer | test.cpp:64:10:64:16 | dataref |
|
||||
| test.cpp:56:12:56:17 | buffer | test.cpp:64:10:64:16 | dataref |
|
||||
| test.cpp:56:12:56:17 | buffer | test.cpp:64:10:64:16 | dataref |
|
||||
| test.cpp:56:12:56:17 | buffer | test.cpp:65:10:65:14 | data2 |
|
||||
| test.cpp:56:12:56:17 | buffer | test.cpp:65:10:65:14 | data2 |
|
||||
| test.cpp:56:12:56:17 | buffer | test.cpp:65:10:65:14 | data2 |
|
||||
| test.cpp:56:12:56:17 | buffer | test.cpp:65:10:65:14 | data2 |
|
||||
| test.cpp:56:12:56:17 | fgets output argument | test.cpp:62:10:62:15 | buffer |
|
||||
| test.cpp:56:12:56:17 | fgets output argument | test.cpp:62:10:62:15 | buffer |
|
||||
| test.cpp:56:12:56:17 | fgets output argument | test.cpp:63:10:63:13 | data |
|
||||
| test.cpp:56:12:56:17 | fgets output argument | test.cpp:63:10:63:13 | data |
|
||||
| test.cpp:56:12:56:17 | fgets output argument | test.cpp:64:10:64:16 | dataref |
|
||||
| test.cpp:56:12:56:17 | fgets output argument | test.cpp:64:10:64:16 | dataref |
|
||||
| test.cpp:56:12:56:17 | fgets output argument | test.cpp:64:10:64:16 | dataref |
|
||||
| test.cpp:56:12:56:17 | fgets output argument | test.cpp:65:10:65:14 | data2 |
|
||||
| test.cpp:56:12:56:17 | fgets output argument | test.cpp:65:10:65:14 | data2 |
|
||||
| test.cpp:76:12:76:17 | buffer | test.cpp:78:10:78:15 | buffer |
|
||||
| test.cpp:76:12:76:17 | buffer | test.cpp:78:10:78:15 | buffer |
|
||||
| test.cpp:76:12:76:17 | buffer | test.cpp:78:10:78:15 | buffer |
|
||||
| test.cpp:76:12:76:17 | buffer | test.cpp:78:10:78:15 | buffer |
|
||||
| test.cpp:76:12:76:17 | fgets output argument | test.cpp:78:10:78:15 | buffer |
|
||||
| test.cpp:76:12:76:17 | fgets output argument | test.cpp:78:10:78:15 | buffer |
|
||||
| test.cpp:98:17:98:22 | buffer | test.cpp:99:15:99:20 | buffer |
|
||||
| test.cpp:98:17:98:22 | buffer | test.cpp:99:15:99:20 | buffer |
|
||||
| test.cpp:98:17:98:22 | buffer | test.cpp:99:15:99:20 | buffer |
|
||||
| test.cpp:98:17:98:22 | buffer | test.cpp:99:15:99:20 | buffer |
|
||||
| test.cpp:98:17:98:22 | recv output argument | test.cpp:99:15:99:20 | buffer |
|
||||
| test.cpp:98:17:98:22 | recv output argument | test.cpp:99:15:99:20 | buffer |
|
||||
| test.cpp:106:17:106:22 | buffer | test.cpp:107:15:107:20 | buffer |
|
||||
| test.cpp:106:17:106:22 | buffer | test.cpp:107:15:107:20 | buffer |
|
||||
| test.cpp:106:17:106:22 | buffer | test.cpp:107:15:107:20 | buffer |
|
||||
| test.cpp:106:17:106:22 | buffer | test.cpp:107:15:107:20 | buffer |
|
||||
| test.cpp:106:17:106:22 | recv output argument | test.cpp:107:15:107:20 | buffer |
|
||||
| test.cpp:106:17:106:22 | recv output argument | test.cpp:107:15:107:20 | buffer |
|
||||
| test.cpp:113:8:113:12 | call to fgets | test.cpp:114:9:114:11 | ptr |
|
||||
| test.cpp:113:8:113:12 | call to fgets | test.cpp:114:9:114:11 | ptr |
|
||||
| test.cpp:113:8:113:12 | call to fgets | test.cpp:114:9:114:11 | ptr |
|
||||
| test.cpp:113:8:113:12 | call to fgets | test.cpp:114:9:114:11 | ptr |
|
||||
subpaths
|
||||
| test.cpp:24:30:24:36 | command indirection | test.cpp:26:10:26:16 | command indirection |
|
||||
| test.cpp:29:30:29:36 | command indirection | test.cpp:31:10:31:16 | command indirection |
|
||||
| test.cpp:42:18:42:34 | call to getenv indirection | test.cpp:24:30:24:36 | command indirection |
|
||||
| test.cpp:43:18:43:34 | call to getenv indirection | test.cpp:29:30:29:36 | command indirection |
|
||||
| test.cpp:56:12:56:17 | fgets output argument | test.cpp:62:10:62:15 | buffer indirection |
|
||||
| test.cpp:56:12:56:17 | fgets output argument | test.cpp:63:10:63:13 | data indirection |
|
||||
| test.cpp:56:12:56:17 | fgets output argument | test.cpp:64:10:64:16 | (reference dereference) indirection |
|
||||
| test.cpp:56:12:56:17 | fgets output argument | test.cpp:64:10:64:16 | dataref indirection |
|
||||
| test.cpp:56:12:56:17 | fgets output argument | test.cpp:65:10:65:14 | data2 indirection |
|
||||
| test.cpp:76:12:76:17 | fgets output argument | test.cpp:78:10:78:15 | buffer indirection |
|
||||
| test.cpp:98:17:98:22 | recv output argument | test.cpp:99:15:99:20 | buffer indirection |
|
||||
| test.cpp:106:17:106:22 | recv output argument | test.cpp:107:15:107:20 | buffer indirection |
|
||||
| test.cpp:113:8:113:12 | call to fgets indirection | test.cpp:114:9:114:11 | ptr indirection |
|
||||
nodes
|
||||
| test.cpp:24:30:24:36 | command | semmle.label | command |
|
||||
| test.cpp:26:10:26:16 | command | semmle.label | command |
|
||||
| test.cpp:26:10:26:16 | command | semmle.label | command |
|
||||
| test.cpp:29:30:29:36 | command | semmle.label | command |
|
||||
| test.cpp:31:10:31:16 | command | semmle.label | command |
|
||||
| test.cpp:31:10:31:16 | command | semmle.label | command |
|
||||
| test.cpp:42:18:42:23 | call to getenv | semmle.label | call to getenv |
|
||||
| test.cpp:42:18:42:34 | call to getenv | semmle.label | call to getenv |
|
||||
| test.cpp:43:18:43:23 | call to getenv | semmle.label | call to getenv |
|
||||
| test.cpp:43:18:43:34 | call to getenv | semmle.label | call to getenv |
|
||||
| test.cpp:56:12:56:17 | buffer | semmle.label | buffer |
|
||||
| test.cpp:56:12:56:17 | buffer | semmle.label | buffer |
|
||||
| test.cpp:24:30:24:36 | command indirection | semmle.label | command indirection |
|
||||
| test.cpp:26:10:26:16 | command indirection | semmle.label | command indirection |
|
||||
| test.cpp:29:30:29:36 | command indirection | semmle.label | command indirection |
|
||||
| test.cpp:31:10:31:16 | command indirection | semmle.label | command indirection |
|
||||
| test.cpp:42:18:42:34 | call to getenv indirection | semmle.label | call to getenv indirection |
|
||||
| test.cpp:43:18:43:34 | call to getenv indirection | semmle.label | call to getenv indirection |
|
||||
| test.cpp:56:12:56:17 | fgets output argument | semmle.label | fgets output argument |
|
||||
| test.cpp:62:10:62:15 | buffer | semmle.label | buffer |
|
||||
| test.cpp:62:10:62:15 | buffer | semmle.label | buffer |
|
||||
| test.cpp:63:10:63:13 | data | semmle.label | data |
|
||||
| test.cpp:63:10:63:13 | data | semmle.label | data |
|
||||
| test.cpp:64:10:64:16 | dataref | semmle.label | dataref |
|
||||
| test.cpp:64:10:64:16 | dataref | semmle.label | dataref |
|
||||
| test.cpp:64:10:64:16 | dataref | semmle.label | dataref |
|
||||
| test.cpp:65:10:65:14 | data2 | semmle.label | data2 |
|
||||
| test.cpp:65:10:65:14 | data2 | semmle.label | data2 |
|
||||
| test.cpp:76:12:76:17 | buffer | semmle.label | buffer |
|
||||
| test.cpp:76:12:76:17 | buffer | semmle.label | buffer |
|
||||
| test.cpp:62:10:62:15 | buffer indirection | semmle.label | buffer indirection |
|
||||
| test.cpp:63:10:63:13 | data indirection | semmle.label | data indirection |
|
||||
| test.cpp:64:10:64:16 | (reference dereference) indirection | semmle.label | (reference dereference) indirection |
|
||||
| test.cpp:64:10:64:16 | dataref indirection | semmle.label | dataref indirection |
|
||||
| test.cpp:65:10:65:14 | data2 indirection | semmle.label | data2 indirection |
|
||||
| test.cpp:76:12:76:17 | fgets output argument | semmle.label | fgets output argument |
|
||||
| test.cpp:78:10:78:15 | buffer | semmle.label | buffer |
|
||||
| test.cpp:78:10:78:15 | buffer | semmle.label | buffer |
|
||||
| test.cpp:98:17:98:22 | buffer | semmle.label | buffer |
|
||||
| test.cpp:98:17:98:22 | buffer | semmle.label | buffer |
|
||||
| test.cpp:78:10:78:15 | buffer indirection | semmle.label | buffer indirection |
|
||||
| test.cpp:98:17:98:22 | recv output argument | semmle.label | recv output argument |
|
||||
| test.cpp:99:15:99:20 | buffer | semmle.label | buffer |
|
||||
| test.cpp:99:15:99:20 | buffer | semmle.label | buffer |
|
||||
| test.cpp:106:17:106:22 | buffer | semmle.label | buffer |
|
||||
| test.cpp:106:17:106:22 | buffer | semmle.label | buffer |
|
||||
| test.cpp:99:15:99:20 | buffer indirection | semmle.label | buffer indirection |
|
||||
| test.cpp:106:17:106:22 | recv output argument | semmle.label | recv output argument |
|
||||
| test.cpp:107:15:107:20 | buffer | semmle.label | buffer |
|
||||
| test.cpp:107:15:107:20 | buffer | semmle.label | buffer |
|
||||
| test.cpp:113:8:113:12 | call to fgets | semmle.label | call to fgets |
|
||||
| test.cpp:113:8:113:12 | call to fgets | semmle.label | call to fgets |
|
||||
| test.cpp:114:9:114:11 | ptr | semmle.label | ptr |
|
||||
| test.cpp:114:9:114:11 | ptr | semmle.label | ptr |
|
||||
| test.cpp:107:15:107:20 | buffer indirection | semmle.label | buffer indirection |
|
||||
| test.cpp:113:8:113:12 | call to fgets indirection | semmle.label | call to fgets indirection |
|
||||
| test.cpp:114:9:114:11 | ptr indirection | semmle.label | ptr indirection |
|
||||
subpaths
|
||||
#select
|
||||
| test.cpp:26:10:26:16 | command | test.cpp:42:18:42:23 | call to getenv | test.cpp:26:10:26:16 | command | The value of this argument may come from $@ and is being passed to system. | test.cpp:42:18:42:23 | call to getenv | call to getenv |
|
||||
| test.cpp:31:10:31:16 | command | test.cpp:43:18:43:23 | call to getenv | test.cpp:31:10:31:16 | command | The value of this argument may come from $@ and is being passed to system. | test.cpp:43:18:43:23 | call to getenv | call to getenv |
|
||||
| test.cpp:62:10:62:15 | buffer | test.cpp:56:12:56:17 | buffer | test.cpp:62:10:62:15 | buffer | The value of this argument may come from $@ and is being passed to system. | test.cpp:56:12:56:17 | buffer | buffer |
|
||||
| test.cpp:63:10:63:13 | data | test.cpp:56:12:56:17 | buffer | test.cpp:63:10:63:13 | data | The value of this argument may come from $@ and is being passed to system. | test.cpp:56:12:56:17 | buffer | buffer |
|
||||
| test.cpp:64:10:64:16 | dataref | test.cpp:56:12:56:17 | buffer | test.cpp:64:10:64:16 | dataref | The value of this argument may come from $@ and is being passed to system. | test.cpp:56:12:56:17 | buffer | buffer |
|
||||
| test.cpp:65:10:65:14 | data2 | test.cpp:56:12:56:17 | buffer | test.cpp:65:10:65:14 | data2 | The value of this argument may come from $@ and is being passed to system. | test.cpp:56:12:56:17 | buffer | buffer |
|
||||
| test.cpp:78:10:78:15 | buffer | test.cpp:76:12:76:17 | buffer | test.cpp:78:10:78:15 | buffer | The value of this argument may come from $@ and is being passed to system. | test.cpp:76:12:76:17 | buffer | buffer |
|
||||
| test.cpp:99:15:99:20 | buffer | test.cpp:98:17:98:22 | buffer | test.cpp:99:15:99:20 | buffer | The value of this argument may come from $@ and is being passed to LoadLibrary. | test.cpp:98:17:98:22 | buffer | buffer |
|
||||
| test.cpp:107:15:107:20 | buffer | test.cpp:106:17:106:22 | buffer | test.cpp:107:15:107:20 | buffer | The value of this argument may come from $@ and is being passed to LoadLibrary. | test.cpp:106:17:106:22 | buffer | buffer |
|
||||
| test.cpp:114:9:114:11 | ptr | test.cpp:113:8:113:12 | call to fgets | test.cpp:114:9:114:11 | ptr | The value of this argument may come from $@ and is being passed to system. | test.cpp:113:8:113:12 | call to fgets | call to fgets |
|
||||
| test.cpp:26:10:26:16 | command indirection | test.cpp:42:18:42:34 | call to getenv indirection | test.cpp:26:10:26:16 | command indirection | The value of this argument may come from $@ and is being passed to system. | test.cpp:42:18:42:34 | call to getenv indirection | an environment variable |
|
||||
| test.cpp:31:10:31:16 | command indirection | test.cpp:43:18:43:34 | call to getenv indirection | test.cpp:31:10:31:16 | command indirection | The value of this argument may come from $@ and is being passed to system. | test.cpp:43:18:43:34 | call to getenv indirection | an environment variable |
|
||||
| test.cpp:62:10:62:15 | buffer indirection | test.cpp:56:12:56:17 | fgets output argument | test.cpp:62:10:62:15 | buffer indirection | The value of this argument may come from $@ and is being passed to system. | test.cpp:56:12:56:17 | fgets output argument | string read by fgets |
|
||||
| test.cpp:63:10:63:13 | data indirection | test.cpp:56:12:56:17 | fgets output argument | test.cpp:63:10:63:13 | data indirection | The value of this argument may come from $@ and is being passed to system. | test.cpp:56:12:56:17 | fgets output argument | string read by fgets |
|
||||
| test.cpp:64:10:64:16 | (reference dereference) indirection | test.cpp:56:12:56:17 | fgets output argument | test.cpp:64:10:64:16 | (reference dereference) indirection | The value of this argument may come from $@ and is being passed to system. | test.cpp:56:12:56:17 | fgets output argument | string read by fgets |
|
||||
| test.cpp:64:10:64:16 | dataref indirection | test.cpp:56:12:56:17 | fgets output argument | test.cpp:64:10:64:16 | dataref indirection | The value of this argument may come from $@ and is being passed to system. | test.cpp:56:12:56:17 | fgets output argument | string read by fgets |
|
||||
| test.cpp:65:10:65:14 | data2 indirection | test.cpp:56:12:56:17 | fgets output argument | test.cpp:65:10:65:14 | data2 indirection | The value of this argument may come from $@ and is being passed to system. | test.cpp:56:12:56:17 | fgets output argument | string read by fgets |
|
||||
| test.cpp:78:10:78:15 | buffer indirection | test.cpp:76:12:76:17 | fgets output argument | test.cpp:78:10:78:15 | buffer indirection | The value of this argument may come from $@ and is being passed to system. | test.cpp:76:12:76:17 | fgets output argument | string read by fgets |
|
||||
| test.cpp:99:15:99:20 | buffer indirection | test.cpp:98:17:98:22 | recv output argument | test.cpp:99:15:99:20 | buffer indirection | The value of this argument may come from $@ and is being passed to LoadLibrary. | test.cpp:98:17:98:22 | recv output argument | buffer read by recv |
|
||||
| test.cpp:107:15:107:20 | buffer indirection | test.cpp:106:17:106:22 | recv output argument | test.cpp:107:15:107:20 | buffer indirection | The value of this argument may come from $@ and is being passed to LoadLibrary. | test.cpp:106:17:106:22 | recv output argument | buffer read by recv |
|
||||
| test.cpp:114:9:114:11 | ptr indirection | test.cpp:113:8:113:12 | call to fgets indirection | test.cpp:114:9:114:11 | ptr indirection | The value of this argument may come from $@ and is being passed to system. | test.cpp:113:8:113:12 | call to fgets indirection | string read by fgets |
|
||||
|
||||
@@ -1,16 +1,32 @@
|
||||
edges
|
||||
| main.cpp:6:27:6:30 | argv indirection | main.cpp:10:20:10:23 | argv indirection |
|
||||
| main.cpp:10:20:10:23 | argv indirection | tests.cpp:618:32:618:35 | argv indirection |
|
||||
| main.cpp:10:20:10:23 | argv indirection | tests.cpp:631:32:631:35 | argv indirection |
|
||||
| tests.cpp:613:19:613:24 | source indirection | tests.cpp:615:17:615:22 | source indirection |
|
||||
| tests.cpp:618:32:618:35 | argv indirection | tests.cpp:643:9:643:15 | access to array indirection |
|
||||
| tests.cpp:643:9:643:15 | access to array indirection | tests.cpp:613:19:613:24 | source indirection |
|
||||
| tests.cpp:622:19:622:24 | source indirection | tests.cpp:625:2:625:16 | ... = ... indirection |
|
||||
| tests.cpp:625:2:625:16 | ... = ... indirection | tests.cpp:625:4:625:7 | s indirection [post update] [home indirection] |
|
||||
| tests.cpp:625:4:625:7 | s indirection [post update] [home indirection] | tests.cpp:628:14:628:14 | s indirection [home indirection] |
|
||||
| tests.cpp:628:14:628:14 | s indirection [home indirection] | tests.cpp:628:14:628:19 | home indirection |
|
||||
| tests.cpp:628:14:628:14 | s indirection [home indirection] | tests.cpp:628:16:628:19 | home indirection |
|
||||
| tests.cpp:628:16:628:19 | home indirection | tests.cpp:628:14:628:19 | home indirection |
|
||||
| tests.cpp:631:32:631:35 | argv indirection | tests.cpp:656:9:656:15 | access to array indirection |
|
||||
| tests.cpp:631:32:631:35 | argv indirection | tests.cpp:657:9:657:15 | access to array indirection |
|
||||
| tests.cpp:656:9:656:15 | access to array indirection | tests.cpp:613:19:613:24 | source indirection |
|
||||
| tests.cpp:657:9:657:15 | access to array indirection | tests.cpp:622:19:622:24 | source indirection |
|
||||
nodes
|
||||
| main.cpp:6:27:6:30 | argv indirection | semmle.label | argv indirection |
|
||||
| main.cpp:10:20:10:23 | argv indirection | semmle.label | argv indirection |
|
||||
| tests.cpp:613:19:613:24 | source indirection | semmle.label | source indirection |
|
||||
| tests.cpp:615:17:615:22 | source indirection | semmle.label | source indirection |
|
||||
| tests.cpp:618:32:618:35 | argv indirection | semmle.label | argv indirection |
|
||||
| tests.cpp:643:9:643:15 | access to array indirection | semmle.label | access to array indirection |
|
||||
| tests.cpp:622:19:622:24 | source indirection | semmle.label | source indirection |
|
||||
| tests.cpp:625:2:625:16 | ... = ... indirection | semmle.label | ... = ... indirection |
|
||||
| tests.cpp:625:4:625:7 | s indirection [post update] [home indirection] | semmle.label | s indirection [post update] [home indirection] |
|
||||
| tests.cpp:628:14:628:14 | s indirection [home indirection] | semmle.label | s indirection [home indirection] |
|
||||
| tests.cpp:628:14:628:19 | home indirection | semmle.label | home indirection |
|
||||
| tests.cpp:628:16:628:19 | home indirection | semmle.label | home indirection |
|
||||
| tests.cpp:631:32:631:35 | argv indirection | semmle.label | argv indirection |
|
||||
| tests.cpp:656:9:656:15 | access to array indirection | semmle.label | access to array indirection |
|
||||
| tests.cpp:657:9:657:15 | access to array indirection | semmle.label | access to array indirection |
|
||||
subpaths
|
||||
#select
|
||||
| tests.cpp:615:2:615:7 | call to strcpy | main.cpp:6:27:6:30 | argv indirection | tests.cpp:615:17:615:22 | source indirection | This 'call to strcpy' with input from $@ may overflow the destination. | main.cpp:6:27:6:30 | argv indirection | a command-line argument |
|
||||
| tests.cpp:628:2:628:7 | call to strcpy | main.cpp:6:27:6:30 | argv indirection | tests.cpp:628:14:628:19 | home indirection | This 'call to strcpy' with input from $@ may overflow the destination. | main.cpp:6:27:6:30 | argv indirection | a command-line argument |
|
||||
|
||||
@@ -615,6 +615,19 @@ void test24(char* source) {
|
||||
strcpy(buffer, source); // BAD
|
||||
}
|
||||
|
||||
struct my_struct {
|
||||
char* home;
|
||||
};
|
||||
|
||||
void test25(char* source) {
|
||||
my_struct s;
|
||||
|
||||
s.home = source;
|
||||
|
||||
char buf[100];
|
||||
strcpy(buf, s.home); // BAD
|
||||
}
|
||||
|
||||
int tests_main(int argc, char *argv[])
|
||||
{
|
||||
long long arr17[19];
|
||||
@@ -641,6 +654,7 @@ int tests_main(int argc, char *argv[])
|
||||
test22(argc == 0, argv[0]);
|
||||
test23();
|
||||
test24(argv[0]);
|
||||
test25(argv[0]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1,69 +0,0 @@
|
||||
edges
|
||||
| globalVars.c:8:7:8:10 | copy | globalVars.c:27:9:27:12 | copy |
|
||||
| globalVars.c:8:7:8:10 | copy | globalVars.c:27:9:27:12 | copy |
|
||||
| globalVars.c:8:7:8:10 | copy | globalVars.c:30:15:30:18 | copy |
|
||||
| globalVars.c:8:7:8:10 | copy | globalVars.c:30:15:30:18 | copy |
|
||||
| globalVars.c:8:7:8:10 | copy | globalVars.c:30:15:30:18 | copy |
|
||||
| globalVars.c:8:7:8:10 | copy | globalVars.c:33:15:33:18 | copy |
|
||||
| globalVars.c:8:7:8:10 | copy | globalVars.c:35:11:35:14 | copy |
|
||||
| globalVars.c:9:7:9:11 | copy2 | globalVars.c:38:9:38:13 | copy2 |
|
||||
| globalVars.c:9:7:9:11 | copy2 | globalVars.c:38:9:38:13 | copy2 |
|
||||
| globalVars.c:9:7:9:11 | copy2 | globalVars.c:41:15:41:19 | copy2 |
|
||||
| globalVars.c:9:7:9:11 | copy2 | globalVars.c:41:15:41:19 | copy2 |
|
||||
| globalVars.c:9:7:9:11 | copy2 | globalVars.c:41:15:41:19 | copy2 |
|
||||
| globalVars.c:9:7:9:11 | copy2 | globalVars.c:44:15:44:19 | copy2 |
|
||||
| globalVars.c:9:7:9:11 | copy2 | globalVars.c:50:9:50:13 | copy2 |
|
||||
| globalVars.c:9:7:9:11 | copy2 | globalVars.c:50:9:50:13 | copy2 |
|
||||
| globalVars.c:11:22:11:25 | argv | globalVars.c:8:7:8:10 | copy |
|
||||
| globalVars.c:11:22:11:25 | argv | globalVars.c:12:2:12:15 | ... = ... |
|
||||
| globalVars.c:12:2:12:15 | ... = ... | globalVars.c:8:7:8:10 | copy |
|
||||
| globalVars.c:15:21:15:23 | val | globalVars.c:9:7:9:11 | copy2 |
|
||||
| globalVars.c:15:21:15:23 | val | globalVars.c:16:2:16:12 | ... = ... |
|
||||
| globalVars.c:16:2:16:12 | ... = ... | globalVars.c:9:7:9:11 | copy2 |
|
||||
| globalVars.c:24:11:24:14 | argv | globalVars.c:11:22:11:25 | argv |
|
||||
| globalVars.c:24:11:24:14 | argv | globalVars.c:11:22:11:25 | argv |
|
||||
| globalVars.c:30:15:30:18 | copy | globalVars.c:30:15:30:18 | copy |
|
||||
| globalVars.c:30:15:30:18 | copy | globalVars.c:30:15:30:18 | copy |
|
||||
| globalVars.c:30:15:30:18 | copy | globalVars.c:30:15:30:18 | copy |
|
||||
| globalVars.c:30:15:30:18 | copy | globalVars.c:35:11:35:14 | copy |
|
||||
| globalVars.c:33:15:33:18 | copy | globalVars.c:35:11:35:14 | copy |
|
||||
| globalVars.c:35:11:35:14 | copy | globalVars.c:15:21:15:23 | val |
|
||||
| globalVars.c:35:11:35:14 | copy | globalVars.c:35:11:35:14 | copy |
|
||||
| globalVars.c:41:15:41:19 | copy2 | globalVars.c:41:15:41:19 | copy2 |
|
||||
| globalVars.c:41:15:41:19 | copy2 | globalVars.c:41:15:41:19 | copy2 |
|
||||
| globalVars.c:41:15:41:19 | copy2 | globalVars.c:41:15:41:19 | copy2 |
|
||||
| globalVars.c:41:15:41:19 | copy2 | globalVars.c:50:9:50:13 | copy2 |
|
||||
| globalVars.c:41:15:41:19 | copy2 | globalVars.c:50:9:50:13 | copy2 |
|
||||
| globalVars.c:44:15:44:19 | copy2 | globalVars.c:50:9:50:13 | copy2 |
|
||||
| globalVars.c:44:15:44:19 | copy2 | globalVars.c:50:9:50:13 | copy2 |
|
||||
subpaths
|
||||
nodes
|
||||
| globalVars.c:8:7:8:10 | copy | semmle.label | copy |
|
||||
| globalVars.c:9:7:9:11 | copy2 | semmle.label | copy2 |
|
||||
| globalVars.c:11:22:11:25 | argv | semmle.label | argv |
|
||||
| globalVars.c:12:2:12:15 | ... = ... | semmle.label | ... = ... |
|
||||
| globalVars.c:15:21:15:23 | val | semmle.label | val |
|
||||
| globalVars.c:16:2:16:12 | ... = ... | semmle.label | ... = ... |
|
||||
| globalVars.c:24:11:24:14 | argv | semmle.label | argv |
|
||||
| globalVars.c:24:11:24:14 | argv | semmle.label | argv |
|
||||
| globalVars.c:27:9:27:12 | copy | semmle.label | copy |
|
||||
| globalVars.c:27:9:27:12 | copy | semmle.label | copy |
|
||||
| globalVars.c:30:15:30:18 | copy | semmle.label | copy |
|
||||
| globalVars.c:30:15:30:18 | copy | semmle.label | copy |
|
||||
| globalVars.c:30:15:30:18 | copy | semmle.label | copy |
|
||||
| globalVars.c:33:15:33:18 | copy | semmle.label | copy |
|
||||
| globalVars.c:35:11:35:14 | copy | semmle.label | copy |
|
||||
| globalVars.c:38:9:38:13 | copy2 | semmle.label | copy2 |
|
||||
| globalVars.c:38:9:38:13 | copy2 | semmle.label | copy2 |
|
||||
| globalVars.c:41:15:41:19 | copy2 | semmle.label | copy2 |
|
||||
| globalVars.c:41:15:41:19 | copy2 | semmle.label | copy2 |
|
||||
| globalVars.c:41:15:41:19 | copy2 | semmle.label | copy2 |
|
||||
| globalVars.c:44:15:44:19 | copy2 | semmle.label | copy2 |
|
||||
| globalVars.c:50:9:50:13 | copy2 | semmle.label | copy2 |
|
||||
| globalVars.c:50:9:50:13 | copy2 | semmle.label | copy2 |
|
||||
#select
|
||||
| globalVars.c:27:9:27:12 | copy | globalVars.c:24:11:24:14 | argv | globalVars.c:27:9:27:12 | copy | The value of this argument may come from $@ and is being used as a formatting argument to printf(format). | globalVars.c:24:11:24:14 | argv | argv |
|
||||
| globalVars.c:30:15:30:18 | copy | globalVars.c:24:11:24:14 | argv | globalVars.c:30:15:30:18 | copy | The value of this argument may come from $@ and is being used as a formatting argument to printWrapper(str), which calls printf(format). | globalVars.c:24:11:24:14 | argv | argv |
|
||||
| globalVars.c:38:9:38:13 | copy2 | globalVars.c:24:11:24:14 | argv | globalVars.c:38:9:38:13 | copy2 | The value of this argument may come from $@ and is being used as a formatting argument to printf(format). | globalVars.c:24:11:24:14 | argv | argv |
|
||||
| globalVars.c:41:15:41:19 | copy2 | globalVars.c:24:11:24:14 | argv | globalVars.c:41:15:41:19 | copy2 | The value of this argument may come from $@ and is being used as a formatting argument to printWrapper(str), which calls printf(format). | globalVars.c:24:11:24:14 | argv | argv |
|
||||
| globalVars.c:50:9:50:13 | copy2 | globalVars.c:24:11:24:14 | argv | globalVars.c:50:9:50:13 | copy2 | The value of this argument may come from $@ and is being used as a formatting argument to printf(format). | globalVars.c:24:11:24:14 | argv | argv |
|
||||
@@ -1 +0,0 @@
|
||||
Security/CWE/CWE-134/UncontrolledFormatStringThroughGlobalVar.ql
|
||||
@@ -1,13 +1,8 @@
|
||||
edges
|
||||
| examples.cpp:63:26:63:30 | & ... | examples.cpp:66:11:66:14 | data |
|
||||
| examples.cpp:63:26:63:30 | & ... | examples.cpp:66:11:66:14 | data |
|
||||
| examples.cpp:63:26:63:30 | fscanf output argument | examples.cpp:66:11:66:14 | data |
|
||||
| examples.cpp:63:26:63:30 | fscanf output argument | examples.cpp:66:11:66:14 | data |
|
||||
subpaths
|
||||
nodes
|
||||
| examples.cpp:63:26:63:30 | & ... | semmle.label | & ... |
|
||||
| examples.cpp:63:26:63:30 | fscanf output argument | semmle.label | fscanf output argument |
|
||||
| examples.cpp:66:11:66:14 | data | semmle.label | data |
|
||||
| examples.cpp:66:11:66:14 | data | semmle.label | data |
|
||||
subpaths
|
||||
#select
|
||||
| examples.cpp:66:11:66:14 | data | examples.cpp:63:26:63:30 | & ... | examples.cpp:66:11:66:14 | data | $@ flows to an operand of an arithmetic expression, potentially causing an underflow. | examples.cpp:63:26:63:30 | & ... | User-provided value |
|
||||
| examples.cpp:66:11:66:14 | data | examples.cpp:63:26:63:30 | fscanf output argument | examples.cpp:66:11:66:14 | data | $@ flows to an operand of an arithmetic expression, potentially causing an underflow. | examples.cpp:63:26:63:30 | fscanf output argument | value read by fscanf |
|
||||
|
||||
@@ -1,86 +1,59 @@
|
||||
edges
|
||||
| test2.cpp:12:21:12:21 | v | test2.cpp:14:11:14:11 | v |
|
||||
| test2.cpp:12:21:12:21 | v | test2.cpp:14:11:14:11 | v |
|
||||
| test2.cpp:25:22:25:23 | & ... | test2.cpp:27:13:27:13 | v |
|
||||
| test2.cpp:25:22:25:23 | fscanf output argument | test2.cpp:27:13:27:13 | v |
|
||||
| test2.cpp:27:13:27:13 | v | test2.cpp:12:21:12:21 | v |
|
||||
| test2.cpp:36:9:36:14 | buffer | test2.cpp:39:9:39:11 | num |
|
||||
| test2.cpp:36:9:36:14 | buffer | test2.cpp:39:9:39:11 | num |
|
||||
| test2.cpp:36:9:36:14 | buffer | test2.cpp:39:9:39:11 | num |
|
||||
| test2.cpp:36:9:36:14 | buffer | test2.cpp:39:9:39:11 | num |
|
||||
| test2.cpp:36:9:36:14 | buffer | test2.cpp:40:3:40:5 | num |
|
||||
| test2.cpp:36:9:36:14 | buffer | test2.cpp:40:3:40:5 | num |
|
||||
| test2.cpp:36:9:36:14 | buffer | test2.cpp:40:3:40:5 | num |
|
||||
| test2.cpp:36:9:36:14 | buffer | test2.cpp:40:3:40:5 | num |
|
||||
| test2.cpp:36:9:36:14 | fgets output argument | test2.cpp:39:9:39:11 | num |
|
||||
| test2.cpp:36:9:36:14 | fgets output argument | test2.cpp:39:9:39:11 | num |
|
||||
| test2.cpp:36:9:36:14 | fgets output argument | test2.cpp:40:3:40:5 | num |
|
||||
| test2.cpp:36:9:36:14 | fgets output argument | test2.cpp:40:3:40:5 | num |
|
||||
| test5.cpp:5:5:5:17 | getTaintedInt indirection | test5.cpp:17:6:17:18 | call to getTaintedInt |
|
||||
| test3.c:10:27:10:30 | argv indirection | test.c:14:15:14:28 | maxConnections |
|
||||
| test3.c:10:27:10:30 | argv indirection | test.c:44:7:44:10 | len2 |
|
||||
| test3.c:10:27:10:30 | argv indirection | test.c:54:7:54:10 | len3 |
|
||||
| test5.cpp:5:5:5:17 | getTaintedInt indirection | test5.cpp:17:6:17:18 | call to getTaintedInt |
|
||||
| test5.cpp:5:5:5:17 | getTaintedInt indirection | test5.cpp:18:6:18:18 | call to getTaintedInt |
|
||||
| test5.cpp:9:7:9:9 | buf | test5.cpp:5:5:5:17 | getTaintedInt indirection |
|
||||
| test5.cpp:9:7:9:9 | buf | test5.cpp:5:5:5:17 | getTaintedInt indirection |
|
||||
| test5.cpp:9:7:9:9 | gets output argument | test5.cpp:5:5:5:17 | getTaintedInt indirection |
|
||||
| test5.cpp:18:6:18:18 | call to getTaintedInt | test5.cpp:19:6:19:6 | y |
|
||||
| test5.cpp:18:6:18:18 | call to getTaintedInt | test5.cpp:19:6:19:6 | y |
|
||||
| test.c:11:29:11:32 | argv | test.c:14:15:14:28 | maxConnections |
|
||||
| test.c:11:29:11:32 | argv | test.c:14:15:14:28 | maxConnections |
|
||||
| test.c:11:29:11:32 | argv | test.c:14:15:14:28 | maxConnections |
|
||||
| test.c:11:29:11:32 | argv | test.c:14:15:14:28 | maxConnections |
|
||||
| test.c:41:17:41:20 | argv | test.c:44:7:44:10 | len2 |
|
||||
| test.c:41:17:41:20 | argv | test.c:44:7:44:10 | len2 |
|
||||
| test.c:41:17:41:20 | argv | test.c:44:7:44:10 | len2 |
|
||||
| test.c:41:17:41:20 | argv | test.c:44:7:44:10 | len2 |
|
||||
| test.c:51:17:51:20 | argv | test.c:54:7:54:10 | len3 |
|
||||
| test.c:51:17:51:20 | argv | test.c:54:7:54:10 | len3 |
|
||||
| test.c:51:17:51:20 | argv | test.c:54:7:54:10 | len3 |
|
||||
| test.c:51:17:51:20 | argv | test.c:54:7:54:10 | len3 |
|
||||
subpaths
|
||||
| test.c:10:27:10:30 | argv indirection | test.c:14:15:14:28 | maxConnections |
|
||||
| test.c:10:27:10:30 | argv indirection | test.c:44:7:44:10 | len2 |
|
||||
| test.c:10:27:10:30 | argv indirection | test.c:54:7:54:10 | len3 |
|
||||
nodes
|
||||
| test2.cpp:12:21:12:21 | v | semmle.label | v |
|
||||
| test2.cpp:14:11:14:11 | v | semmle.label | v |
|
||||
| test2.cpp:14:11:14:11 | v | semmle.label | v |
|
||||
| test2.cpp:25:22:25:23 | & ... | semmle.label | & ... |
|
||||
| test2.cpp:25:22:25:23 | fscanf output argument | semmle.label | fscanf output argument |
|
||||
| test2.cpp:27:13:27:13 | v | semmle.label | v |
|
||||
| test2.cpp:36:9:36:14 | buffer | semmle.label | buffer |
|
||||
| test2.cpp:36:9:36:14 | buffer | semmle.label | buffer |
|
||||
| test2.cpp:36:9:36:14 | fgets output argument | semmle.label | fgets output argument |
|
||||
| test2.cpp:39:9:39:11 | num | semmle.label | num |
|
||||
| test2.cpp:39:9:39:11 | num | semmle.label | num |
|
||||
| test2.cpp:40:3:40:5 | num | semmle.label | num |
|
||||
| test2.cpp:40:3:40:5 | num | semmle.label | num |
|
||||
| test3.c:10:27:10:30 | argv indirection | semmle.label | argv indirection |
|
||||
| test5.cpp:5:5:5:17 | getTaintedInt indirection | semmle.label | getTaintedInt indirection |
|
||||
| test5.cpp:9:7:9:9 | buf | semmle.label | buf |
|
||||
| test5.cpp:9:7:9:9 | buf | semmle.label | buf |
|
||||
| test5.cpp:9:7:9:9 | gets output argument | semmle.label | gets output argument |
|
||||
| test5.cpp:17:6:17:18 | call to getTaintedInt | semmle.label | call to getTaintedInt |
|
||||
| test5.cpp:17:6:17:18 | call to getTaintedInt | semmle.label | call to getTaintedInt |
|
||||
| test5.cpp:18:6:18:18 | call to getTaintedInt | semmle.label | call to getTaintedInt |
|
||||
| test5.cpp:19:6:19:6 | y | semmle.label | y |
|
||||
| test5.cpp:19:6:19:6 | y | semmle.label | y |
|
||||
| test.c:11:29:11:32 | argv | semmle.label | argv |
|
||||
| test.c:11:29:11:32 | argv | semmle.label | argv |
|
||||
| test.c:10:27:10:30 | argv indirection | semmle.label | argv indirection |
|
||||
| test.c:14:15:14:28 | maxConnections | semmle.label | maxConnections |
|
||||
| test.c:14:15:14:28 | maxConnections | semmle.label | maxConnections |
|
||||
| test.c:41:17:41:20 | argv | semmle.label | argv |
|
||||
| test.c:41:17:41:20 | argv | semmle.label | argv |
|
||||
| test.c:44:7:44:10 | len2 | semmle.label | len2 |
|
||||
| test.c:44:7:44:10 | len2 | semmle.label | len2 |
|
||||
| test.c:51:17:51:20 | argv | semmle.label | argv |
|
||||
| test.c:51:17:51:20 | argv | semmle.label | argv |
|
||||
| test.c:54:7:54:10 | len3 | semmle.label | len3 |
|
||||
| test.c:54:7:54:10 | len3 | semmle.label | len3 |
|
||||
subpaths
|
||||
#select
|
||||
| test2.cpp:14:11:14:11 | v | test2.cpp:25:22:25:23 | & ... | test2.cpp:14:11:14:11 | v | $@ flows to an operand of an arithmetic expression, potentially causing an overflow. | test2.cpp:25:22:25:23 | & ... | User-provided value |
|
||||
| test2.cpp:14:11:14:11 | v | test2.cpp:25:22:25:23 | & ... | test2.cpp:14:11:14:11 | v | $@ flows to an operand of an arithmetic expression, potentially causing an underflow. | test2.cpp:25:22:25:23 | & ... | User-provided value |
|
||||
| test2.cpp:39:9:39:11 | num | test2.cpp:36:9:36:14 | buffer | test2.cpp:39:9:39:11 | num | $@ flows to an operand of an arithmetic expression, potentially causing an overflow. | test2.cpp:36:9:36:14 | buffer | User-provided value |
|
||||
| test2.cpp:40:3:40:5 | num | test2.cpp:36:9:36:14 | buffer | test2.cpp:40:3:40:5 | num | $@ flows to an operand of an arithmetic expression, potentially causing an overflow. | test2.cpp:36:9:36:14 | buffer | User-provided value |
|
||||
| test5.cpp:17:6:17:18 | call to getTaintedInt | test5.cpp:9:7:9:9 | buf | test5.cpp:17:6:17:18 | call to getTaintedInt | $@ flows to an operand of an arithmetic expression, potentially causing an overflow. | test5.cpp:9:7:9:9 | buf | User-provided value |
|
||||
| test5.cpp:19:6:19:6 | y | test5.cpp:9:7:9:9 | buf | test5.cpp:19:6:19:6 | y | $@ flows to an operand of an arithmetic expression, potentially causing an overflow. | test5.cpp:9:7:9:9 | buf | User-provided value |
|
||||
| test5.cpp:19:6:19:6 | y | test5.cpp:9:7:9:9 | buf | test5.cpp:19:6:19:6 | y | $@ flows to an operand of an arithmetic expression, potentially causing an underflow. | test5.cpp:9:7:9:9 | buf | User-provided value |
|
||||
| test.c:14:15:14:28 | maxConnections | test.c:11:29:11:32 | argv | test.c:14:15:14:28 | maxConnections | $@ flows to an operand of an arithmetic expression, potentially causing an overflow. | test.c:11:29:11:32 | argv | User-provided value |
|
||||
| test.c:14:15:14:28 | maxConnections | test.c:11:29:11:32 | argv | test.c:14:15:14:28 | maxConnections | $@ flows to an operand of an arithmetic expression, potentially causing an underflow. | test.c:11:29:11:32 | argv | User-provided value |
|
||||
| test.c:44:7:44:10 | len2 | test.c:41:17:41:20 | argv | test.c:44:7:44:10 | len2 | $@ flows to an operand of an arithmetic expression, potentially causing an underflow. | test.c:41:17:41:20 | argv | User-provided value |
|
||||
| test.c:54:7:54:10 | len3 | test.c:51:17:51:20 | argv | test.c:54:7:54:10 | len3 | $@ flows to an operand of an arithmetic expression, potentially causing an underflow. | test.c:51:17:51:20 | argv | User-provided value |
|
||||
| test2.cpp:14:11:14:11 | v | test2.cpp:25:22:25:23 | fscanf output argument | test2.cpp:14:11:14:11 | v | $@ flows to an operand of an arithmetic expression, potentially causing an overflow. | test2.cpp:25:22:25:23 | fscanf output argument | value read by fscanf |
|
||||
| test2.cpp:14:11:14:11 | v | test2.cpp:25:22:25:23 | fscanf output argument | test2.cpp:14:11:14:11 | v | $@ flows to an operand of an arithmetic expression, potentially causing an underflow. | test2.cpp:25:22:25:23 | fscanf output argument | value read by fscanf |
|
||||
| test2.cpp:39:9:39:11 | num | test2.cpp:36:9:36:14 | fgets output argument | test2.cpp:39:9:39:11 | num | $@ flows to an operand of an arithmetic expression, potentially causing an overflow. | test2.cpp:36:9:36:14 | fgets output argument | string read by fgets |
|
||||
| test2.cpp:40:3:40:5 | num | test2.cpp:36:9:36:14 | fgets output argument | test2.cpp:40:3:40:5 | num | $@ flows to an operand of an arithmetic expression, potentially causing an overflow. | test2.cpp:36:9:36:14 | fgets output argument | string read by fgets |
|
||||
| test5.cpp:17:6:17:18 | call to getTaintedInt | test5.cpp:9:7:9:9 | gets output argument | test5.cpp:17:6:17:18 | call to getTaintedInt | $@ flows to an operand of an arithmetic expression, potentially causing an overflow. | test5.cpp:9:7:9:9 | gets output argument | string read by gets |
|
||||
| test5.cpp:19:6:19:6 | y | test5.cpp:9:7:9:9 | gets output argument | test5.cpp:19:6:19:6 | y | $@ flows to an operand of an arithmetic expression, potentially causing an overflow. | test5.cpp:9:7:9:9 | gets output argument | string read by gets |
|
||||
| test5.cpp:19:6:19:6 | y | test5.cpp:9:7:9:9 | gets output argument | test5.cpp:19:6:19:6 | y | $@ flows to an operand of an arithmetic expression, potentially causing an underflow. | test5.cpp:9:7:9:9 | gets output argument | string read by gets |
|
||||
| test.c:14:15:14:28 | maxConnections | test3.c:10:27:10:30 | argv indirection | test.c:14:15:14:28 | maxConnections | $@ flows to an operand of an arithmetic expression, potentially causing an overflow. | test3.c:10:27:10:30 | argv indirection | a command-line argument |
|
||||
| test.c:14:15:14:28 | maxConnections | test3.c:10:27:10:30 | argv indirection | test.c:14:15:14:28 | maxConnections | $@ flows to an operand of an arithmetic expression, potentially causing an overflow. | test.c:10:27:10:30 | argv indirection | a command-line argument |
|
||||
| test.c:14:15:14:28 | maxConnections | test3.c:10:27:10:30 | argv indirection | test.c:14:15:14:28 | maxConnections | $@ flows to an operand of an arithmetic expression, potentially causing an underflow. | test3.c:10:27:10:30 | argv indirection | a command-line argument |
|
||||
| test.c:14:15:14:28 | maxConnections | test3.c:10:27:10:30 | argv indirection | test.c:14:15:14:28 | maxConnections | $@ flows to an operand of an arithmetic expression, potentially causing an underflow. | test.c:10:27:10:30 | argv indirection | a command-line argument |
|
||||
| test.c:14:15:14:28 | maxConnections | test.c:10:27:10:30 | argv indirection | test.c:14:15:14:28 | maxConnections | $@ flows to an operand of an arithmetic expression, potentially causing an overflow. | test3.c:10:27:10:30 | argv indirection | a command-line argument |
|
||||
| test.c:14:15:14:28 | maxConnections | test.c:10:27:10:30 | argv indirection | test.c:14:15:14:28 | maxConnections | $@ flows to an operand of an arithmetic expression, potentially causing an overflow. | test.c:10:27:10:30 | argv indirection | a command-line argument |
|
||||
| test.c:14:15:14:28 | maxConnections | test.c:10:27:10:30 | argv indirection | test.c:14:15:14:28 | maxConnections | $@ flows to an operand of an arithmetic expression, potentially causing an underflow. | test3.c:10:27:10:30 | argv indirection | a command-line argument |
|
||||
| test.c:14:15:14:28 | maxConnections | test.c:10:27:10:30 | argv indirection | test.c:14:15:14:28 | maxConnections | $@ flows to an operand of an arithmetic expression, potentially causing an underflow. | test.c:10:27:10:30 | argv indirection | a command-line argument |
|
||||
| test.c:44:7:44:10 | len2 | test3.c:10:27:10:30 | argv indirection | test.c:44:7:44:10 | len2 | $@ flows to an operand of an arithmetic expression, potentially causing an underflow. | test3.c:10:27:10:30 | argv indirection | a command-line argument |
|
||||
| test.c:44:7:44:10 | len2 | test3.c:10:27:10:30 | argv indirection | test.c:44:7:44:10 | len2 | $@ flows to an operand of an arithmetic expression, potentially causing an underflow. | test.c:10:27:10:30 | argv indirection | a command-line argument |
|
||||
| test.c:44:7:44:10 | len2 | test.c:10:27:10:30 | argv indirection | test.c:44:7:44:10 | len2 | $@ flows to an operand of an arithmetic expression, potentially causing an underflow. | test3.c:10:27:10:30 | argv indirection | a command-line argument |
|
||||
| test.c:44:7:44:10 | len2 | test.c:10:27:10:30 | argv indirection | test.c:44:7:44:10 | len2 | $@ flows to an operand of an arithmetic expression, potentially causing an underflow. | test.c:10:27:10:30 | argv indirection | a command-line argument |
|
||||
| test.c:54:7:54:10 | len3 | test3.c:10:27:10:30 | argv indirection | test.c:54:7:54:10 | len3 | $@ flows to an operand of an arithmetic expression, potentially causing an underflow. | test3.c:10:27:10:30 | argv indirection | a command-line argument |
|
||||
| test.c:54:7:54:10 | len3 | test3.c:10:27:10:30 | argv indirection | test.c:54:7:54:10 | len3 | $@ flows to an operand of an arithmetic expression, potentially causing an underflow. | test.c:10:27:10:30 | argv indirection | a command-line argument |
|
||||
| test.c:54:7:54:10 | len3 | test.c:10:27:10:30 | argv indirection | test.c:54:7:54:10 | len3 | $@ flows to an operand of an arithmetic expression, potentially causing an underflow. | test3.c:10:27:10:30 | argv indirection | a command-line argument |
|
||||
| test.c:54:7:54:10 | len3 | test.c:10:27:10:30 | argv indirection | test.c:54:7:54:10 | len3 | $@ flows to an operand of an arithmetic expression, potentially causing an underflow. | test.c:10:27:10:30 | argv indirection | a command-line argument |
|
||||
|
||||
@@ -559,6 +559,7 @@ namespace Semmle.Autobuild.CSharp.Tests
|
||||
{
|
||||
actions.RunProcess[@"C:\codeql\csharp/tools/linux64/Semmle.Extraction.CSharp.Standalone"] = 0;
|
||||
actions.FileExists["csharp.log"] = true;
|
||||
actions.FileExists["test.sln"] = false;
|
||||
actions.GetEnvironmentVariable["CODEQL_EXTRACTOR_CSHARP_TRAP_DIR"] = "";
|
||||
actions.GetEnvironmentVariable["CODEQL_EXTRACTOR_CSHARP_SOURCE_ARCHIVE_DIR"] = "";
|
||||
actions.EnumerateFiles[@"C:\Project"] = "foo.cs\ntest.sln";
|
||||
@@ -573,6 +574,7 @@ namespace Semmle.Autobuild.CSharp.Tests
|
||||
{
|
||||
actions.RunProcess[@"C:\codeql\csharp/tools/linux64/Semmle.Extraction.CSharp.Standalone"] = 10;
|
||||
actions.FileExists["csharp.log"] = true;
|
||||
actions.FileExists["test.sln"] = false;
|
||||
actions.GetEnvironmentVariable["CODEQL_EXTRACTOR_CSHARP_TRAP_DIR"] = "";
|
||||
actions.GetEnvironmentVariable["CODEQL_EXTRACTOR_CSHARP_SOURCE_ARCHIVE_DIR"] = "";
|
||||
actions.EnumerateFiles[@"C:\Project"] = "foo.cs\ntest.sln";
|
||||
@@ -587,6 +589,7 @@ namespace Semmle.Autobuild.CSharp.Tests
|
||||
{
|
||||
actions.RunProcess[@"C:\codeql\csharp/tools/linux64/Semmle.Extraction.CSharp.Standalone foo.sln"] = 0;
|
||||
actions.FileExists["csharp.log"] = true;
|
||||
actions.FileExists["foo.sln"] = false;
|
||||
actions.GetEnvironmentVariable["CODEQL_EXTRACTOR_CSHARP_TRAP_DIR"] = "";
|
||||
actions.GetEnvironmentVariable["CODEQL_EXTRACTOR_CSHARP_SOURCE_ARCHIVE_DIR"] = "";
|
||||
actions.EnumerateFiles[@"C:\Project"] = "foo.cs\ntest.sln";
|
||||
@@ -629,6 +632,7 @@ namespace Semmle.Autobuild.CSharp.Tests
|
||||
{
|
||||
actions.RunProcess["./build.sh --skip-tests"] = 0;
|
||||
actions.FileExists["csharp.log"] = true;
|
||||
actions.FileExists["test.sln"] = false;
|
||||
actions.GetEnvironmentVariable["CODEQL_EXTRACTOR_CSHARP_TRAP_DIR"] = "";
|
||||
actions.GetEnvironmentVariable["CODEQL_EXTRACTOR_CSHARP_SOURCE_ARCHIVE_DIR"] = "";
|
||||
actions.EnumerateFiles[@"C:\Project"] = "foo.cs\ntest.sln";
|
||||
@@ -729,6 +733,7 @@ namespace Semmle.Autobuild.CSharp.Tests
|
||||
actions.RunProcess[@"cmd.exe /C C:\codeql\tools\java\bin\java -jar C:\codeql\csharp\tools\extractor-asp.jar ."] = 0;
|
||||
actions.RunProcess[@"cmd.exe /C C:\codeql\tools\codeql index --xml --extensions config"] = 0;
|
||||
actions.FileExists["csharp.log"] = true;
|
||||
actions.FileExists[@"C:\Project\test.sln"] = false;
|
||||
SkipVsWhere();
|
||||
|
||||
actions.GetEnvironmentVariable["CODEQL_EXTRACTOR_CSHARP_TRAP_DIR"] = "";
|
||||
@@ -875,6 +880,7 @@ namespace Semmle.Autobuild.CSharp.Tests
|
||||
{
|
||||
actions.RunProcess[@"C:\codeql\csharp/tools/linux64/Semmle.Extraction.CSharp.Standalone foo.sln --skip-nuget"] = 0;
|
||||
actions.FileExists["csharp.log"] = true;
|
||||
actions.FileExists["foo.sln"] = false;
|
||||
actions.GetEnvironmentVariable["CODEQL_EXTRACTOR_CSHARP_TRAP_DIR"] = "";
|
||||
actions.GetEnvironmentVariable["CODEQL_EXTRACTOR_CSHARP_SOURCE_ARCHIVE_DIR"] = "";
|
||||
actions.EnumerateFiles[@"C:\Project"] = "foo.cs\ntest.sln";
|
||||
@@ -946,6 +952,40 @@ namespace Semmle.Autobuild.CSharp.Tests
|
||||
TestAutobuilderScript(autobuilder, 0, 8);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void TestDotnetVersionInstalledFromTargetFramework()
|
||||
{
|
||||
actions.RunProcess["dotnet --list-sdks"] = 0;
|
||||
actions.RunProcessOut["dotnet --list-sdks"] = "6.0.404 [C:\\Program Files\\dotnet\\sdks]\n7.0.102 [C:\\Program Files\\dotnet\\sdks]";
|
||||
actions.RunProcess[@"chmod u+x dotnet-install.sh"] = 0;
|
||||
actions.RunProcess[@"./dotnet-install.sh --channel 8.0 --version latest --install-dir C:\Project/.dotnet"] = 0;
|
||||
actions.RunProcess[@"rm dotnet-install.sh"] = 0;
|
||||
actions.RunProcess[@"C:\Project/.dotnet/dotnet --info"] = 0;
|
||||
actions.RunProcess[@"C:\Project/.dotnet/dotnet clean C:\Project/test.csproj"] = 0;
|
||||
actions.RunProcess[@"C:\Project/.dotnet/dotnet restore C:\Project/test.csproj"] = 0;
|
||||
actions.RunProcess[@"C:\Project/.dotnet/dotnet build --no-incremental C:\Project/test.csproj"] = 0;
|
||||
actions.FileExists["csharp.log"] = true;
|
||||
actions.FileExists["test.csproj"] = true;
|
||||
actions.GetEnvironmentVariable["CODEQL_EXTRACTOR_CSHARP_TRAP_DIR"] = "";
|
||||
actions.GetEnvironmentVariable["CODEQL_EXTRACTOR_CSHARP_SOURCE_ARCHIVE_DIR"] = "";
|
||||
actions.GetEnvironmentVariable["PATH"] = "/bin:/usr/bin";
|
||||
actions.EnumerateFiles[@"C:\Project"] = "foo.cs\ntest.cs\ntest.csproj";
|
||||
actions.EnumerateDirectories[@"C:\Project"] = "";
|
||||
var xml = new XmlDocument();
|
||||
xml.LoadXml(@"<Project Sdk=""Microsoft.NET.Sdk"">
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
</PropertyGroup>
|
||||
|
||||
</Project>");
|
||||
actions.LoadXml[@"C:\Project/test.csproj"] = xml;
|
||||
actions.DownloadFiles.Add(("https://dot.net/v1/dotnet-install.sh", "dotnet-install.sh"));
|
||||
|
||||
var autobuilder = CreateAutoBuilder(false);
|
||||
TestAutobuilderScript(autobuilder, 0, 8);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void TestDotnetVersionAlreadyInstalled()
|
||||
{
|
||||
@@ -1016,7 +1056,7 @@ namespace Semmle.Autobuild.CSharp.Tests
|
||||
{
|
||||
TestDotnetVersionWindows(() =>
|
||||
{
|
||||
actions.RunProcess[@"cmd.exe /C pwsh -NoProfile -ExecutionPolicy unrestricted -Command ""[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; &([scriptblock]::Create((Invoke-WebRequest -UseBasicParsing 'https://dot.net/v1/dotnet-install.ps1'))) -Version 2.1.3 -InstallDir C:\Project\.dotnet"""] = 0;
|
||||
actions.RunProcess[@"cmd.exe /C pwsh -NoProfile -ExecutionPolicy unrestricted -Command ""[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; &([scriptblock]::Create((Invoke-WebRequest -UseBasicParsing 'https://dot.net/v1/dotnet-install.ps1'))) -Channel release -Version 2.1.3 -InstallDir C:\Project\.dotnet"""] = 0;
|
||||
},
|
||||
6);
|
||||
}
|
||||
@@ -1026,8 +1066,8 @@ namespace Semmle.Autobuild.CSharp.Tests
|
||||
{
|
||||
TestDotnetVersionWindows(() =>
|
||||
{
|
||||
actions.RunProcess[@"cmd.exe /C pwsh -NoProfile -ExecutionPolicy unrestricted -Command ""[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; &([scriptblock]::Create((Invoke-WebRequest -UseBasicParsing 'https://dot.net/v1/dotnet-install.ps1'))) -Version 2.1.3 -InstallDir C:\Project\.dotnet"""] = 1;
|
||||
actions.RunProcess[@"cmd.exe /C powershell -NoProfile -ExecutionPolicy unrestricted -Command ""[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; &([scriptblock]::Create((Invoke-WebRequest -UseBasicParsing 'https://dot.net/v1/dotnet-install.ps1'))) -Version 2.1.3 -InstallDir C:\Project\.dotnet"""] = 0;
|
||||
actions.RunProcess[@"cmd.exe /C pwsh -NoProfile -ExecutionPolicy unrestricted -Command ""[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; &([scriptblock]::Create((Invoke-WebRequest -UseBasicParsing 'https://dot.net/v1/dotnet-install.ps1'))) -Channel release -Version 2.1.3 -InstallDir C:\Project\.dotnet"""] = 1;
|
||||
actions.RunProcess[@"cmd.exe /C powershell -NoProfile -ExecutionPolicy unrestricted -Command ""[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; &([scriptblock]::Create((Invoke-WebRequest -UseBasicParsing 'https://dot.net/v1/dotnet-install.ps1'))) -Channel release -Version 2.1.3 -InstallDir C:\Project\.dotnet"""] = 0;
|
||||
},
|
||||
7);
|
||||
}
|
||||
|
||||
@@ -119,20 +119,13 @@ namespace Semmle.Autobuild.CSharp
|
||||
=> WithDotNet(builder, (_1, env) => f(env));
|
||||
|
||||
/// <summary>
|
||||
/// Returns a script for downloading relevant versions of the
|
||||
/// .NET Core SDK. The SDK(s) will be installed at <code>installDir</code>
|
||||
/// (provided that the script succeeds).
|
||||
/// Tries to determine the version of .NET that's required for the project from a <code>global.json</code> file, if present.
|
||||
/// </summary>
|
||||
private static BuildScript DownloadDotNet(IAutobuilder<AutobuildOptionsShared> builder, string installDir)
|
||||
/// <returns>
|
||||
/// Returns the .NET version specified in <code>global.json<code> as a string or null if no version could be retrieved.
|
||||
/// </returns>
|
||||
private static string? SdkVersionFromGlobalJson(IAutobuilder<AutobuildOptionsShared> builder)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(builder.Options.DotNetVersion))
|
||||
// Specific version supplied in configuration: always use that
|
||||
return DownloadDotNetVersion(builder, installDir, builder.Options.DotNetVersion);
|
||||
|
||||
// Download versions mentioned in `global.json` files
|
||||
// See https://docs.microsoft.com/en-us/dotnet/core/tools/global-json
|
||||
var installScript = BuildScript.Success;
|
||||
var validGlobalJson = false;
|
||||
foreach (var path in builder.Paths.Select(p => p.Item1).Where(p => p.EndsWith("global.json", StringComparison.Ordinal)))
|
||||
{
|
||||
string version;
|
||||
@@ -147,11 +140,59 @@ namespace Semmle.Autobuild.CSharp
|
||||
continue;
|
||||
}
|
||||
|
||||
installScript &= DownloadDotNetVersion(builder, installDir, version);
|
||||
validGlobalJson = true;
|
||||
return version;
|
||||
}
|
||||
|
||||
return validGlobalJson ? installScript : BuildScript.Failure;
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a script for downloading relevant versions of the
|
||||
/// .NET Core SDK. The SDK(s) will be installed at <code>installDir</code>
|
||||
/// (provided that the script succeeds).
|
||||
/// </summary>
|
||||
private static BuildScript DownloadDotNet(IAutobuilder<AutobuildOptionsShared> builder, string installDir)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(builder.Options.DotNetVersion))
|
||||
// Specific version supplied in configuration: always use that
|
||||
return DownloadDotNetVersion(builder, installDir, builder.Options.DotNetVersion);
|
||||
|
||||
// Download versions mentioned in `global.json` files
|
||||
// See https://docs.microsoft.com/en-us/dotnet/core/tools/global-json
|
||||
var installScript = BuildScript.Success;
|
||||
var foundFrameworkVersion = false;
|
||||
var globalJsonSdkVersion = SdkVersionFromGlobalJson(builder);
|
||||
|
||||
if (!string.IsNullOrEmpty(globalJsonSdkVersion))
|
||||
{
|
||||
installScript &= DownloadDotNetVersion(builder, installDir, globalJsonSdkVersion);
|
||||
foundFrameworkVersion = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
// If there is no `global.json` to retrieve the .NET version from, we find all the
|
||||
// TargetFramework values in the project files and install the latest versions
|
||||
// from the corresponding channels
|
||||
var targetFrameworkVersions = builder.ProjectsOrSolutionsToBuild
|
||||
.SelectMany(p => Enumerators.Singleton(p).Concat(p.IncludedProjects))
|
||||
.OfType<Project<CSharpAutobuildOptions>>()
|
||||
.Select(p => p.TargetFramework)
|
||||
.OfType<string>()
|
||||
.Where(v => v.StartsWith("net"));
|
||||
|
||||
foreach (var targetFrameworkVersion in targetFrameworkVersions)
|
||||
{
|
||||
// For simplicity, we only accept target frameworks of the form "netX.Y"
|
||||
Version? version = null;
|
||||
if (Version.TryParse(targetFrameworkVersion[3..], out version))
|
||||
{
|
||||
installScript &= DownloadDotNetVersion(builder, installDir, "latest", channel: version.ToString());
|
||||
foundFrameworkVersion = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return foundFrameworkVersion ? installScript : BuildScript.Failure;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -160,7 +201,7 @@ namespace Semmle.Autobuild.CSharp
|
||||
///
|
||||
/// See https://docs.microsoft.com/en-us/dotnet/core/tools/dotnet-install-script.
|
||||
/// </summary>
|
||||
private static BuildScript DownloadDotNetVersion(IAutobuilder<AutobuildOptionsShared> builder, string path, string version)
|
||||
private static BuildScript DownloadDotNetVersion(IAutobuilder<AutobuildOptionsShared> builder, string path, string version, string? channel = "release")
|
||||
{
|
||||
return BuildScript.Bind(GetInstalledSdksScript(builder.Actions), (sdks, sdksRet) =>
|
||||
{
|
||||
@@ -174,7 +215,7 @@ namespace Semmle.Autobuild.CSharp
|
||||
if (builder.Actions.IsWindows())
|
||||
{
|
||||
|
||||
var psCommand = $"[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; &([scriptblock]::Create((Invoke-WebRequest -UseBasicParsing 'https://dot.net/v1/dotnet-install.ps1'))) -Version {version} -InstallDir {path}";
|
||||
var psCommand = $"[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; &([scriptblock]::Create((Invoke-WebRequest -UseBasicParsing 'https://dot.net/v1/dotnet-install.ps1'))) -Channel {channel} -Version {version} -InstallDir {path}";
|
||||
|
||||
BuildScript GetInstall(string pwsh) =>
|
||||
new CommandBuilder(builder.Actions).
|
||||
@@ -203,7 +244,7 @@ namespace Semmle.Autobuild.CSharp
|
||||
var install = new CommandBuilder(builder.Actions).
|
||||
RunCommand("./dotnet-install.sh").
|
||||
Argument("--channel").
|
||||
Argument("release").
|
||||
Argument(channel).
|
||||
Argument("--version").
|
||||
Argument(version).
|
||||
Argument("--install-dir").
|
||||
|
||||
@@ -82,7 +82,12 @@ namespace Semmle.Autobuild.Shared
|
||||
Argument("/t:restore").
|
||||
QuoteArgument(projectOrSolution.FullPath);
|
||||
|
||||
if (nugetDownloaded)
|
||||
if (builder.Actions.IsRunningOnAppleSilicon())
|
||||
{
|
||||
// On Apple Silicon, only try package restore with `dotnet msbuild /t:restore`
|
||||
ret &= BuildScript.Try(msbuildRestoreCommand.Script);
|
||||
}
|
||||
else if (nugetDownloaded)
|
||||
{
|
||||
ret &= BuildScript.Try(nugetRestore | msbuildRestoreCommand.Script);
|
||||
}
|
||||
|
||||
@@ -23,6 +23,8 @@ namespace Semmle.Autobuild.Shared
|
||||
|
||||
public Version ToolsVersion { get; private set; }
|
||||
|
||||
public string? TargetFramework { get; private set; }
|
||||
|
||||
private readonly Lazy<List<Project<TAutobuildOptions>>> includedProjectsLazy;
|
||||
public override IEnumerable<IProjectOrSolution> IncludedProjects => includedProjectsLazy.Value;
|
||||
|
||||
@@ -51,7 +53,8 @@ namespace Semmle.Autobuild.Shared
|
||||
{
|
||||
if (root.HasAttribute("Sdk"))
|
||||
{
|
||||
DotNetProject = true;
|
||||
this.DotNetProject = true;
|
||||
this.TargetFramework = root.SelectSingleNode("//Project/PropertyGroup/TargetFramework/text()")?.Value;
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -72,11 +75,12 @@ namespace Semmle.Autobuild.Shared
|
||||
|
||||
includedProjectsLazy = new Lazy<List<Project<TAutobuildOptions>>>(() =>
|
||||
{
|
||||
var mgr = new XmlNamespaceManager(projFile.NameTable);
|
||||
mgr.AddNamespace("msbuild", "http://schemas.microsoft.com/developer/msbuild/2003");
|
||||
|
||||
var ret = new List<Project<TAutobuildOptions>>();
|
||||
// The documentation on `.proj` files is very limited, but it appears that both
|
||||
// `<ProjectFile Include="X"/>` and `<ProjectFiles Include="X"/>` is valid
|
||||
var mgr = new XmlNamespaceManager(projFile.NameTable);
|
||||
mgr.AddNamespace("msbuild", "http://schemas.microsoft.com/developer/msbuild/2003");
|
||||
var projectFileIncludes = root.SelectNodes("//msbuild:Project/msbuild:ItemGroup/msbuild:ProjectFile/@Include", mgr)
|
||||
?.OfType<XmlNode>() ?? Array.Empty<XmlNode>();
|
||||
var projectFilesIncludes = root.SelectNodes("//msbuild:Project/msbuild:ItemGroup/msbuild:ProjectFiles/@Include", mgr)
|
||||
|
||||
@@ -61,6 +61,12 @@ namespace Semmle.Autobuild.Shared
|
||||
{
|
||||
try
|
||||
{
|
||||
// SolutionFile.Parse won't throw a FileNotFoundException if it is given a Windows path on a non-Windows platform
|
||||
if (!builder.Actions.FileExists(FullPath))
|
||||
{
|
||||
throw new FileNotFoundException(FullPath);
|
||||
}
|
||||
|
||||
solution = SolutionFile.Parse(FullPath);
|
||||
}
|
||||
catch (Exception ex) when (ex is InvalidProjectFileException || ex is FileNotFoundException)
|
||||
|
||||
@@ -89,8 +89,10 @@ namespace Semmle.Extraction.CSharp.Populators
|
||||
SyntaxKind.ModuleKeyword => Entities.AttributeKind.Module,
|
||||
_ => throw new InternalError(node, "Unhandled global target")
|
||||
};
|
||||
foreach (var attribute in node.Attributes)
|
||||
var attributes = node.Attributes;
|
||||
for (var i = 0; i < attributes.Count; i++)
|
||||
{
|
||||
var attribute = attributes[i];
|
||||
if (attributeLookup.Value(attribute) is AttributeData attributeData)
|
||||
{
|
||||
var ae = Entities.Attribute.Create(Cx, attributeData, outputAssembly, kind);
|
||||
|
||||
@@ -1,24 +1,6 @@
|
||||
import os
|
||||
|
||||
from create_database_utils import *
|
||||
from diagnostics_test_utils import *
|
||||
|
||||
def is_running_on_apple_silicon():
|
||||
arch = subprocess.Popen(['sysctl', 'machdep.cpu.brand_string'], stdout=subprocess.PIPE)
|
||||
output, errors = arch.communicate()
|
||||
if b'apple' in output.lower():
|
||||
return True
|
||||
return False
|
||||
|
||||
# if on ARM runners, remove Mono from the path, so we're using
|
||||
# dotnet restore instead of nuget.exe restore - on ARM machines
|
||||
# we run dotnet msbuild (instead of the mono-provided msbuild.exe)
|
||||
# so we need to match the restore command, too.
|
||||
|
||||
platform_name = sys.platform.lower()
|
||||
if platform_name.startswith("darwin") and is_running_on_apple_silicon():
|
||||
os.environ["PATH"] = os.environ["PATH"].replace("/Library/Frameworks/Mono.framework/Versions/Current/Commands:", "")
|
||||
|
||||
# force CodeQL to use MSBuild by setting `LGTM_INDEX_MSBUILD_TARGET`
|
||||
run_codeql_database_create([], db=None, lang="csharp", extra_env={ 'LGTM_INDEX_MSBUILD_TARGET': 'Build' })
|
||||
check_diagnostics()
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
Skipping the test on the ARM runners, as we're running into trouble with Mono and nuget.
|
||||
@@ -0,0 +1,2 @@
|
||||
| standalone.cs:3:12:3:29 | [assembly: Attribute1(...)] |
|
||||
| standalone.cs:9:2:9:11 | [Attribute1(...)] |
|
||||
@@ -0,0 +1,5 @@
|
||||
import csharp
|
||||
|
||||
from Attribute a
|
||||
where a.getType().getName() = "Attribute1Attribute"
|
||||
select a
|
||||
@@ -0,0 +1 @@
|
||||
semmle-extractor-options: --standalone
|
||||
@@ -0,0 +1,12 @@
|
||||
using System;
|
||||
|
||||
[assembly: global::Attribute1]
|
||||
|
||||
class Attribute1Attribute : Attribute
|
||||
{
|
||||
}
|
||||
|
||||
[Attribute1]
|
||||
class A
|
||||
{
|
||||
}
|
||||
@@ -42,14 +42,47 @@ Downloading a database from GitHub
|
||||
|
||||
.. include:: ../reusables/download-github-database.rst
|
||||
|
||||
.. _filtering-databases-and-queries-by-language:
|
||||
|
||||
Filtering databases and queries by language
|
||||
-------------------------------------------
|
||||
|
||||
Optionally, to see databases containing a specific language and queries written for that language, you can apply a language filter using the language selector.
|
||||
|
||||
#. To see available language filters, in the sidebar, click the **Language** title bar.
|
||||
#. Hover over the language filter you would like to apply, then click **Select**.
|
||||
|
||||
.. image:: ../images/codeql-for-visual-studio-code/choose-language-filter.png
|
||||
:width: 350
|
||||
:alt: Screenshot of the language selector. The "Select" button for a language filter is outlined in dark orange.
|
||||
|
||||
Creating a custom query
|
||||
------------------------
|
||||
|
||||
You can generate a query template for a specific language from the queries panel, then write your own code to quickly create a custom query.
|
||||
|
||||
#. Optionally, to create a custom query in an existing directory, in the sidebar, click the **Queries** title bar to expand the queries panel, then select the desired directory.
|
||||
#. In the sidebar, hover over the **Queries** title bar, then click the **Create query** icon.
|
||||
|
||||
.. image:: ../images/codeql-for-visual-studio-code/create-query-icon.png
|
||||
:width: 350
|
||||
:alt: Screenshot of the queries panel. The "Create query" icon is outlined in dark orange.
|
||||
|
||||
#. In the Command Palette, select the target language for your query. If you've chosen not to create your custom query in an existing directory, selecting a language will autogenerate a directory labeled ``codeql-custom-queries-<language>``, where ``<language>`` is the name of the selected language. A query template labeled ``example.ql`` will then be added to the existing or autogenerated directory.
|
||||
#. In the template, write your custom query, then save the file. Once your query is finished, you can run it from the queries panel.
|
||||
|
||||
Running a query
|
||||
------------------------
|
||||
|
||||
The `CodeQL repository <https://github.com/github/codeql>`__ on GitHub contains lots of example queries.
|
||||
If you have that folder (or a different CodeQL pack) available in your workspace, you can access existing queries under ``<language>/ql/src/<category>``, for example ``java/ql/src/Likely Bugs``.
|
||||
You can access any existing queries in your workspace through the queries panel.
|
||||
|
||||
#. Open a query (``.ql``) file. It is displayed in the editor, with IntelliSense features such as syntax highlighting and autocomplete suggestions.
|
||||
#. Right-click in the query window and select **CodeQL: Run Query on Selected Database**. (Alternatively, run the command from the Command Palette.)
|
||||
#. In the sidebar, to expand the queries panel, click the **Queries** title bar.
|
||||
#. To run a query against the selected database, hover over the desired query, then click the **Run local query** icon.
|
||||
|
||||
.. image:: ../images/codeql-for-visual-studio-code/run-local-query-icon.png
|
||||
:width: 350
|
||||
:alt: Screenshot of the mouse pointer hovering over a query in the queries panel. The "Run local query" icon is outlined in dark orange.
|
||||
|
||||
The CodeQL extension runs the query on the current database and reports progress in the bottom right corner of the application.
|
||||
When the results are ready, they're displayed in the Results view.
|
||||
@@ -61,6 +94,23 @@ For more information, see ":doc:`Troubleshooting CodeQL for Visual Studio Code <
|
||||
Running multiple queries
|
||||
--------------------------
|
||||
|
||||
You can quickly run multiple queries against the database you've selected using the queries panel or a single command.
|
||||
|
||||
Running all queries in a directory
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
You can easily run every query in a directory using the queries panel.
|
||||
|
||||
#. In the sidebar, to expand the queries panel, click the **Queries** title bar.
|
||||
#. Hover over the desired directory of queries, then click the **Run local queries** icon.
|
||||
|
||||
.. image:: ../images/codeql-for-visual-studio-code/run-local-queries-icon.png
|
||||
:width: 350
|
||||
:alt: Screenshot of the mouse pointer hovering over a directory of queries in the queries panel. The "Run local queries" icon is outlined in dark orange.
|
||||
|
||||
Running a selection of queries
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
You can run multiple queries with a single command.
|
||||
|
||||
#. Go to the File Explorer.
|
||||
@@ -122,6 +172,7 @@ To see the queries that you have run in the current session, open the Query Hist
|
||||
|
||||
The Query History contains information including the date and time when the query was run, the name of the query, the database on which it was run, and how long it took to run the query.
|
||||
To customize the information that is displayed, right-click an entry and select **Rename**.
|
||||
You can also filter the Query History view by language using the language selector. For more information, see ":ref:`Filtering databases and queries by language <filtering-databases-and-queries-by-language>`."
|
||||
|
||||
Click an entry to display the corresponding results in the Query Results view, and double-click
|
||||
to display the query itself in the editor (or right-click and select **View Query**).
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 60 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 41 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 47 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 69 KiB |
@@ -49,7 +49,7 @@ The following properties are supported by all query files:
|
||||
| | | ``warning`` | |
|
||||
| | | ``recommendation`` | |
|
||||
+-----------------------+---------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|
||||
| ``@security-severity``| ``<score>`` | Defines the level of severity, between 0.0 and 10.0, for queries with ``@tags security``. For more information about calculating ``@security-severity``, see the `GitHub changelog <https://github.blog/changelog/2021-07-19-codeql-code-scanning-new-severity-levels-for-security-alerts/>`__. |
|
||||
| ``@security-severity``| ``<score>`` | Defines the level of severity, between 0.0 and 10.0, for queries with ``@tags security``. For more information about calculating ``@security-severity``, see the `GitHub changelog <https://gh.io/2021-07-19-codeql-security-severity>`__. |
|
||||
+-----------------------+---------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|
||||
|
||||
Example
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
---
|
||||
category: fix
|
||||
---
|
||||
* A bug has been fixed that meant that value flow through an array was not tracked correctly in some circumstances. Taint flow was tracked correctly.
|
||||
@@ -724,16 +724,19 @@ class GenericTypeInstantiationExpr extends Expr {
|
||||
* ```go
|
||||
* a[1:3]
|
||||
* a[1:3:5]
|
||||
* a[1:]
|
||||
* a[:3]
|
||||
* a[:]
|
||||
* ```
|
||||
*/
|
||||
class SliceExpr extends @sliceexpr, Expr {
|
||||
/** Gets the base of this slice expression. */
|
||||
Expr getBase() { result = this.getChildExpr(0) }
|
||||
|
||||
/** Gets the lower bound of this slice expression. */
|
||||
/** Gets the lower bound of this slice expression, if any. */
|
||||
Expr getLow() { result = this.getChildExpr(1) }
|
||||
|
||||
/** Gets the upper bound of this slice expression. */
|
||||
/** Gets the upper bound of this slice expression, if any. */
|
||||
Expr getHigh() { result = this.getChildExpr(2) }
|
||||
|
||||
/** Gets the maximum of this slice expression, if any. */
|
||||
|
||||
@@ -21,7 +21,7 @@ predicate containerStoreStep(Node node1, Node node2, Content c) {
|
||||
node2.getType() instanceof SliceType
|
||||
) and
|
||||
(
|
||||
exists(Write w | w.writesElement(node2, _, node1))
|
||||
exists(Write w | w.writesElement(node2.(PostUpdateNode).getPreUpdateNode(), _, node1))
|
||||
or
|
||||
node1 = node2.(ImplicitVarargsSlice).getCallNode().getAnImplicitVarargsArgument()
|
||||
)
|
||||
|
||||
@@ -21,5 +21,5 @@ func main() {
|
||||
// Compare with the standard dataflow support for arrays
|
||||
var b [4]string
|
||||
b[0] = source()
|
||||
sink(b[0]) // $ hasTaintFlow="index expression"
|
||||
sink(b[0]) // $ hasValueFlow="index expression"
|
||||
}
|
||||
|
||||
@@ -47,6 +47,7 @@ edges
|
||||
| test.go:246:15:246:36 | call to GetString | test.go:249:21:249:29 | untrusted |
|
||||
| test.go:259:23:259:44 | call to GetCookie | test.go:259:16:259:45 | type conversion |
|
||||
| test.go:270:62:270:83 | call to GetCookie | test.go:270:55:270:84 | type conversion |
|
||||
| test.go:275:2:275:40 | ... := ...[0] | test.go:278:21:278:28 | index expression |
|
||||
| test.go:275:2:275:40 | ... := ...[0] | test.go:283:44:283:60 | selection of Filename |
|
||||
| test.go:275:2:275:40 | ... := ...[0] | test.go:284:38:284:49 | genericFiles |
|
||||
| test.go:275:2:275:40 | ... := ...[0] | test.go:285:37:285:48 | genericFiles |
|
||||
@@ -61,6 +62,8 @@ edges
|
||||
| test.go:275:2:275:40 | ... := ...[0] | test.go:301:39:301:50 | genericFiles |
|
||||
| test.go:275:2:275:40 | ... := ...[0] | test.go:302:40:302:51 | genericFiles |
|
||||
| test.go:275:2:275:40 | ... := ...[0] | test.go:303:39:303:50 | genericFiles |
|
||||
| test.go:276:2:276:13 | definition of genericFiles [array] | test.go:297:51:297:62 | genericFiles [array] |
|
||||
| test.go:278:21:278:28 | index expression | test.go:276:2:276:13 | definition of genericFiles [array] |
|
||||
| test.go:283:44:283:60 | selection of Filename | test.go:283:21:283:61 | call to GetDisplayString |
|
||||
| test.go:284:21:284:53 | call to SliceChunk | test.go:284:21:284:92 | selection of Filename |
|
||||
| test.go:284:38:284:49 | genericFiles | test.go:284:21:284:53 | call to SliceChunk |
|
||||
@@ -77,6 +80,7 @@ edges
|
||||
| test.go:296:21:296:61 | call to SliceMerge | test.go:296:21:296:97 | selection of Filename |
|
||||
| test.go:296:49:296:60 | genericFiles | test.go:296:21:296:61 | call to SliceMerge |
|
||||
| test.go:297:21:297:66 | call to SlicePad | test.go:297:21:297:102 | selection of Filename |
|
||||
| test.go:297:51:297:62 | genericFiles [array] | test.go:297:51:297:65 | index expression |
|
||||
| test.go:297:51:297:65 | index expression | test.go:297:21:297:66 | call to SlicePad |
|
||||
| test.go:298:21:298:66 | call to SlicePad | test.go:298:21:298:102 | selection of Filename |
|
||||
| test.go:298:36:298:47 | genericFiles | test.go:298:21:298:66 | call to SlicePad |
|
||||
@@ -177,6 +181,8 @@ nodes
|
||||
| test.go:270:55:270:84 | type conversion | semmle.label | type conversion |
|
||||
| test.go:270:62:270:83 | call to GetCookie | semmle.label | call to GetCookie |
|
||||
| test.go:275:2:275:40 | ... := ...[0] | semmle.label | ... := ...[0] |
|
||||
| test.go:276:2:276:13 | definition of genericFiles [array] | semmle.label | definition of genericFiles [array] |
|
||||
| test.go:278:21:278:28 | index expression | semmle.label | index expression |
|
||||
| test.go:283:21:283:61 | call to GetDisplayString | semmle.label | call to GetDisplayString |
|
||||
| test.go:283:44:283:60 | selection of Filename | semmle.label | selection of Filename |
|
||||
| test.go:284:21:284:53 | call to SliceChunk | semmle.label | call to SliceChunk |
|
||||
@@ -202,6 +208,7 @@ nodes
|
||||
| test.go:296:49:296:60 | genericFiles | semmle.label | genericFiles |
|
||||
| test.go:297:21:297:66 | call to SlicePad | semmle.label | call to SlicePad |
|
||||
| test.go:297:21:297:102 | selection of Filename | semmle.label | selection of Filename |
|
||||
| test.go:297:51:297:62 | genericFiles [array] | semmle.label | genericFiles [array] |
|
||||
| test.go:297:51:297:65 | index expression | semmle.label | index expression |
|
||||
| test.go:298:21:298:66 | call to SlicePad | semmle.label | call to SlicePad |
|
||||
| test.go:298:21:298:102 | selection of Filename | semmle.label | selection of Filename |
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
#!/bin/sh
|
||||
set -e
|
||||
|
||||
# Before running this, make sure there is an SSO-enabled token with package:write
|
||||
# permissions to codeql supplied via the GITHUB_TOKEN environment variable
|
||||
|
||||
AUTOMODEL_ROOT="$(readlink -f "$(dirname $0)")"
|
||||
WORKSPACE_ROOT="$AUTOMODEL_ROOT/../../.."
|
||||
GRPS="automodel,-test"
|
||||
|
||||
@@ -30,7 +30,9 @@ newtype TApplicationModeEndpoint =
|
||||
arg.asExpr() = argExpr and call = argExpr.getCall() and not argExpr.isVararg()
|
||||
)
|
||||
} or
|
||||
TInstanceArgument(Call call, DataFlow::Node arg) { arg = DataFlow::getInstanceArgument(call) } or
|
||||
TInstanceArgument(Call call, DataFlow::Node arg) {
|
||||
arg = DataFlow::getInstanceArgument(call) and not call instanceof ConstructorCall
|
||||
} or
|
||||
TImplicitVarargsArray(Call call, DataFlow::Node arg, int idx) {
|
||||
exists(Argument argExpr |
|
||||
arg.asExpr() = argExpr and
|
||||
|
||||
@@ -25,7 +25,7 @@ newtype JavaRelatedLocationType =
|
||||
|
||||
newtype TFrameworkModeEndpoint =
|
||||
TExplicitParameter(Parameter p) or
|
||||
TQualifier(Callable c) or
|
||||
TQualifier(Callable c) { not c instanceof Constructor } or
|
||||
TReturnValue(Callable c) or
|
||||
TOverridableParameter(Method m, Parameter p) {
|
||||
p.getCallable() = m and
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
## 0.0.7
|
||||
|
||||
No user-facing changes.
|
||||
Support for extracting source candidates.
|
||||
@@ -1,13 +1,13 @@
|
||||
| PluginImpl.java:5:27:5:37 | name | Related locations: $@, $@, $@.\nmetadata: $@, $@, $@, $@, $@, $@, $@, $@, $@, $@. | PluginImpl.java:5:27:5:37 | name | CallContext | hudson/Plugin.java:5:5:5:31 | /** Configure method doc */ | MethodDoc | hudson/Plugin.java:3:1:3:17 | /** Plugin doc */ | ClassDoc | file://hudson:1:1:1:1 | hudson | package | file://Plugin:1:1:1:1 | Plugin | type | file://true:1:1:1:1 | true | subtypes | file://configure:1:1:1:1 | configure | name | file://(String,String):1:1:1:1 | (String,String) | signature | file://:1:1:1:1 | | input | file://Parameter[0]:1:1:1:1 | Parameter[0] | output | file://false:1:1:1:1 | false | isVarargsArray | file://:1:1:1:1 | | alreadyAiModeled | file://sourceModel:1:1:1:1 | sourceModel | extensibleType |
|
||||
| PluginImpl.java:5:40:5:51 | value | Related locations: $@, $@, $@.\nmetadata: $@, $@, $@, $@, $@, $@, $@, $@, $@, $@. | PluginImpl.java:5:40:5:51 | value | CallContext | hudson/Plugin.java:5:5:5:31 | /** Configure method doc */ | MethodDoc | hudson/Plugin.java:3:1:3:17 | /** Plugin doc */ | ClassDoc | file://hudson:1:1:1:1 | hudson | package | file://Plugin:1:1:1:1 | Plugin | type | file://true:1:1:1:1 | true | subtypes | file://configure:1:1:1:1 | configure | name | file://(String,String):1:1:1:1 | (String,String) | signature | file://:1:1:1:1 | | input | file://Parameter[1]:1:1:1:1 | Parameter[1] | output | file://false:1:1:1:1 | false | isVarargsArray | file://:1:1:1:1 | | alreadyAiModeled | file://sourceModel:1:1:1:1 | sourceModel | extensibleType |
|
||||
| Test.java:18:3:18:11 | reference | Related locations: $@, $@, $@.\nmetadata: $@, $@, $@, $@, $@, $@, $@, $@, $@, $@. | Test.java:18:3:18:24 | set(...) | CallContext | Test.java:18:3:18:11 | reference | MethodDoc | Test.java:18:3:18:11 | reference | ClassDoc | file://java.util.concurrent.atomic:1:1:1:1 | java.util.concurrent.atomic | package | file://AtomicReference:1:1:1:1 | AtomicReference | type | file://false:1:1:1:1 | false | subtypes | file://set:1:1:1:1 | set | name | file://(String):1:1:1:1 | (String) | signature | file://Argument[this]:1:1:1:1 | Argument[this] | input | file://:1:1:1:1 | | output | file://false:1:1:1:1 | false | isVarargsArray | file://:1:1:1:1 | | alreadyAiModeled | file://sinkModel:1:1:1:1 | sinkModel | extensibleType |
|
||||
| Test.java:23:3:23:10 | supplier | Related locations: $@, $@, $@.\nmetadata: $@, $@, $@, $@, $@, $@, $@, $@, $@, $@. | Test.java:23:3:23:16 | get(...) | CallContext | Test.java:23:3:23:10 | supplier | MethodDoc | Test.java:23:3:23:10 | supplier | ClassDoc | file://java.util.function:1:1:1:1 | java.util.function | package | file://Supplier:1:1:1:1 | Supplier | type | file://true:1:1:1:1 | true | subtypes | file://get:1:1:1:1 | get | name | file://():1:1:1:1 | () | signature | file://Argument[this]:1:1:1:1 | Argument[this] | input | file://:1:1:1:1 | | output | file://false:1:1:1:1 | false | isVarargsArray | file://:1:1:1:1 | | alreadyAiModeled | file://sinkModel:1:1:1:1 | sinkModel | extensibleType |
|
||||
| Test.java:23:3:23:16 | get(...) | Related locations: $@, $@, $@.\nmetadata: $@, $@, $@, $@, $@, $@, $@, $@, $@, $@. | Test.java:23:3:23:16 | get(...) | CallContext | Test.java:23:3:23:16 | get(...) | MethodDoc | Test.java:23:3:23:16 | get(...) | ClassDoc | file://java.util.function:1:1:1:1 | java.util.function | package | file://Supplier:1:1:1:1 | Supplier | type | file://true:1:1:1:1 | true | subtypes | file://get:1:1:1:1 | get | name | file://():1:1:1:1 | () | signature | file://:1:1:1:1 | | input | file://ReturnValue:1:1:1:1 | ReturnValue | output | file://false:1:1:1:1 | false | isVarargsArray | file://:1:1:1:1 | | alreadyAiModeled | file://sourceModel:1:1:1:1 | sourceModel | extensibleType |
|
||||
| Test.java:27:3:31:3 | copy(...) | Related locations: $@, $@, $@.\nmetadata: $@, $@, $@, $@, $@, $@, $@, $@, $@, $@. | Test.java:27:3:31:3 | copy(...) | CallContext | Test.java:27:3:31:3 | copy(...) | MethodDoc | Test.java:27:3:31:3 | copy(...) | ClassDoc | file://java.nio.file:1:1:1:1 | java.nio.file | package | file://Files:1:1:1:1 | Files | type | file://false:1:1:1:1 | false | subtypes | file://copy:1:1:1:1 | copy | name | file://(Path,Path,CopyOption[]):1:1:1:1 | (Path,Path,CopyOption[]) | signature | file://:1:1:1:1 | | input | file://ReturnValue:1:1:1:1 | ReturnValue | output | file://false:1:1:1:1 | false | isVarargsArray | file://:1:1:1:1 | | alreadyAiModeled | file://sourceModel:1:1:1:1 | sourceModel | extensibleType |
|
||||
| Test.java:35:10:37:3 | newInputStream(...) | Related locations: $@, $@, $@.\nmetadata: $@, $@, $@, $@, $@, $@, $@, $@, $@, $@. | Test.java:35:10:37:3 | newInputStream(...) | CallContext | Test.java:35:10:37:3 | newInputStream(...) | MethodDoc | Test.java:35:10:37:3 | newInputStream(...) | ClassDoc | file://java.nio.file:1:1:1:1 | java.nio.file | package | file://Files:1:1:1:1 | Files | type | file://false:1:1:1:1 | false | subtypes | file://newInputStream:1:1:1:1 | newInputStream | name | file://(Path,OpenOption[]):1:1:1:1 | (Path,OpenOption[]) | signature | file://:1:1:1:1 | | input | file://ReturnValue:1:1:1:1 | ReturnValue | output | file://false:1:1:1:1 | false | isVarargsArray | file://:1:1:1:1 | | alreadyAiModeled | file://sourceModel:1:1:1:1 | sourceModel | extensibleType |
|
||||
| Test.java:36:4:36:11 | openPath | Related locations: $@, $@, $@.\nmetadata: $@, $@, $@, $@, $@, $@, $@, $@, $@, $@. | Test.java:35:10:37:3 | newInputStream(...) | CallContext | Test.java:36:4:36:11 | openPath | MethodDoc | Test.java:36:4:36:11 | openPath | ClassDoc | file://java.nio.file:1:1:1:1 | java.nio.file | package | file://Files:1:1:1:1 | Files | type | file://false:1:1:1:1 | false | subtypes | file://newInputStream:1:1:1:1 | newInputStream | name | file://(Path,OpenOption[]):1:1:1:1 | (Path,OpenOption[]) | signature | file://Argument[0]:1:1:1:1 | Argument[0] | input | file://:1:1:1:1 | | output | file://false:1:1:1:1 | false | isVarargsArray | file://ai-manual:1:1:1:1 | ai-manual | alreadyAiModeled | file://sinkModel:1:1:1:1 | sinkModel | extensibleType |
|
||||
| Test.java:42:4:42:22 | get(...) | Related locations: $@, $@, $@.\nmetadata: $@, $@, $@, $@, $@, $@, $@, $@, $@, $@. | Test.java:42:4:42:22 | get(...) | CallContext | Test.java:42:4:42:22 | get(...) | MethodDoc | Test.java:42:4:42:22 | get(...) | ClassDoc | file://java.nio.file:1:1:1:1 | java.nio.file | package | file://Paths:1:1:1:1 | Paths | type | file://false:1:1:1:1 | false | subtypes | file://get:1:1:1:1 | get | name | file://(String,String[]):1:1:1:1 | (String,String[]) | signature | file://:1:1:1:1 | | input | file://ReturnValue:1:1:1:1 | ReturnValue | output | file://false:1:1:1:1 | false | isVarargsArray | file://:1:1:1:1 | | alreadyAiModeled | file://sourceModel:1:1:1:1 | sourceModel | extensibleType |
|
||||
| Test.java:53:3:58:3 | walk(...) | Related locations: $@, $@, $@.\nmetadata: $@, $@, $@, $@, $@, $@, $@, $@, $@, $@. | Test.java:53:3:58:3 | walk(...) | CallContext | Test.java:53:3:58:3 | walk(...) | MethodDoc | Test.java:53:3:58:3 | walk(...) | ClassDoc | file://java.nio.file:1:1:1:1 | java.nio.file | package | file://Files:1:1:1:1 | Files | type | file://false:1:1:1:1 | false | subtypes | file://walk:1:1:1:1 | walk | name | file://(Path,FileVisitOption[]):1:1:1:1 | (Path,FileVisitOption[]) | signature | file://:1:1:1:1 | | input | file://ReturnValue:1:1:1:1 | ReturnValue | output | file://false:1:1:1:1 | false | isVarargsArray | file://:1:1:1:1 | | alreadyAiModeled | file://sourceModel:1:1:1:1 | sourceModel | extensibleType |
|
||||
| Test.java:55:4:55:4 | o | Related locations: $@, $@, $@.\nmetadata: $@, $@, $@, $@, $@, $@, $@, $@, $@, $@. | Test.java:53:3:58:3 | walk(...) | CallContext | Test.java:53:3:58:3 | walk(...) | MethodDoc | Test.java:53:3:58:3 | walk(...) | ClassDoc | file://java.nio.file:1:1:1:1 | java.nio.file | package | file://Files:1:1:1:1 | Files | type | file://false:1:1:1:1 | false | subtypes | file://walk:1:1:1:1 | walk | name | file://(Path,FileVisitOption[]):1:1:1:1 | (Path,FileVisitOption[]) | signature | file://Argument[1]:1:1:1:1 | Argument[1] | input | file://:1:1:1:1 | | output | file://true:1:1:1:1 | true | isVarargsArray | file://:1:1:1:1 | | alreadyAiModeled | file://sinkModel:1:1:1:1 | sinkModel | extensibleType |
|
||||
| Test.java:62:3:62:3 | c | Related locations: $@, $@, $@.\nmetadata: $@, $@, $@, $@, $@, $@, $@, $@, $@, $@. | Test.java:62:3:62:20 | getInputStream(...) | CallContext | Test.java:62:3:62:3 | c | MethodDoc | Test.java:62:3:62:3 | c | ClassDoc | file://java.net:1:1:1:1 | java.net | package | file://URLConnection:1:1:1:1 | URLConnection | type | file://true:1:1:1:1 | true | subtypes | file://getInputStream:1:1:1:1 | getInputStream | name | file://():1:1:1:1 | () | signature | file://Argument[this]:1:1:1:1 | Argument[this] | input | file://:1:1:1:1 | | output | file://false:1:1:1:1 | false | isVarargsArray | file://:1:1:1:1 | | alreadyAiModeled | file://sinkModel:1:1:1:1 | sinkModel | extensibleType |
|
||||
| Test.java:67:30:67:47 | writer | Related locations: $@, $@, $@.\nmetadata: $@, $@, $@, $@, $@, $@, $@, $@, $@, $@. | Test.java:67:30:67:47 | writer | CallContext | Test.java:67:30:67:47 | writer | MethodDoc | Test.java:67:30:67:47 | writer | ClassDoc | file://java.lang:1:1:1:1 | java.lang | package | file://Throwable:1:1:1:1 | Throwable | type | file://true:1:1:1:1 | true | subtypes | file://printStackTrace:1:1:1:1 | printStackTrace | name | file://(PrintWriter):1:1:1:1 | (PrintWriter) | signature | file://:1:1:1:1 | | input | file://Parameter[0]:1:1:1:1 | Parameter[0] | output | file://false:1:1:1:1 | false | isVarargsArray | file://:1:1:1:1 | | alreadyAiModeled | file://sourceModel:1:1:1:1 | sourceModel | extensibleType |
|
||||
| Test.java:19:3:19:11 | reference | Related locations: $@, $@, $@.\nmetadata: $@, $@, $@, $@, $@, $@, $@, $@, $@, $@. | Test.java:19:3:19:24 | set(...) | CallContext | Test.java:19:3:19:11 | reference | MethodDoc | Test.java:19:3:19:11 | reference | ClassDoc | file://java.util.concurrent.atomic:1:1:1:1 | java.util.concurrent.atomic | package | file://AtomicReference:1:1:1:1 | AtomicReference | type | file://false:1:1:1:1 | false | subtypes | file://set:1:1:1:1 | set | name | file://(String):1:1:1:1 | (String) | signature | file://Argument[this]:1:1:1:1 | Argument[this] | input | file://:1:1:1:1 | | output | file://false:1:1:1:1 | false | isVarargsArray | file://:1:1:1:1 | | alreadyAiModeled | file://sinkModel:1:1:1:1 | sinkModel | extensibleType |
|
||||
| Test.java:24:3:24:10 | supplier | Related locations: $@, $@, $@.\nmetadata: $@, $@, $@, $@, $@, $@, $@, $@, $@, $@. | Test.java:24:3:24:16 | get(...) | CallContext | Test.java:24:3:24:10 | supplier | MethodDoc | Test.java:24:3:24:10 | supplier | ClassDoc | file://java.util.function:1:1:1:1 | java.util.function | package | file://Supplier:1:1:1:1 | Supplier | type | file://true:1:1:1:1 | true | subtypes | file://get:1:1:1:1 | get | name | file://():1:1:1:1 | () | signature | file://Argument[this]:1:1:1:1 | Argument[this] | input | file://:1:1:1:1 | | output | file://false:1:1:1:1 | false | isVarargsArray | file://:1:1:1:1 | | alreadyAiModeled | file://sinkModel:1:1:1:1 | sinkModel | extensibleType |
|
||||
| Test.java:24:3:24:16 | get(...) | Related locations: $@, $@, $@.\nmetadata: $@, $@, $@, $@, $@, $@, $@, $@, $@, $@. | Test.java:24:3:24:16 | get(...) | CallContext | Test.java:24:3:24:16 | get(...) | MethodDoc | Test.java:24:3:24:16 | get(...) | ClassDoc | file://java.util.function:1:1:1:1 | java.util.function | package | file://Supplier:1:1:1:1 | Supplier | type | file://true:1:1:1:1 | true | subtypes | file://get:1:1:1:1 | get | name | file://():1:1:1:1 | () | signature | file://:1:1:1:1 | | input | file://ReturnValue:1:1:1:1 | ReturnValue | output | file://false:1:1:1:1 | false | isVarargsArray | file://:1:1:1:1 | | alreadyAiModeled | file://sourceModel:1:1:1:1 | sourceModel | extensibleType |
|
||||
| Test.java:28:3:32:3 | copy(...) | Related locations: $@, $@, $@.\nmetadata: $@, $@, $@, $@, $@, $@, $@, $@, $@, $@. | Test.java:28:3:32:3 | copy(...) | CallContext | Test.java:28:3:32:3 | copy(...) | MethodDoc | Test.java:28:3:32:3 | copy(...) | ClassDoc | file://java.nio.file:1:1:1:1 | java.nio.file | package | file://Files:1:1:1:1 | Files | type | file://false:1:1:1:1 | false | subtypes | file://copy:1:1:1:1 | copy | name | file://(Path,Path,CopyOption[]):1:1:1:1 | (Path,Path,CopyOption[]) | signature | file://:1:1:1:1 | | input | file://ReturnValue:1:1:1:1 | ReturnValue | output | file://false:1:1:1:1 | false | isVarargsArray | file://:1:1:1:1 | | alreadyAiModeled | file://sourceModel:1:1:1:1 | sourceModel | extensibleType |
|
||||
| Test.java:36:10:38:3 | newInputStream(...) | Related locations: $@, $@, $@.\nmetadata: $@, $@, $@, $@, $@, $@, $@, $@, $@, $@. | Test.java:36:10:38:3 | newInputStream(...) | CallContext | Test.java:36:10:38:3 | newInputStream(...) | MethodDoc | Test.java:36:10:38:3 | newInputStream(...) | ClassDoc | file://java.nio.file:1:1:1:1 | java.nio.file | package | file://Files:1:1:1:1 | Files | type | file://false:1:1:1:1 | false | subtypes | file://newInputStream:1:1:1:1 | newInputStream | name | file://(Path,OpenOption[]):1:1:1:1 | (Path,OpenOption[]) | signature | file://:1:1:1:1 | | input | file://ReturnValue:1:1:1:1 | ReturnValue | output | file://false:1:1:1:1 | false | isVarargsArray | file://:1:1:1:1 | | alreadyAiModeled | file://sourceModel:1:1:1:1 | sourceModel | extensibleType |
|
||||
| Test.java:37:4:37:11 | openPath | Related locations: $@, $@, $@.\nmetadata: $@, $@, $@, $@, $@, $@, $@, $@, $@, $@. | Test.java:36:10:38:3 | newInputStream(...) | CallContext | Test.java:37:4:37:11 | openPath | MethodDoc | Test.java:37:4:37:11 | openPath | ClassDoc | file://java.nio.file:1:1:1:1 | java.nio.file | package | file://Files:1:1:1:1 | Files | type | file://false:1:1:1:1 | false | subtypes | file://newInputStream:1:1:1:1 | newInputStream | name | file://(Path,OpenOption[]):1:1:1:1 | (Path,OpenOption[]) | signature | file://Argument[0]:1:1:1:1 | Argument[0] | input | file://:1:1:1:1 | | output | file://false:1:1:1:1 | false | isVarargsArray | file://ai-manual:1:1:1:1 | ai-manual | alreadyAiModeled | file://sinkModel:1:1:1:1 | sinkModel | extensibleType |
|
||||
| Test.java:43:4:43:22 | get(...) | Related locations: $@, $@, $@.\nmetadata: $@, $@, $@, $@, $@, $@, $@, $@, $@, $@. | Test.java:43:4:43:22 | get(...) | CallContext | Test.java:43:4:43:22 | get(...) | MethodDoc | Test.java:43:4:43:22 | get(...) | ClassDoc | file://java.nio.file:1:1:1:1 | java.nio.file | package | file://Paths:1:1:1:1 | Paths | type | file://false:1:1:1:1 | false | subtypes | file://get:1:1:1:1 | get | name | file://(String,String[]):1:1:1:1 | (String,String[]) | signature | file://:1:1:1:1 | | input | file://ReturnValue:1:1:1:1 | ReturnValue | output | file://false:1:1:1:1 | false | isVarargsArray | file://:1:1:1:1 | | alreadyAiModeled | file://sourceModel:1:1:1:1 | sourceModel | extensibleType |
|
||||
| Test.java:54:3:59:3 | walk(...) | Related locations: $@, $@, $@.\nmetadata: $@, $@, $@, $@, $@, $@, $@, $@, $@, $@. | Test.java:54:3:59:3 | walk(...) | CallContext | Test.java:54:3:59:3 | walk(...) | MethodDoc | Test.java:54:3:59:3 | walk(...) | ClassDoc | file://java.nio.file:1:1:1:1 | java.nio.file | package | file://Files:1:1:1:1 | Files | type | file://false:1:1:1:1 | false | subtypes | file://walk:1:1:1:1 | walk | name | file://(Path,FileVisitOption[]):1:1:1:1 | (Path,FileVisitOption[]) | signature | file://:1:1:1:1 | | input | file://ReturnValue:1:1:1:1 | ReturnValue | output | file://false:1:1:1:1 | false | isVarargsArray | file://:1:1:1:1 | | alreadyAiModeled | file://sourceModel:1:1:1:1 | sourceModel | extensibleType |
|
||||
| Test.java:56:4:56:4 | o | Related locations: $@, $@, $@.\nmetadata: $@, $@, $@, $@, $@, $@, $@, $@, $@, $@. | Test.java:54:3:59:3 | walk(...) | CallContext | Test.java:54:3:59:3 | walk(...) | MethodDoc | Test.java:54:3:59:3 | walk(...) | ClassDoc | file://java.nio.file:1:1:1:1 | java.nio.file | package | file://Files:1:1:1:1 | Files | type | file://false:1:1:1:1 | false | subtypes | file://walk:1:1:1:1 | walk | name | file://(Path,FileVisitOption[]):1:1:1:1 | (Path,FileVisitOption[]) | signature | file://Argument[1]:1:1:1:1 | Argument[1] | input | file://:1:1:1:1 | | output | file://true:1:1:1:1 | true | isVarargsArray | file://:1:1:1:1 | | alreadyAiModeled | file://sinkModel:1:1:1:1 | sinkModel | extensibleType |
|
||||
| Test.java:63:3:63:3 | c | Related locations: $@, $@, $@.\nmetadata: $@, $@, $@, $@, $@, $@, $@, $@, $@, $@. | Test.java:63:3:63:20 | getInputStream(...) | CallContext | Test.java:63:3:63:3 | c | MethodDoc | Test.java:63:3:63:3 | c | ClassDoc | file://java.net:1:1:1:1 | java.net | package | file://URLConnection:1:1:1:1 | URLConnection | type | file://true:1:1:1:1 | true | subtypes | file://getInputStream:1:1:1:1 | getInputStream | name | file://():1:1:1:1 | () | signature | file://Argument[this]:1:1:1:1 | Argument[this] | input | file://:1:1:1:1 | | output | file://false:1:1:1:1 | false | isVarargsArray | file://:1:1:1:1 | | alreadyAiModeled | file://sinkModel:1:1:1:1 | sinkModel | extensibleType |
|
||||
| Test.java:68:30:68:47 | writer | Related locations: $@, $@, $@.\nmetadata: $@, $@, $@, $@, $@, $@, $@, $@, $@, $@. | Test.java:68:30:68:47 | writer | CallContext | Test.java:68:30:68:47 | writer | MethodDoc | Test.java:68:30:68:47 | writer | ClassDoc | file://java.lang:1:1:1:1 | java.lang | package | file://Throwable:1:1:1:1 | Throwable | type | file://true:1:1:1:1 | true | subtypes | file://printStackTrace:1:1:1:1 | printStackTrace | name | file://(PrintWriter):1:1:1:1 | (PrintWriter) | signature | file://:1:1:1:1 | | input | file://Parameter[0]:1:1:1:1 | Parameter[0] | output | file://false:1:1:1:1 | false | isVarargsArray | file://:1:1:1:1 | | alreadyAiModeled | file://sourceModel:1:1:1:1 | sourceModel | extensibleType |
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
| Test.java:47:10:49:3 | compareTo(...) | known sanitizer\nrelated locations: $@, $@, $@.\nmetadata: $@, $@, $@, $@, $@, $@, $@, $@, $@. | Test.java:47:10:49:3 | compareTo(...) | CallContext | Test.java:47:10:49:3 | compareTo(...) | MethodDoc | Test.java:47:10:49:3 | compareTo(...) | ClassDoc | file://java.io:1:1:1:1 | java.io | package | file://File:1:1:1:1 | File | type | file://true:1:1:1:1 | true | subtypes | file://compareTo:1:1:1:1 | compareTo | name | file://(File):1:1:1:1 | (File) | signature | file://:1:1:1:1 | | input | file://ReturnValue:1:1:1:1 | ReturnValue | output | file://false:1:1:1:1 | false | isVarargsArray | file://sourceModel:1:1:1:1 | sourceModel | extensibleType |
|
||||
| Test.java:48:4:48:5 | f2 | known non-sink\nrelated locations: $@, $@, $@.\nmetadata: $@, $@, $@, $@, $@, $@, $@, $@, $@. | Test.java:47:10:49:3 | compareTo(...) | CallContext | Test.java:48:4:48:5 | f2 | MethodDoc | Test.java:48:4:48:5 | f2 | ClassDoc | file://java.io:1:1:1:1 | java.io | package | file://File:1:1:1:1 | File | type | file://true:1:1:1:1 | true | subtypes | file://compareTo:1:1:1:1 | compareTo | name | file://(File):1:1:1:1 | (File) | signature | file://Argument[0]:1:1:1:1 | Argument[0] | input | file://:1:1:1:1 | | output | file://false:1:1:1:1 | false | isVarargsArray | file://sinkModel:1:1:1:1 | sinkModel | extensibleType |
|
||||
| Test.java:54:4:54:4 | p | taint step\nrelated locations: $@, $@, $@.\nmetadata: $@, $@, $@, $@, $@, $@, $@, $@, $@. | Test.java:53:3:58:3 | walk(...) | CallContext | Test.java:54:4:54:4 | p | MethodDoc | Test.java:54:4:54:4 | p | ClassDoc | file://java.nio.file:1:1:1:1 | java.nio.file | package | file://Files:1:1:1:1 | Files | type | file://false:1:1:1:1 | false | subtypes | file://walk:1:1:1:1 | walk | name | file://(Path,FileVisitOption[]):1:1:1:1 | (Path,FileVisitOption[]) | signature | file://Argument[0]:1:1:1:1 | Argument[0] | input | file://:1:1:1:1 | | output | file://false:1:1:1:1 | false | isVarargsArray | file://sinkModel:1:1:1:1 | sinkModel | extensibleType |
|
||||
| Test.java:66:7:66:18 | this <constr(this)> | exception\nrelated locations: $@, $@, $@.\nmetadata: $@, $@, $@, $@, $@, $@, $@, $@, $@. | Test.java:66:7:66:18 | super(...) | CallContext | Test.java:66:7:66:18 | super(...) | MethodDoc | Test.java:66:7:66:18 | super(...) | ClassDoc | file://java.lang:1:1:1:1 | java.lang | package | file://Exception:1:1:1:1 | Exception | type | file://true:1:1:1:1 | true | subtypes | file://Exception:1:1:1:1 | Exception | name | file://():1:1:1:1 | () | signature | file://Argument[this]:1:1:1:1 | Argument[this] | input | file://:1:1:1:1 | | output | file://false:1:1:1:1 | false | isVarargsArray | file://sinkModel:1:1:1:1 | sinkModel | extensibleType |
|
||||
| Test.java:48:10:50:3 | compareTo(...) | known sanitizer\nrelated locations: $@, $@, $@.\nmetadata: $@, $@, $@, $@, $@, $@, $@, $@, $@. | Test.java:48:10:50:3 | compareTo(...) | CallContext | Test.java:48:10:50:3 | compareTo(...) | MethodDoc | Test.java:48:10:50:3 | compareTo(...) | ClassDoc | file://java.io:1:1:1:1 | java.io | package | file://File:1:1:1:1 | File | type | file://true:1:1:1:1 | true | subtypes | file://compareTo:1:1:1:1 | compareTo | name | file://(File):1:1:1:1 | (File) | signature | file://:1:1:1:1 | | input | file://ReturnValue:1:1:1:1 | ReturnValue | output | file://false:1:1:1:1 | false | isVarargsArray | file://sourceModel:1:1:1:1 | sourceModel | extensibleType |
|
||||
| Test.java:49:4:49:5 | f2 | known non-sink\nrelated locations: $@, $@, $@.\nmetadata: $@, $@, $@, $@, $@, $@, $@, $@, $@. | Test.java:48:10:50:3 | compareTo(...) | CallContext | Test.java:49:4:49:5 | f2 | MethodDoc | Test.java:49:4:49:5 | f2 | ClassDoc | file://java.io:1:1:1:1 | java.io | package | file://File:1:1:1:1 | File | type | file://true:1:1:1:1 | true | subtypes | file://compareTo:1:1:1:1 | compareTo | name | file://(File):1:1:1:1 | (File) | signature | file://Argument[0]:1:1:1:1 | Argument[0] | input | file://:1:1:1:1 | | output | file://false:1:1:1:1 | false | isVarargsArray | file://sinkModel:1:1:1:1 | sinkModel | extensibleType |
|
||||
| Test.java:55:4:55:4 | p | taint step\nrelated locations: $@, $@, $@.\nmetadata: $@, $@, $@, $@, $@, $@, $@, $@, $@. | Test.java:54:3:59:3 | walk(...) | CallContext | Test.java:55:4:55:4 | p | MethodDoc | Test.java:55:4:55:4 | p | ClassDoc | file://java.nio.file:1:1:1:1 | java.nio.file | package | file://Files:1:1:1:1 | Files | type | file://false:1:1:1:1 | false | subtypes | file://walk:1:1:1:1 | walk | name | file://(Path,FileVisitOption[]):1:1:1:1 | (Path,FileVisitOption[]) | signature | file://Argument[0]:1:1:1:1 | Argument[0] | input | file://:1:1:1:1 | | output | file://false:1:1:1:1 | false | isVarargsArray | file://sinkModel:1:1:1:1 | sinkModel | extensibleType |
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
| Test.java:28:4:28:9 | source | path-injection\nrelated locations: $@, $@, $@.\nmetadata: $@, $@, $@, $@, $@, $@, $@, $@, $@. | Test.java:27:3:31:3 | copy(...) | CallContext | Test.java:28:4:28:9 | source | MethodDoc | Test.java:28:4:28:9 | source | ClassDoc | file://java.nio.file:1:1:1:1 | java.nio.file | package | file://Files:1:1:1:1 | Files | type | file://false:1:1:1:1 | false | subtypes | file://copy:1:1:1:1 | copy | name | file://(Path,Path,CopyOption[]):1:1:1:1 | (Path,Path,CopyOption[]) | signature | file://Argument[0]:1:1:1:1 | Argument[0] | input | file://:1:1:1:1 | | output | file://false:1:1:1:1 | false | isVarargsArray | file://sinkModel:1:1:1:1 | sinkModel | extensibleType |
|
||||
| Test.java:29:4:29:9 | target | path-injection\nrelated locations: $@, $@, $@.\nmetadata: $@, $@, $@, $@, $@, $@, $@, $@, $@. | Test.java:27:3:31:3 | copy(...) | CallContext | Test.java:29:4:29:9 | target | MethodDoc | Test.java:29:4:29:9 | target | ClassDoc | file://java.nio.file:1:1:1:1 | java.nio.file | package | file://Files:1:1:1:1 | Files | type | file://false:1:1:1:1 | false | subtypes | file://copy:1:1:1:1 | copy | name | file://(Path,Path,CopyOption[]):1:1:1:1 | (Path,Path,CopyOption[]) | signature | file://Argument[1]:1:1:1:1 | Argument[1] | input | file://:1:1:1:1 | | output | file://false:1:1:1:1 | false | isVarargsArray | file://sinkModel:1:1:1:1 | sinkModel | extensibleType |
|
||||
| Test.java:36:4:36:11 | openPath | path-injection\nrelated locations: $@, $@, $@.\nmetadata: $@, $@, $@, $@, $@, $@, $@, $@, $@. | Test.java:35:10:37:3 | newInputStream(...) | CallContext | Test.java:36:4:36:11 | openPath | MethodDoc | Test.java:36:4:36:11 | openPath | ClassDoc | file://java.nio.file:1:1:1:1 | java.nio.file | package | file://Files:1:1:1:1 | Files | type | file://false:1:1:1:1 | false | subtypes | file://newInputStream:1:1:1:1 | newInputStream | name | file://(Path,OpenOption[]):1:1:1:1 | (Path,OpenOption[]) | signature | file://Argument[0]:1:1:1:1 | Argument[0] | input | file://:1:1:1:1 | | output | file://false:1:1:1:1 | false | isVarargsArray | file://sinkModel:1:1:1:1 | sinkModel | extensibleType |
|
||||
| Test.java:62:3:62:20 | getInputStream(...) | remote\nrelated locations: $@, $@, $@.\nmetadata: $@, $@, $@, $@, $@, $@, $@, $@, $@. | Test.java:62:3:62:20 | getInputStream(...) | CallContext | Test.java:62:3:62:20 | getInputStream(...) | MethodDoc | Test.java:62:3:62:20 | getInputStream(...) | ClassDoc | file://java.net:1:1:1:1 | java.net | package | file://URLConnection:1:1:1:1 | URLConnection | type | file://true:1:1:1:1 | true | subtypes | file://getInputStream:1:1:1:1 | getInputStream | name | file://():1:1:1:1 | () | signature | file://:1:1:1:1 | | input | file://ReturnValue:1:1:1:1 | ReturnValue | output | file://false:1:1:1:1 | false | isVarargsArray | file://sourceModel:1:1:1:1 | sourceModel | extensibleType |
|
||||
| Test.java:29:4:29:9 | source | path-injection\nrelated locations: $@, $@, $@.\nmetadata: $@, $@, $@, $@, $@, $@, $@, $@, $@. | Test.java:28:3:32:3 | copy(...) | CallContext | Test.java:29:4:29:9 | source | MethodDoc | Test.java:29:4:29:9 | source | ClassDoc | file://java.nio.file:1:1:1:1 | java.nio.file | package | file://Files:1:1:1:1 | Files | type | file://false:1:1:1:1 | false | subtypes | file://copy:1:1:1:1 | copy | name | file://(Path,Path,CopyOption[]):1:1:1:1 | (Path,Path,CopyOption[]) | signature | file://Argument[0]:1:1:1:1 | Argument[0] | input | file://:1:1:1:1 | | output | file://false:1:1:1:1 | false | isVarargsArray | file://sinkModel:1:1:1:1 | sinkModel | extensibleType |
|
||||
| Test.java:30:4:30:9 | target | path-injection\nrelated locations: $@, $@, $@.\nmetadata: $@, $@, $@, $@, $@, $@, $@, $@, $@. | Test.java:28:3:32:3 | copy(...) | CallContext | Test.java:30:4:30:9 | target | MethodDoc | Test.java:30:4:30:9 | target | ClassDoc | file://java.nio.file:1:1:1:1 | java.nio.file | package | file://Files:1:1:1:1 | Files | type | file://false:1:1:1:1 | false | subtypes | file://copy:1:1:1:1 | copy | name | file://(Path,Path,CopyOption[]):1:1:1:1 | (Path,Path,CopyOption[]) | signature | file://Argument[1]:1:1:1:1 | Argument[1] | input | file://:1:1:1:1 | | output | file://false:1:1:1:1 | false | isVarargsArray | file://sinkModel:1:1:1:1 | sinkModel | extensibleType |
|
||||
| Test.java:37:4:37:11 | openPath | path-injection\nrelated locations: $@, $@, $@.\nmetadata: $@, $@, $@, $@, $@, $@, $@, $@, $@. | Test.java:36:10:38:3 | newInputStream(...) | CallContext | Test.java:37:4:37:11 | openPath | MethodDoc | Test.java:37:4:37:11 | openPath | ClassDoc | file://java.nio.file:1:1:1:1 | java.nio.file | package | file://Files:1:1:1:1 | Files | type | file://false:1:1:1:1 | false | subtypes | file://newInputStream:1:1:1:1 | newInputStream | name | file://(Path,OpenOption[]):1:1:1:1 | (Path,OpenOption[]) | signature | file://Argument[0]:1:1:1:1 | Argument[0] | input | file://:1:1:1:1 | | output | file://false:1:1:1:1 | false | isVarargsArray | file://sinkModel:1:1:1:1 | sinkModel | extensibleType |
|
||||
| Test.java:63:3:63:20 | getInputStream(...) | remote\nrelated locations: $@, $@, $@.\nmetadata: $@, $@, $@, $@, $@, $@, $@, $@, $@. | Test.java:63:3:63:20 | getInputStream(...) | CallContext | Test.java:63:3:63:20 | getInputStream(...) | MethodDoc | Test.java:63:3:63:20 | getInputStream(...) | ClassDoc | file://java.net:1:1:1:1 | java.net | package | file://URLConnection:1:1:1:1 | URLConnection | type | file://true:1:1:1:1 | true | subtypes | file://getInputStream:1:1:1:1 | getInputStream | name | file://():1:1:1:1 | () | signature | file://:1:1:1:1 | | input | file://ReturnValue:1:1:1:1 | ReturnValue | output | file://false:1:1:1:1 | false | isVarargsArray | file://sourceModel:1:1:1:1 | sourceModel | extensibleType |
|
||||
|
||||
@@ -11,6 +11,7 @@ import java.util.function.Supplier;
|
||||
import java.io.File;
|
||||
import java.nio.file.FileVisitOption;
|
||||
import java.net.URLConnection;
|
||||
import java.util.concurrent.FutureTask;
|
||||
|
||||
class Test {
|
||||
public static void main(String[] args) throws Exception {
|
||||
@@ -67,4 +68,15 @@ class OverrideTest extends Exception {
|
||||
public void printStackTrace(PrintWriter writer) { // writer is a source candidate because it overrides an existing method
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class TaskUtils {
|
||||
public FutureTask getTask() {
|
||||
FutureTask ft = new FutureTask(() -> {
|
||||
// ^-- no sink candidate for the `this` qualifier of a constructor
|
||||
return 42;
|
||||
});
|
||||
return ft;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,6 +10,8 @@
|
||||
| com/github/codeql/test/PublicClass.java:13:18:13:31 | nonPublicStuff | Related locations: $@, $@.\nmetadata: $@, $@, $@, $@, $@, $@, $@, $@, $@, $@. | com/github/codeql/test/PublicClass.java:13:18:13:31 | nonPublicStuff | MethodDoc | com/github/codeql/test/PublicClass.java:13:18:13:31 | nonPublicStuff | ClassDoc | file://com.github.codeql.test:1:1:1:1 | com.github.codeql.test | package | file://PublicClass:1:1:1:1 | PublicClass | type | file://true:1:1:1:1 | true | subtypes | file://nonPublicStuff:1:1:1:1 | nonPublicStuff | name | file://(String):1:1:1:1 | (String) | signature | file://Argument[this]:1:1:1:1 | Argument[this] | input | file://:1:1:1:1 | | output | file://this:1:1:1:1 | this | parameterName | file://:1:1:1:1 | | alreadyAiModeled | file://sinkModel:1:1:1:1 | sinkModel | extensibleType |
|
||||
| com/github/codeql/test/PublicClass.java:13:33:13:42 | arg | Related locations: $@, $@.\nmetadata: $@, $@, $@, $@, $@, $@, $@, $@, $@, $@. | com/github/codeql/test/PublicClass.java:13:33:13:42 | arg | MethodDoc | com/github/codeql/test/PublicClass.java:13:33:13:42 | arg | ClassDoc | file://com.github.codeql.test:1:1:1:1 | com.github.codeql.test | package | file://PublicClass:1:1:1:1 | PublicClass | type | file://true:1:1:1:1 | true | subtypes | file://nonPublicStuff:1:1:1:1 | nonPublicStuff | name | file://(String):1:1:1:1 | (String) | signature | file://:1:1:1:1 | | input | file://Parameter[0]:1:1:1:1 | Parameter[0] | output | file://arg:1:1:1:1 | arg | parameterName | file://:1:1:1:1 | | alreadyAiModeled | file://sourceModel:1:1:1:1 | sourceModel | extensibleType |
|
||||
| com/github/codeql/test/PublicClass.java:13:33:13:42 | arg | Related locations: $@, $@.\nmetadata: $@, $@, $@, $@, $@, $@, $@, $@, $@, $@. | com/github/codeql/test/PublicClass.java:13:33:13:42 | arg | MethodDoc | com/github/codeql/test/PublicClass.java:13:33:13:42 | arg | ClassDoc | file://com.github.codeql.test:1:1:1:1 | com.github.codeql.test | package | file://PublicClass:1:1:1:1 | PublicClass | type | file://true:1:1:1:1 | true | subtypes | file://nonPublicStuff:1:1:1:1 | nonPublicStuff | name | file://(String):1:1:1:1 | (String) | signature | file://Argument[0]:1:1:1:1 | Argument[0] | input | file://:1:1:1:1 | | output | file://arg:1:1:1:1 | arg | parameterName | file://:1:1:1:1 | | alreadyAiModeled | file://sinkModel:1:1:1:1 | sinkModel | extensibleType |
|
||||
| com/github/codeql/test/PublicClass.java:22:10:22:20 | PublicClass | Related locations: $@, $@.\nmetadata: $@, $@, $@, $@, $@, $@, $@, $@, $@, $@. | com/github/codeql/test/PublicClass.java:22:10:22:20 | PublicClass | MethodDoc | com/github/codeql/test/PublicClass.java:22:10:22:20 | PublicClass | ClassDoc | file://com.github.codeql.test:1:1:1:1 | com.github.codeql.test | package | file://PublicClass:1:1:1:1 | PublicClass | type | file://true:1:1:1:1 | true | subtypes | file://PublicClass:1:1:1:1 | PublicClass | name | file://(Object):1:1:1:1 | (Object) | signature | file://:1:1:1:1 | | input | file://ReturnValue:1:1:1:1 | ReturnValue | output | file://:1:1:1:1 | | parameterName | file://:1:1:1:1 | | alreadyAiModeled | file://sourceModel:1:1:1:1 | sourceModel | extensibleType |
|
||||
| com/github/codeql/test/PublicClass.java:22:22:22:33 | input | Related locations: $@, $@.\nmetadata: $@, $@, $@, $@, $@, $@, $@, $@, $@, $@. | com/github/codeql/test/PublicClass.java:22:22:22:33 | input | MethodDoc | com/github/codeql/test/PublicClass.java:22:22:22:33 | input | ClassDoc | file://com.github.codeql.test:1:1:1:1 | com.github.codeql.test | package | file://PublicClass:1:1:1:1 | PublicClass | type | file://true:1:1:1:1 | true | subtypes | file://PublicClass:1:1:1:1 | PublicClass | name | file://(Object):1:1:1:1 | (Object) | signature | file://Argument[0]:1:1:1:1 | Argument[0] | input | file://:1:1:1:1 | | output | file://input:1:1:1:1 | input | parameterName | file://:1:1:1:1 | | alreadyAiModeled | file://sinkModel:1:1:1:1 | sinkModel | extensibleType |
|
||||
| com/github/codeql/test/PublicInterface.java:4:17:4:21 | stuff | Related locations: $@, $@.\nmetadata: $@, $@, $@, $@, $@, $@, $@, $@, $@, $@. | com/github/codeql/test/PublicInterface.java:4:17:4:21 | stuff | MethodDoc | com/github/codeql/test/PublicInterface.java:4:17:4:21 | stuff | ClassDoc | file://com.github.codeql.test:1:1:1:1 | com.github.codeql.test | package | file://PublicInterface:1:1:1:1 | PublicInterface | type | file://true:1:1:1:1 | true | subtypes | file://stuff:1:1:1:1 | stuff | name | file://(String):1:1:1:1 | (String) | signature | file://:1:1:1:1 | | input | file://Parameter[this]:1:1:1:1 | Parameter[this] | output | file://this:1:1:1:1 | this | parameterName | file://:1:1:1:1 | | alreadyAiModeled | file://sourceModel:1:1:1:1 | sourceModel | extensibleType |
|
||||
| com/github/codeql/test/PublicInterface.java:4:17:4:21 | stuff | Related locations: $@, $@.\nmetadata: $@, $@, $@, $@, $@, $@, $@, $@, $@, $@. | com/github/codeql/test/PublicInterface.java:4:17:4:21 | stuff | MethodDoc | com/github/codeql/test/PublicInterface.java:4:17:4:21 | stuff | ClassDoc | file://com.github.codeql.test:1:1:1:1 | com.github.codeql.test | package | file://PublicInterface:1:1:1:1 | PublicInterface | type | file://true:1:1:1:1 | true | subtypes | file://stuff:1:1:1:1 | stuff | name | file://(String):1:1:1:1 | (String) | signature | file://:1:1:1:1 | | input | file://ReturnValue:1:1:1:1 | ReturnValue | output | file://:1:1:1:1 | | parameterName | file://:1:1:1:1 | | alreadyAiModeled | file://sourceModel:1:1:1:1 | sourceModel | extensibleType |
|
||||
| com/github/codeql/test/PublicInterface.java:4:17:4:21 | stuff | Related locations: $@, $@.\nmetadata: $@, $@, $@, $@, $@, $@, $@, $@, $@, $@. | com/github/codeql/test/PublicInterface.java:4:17:4:21 | stuff | MethodDoc | com/github/codeql/test/PublicInterface.java:4:17:4:21 | stuff | ClassDoc | file://com.github.codeql.test:1:1:1:1 | com.github.codeql.test | package | file://PublicInterface:1:1:1:1 | PublicInterface | type | file://true:1:1:1:1 | true | subtypes | file://stuff:1:1:1:1 | stuff | name | file://(String):1:1:1:1 | (String) | signature | file://Argument[this]:1:1:1:1 | Argument[this] | input | file://:1:1:1:1 | | output | file://this:1:1:1:1 | this | parameterName | file://:1:1:1:1 | | alreadyAiModeled | file://sinkModel:1:1:1:1 | sinkModel | extensibleType |
|
||||
|
||||
@@ -18,4 +18,8 @@ public class PublicClass {
|
||||
void packagePrivateStuff(String arg) {
|
||||
System.out.println(arg);
|
||||
}
|
||||
|
||||
public PublicClass(Object input) {
|
||||
// the `this` qualifier is not a candidate
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,23 +2,11 @@ public void sendUserFile(Socket sock, String user) {
|
||||
BufferedReader filenameReader = new BufferedReader(
|
||||
new InputStreamReader(sock.getInputStream(), "UTF-8"));
|
||||
String filename = filenameReader.readLine();
|
||||
// BAD: read from a file using a path controlled by the user
|
||||
BufferedReader fileReader = new BufferedReader(
|
||||
new FileReader("/home/" + user + "/" + filename));
|
||||
// BAD: read from a file without checking its path
|
||||
BufferedReader fileReader = new BufferedReader(new FileReader(filename));
|
||||
String fileLine = fileReader.readLine();
|
||||
while(fileLine != null) {
|
||||
sock.getOutputStream().write(fileLine.getBytes());
|
||||
fileLine = fileReader.readLine();
|
||||
}
|
||||
}
|
||||
|
||||
public void sendUserFileFixed(Socket sock, String user) {
|
||||
// ...
|
||||
|
||||
// GOOD: remove all dots and directory delimiters from the filename before using
|
||||
String filename = filenameReader.readLine().replaceAll("\\.", "").replaceAll("/", "");
|
||||
BufferedReader fileReader = new BufferedReader(
|
||||
new FileReader("/home/" + user + "/" + filename));
|
||||
|
||||
// ...
|
||||
}
|
||||
|
||||
@@ -8,32 +8,44 @@ can result in sensitive information being revealed or deleted, or an attacker be
|
||||
behavior by modifying unexpected files.</p>
|
||||
|
||||
<p>Paths that are naively constructed from data controlled by a user may contain unexpected special characters,
|
||||
such as "..". Such a path may potentially point to any directory on the file system.</p>
|
||||
such as "..". Such a path may potentially point anywhere on the file system.</p>
|
||||
|
||||
</overview>
|
||||
<recommendation>
|
||||
|
||||
<p>Validate user input before using it to construct a file path. Ideally, follow these rules:</p>
|
||||
<p>Validate user input before using it to construct a file path.</p>
|
||||
|
||||
<ul>
|
||||
<li>Do not allow more than a single "." character.</li>
|
||||
<li>Do not allow directory separators such as "/" or "\" (depending on the file system).</li>
|
||||
<li>Do not rely on simply replacing problematic sequences such as "../". For example, after applying this filter to
|
||||
".../...//" the resulting string would still be "../".</li>
|
||||
<li>Ideally use a whitelist of known good patterns.</li>
|
||||
</ul>
|
||||
<p>The choice of validation depends on whether you want to allow the user to specify complex paths with
|
||||
multiple components that may span multiple folders, or only simple filenames without a path component.</p>
|
||||
|
||||
<p>In the former case, a common strategy is to make sure that the constructed file path is contained within
|
||||
a safe root folder, for example by checking that the path starts with the root folder. Additionally,
|
||||
you need to ensure that the path does not contain any ".." components, since otherwise
|
||||
even a path that starts with the root folder could be used to access files outside the root folder.</p>
|
||||
|
||||
<p>In the latter case, if you want to ensure that the user input is interpreted as a simple filename without
|
||||
a path component, you can remove all path separators ("/" or "\") and all ".." sequences from the input
|
||||
before using it to construct a file path. Note that it is <i>not</i> sufficient to only remove "../" sequences:
|
||||
for example, applying this filter to ".../...//" would still result in the string "../".</p>
|
||||
|
||||
<p>Finally, the simplest (but most restrictive) option is to use an allow list of safe patterns and make sure that
|
||||
the user input matches one of these patterns.</p>
|
||||
|
||||
</recommendation>
|
||||
<example>
|
||||
|
||||
<p>In this example, a file name is read from a <code>java.net.Socket</code> and then used to access a file in the
|
||||
user's home directory and send it back over the socket. However, a malicious user could enter a file name which contains special
|
||||
characters. For example, the string "../../etc/passwd" will result in the code reading the file located at
|
||||
"/home/[user]/../../etc/passwd", which is the system's password file. This file would then be sent back to the user,
|
||||
giving them access to all the system's passwords.</p>
|
||||
<p>In this example, a file name is read from a <code>java.net.Socket</code> and then used to access a file
|
||||
and send it back over the socket. However, a malicious user could enter a file name anywhere on the file system,
|
||||
such as "/etc/passwd".</p>
|
||||
|
||||
<sample src="TaintedPath.java" />
|
||||
|
||||
<p>Simply checking that the path is under a trusted location (such as a known public folder) is not enough,
|
||||
however, since the path could contain relative components such as "..". To fix this, check that it does
|
||||
not contain ".." and starts with the public folder.</p>
|
||||
|
||||
<sample src="TaintedPathGood.java" />
|
||||
|
||||
</example>
|
||||
<references>
|
||||
|
||||
|
||||
14
java/ql/src/Security/CWE/CWE-022/TaintedPathGood.java
Normal file
14
java/ql/src/Security/CWE/CWE-022/TaintedPathGood.java
Normal file
@@ -0,0 +1,14 @@
|
||||
public void sendUserFileGood(Socket sock, String user) {
|
||||
BufferedReader filenameReader = new BufferedReader(
|
||||
new InputStreamReader(sock.getInputStream(), "UTF-8"));
|
||||
String filename = filenameReader.readLine();
|
||||
// GOOD: ensure that the file is in a designated folder in the user's home directory
|
||||
if (!filename.contains("..") && filename.startsWith("/home/" + user + "/public/")) {
|
||||
BufferedReader fileReader = new BufferedReader(new FileReader(filename));
|
||||
String fileLine = fileReader.readLine();
|
||||
while(fileLine != null) {
|
||||
sock.getOutputStream().write(fileLine.getBytes());
|
||||
fileLine = fileReader.readLine();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,9 @@
|
||||
edges
|
||||
| TaintedPath.java:11:38:11:110 | new BufferedReader(...) : BufferedReader | TaintedPath.java:12:24:12:37 | filenameReader : BufferedReader |
|
||||
| TaintedPath.java:11:57:11:109 | new InputStreamReader(...) : InputStreamReader | TaintedPath.java:11:38:11:110 | new BufferedReader(...) : BufferedReader |
|
||||
| TaintedPath.java:11:79:11:99 | getInputStream(...) : InputStream | TaintedPath.java:11:57:11:109 | new InputStreamReader(...) : InputStreamReader |
|
||||
| TaintedPath.java:12:24:12:37 | filenameReader : BufferedReader | TaintedPath.java:12:24:12:48 | readLine(...) : String |
|
||||
| TaintedPath.java:12:24:12:48 | readLine(...) : String | TaintedPath.java:14:68:14:75 | filename |
|
||||
| Test.java:19:18:19:38 | getHostName(...) : String | Test.java:24:20:24:23 | temp |
|
||||
| Test.java:19:18:19:38 | getHostName(...) : String | Test.java:27:21:27:24 | temp |
|
||||
| Test.java:19:18:19:38 | getHostName(...) : String | Test.java:30:44:30:47 | temp |
|
||||
@@ -184,6 +189,12 @@ edges
|
||||
| mad/Test.java:221:26:221:33 | source(...) : String | mad/Test.java:221:19:221:33 | (...)... |
|
||||
| mad/Test.java:226:29:226:36 | source(...) : String | mad/Test.java:226:20:226:36 | (...)... |
|
||||
nodes
|
||||
| TaintedPath.java:11:38:11:110 | new BufferedReader(...) : BufferedReader | semmle.label | new BufferedReader(...) : BufferedReader |
|
||||
| TaintedPath.java:11:57:11:109 | new InputStreamReader(...) : InputStreamReader | semmle.label | new InputStreamReader(...) : InputStreamReader |
|
||||
| TaintedPath.java:11:79:11:99 | getInputStream(...) : InputStream | semmle.label | getInputStream(...) : InputStream |
|
||||
| TaintedPath.java:12:24:12:37 | filenameReader : BufferedReader | semmle.label | filenameReader : BufferedReader |
|
||||
| TaintedPath.java:12:24:12:48 | readLine(...) : String | semmle.label | readLine(...) : String |
|
||||
| TaintedPath.java:14:68:14:75 | filename | semmle.label | filename |
|
||||
| Test.java:19:18:19:38 | getHostName(...) : String | semmle.label | getHostName(...) : String |
|
||||
| Test.java:24:20:24:23 | temp | semmle.label | temp |
|
||||
| Test.java:27:21:27:24 | temp | semmle.label | temp |
|
||||
@@ -375,6 +386,7 @@ nodes
|
||||
| mad/Test.java:226:29:226:36 | source(...) : String | semmle.label | source(...) : String |
|
||||
subpaths
|
||||
#select
|
||||
| TaintedPath.java:14:53:14:76 | new FileReader(...) | TaintedPath.java:11:79:11:99 | getInputStream(...) : InputStream | TaintedPath.java:14:68:14:75 | filename | This path depends on a $@. | TaintedPath.java:11:79:11:99 | getInputStream(...) | user-provided value |
|
||||
| Test.java:24:11:24:24 | new File(...) | Test.java:19:18:19:38 | getHostName(...) : String | Test.java:24:20:24:23 | temp | This path depends on a $@. | Test.java:19:18:19:38 | getHostName(...) | user-provided value |
|
||||
| Test.java:27:11:27:25 | get(...) | Test.java:19:18:19:38 | getHostName(...) : String | Test.java:27:21:27:24 | temp | This path depends on a $@. | Test.java:19:18:19:38 | getHostName(...) | user-provided value |
|
||||
| Test.java:30:11:30:48 | getPath(...) | Test.java:19:18:19:38 | getHostName(...) : String | Test.java:30:44:30:47 | temp | This path depends on a $@. | Test.java:19:18:19:38 | getHostName(...) | user-provided value |
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
import java.io.BufferedReader;
|
||||
import java.io.FileReader;
|
||||
import java.io.InputStreamReader;
|
||||
import java.net.Socket;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.io.IOException;
|
||||
|
||||
public class TaintedPath {
|
||||
public void sendUserFile(Socket sock, String user) throws IOException {
|
||||
BufferedReader filenameReader = new BufferedReader(new InputStreamReader(sock.getInputStream(), "UTF-8"));
|
||||
String filename = filenameReader.readLine();
|
||||
// BAD: read from a file without checking its path
|
||||
BufferedReader fileReader = new BufferedReader(new FileReader(filename));
|
||||
String fileLine = fileReader.readLine();
|
||||
while(fileLine != null) {
|
||||
sock.getOutputStream().write(fileLine.getBytes());
|
||||
fileLine = fileReader.readLine();
|
||||
}
|
||||
}
|
||||
|
||||
public void sendUserFileGood(Socket sock, String user) throws IOException {
|
||||
BufferedReader filenameReader = new BufferedReader(new InputStreamReader(sock.getInputStream(), "UTF-8"));
|
||||
String filename = filenameReader.readLine();
|
||||
// GOOD: ensure that the file is in a designated folder in the user's home directory
|
||||
if (!filename.contains("..") && filename.startsWith("/home/" + user + "/public/")) {
|
||||
BufferedReader fileReader = new BufferedReader(new FileReader(filename));
|
||||
String fileLine = fileReader.readLine();
|
||||
while(fileLine != null) {
|
||||
sock.getOutputStream().write(fileLine.getBytes());
|
||||
fileLine = fileReader.readLine();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -101,4 +101,12 @@ class Test {
|
||||
new File(new URI(null, null, null, 0, t, null, null));
|
||||
}
|
||||
|
||||
void doGet6(String root, InetAddress address)
|
||||
throws IOException{
|
||||
String temp = address.getHostName();
|
||||
// GOOD: Use `contains` and `startsWith` to check if the path is safe
|
||||
if (!temp.contains("..") && temp.startsWith(root + "/")) {
|
||||
File file = new File(temp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
* a cross-site scripting vulnerability.
|
||||
* @kind path-problem
|
||||
* @problem.severity error
|
||||
* @security-severity 6.1
|
||||
* @security-severity 7.8
|
||||
* @precision high
|
||||
* @id js/reflected-xss
|
||||
* @tags security
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
* a stored cross-site scripting vulnerability.
|
||||
* @kind path-problem
|
||||
* @problem.severity error
|
||||
* @security-severity 6.1
|
||||
* @security-severity 7.8
|
||||
* @precision high
|
||||
* @id js/stored-xss
|
||||
* @tags security
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
* a cross-site scripting vulnerability.
|
||||
* @kind path-problem
|
||||
* @problem.severity error
|
||||
* @security-severity 6.1
|
||||
* @security-severity 7.8
|
||||
* @precision high
|
||||
* @id js/xss
|
||||
* @tags security
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
* insertion of forged log entries by a malicious user.
|
||||
* @kind path-problem
|
||||
* @problem.severity error
|
||||
* @security-severity 7.8
|
||||
* @security-severity 6.1
|
||||
* @precision medium
|
||||
* @id js/log-injection
|
||||
* @tags security
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
* @description The total number of lines of JavaScript or TypeScript code across all files checked into the repository, except in `node_modules`. This is a useful metric of the size of a database. For all files that were seen during extraction, this query counts the lines of code, excluding whitespace or comments.
|
||||
* @kind metric
|
||||
* @tags summary
|
||||
* telemetry
|
||||
*/
|
||||
|
||||
import javascript
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
---
|
||||
category: queryMetadata
|
||||
---
|
||||
|
||||
* Lower the severity of log-injection to medium.
|
||||
* Increase the severity of XSS to high.
|
||||
@@ -0,0 +1,4 @@
|
||||
---
|
||||
category: minorAnalysis
|
||||
---
|
||||
* Added basic flow for attributes defined on classes, when the attribute lookup is on a direct reference to that class (so not instance, cls parameter, or self parameter). Example: class definition `class Foo: my_tuples = (dangerous, safe)` and usage `SINK(Foo.my_tuples[0])`.
|
||||
@@ -5,13 +5,18 @@
|
||||
// If you add modeling of a new framework/library, remember to add it to the docs in
|
||||
// `docs/codeql/reusables/supported-frameworks.rst`
|
||||
private import semmle.python.frameworks.Aioch
|
||||
private import semmle.python.frameworks.Aiofile
|
||||
private import semmle.python.frameworks.Aiofiles
|
||||
private import semmle.python.frameworks.Aiohttp
|
||||
private import semmle.python.frameworks.Aiomysql
|
||||
private import semmle.python.frameworks.Aiopg
|
||||
private import semmle.python.frameworks.Aiosqlite
|
||||
private import semmle.python.frameworks.Anyio
|
||||
private import semmle.python.frameworks.Asyncpg
|
||||
private import semmle.python.frameworks.Baize
|
||||
private import semmle.python.frameworks.BSon
|
||||
private import semmle.python.frameworks.CassandraDriver
|
||||
private import semmle.python.frameworks.Cherrypy
|
||||
private import semmle.python.frameworks.ClickhouseDriver
|
||||
private import semmle.python.frameworks.Cryptodome
|
||||
private import semmle.python.frameworks.Cryptography
|
||||
@@ -54,6 +59,7 @@ private import semmle.python.frameworks.Requests
|
||||
private import semmle.python.frameworks.RestFramework
|
||||
private import semmle.python.frameworks.Rsa
|
||||
private import semmle.python.frameworks.RuamelYaml
|
||||
private import semmle.python.frameworks.Sanic
|
||||
private import semmle.python.frameworks.ServerLess
|
||||
private import semmle.python.frameworks.Setuptools
|
||||
private import semmle.python.frameworks.Simplejson
|
||||
|
||||
@@ -846,10 +846,27 @@ predicate comprehensionStoreStep(CfgNode nodeFrom, Content c, CfgNode nodeTo) {
|
||||
* ```
|
||||
* data flows from `x` to the attribute `foo` of (the post-update node for) `obj`.
|
||||
*/
|
||||
predicate attributeStoreStep(Node nodeFrom, AttributeContent c, PostUpdateNode nodeTo) {
|
||||
exists(AttrWrite write |
|
||||
write.accesses(nodeTo.getPreUpdateNode(), c.getAttribute()) and
|
||||
nodeFrom = write.getValue()
|
||||
predicate attributeStoreStep(Node nodeFrom, AttributeContent c, Node nodeTo) {
|
||||
exists(Node object |
|
||||
// Normally we target a PostUpdateNode. However, for class definitions the class
|
||||
// is only constructed after evaluating its' entire scope, so in terms of python
|
||||
// evaluations there is no post or pre update nodes, just one node for the class
|
||||
// expression. Therefore we target the class expression directly.
|
||||
//
|
||||
// Note: Due to the way we handle decorators, using a class decorator will result in
|
||||
// there being a post-update node for the class (argument to the decorator). We do
|
||||
// not want to differentiate between these two cases, so still target the class
|
||||
// expression directly.
|
||||
object = nodeTo.(PostUpdateNode).getPreUpdateNode() and
|
||||
not object.asExpr() instanceof ClassExpr
|
||||
or
|
||||
object = nodeTo and
|
||||
object.asExpr() instanceof ClassExpr
|
||||
|
|
||||
exists(AttrWrite write |
|
||||
write.accesses(object, c.getAttribute()) and
|
||||
nodeFrom = write.getValue()
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
42
python/ql/lib/semmle/python/frameworks/Aiofile.qll
Normal file
42
python/ql/lib/semmle/python/frameworks/Aiofile.qll
Normal file
@@ -0,0 +1,42 @@
|
||||
/**
|
||||
* Provides classes modeling security-relevant aspects of the `aiofile` PyPI package.
|
||||
*
|
||||
* See https://pypi.org/project/aiofile.
|
||||
*/
|
||||
|
||||
private import python
|
||||
private import semmle.python.dataflow.new.DataFlow
|
||||
private import semmle.python.dataflow.new.RemoteFlowSources
|
||||
private import semmle.python.dataflow.new.TaintTracking
|
||||
private import semmle.python.Concepts
|
||||
private import semmle.python.ApiGraphs
|
||||
|
||||
/**
|
||||
* Provides models for the `aiofile` PyPI package.
|
||||
*
|
||||
* See https://pypi.org/project/aiofile.
|
||||
*/
|
||||
private module Aiofile {
|
||||
/**
|
||||
* A call to the `async_open` function or `AIOFile` constructor from `aiofile` as a sink for Filesystem access.
|
||||
*/
|
||||
class FileResponseCall extends FileSystemAccess::Range, API::CallNode {
|
||||
string methodName;
|
||||
|
||||
FileResponseCall() {
|
||||
this = API::moduleImport("aiofile").getMember("async_open").getACall() and
|
||||
methodName = "async_open"
|
||||
or
|
||||
this = API::moduleImport("aiofile").getMember("AIOFile").getACall() and
|
||||
methodName = "AIOFile"
|
||||
}
|
||||
|
||||
override DataFlow::Node getAPathArgument() {
|
||||
result = this.getParameter(0, "file_specifier").asSink() and
|
||||
methodName = "async_open"
|
||||
or
|
||||
result = this.getParameter(0, "filename").asSink() and
|
||||
methodName = "AIOFile"
|
||||
}
|
||||
}
|
||||
}
|
||||
28
python/ql/lib/semmle/python/frameworks/Aiofiles.qll
Normal file
28
python/ql/lib/semmle/python/frameworks/Aiofiles.qll
Normal file
@@ -0,0 +1,28 @@
|
||||
/**
|
||||
* Provides classes modeling security-relevant aspects of the `aiofiles` PyPI package.
|
||||
*
|
||||
* See https://pypi.org/project/aiofiles.
|
||||
*/
|
||||
|
||||
private import python
|
||||
private import semmle.python.dataflow.new.DataFlow
|
||||
private import semmle.python.dataflow.new.RemoteFlowSources
|
||||
private import semmle.python.dataflow.new.TaintTracking
|
||||
private import semmle.python.Concepts
|
||||
private import semmle.python.ApiGraphs
|
||||
|
||||
/**
|
||||
* Provides models for the `aiofiles` PyPI package.
|
||||
*
|
||||
* See https://pypi.org/project/aiofiles.
|
||||
*/
|
||||
private module Aiofiles {
|
||||
/**
|
||||
* A call to the `open` function from `aiofiles` as a sink for Filesystem access.
|
||||
*/
|
||||
class FileResponseCall extends FileSystemAccess::Range, API::CallNode {
|
||||
FileResponseCall() { this = API::moduleImport("aiofiles").getMember("open").getACall() }
|
||||
|
||||
override DataFlow::Node getAPathArgument() { result = this.getParameter(0, "file").asSink() }
|
||||
}
|
||||
}
|
||||
54
python/ql/lib/semmle/python/frameworks/Anyio.qll
Normal file
54
python/ql/lib/semmle/python/frameworks/Anyio.qll
Normal file
@@ -0,0 +1,54 @@
|
||||
/**
|
||||
* Provides classes modeling security-relevant aspects of the `anyio` PyPI package.
|
||||
*
|
||||
* See https://pypi.org/project/anyio.
|
||||
*/
|
||||
|
||||
private import python
|
||||
private import semmle.python.dataflow.new.DataFlow
|
||||
private import semmle.python.dataflow.new.RemoteFlowSources
|
||||
private import semmle.python.dataflow.new.TaintTracking
|
||||
private import semmle.python.Concepts
|
||||
private import semmle.python.ApiGraphs
|
||||
|
||||
/**
|
||||
* Provides models for the `anyio` PyPI package.
|
||||
*
|
||||
* See https://pypi.org/project/anyio.
|
||||
*/
|
||||
private module Anyio {
|
||||
/**
|
||||
* A call to the `from_path` function from `FileReadStream` or `FileWriteStream` constructors of `anyio.streams.file` as a sink for Filesystem access.
|
||||
*/
|
||||
class FileStreamCall extends FileSystemAccess::Range, API::CallNode {
|
||||
FileStreamCall() {
|
||||
this =
|
||||
API::moduleImport("anyio")
|
||||
.getMember("streams")
|
||||
.getMember("file")
|
||||
.getMember(["FileReadStream", "FileWriteStream"])
|
||||
.getMember("from_path")
|
||||
.getACall()
|
||||
}
|
||||
|
||||
override DataFlow::Node getAPathArgument() { result = this.getParameter(0, "path").asSink() }
|
||||
}
|
||||
|
||||
/**
|
||||
* A call to the `Path` constructor from `anyio` as a sink for Filesystem access.
|
||||
*/
|
||||
class PathCall extends FileSystemAccess::Range, API::CallNode {
|
||||
PathCall() { this = API::moduleImport("anyio").getMember("Path").getACall() }
|
||||
|
||||
override DataFlow::Node getAPathArgument() { result = this.getParameter(0).asSink() }
|
||||
}
|
||||
|
||||
/**
|
||||
* A call to the `open_file` function from `anyio` as a sink for Filesystem access.
|
||||
*/
|
||||
class OpenFileCall extends FileSystemAccess::Range, API::CallNode {
|
||||
OpenFileCall() { this = API::moduleImport("anyio").getMember("open_file").getACall() }
|
||||
|
||||
override DataFlow::Node getAPathArgument() { result = this.getParameter(0, "file").asSink() }
|
||||
}
|
||||
}
|
||||
35
python/ql/lib/semmle/python/frameworks/Baize.qll
Normal file
35
python/ql/lib/semmle/python/frameworks/Baize.qll
Normal file
@@ -0,0 +1,35 @@
|
||||
/**
|
||||
* Provides classes modeling security-relevant aspects of the `baize` PyPI package.
|
||||
*
|
||||
* See https://pypi.org/project/baize.
|
||||
*/
|
||||
|
||||
private import python
|
||||
private import semmle.python.dataflow.new.DataFlow
|
||||
private import semmle.python.dataflow.new.TaintTracking
|
||||
private import semmle.python.Concepts
|
||||
private import semmle.python.ApiGraphs
|
||||
private import semmle.python.frameworks.internal.InstanceTaintStepsHelper
|
||||
private import semmle.python.frameworks.Stdlib
|
||||
|
||||
/**
|
||||
* Provides models for `baize` PyPI package.
|
||||
*
|
||||
* See https://pypi.org/project/baize.
|
||||
*/
|
||||
module Baize {
|
||||
/**
|
||||
* A call to the `baize.asgi.FileResponse` constructor as a sink for Filesystem access.
|
||||
*
|
||||
* it is not contained to Starlette source code but it is mentioned in documents as an alternative to Starlette FileResponse
|
||||
*/
|
||||
class BaizeFileResponseCall extends FileSystemAccess::Range, API::CallNode {
|
||||
BaizeFileResponseCall() {
|
||||
this = API::moduleImport("baize").getMember("asgi").getMember("FileResponse").getACall()
|
||||
}
|
||||
|
||||
override DataFlow::Node getAPathArgument() {
|
||||
result = this.getParameter(0, "filepath").asSink()
|
||||
}
|
||||
}
|
||||
}
|
||||
48
python/ql/lib/semmle/python/frameworks/Cherrypy.qll
Normal file
48
python/ql/lib/semmle/python/frameworks/Cherrypy.qll
Normal file
@@ -0,0 +1,48 @@
|
||||
/**
|
||||
* Provides classes modeling security-relevant aspects of the `cherrypy` PyPI package.
|
||||
*/
|
||||
|
||||
private import python
|
||||
private import semmle.python.dataflow.new.DataFlow
|
||||
private import semmle.python.dataflow.new.RemoteFlowSources
|
||||
private import semmle.python.dataflow.new.TaintTracking
|
||||
private import semmle.python.Concepts
|
||||
private import semmle.python.ApiGraphs
|
||||
|
||||
/**
|
||||
* Provides models for the `cherrypy` PyPI package.
|
||||
* See https://cherrypy.dev/.
|
||||
*/
|
||||
private module Cherrypy {
|
||||
/**
|
||||
* Holds for an instance of `cherrypy.lib.static`
|
||||
*/
|
||||
API::Node libStatic() {
|
||||
result = API::moduleImport("cherrypy").getMember("lib").getMember("static")
|
||||
}
|
||||
|
||||
/**
|
||||
* A call to the `serve_file` or `serve_download`or `staticfile` functions of `cherrypy.lib.static` as a sink for Filesystem access.
|
||||
*/
|
||||
class FileResponseCall extends FileSystemAccess::Range, API::CallNode {
|
||||
string funcName;
|
||||
|
||||
FileResponseCall() {
|
||||
this = libStatic().getMember("staticfile").getACall() and
|
||||
funcName = "staticfile"
|
||||
or
|
||||
this = libStatic().getMember("serve_file").getACall() and
|
||||
funcName = "serve_file"
|
||||
or
|
||||
this = libStatic().getMember("serve_download").getACall() and
|
||||
funcName = "serve_download"
|
||||
}
|
||||
|
||||
override DataFlow::Node getAPathArgument() {
|
||||
result = this.getParameter(0, "path").asSink() and funcName = ["serve_download", "serve_file"]
|
||||
or
|
||||
result = this.getParameter(0, "filename").asSink() and
|
||||
funcName = "staticfile"
|
||||
}
|
||||
}
|
||||
}
|
||||
42
python/ql/lib/semmle/python/frameworks/Sanic.qll
Normal file
42
python/ql/lib/semmle/python/frameworks/Sanic.qll
Normal file
@@ -0,0 +1,42 @@
|
||||
/**
|
||||
* Provides classes modeling security-relevant aspects of the `sanic` PyPI package.
|
||||
* See https://sanic.dev/.
|
||||
*/
|
||||
|
||||
private import python
|
||||
private import semmle.python.dataflow.new.DataFlow
|
||||
private import semmle.python.dataflow.new.RemoteFlowSources
|
||||
private import semmle.python.dataflow.new.TaintTracking
|
||||
private import semmle.python.Concepts
|
||||
private import semmle.python.ApiGraphs
|
||||
|
||||
/**
|
||||
* Provides models for the `sanic` PyPI package.
|
||||
* See https://sanic.dev/.
|
||||
*/
|
||||
private module Sanic {
|
||||
/**
|
||||
* Provides models for Sanic applications (an instance of `sanic.Sanic`).
|
||||
*/
|
||||
module App {
|
||||
/** Gets a reference to a Sanic application (an instance of `sanic.Sanic`). */
|
||||
API::Node instance() { result = API::moduleImport("sanic").getMember("Sanic").getReturn() }
|
||||
}
|
||||
|
||||
/**
|
||||
* A call to the `file` or `file_stream` functions of `sanic.response` as a sink for Filesystem access.
|
||||
*/
|
||||
class FileResponseCall extends FileSystemAccess::Range, API::CallNode {
|
||||
FileResponseCall() {
|
||||
this =
|
||||
API::moduleImport("sanic")
|
||||
.getMember("response")
|
||||
.getMember(["file", "file_stream"])
|
||||
.getACall()
|
||||
}
|
||||
|
||||
override DataFlow::Node getAPathArgument() {
|
||||
result = this.getParameter(0, "location").asSink()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -163,4 +163,16 @@ module Starlette {
|
||||
|
||||
/** DEPRECATED: Alias for Url */
|
||||
deprecated module URL = Url;
|
||||
|
||||
/**
|
||||
* A call to the `starlette.responses.FileResponse` constructor as a sink for Filesystem access.
|
||||
*/
|
||||
class FileResponseCall extends FileSystemAccess::Range, API::CallNode {
|
||||
FileResponseCall() {
|
||||
this =
|
||||
API::moduleImport("starlette").getMember("responses").getMember("FileResponse").getACall()
|
||||
}
|
||||
|
||||
override DataFlow::Node getAPathArgument() { result = this.getParameter(0, "path").asSink() }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1479,6 +1479,26 @@ private module StdlibPrivate {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A call to the `io.FileIO` constructor.
|
||||
* See https://docs.python.org/3/library/io.html#io.FileIO
|
||||
*/
|
||||
private class FileIOCall extends FileSystemAccess::Range, API::CallNode {
|
||||
FileIOCall() { this = API::moduleImport("io").getMember("FileIO").getACall() }
|
||||
|
||||
override DataFlow::Node getAPathArgument() { result = this.getParameter(0, "file").asSink() }
|
||||
}
|
||||
|
||||
/**
|
||||
* A call to the `io.open_code` function.
|
||||
* See https://docs.python.org/3.11/library/io.html#io.open_code
|
||||
*/
|
||||
private class OpenCodeCall extends FileSystemAccess::Range, API::CallNode {
|
||||
OpenCodeCall() { this = API::moduleImport("io").getMember("open_code").getACall() }
|
||||
|
||||
override DataFlow::Node getAPathArgument() { result = this.getParameter(0, "path").asSink() }
|
||||
}
|
||||
|
||||
/** Gets a reference to an open file. */
|
||||
private DataFlow::TypeTrackingNode openFile(DataFlow::TypeTracker t, FileSystemAccess openCall) {
|
||||
t.start() and
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
* database. This query counts the lines of code, excluding whitespace or comments.
|
||||
* @kind metric
|
||||
* @tags summary
|
||||
* telemetry
|
||||
* @id py/summary/lines-of-code
|
||||
*/
|
||||
|
||||
|
||||
1
python/ql/src/Summary/options
Normal file
1
python/ql/src/Summary/options
Normal file
@@ -0,0 +1 @@
|
||||
semmle-extractor-options: --lang=3
|
||||
@@ -0,0 +1,4 @@
|
||||
---
|
||||
category: minorAnalysis
|
||||
---
|
||||
* Added modeling of more `FileSystemAccess` in packages `cherrypy`, `aiofile`, `aiofiles`, `anyio`, `sanic`, `starlette`, `baize`, and `io`. This will mainly affect the _Uncontrolled data used in path expression_ (`py/path-injection`) query.
|
||||
@@ -8,4 +8,4 @@
|
||||
| 38 | ControlFlowNode for ExceptStmt | builtin-class AttributeError |
|
||||
| 40 | ControlFlowNode for ExceptStmt | builtin-class IndexError |
|
||||
| 42 | ControlFlowNode for ExceptStmt | builtin-class KeyError |
|
||||
| 57 | ControlFlowNode for ExceptStmt | builtin-class IOError |
|
||||
| 57 | ControlFlowNode for ExceptStmt | builtin-class IOError |
|
||||
|
||||
@@ -12,4 +12,4 @@
|
||||
| 35 | ControlFlowNode for Attribute | builtin-class AttributeError |
|
||||
| 37 | ControlFlowNode for Raise | builtin-class Exception |
|
||||
| 53 | ControlFlowNode for Attribute() | builtin-class IOError |
|
||||
| 54 | ControlFlowNode for Attribute() | builtin-class IOError |
|
||||
| 54 | ControlFlowNode for Attribute() | builtin-class IOError |
|
||||
|
||||
@@ -3,4 +3,4 @@
|
||||
| 36 | ControlFlowNode for a() |
|
||||
| 51 | ControlFlowNode for open() |
|
||||
| 56 | ControlFlowNode for Attribute() |
|
||||
| 58 | ControlFlowNode for Attribute() |
|
||||
| 58 | ControlFlowNode for Attribute() |
|
||||
|
||||
1
python/ql/test/2/library-tests/PointsTo/imports2/options
Normal file
1
python/ql/test/2/library-tests/PointsTo/imports2/options
Normal file
@@ -0,0 +1 @@
|
||||
semmle-extractor-options: --lang=2 --max-import-depth=2 -r package
|
||||
@@ -7,4 +7,4 @@
|
||||
| 36 | class DerivedFromBuiltin | pop |
|
||||
| 36 | class DerivedFromBuiltin | remove |
|
||||
| 36 | class DerivedFromBuiltin | reverse |
|
||||
| 36 | class DerivedFromBuiltin | sort |
|
||||
| 36 | class DerivedFromBuiltin | sort |
|
||||
|
||||
@@ -1 +1 @@
|
||||
| 0 |
|
||||
| 0 |
|
||||
|
||||
@@ -12,4 +12,4 @@
|
||||
| Module package.helper | 2 | ImportExpr | 0 | bottom | absolute | assistant |
|
||||
| Module package.helper | 3 | ImportExpr | 0 | top | absolute | sys |
|
||||
| Module package.helper | 10 | ImportExpr | 1 | bottom | relative | package |
|
||||
| Module test_star | 1 | ImportExpr | -1 | bottom | absolute | test_package |
|
||||
| Module test_star | 1 | ImportExpr | -1 | bottom | absolute | test_package |
|
||||
|
||||
@@ -54,4 +54,4 @@
|
||||
| Module test_star | p | str b'p' |
|
||||
| Module test_star | q | str b'q' |
|
||||
| Module test_star | r | str b'r' |
|
||||
| Module test_star | sys | Module sys |
|
||||
| Module test_star | sys | Module sys |
|
||||
|
||||
@@ -39,4 +39,4 @@
|
||||
| Module test_star | p |
|
||||
| Module test_star | q |
|
||||
| Module test_star | r |
|
||||
| Module test_star | sys |
|
||||
| Module test_star | sys |
|
||||
|
||||
@@ -5,4 +5,4 @@
|
||||
| Module test_package.module2 | test_package.module2 |
|
||||
| Module test_package.module3 | test_package.module3 |
|
||||
| Module test_package.module4 | test_package.module4 |
|
||||
| Module test_star | test_star |
|
||||
| Module test_star | test_star |
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user