Merge remote-tracking branch 'upstream/main' into

uncontrolled-alloc-size
This commit is contained in:
Geoffrey White 2020-08-17 20:49:35 +01:00
Родитель be91cec7ad 9decb47bf0
Коммит 5d485859af
84 изменённых файлов: 4612 добавлений и 1759 удалений

Просмотреть файл

@ -15,6 +15,10 @@ The following changes in version 1.26 affect C/C++ analysis in all applications.
|----------------------------|------------------------|------------------------------------------------------------------|
| Inconsistent direction of for loop (`cpp/inconsistent-loop-direction`) | Fewer false positive results | The query now accounts for intentional wrapping of an unsigned loop counter. |
| Overflow in uncontrolled allocation size (`cpp/uncontrolled-allocation-size`) | | The precision of this query has been decreased from "high" to "medium". As a result, the query is still run but results are no longer displayed on LGTM by default. |
| Comparison result is always the same (`cpp/constant-comparison`) | More correct results | Bounds on expressions involving multiplication can now be determined in more cases. |
## Changes to libraries
* The models library now models more taint flows through `std::string`.
* The `SimpleRangeAnalysis` library now supports multiplications of the form
`e1 * e2` when `e1` and `e2` are unsigned.

Просмотреть файл

@ -24,7 +24,7 @@
| **Query** | **Expected impact** | **Change** |
|--------------------------------|------------------------------|---------------------------------------------------------------------------|
| Incomplete URL substring sanitization (`js/incomplete-url-substring-sanitization`) | More results | This query now recognizes additional URLs when the substring check is an inclusion check. |
## Changes to libraries

Просмотреть файл

@ -18,6 +18,9 @@ Expr getTest() {
or
// boost tests; http://www.boost.org/
result.(FunctionCall).getTarget().hasQualifiedName("boost::unit_test", "make_test_case")
or
// googletest tests; https://github.com/google/googletest/
result.(FunctionCall).getTarget().hasQualifiedName("testing::internal", "MakeAndRegisterTestInfo")
}
from File f, int n

Просмотреть файл

@ -1,5 +1,13 @@
/**
* Provides classes for identifying and reasoning about Microsoft source code
* annotation language (SAL) macros.
*/
import cpp
/**
* A SAL macro defined in `sal.h` or a similar header file.
*/
class SALMacro extends Macro {
SALMacro() {
exists(string filename | filename = this.getFile().getBaseName() |
@ -20,27 +28,34 @@ class SALMacro extends Macro {
}
pragma[noinline]
predicate isTopLevelMacroAccess(MacroAccess ma) { not exists(ma.getParentInvocation()) }
private predicate isTopLevelMacroAccess(MacroAccess ma) { not exists(ma.getParentInvocation()) }
/**
* An invocation of a SAL macro (excluding invocations inside other macros).
*/
class SALAnnotation extends MacroInvocation {
SALAnnotation() {
this.getMacro() instanceof SALMacro and
isTopLevelMacroAccess(this)
}
/** Returns the `Declaration` annotated by `this`. */
/** Gets the `Declaration` annotated by `this`. */
Declaration getDeclaration() {
annotatesAt(this, result.getADeclarationEntry(), _, _) and
not result instanceof Type // exclude typedefs
}
/** Returns the `DeclarationEntry` annotated by `this`. */
/** Gets the `DeclarationEntry` annotated by `this`. */
DeclarationEntry getDeclarationEntry() {
annotatesAt(this, result, _, _) and
not result instanceof TypeDeclarationEntry // exclude typedefs
}
}
/**
* A SAL macro indicating that the return value of a function should always be
* checked.
*/
class SALCheckReturn extends SALAnnotation {
SALCheckReturn() {
exists(SALMacro m | m = this.getMacro() |
@ -50,6 +65,10 @@ class SALCheckReturn extends SALAnnotation {
}
}
/**
* A SAL macro indicating that a pointer variable or return value should not be
* `NULL`.
*/
class SALNotNull extends SALAnnotation {
SALNotNull() {
exists(SALMacro m | m = this.getMacro() |
@ -69,6 +88,9 @@ class SALNotNull extends SALAnnotation {
}
}
/**
* A SAL macro indicating that a value may be `NULL`.
*/
class SALMaybeNull extends SALAnnotation {
SALMaybeNull() {
exists(SALMacro m | m = this.getMacro() |
@ -79,13 +101,29 @@ class SALMaybeNull extends SALAnnotation {
}
}
/**
* A parameter annotated by one or more SAL annotations.
*/
class SALParameter extends Parameter {
/** One of this parameter's annotations. */
SALAnnotation a;
SALParameter() { annotatesAt(a, this.getADeclarationEntry(), _, _) }
predicate isIn() { a.getMacroName().toLowerCase().matches("%\\_in%") }
predicate isOut() { a.getMacroName().toLowerCase().matches("%\\_out%") }
predicate isInOut() { a.getMacroName().toLowerCase().matches("%\\_inout%") }
}
///////////////////////////////////////////////////////////////////////////////
// Implementation details
/**
* Holds if `a` annotates the declaration entry `d` and
* its start position is the `idx`th position in `file` that holds a SAL element.
*/
predicate annotatesAt(SALAnnotation a, DeclarationEntry d, File file, int idx) {
private predicate annotatesAt(SALAnnotation a, DeclarationEntry d, File file, int idx) {
annotatesAtPosition(a.(SALElement).getStartPosition(), d, file, idx)
}
@ -109,22 +147,6 @@ private predicate annotatesAtPosition(SALPosition pos, DeclarationEntry d, File
)
}
/**
* A parameter annotated by one or more SAL annotations.
*/
class SALParameter extends Parameter {
/** One of this parameter's annotations. */
SALAnnotation a;
SALParameter() { annotatesAt(a, this.getADeclarationEntry(), _, _) }
predicate isIn() { a.getMacroName().toLowerCase().matches("%\\_in%") }
predicate isOut() { a.getMacroName().toLowerCase().matches("%\\_out%") }
predicate isInOut() { a.getMacroName().toLowerCase().matches("%\\_inout%") }
}
/**
* A SAL element, that is, a SAL annotation or a declaration entry
* that may have SAL annotations.

Просмотреть файл

@ -0,0 +1,32 @@
<!DOCTYPE qhelp PUBLIC
"-//Semmle//qhelp//EN"
"qhelp.dtd">
<qhelp>
<overview>
<p>Private data that is stored in a file or buffer unencrypted is accessible to an attacker who gains access to the
storage.</p>
</overview>
<recommendation>
<p>Ensure that private data is always encrypted before being stored.
It may be wise to encrypt information before it is put into a buffer that may be readable in memory.</p>
<p>In general, decrypt private data only at the point where it is necessary for it to be used in
cleartext.</p>
</recommendation>
<references>
<li><a href="https://owasp.org/www-project-top-ten/OWASP_Top_Ten_2017/Top_10-2017_A3-Sensitive_Data_Exposure">OWASP Sensitive_Data_Exposure</a></li>
<li>M. Dowd, J. McDonald and J. Schuhm, <i>The Art of Software Security Assessment</i>, 1st Edition, Chapter 2 - 'Common Vulnerabilities of Encryption', p. 43. Addison Wesley, 2006.</li>
<li>M. Howard and D. LeBlanc, <i>Writing Secure Code</i>, 2nd Edition, Chapter 9 - 'Protecting Secret Data', p. 299. Microsoft, 2002.</li>
<!-- LocalWords: CWE
-->
</references>
</qhelp>

Просмотреть файл

@ -0,0 +1,21 @@
/**
* @name Exposure of private information
* @description If private information is written to an external location, it may be accessible by
* unauthorized persons.
* @kind path-problem
* @problem.severity error
* @id cpp/private-cleartext-write
* @tags security
* external/cwe/cwe-359
*/
import cpp
import experimental.semmle.code.cpp.security.PrivateCleartextWrite
import experimental.semmle.code.cpp.security.PrivateCleartextWrite::PrivateCleartextWrite
import DataFlow::PathGraph
from WriteConfig b, DataFlow::PathNode source, DataFlow::PathNode sink
where b.hasFlowPath(source, sink)
select sink.getNode(),
"This write into the external location '" + sink + "' may contain unencrypted data from $@",
source, "this source."

Просмотреть файл

@ -0,0 +1,78 @@
/**
* EXPERIMENTAL: The API of this module may change without notice.
*
* Provides a class for modeling `Expr`s with a restricted range.
*/
import cpp
import semmle.code.cpp.rangeanalysis.SimpleRangeAnalysis
/**
* EXPERIMENTAL: The API of this class may change without notice.
*
* An expression for which a range can be deduced. Extend this class to add
* functionality to the range analysis library.
*/
abstract class SimpleRangeAnalysisExpr extends Expr {
/**
* Gets the lower bound of the expression.
*
* Implementations of this predicate should use
* `getFullyConvertedLowerBounds` and `getFullyConvertedUpperBounds` for
* recursive calls to get the bounds of their children.
*/
abstract float getLowerBounds();
/**
* Gets the upper bound of the expression.
*
* Implementations of this predicate should use
* `getFullyConvertedLowerBounds` and `getFullyConvertedUpperBounds` for
* recursive calls to get the bounds of their children.
*/
abstract float getUpperBounds();
/**
* Holds if the range this expression depends on the definition `srcDef` for
* StackVariable `srcVar`.
*
* Because this predicate cannot be recursive, most implementations should
* override `dependsOnChild` instead.
*/
predicate dependsOnDef(RangeSsaDefinition srcDef, StackVariable srcVar) { none() }
/**
* Holds if this expression depends on the range of its unconverted
* subexpression `child`. This information is used to inform the range
* analysis about cyclic dependencies. Without this information, range
* analysis might work for simple cases but will go into infinite loops on
* complex code.
*
* For example, when modeling a function call whose return value depends on
* all of its arguments, implement this predicate as
* `child = this.getAnArgument()`.
*/
abstract predicate dependsOnChild(Expr child);
}
import SimpleRangeAnalysisInternal
/**
* This class exists to prevent the QL front end from emitting compile errors
* inside `SimpleRangeAnalysis.qll` about certain conjuncts being empty
* because the overrides of `SimpleRangeAnalysisExpr` that happen to be in
* scope do not make use of every feature it offers.
*/
private class Empty extends SimpleRangeAnalysisExpr {
Empty() {
// This predicate is complicated enough that the QL type checker doesn't
// see it as empty but simple enough that the optimizer should.
this = this and none()
}
override float getLowerBounds() { none() }
override float getUpperBounds() { none() }
override predicate dependsOnChild(Expr child) { none() }
}

Просмотреть файл

@ -0,0 +1,63 @@
/**
* Provides a taint-tracking configuration for reasoning about private information flowing unencrypted to an external location.
*/
import cpp
import semmle.code.cpp.dataflow.TaintTracking
import experimental.semmle.code.cpp.security.PrivateData
import semmle.code.cpp.security.FileWrite
import semmle.code.cpp.security.BufferWrite
import semmle.code.cpp.dataflow.TaintTracking
module PrivateCleartextWrite {
/**
* A data flow source for private information flowing unencrypted to an external location.
*/
abstract class Source extends DataFlow::ExprNode { }
/**
* A data flow sink for private information flowing unencrypted to an external location.
*/
abstract class Sink extends DataFlow::ExprNode { }
/**
* A sanitizer for private information flowing unencrypted to an external location.
*/
abstract class Sanitizer extends DataFlow::ExprNode { }
/** A call to any method whose name suggests that it encodes or encrypts the parameter. */
class ProtectSanitizer extends Sanitizer {
ProtectSanitizer() {
exists(Function m, string s |
this.getExpr().(FunctionCall).getTarget() = m and
m.getName().regexpMatch("(?i).*" + s + ".*")
|
s = "protect" or s = "encode" or s = "encrypt"
)
}
}
class WriteConfig extends TaintTracking::Configuration {
WriteConfig() { this = "Write configuration" }
override predicate isSource(DataFlow::Node source) { source instanceof Source }
override predicate isSink(DataFlow::Node sink) { sink instanceof Sink }
override predicate isSanitizer(DataFlow::Node node) { node instanceof Sanitizer }
}
class PrivateDataSource extends Source {
PrivateDataSource() { this.getExpr() instanceof PrivateDataExpr }
}
class WriteSink extends Sink {
WriteSink() {
exists(FileWrite f, BufferWrite b |
this.asExpr() = f.getASource()
or
this.asExpr() = b.getAChild()
)
}
}
}

Просмотреть файл

@ -0,0 +1,53 @@
/**
* Provides classes and predicates for identifying private data and functions for security.
*
* 'Private' data in general is anything that would compromise user privacy if exposed. This
* library tries to guess where private data may either be stored in a variable or produced by a
* function.
*
* This library is not concerned with credentials. See `SensitiveActions` for expressions related
* to credentials.
*/
import cpp
/** A string for `match` that identifies strings that look like they represent private data. */
private string privateNames() {
// Inspired by the list on https://cwe.mitre.org/data/definitions/359.html
// Government identifiers, such as Social Security Numbers
result = "%social%security%number%" or
// Contact information, such as home addresses and telephone numbers
result = "%postcode%" or
result = "%zipcode%" or
// result = "%telephone%" or
// Geographic location - where the user is (or was)
result = "%latitude%" or
result = "%longitude%" or
// Financial data - such as credit card numbers, salary, bank accounts, and debts
result = "%creditcard%" or
result = "%salary%" or
result = "%bankaccount%" or
// Communications - e-mail addresses, private e-mail messages, SMS text messages, chat logs, etc.
// result = "%email%" or
// result = "%mobile%" or
result = "%employer%" or
// Health - medical conditions, insurance status, prescription records
result = "%medical%"
}
/** An expression that might contain private data. */
abstract class PrivateDataExpr extends Expr { }
/** A functiond call that might produce private data. */
class PrivateFunctionCall extends PrivateDataExpr, FunctionCall {
PrivateFunctionCall() {
exists(string s | this.getTarget().getName().toLowerCase() = s | s.matches(privateNames()))
}
}
/** An access to a variable that might contain private data. */
class PrivateVariableAccess extends PrivateDataExpr, VariableAccess {
PrivateVariableAccess() {
exists(string s | this.getTarget().getName().toLowerCase() = s | s.matches(privateNames()))
}
}

Просмотреть файл

@ -1,5 +1,12 @@
import semmle.code.cpp.models.interfaces.Taint
/**
* The `std::basic_string` template class.
*/
class StdBasicString extends TemplateClass {
StdBasicString() { this.hasQualifiedName("std", "basic_string") }
}
/**
* The standard function `std::string.c_str`.
*/
@ -12,3 +19,51 @@ class StdStringCStr extends TaintFunction {
output.isReturnValue()
}
}
/**
* The `std::string` function `operator+`.
*/
class StdStringPlus extends TaintFunction {
StdStringPlus() {
this.hasQualifiedName("std", "operator+") and
this.getUnspecifiedType() = any(StdBasicString s).getAnInstantiation()
}
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
// flow from parameters to return value
(
input.isParameterDeref(0) or
input.isParameterDeref(1)
) and
output.isReturnValue()
}
}
/**
* The `std::string` functions `operator+=` and `append`.
*/
class StdStringAppend extends TaintFunction {
StdStringAppend() {
this.hasQualifiedName("std", "basic_string", "operator+=") or
this.hasQualifiedName("std", "basic_string", "append")
}
/**
* Gets the index of a parameter to this function that is a string (or
* character).
*/
int getAStringParameter() {
getParameter(result).getType() instanceof PointerType or
getParameter(result).getType() instanceof ReferenceType or
getParameter(result).getType() = getDeclaringType().getTemplateArgument(0) // i.e. `std::basic_string::CharT`
}
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
// flow from parameter to string itself (qualifier) and return value
input.isParameterDeref(getAStringParameter()) and
(
output.isQualifierObject() or
output.isReturnValueDeref()
)
}
}

Просмотреть файл

@ -44,6 +44,7 @@
import cpp
private import RangeAnalysisUtils
private import experimental.semmle.code.cpp.models.interfaces.SimpleRangeAnalysisExpr
import RangeSSA
import SimpleRangeAnalysisCached
private import NanAnalysis
@ -156,6 +157,10 @@ float safeFloor(float v) {
result = v
}
private class UnsignedMulExpr extends MulExpr {
UnsignedMulExpr() { this.getType().(IntegralType).isUnsigned() }
}
/** Set of expressions which we know how to analyze. */
private predicate analyzableExpr(Expr e) {
// The type of the expression must be arithmetic. We reuse the logic in
@ -178,6 +183,8 @@ private predicate analyzableExpr(Expr e) {
or
e instanceof SubExpr
or
e instanceof UnsignedMulExpr
or
e instanceof AssignExpr
or
e instanceof AssignAddExpr
@ -207,6 +214,9 @@ private predicate analyzableExpr(Expr e) {
or
// `>>` by a constant
exists(e.(RShiftExpr).getRightOperand().getValue())
or
// A modeled expression for range analysis
e instanceof SimpleRangeAnalysisExpr
)
}
@ -278,6 +288,10 @@ private predicate exprDependsOnDef(Expr e, RangeSsaDefinition srcDef, StackVaria
or
exists(SubExpr subExpr | e = subExpr | exprDependsOnDef(subExpr.getAnOperand(), srcDef, srcVar))
or
exists(UnsignedMulExpr mulExpr | e = mulExpr |
exprDependsOnDef(mulExpr.getAnOperand(), srcDef, srcVar)
)
or
exists(AssignExpr addExpr | e = addExpr | exprDependsOnDef(addExpr.getRValue(), srcDef, srcVar))
or
exists(AssignAddExpr addExpr | e = addExpr |
@ -318,6 +332,16 @@ private predicate exprDependsOnDef(Expr e, RangeSsaDefinition srcDef, StackVaria
)
or
e = srcDef.getAUse(srcVar)
or
// A modeled expression for range analysis
exists(SimpleRangeAnalysisExpr rae | rae = e |
rae.dependsOnDef(srcDef, srcVar)
or
exists(Expr child |
rae.dependsOnChild(child) and
exprDependsOnDef(child, srcDef, srcVar)
)
)
}
/**
@ -381,9 +405,17 @@ private predicate assignmentDef(RangeSsaDefinition def, StackVariable v, Expr ex
)
}
/** See comment above sourceDef. */
/** See comment above assignmentDef. */
private predicate analyzableDef(RangeSsaDefinition def, StackVariable v) {
assignmentDef(def, v, _) or defDependsOnDef(def, v, _, _)
assignmentDef(def, v, _)
or
analyzableExpr(def.(AssignOperation)) and
v = def.getAVariable()
or
analyzableExpr(def.(CrementOperation)) and
v = def.getAVariable()
or
phiDependsOnDef(def, v, _, _)
}
/**
@ -435,13 +467,6 @@ private float addRoundingDownSmall(float x, float small) {
if (x + small) - x > small then result = (x + small).nextDown() else result = (x + small)
}
/**
* Gets the truncated lower bounds of the fully converted expression.
*/
private float getFullyConvertedLowerBounds(Expr expr) {
result = getTruncatedLowerBounds(expr.getFullyConverted())
}
/**
* Gets the lower bounds of the expression.
*
@ -488,13 +513,6 @@ private float getTruncatedLowerBounds(Expr expr) {
result = exprMinVal(expr)
}
/**
* Gets the truncated upper bounds of the fully converted expression.
*/
private float getFullyConvertedUpperBounds(Expr expr) {
result = getTruncatedUpperBounds(expr.getFullyConverted())
}
/**
* Gets the upper bounds of the expression.
*
@ -625,6 +643,13 @@ private float getLowerBoundsImpl(Expr expr) {
result = addRoundingDown(xLow, -yHigh)
)
or
exists(UnsignedMulExpr mulExpr, float xLow, float yLow |
expr = mulExpr and
xLow = getFullyConvertedLowerBounds(mulExpr.getLeftOperand()) and
yLow = getFullyConvertedLowerBounds(mulExpr.getRightOperand()) and
result = xLow * yLow
)
or
exists(AssignExpr assign |
expr = assign and
result = getFullyConvertedLowerBounds(assign.getRValue())
@ -711,7 +736,9 @@ private float getLowerBoundsImpl(Expr expr) {
or
// Use SSA to get the lower bounds for a variable use.
exists(RangeSsaDefinition def, StackVariable v | expr = def.getAUse(v) |
result = getDefLowerBounds(def, v)
result = getDefLowerBounds(def, v) and
// Not explicitly modeled by a SimpleRangeAnalysisExpr
not expr instanceof SimpleRangeAnalysisExpr
)
or
// unsigned `&` (tighter bounds may exist)
@ -727,6 +754,12 @@ private float getLowerBoundsImpl(Expr expr) {
right = rsExpr.getRightOperand().getFullyConverted().getValue().toInt() and
result = safeFloor(left / 2.pow(right))
)
or
// A modeled expression for range analysis
exists(SimpleRangeAnalysisExpr rangeAnalysisExpr |
rangeAnalysisExpr = expr and
result = rangeAnalysisExpr.getLowerBounds()
)
}
/** Only to be called by `getTruncatedUpperBounds`. */
@ -794,6 +827,13 @@ private float getUpperBoundsImpl(Expr expr) {
result = addRoundingUp(xHigh, -yLow)
)
or
exists(UnsignedMulExpr mulExpr, float xHigh, float yHigh |
expr = mulExpr and
xHigh = getFullyConvertedUpperBounds(mulExpr.getLeftOperand()) and
yHigh = getFullyConvertedUpperBounds(mulExpr.getRightOperand()) and
result = xHigh * yHigh
)
or
exists(AssignExpr assign |
expr = assign and
result = getFullyConvertedUpperBounds(assign.getRValue())
@ -878,7 +918,9 @@ private float getUpperBoundsImpl(Expr expr) {
or
// Use SSA to get the upper bounds for a variable use.
exists(RangeSsaDefinition def, StackVariable v | expr = def.getAUse(v) |
result = getDefUpperBounds(def, v)
result = getDefUpperBounds(def, v) and
// Not explicitly modeled by a SimpleRangeAnalysisExpr
not expr instanceof SimpleRangeAnalysisExpr
)
or
// unsigned `&` (tighter bounds may exist)
@ -896,6 +938,12 @@ private float getUpperBoundsImpl(Expr expr) {
right = rsExpr.getRightOperand().getFullyConverted().getValue().toInt() and
result = safeFloor(left / 2.pow(right))
)
or
// A modeled expression for range analysis
exists(SimpleRangeAnalysisExpr rangeAnalysisExpr |
rangeAnalysisExpr = expr and
result = rangeAnalysisExpr.getUpperBounds()
)
}
/**
@ -1480,3 +1528,25 @@ private module SimpleRangeAnalysisCached {
convertedExprMightOverflowPositively(expr)
}
}
/**
* INTERNAL: do not use. This module contains utilities for use in the
* experimental `SimpleRangeAnalysisExpr` module.
*/
module SimpleRangeAnalysisInternal {
/**
* Gets the truncated lower bounds of the fully converted expression.
*/
float getFullyConvertedLowerBounds(Expr expr) {
result = getTruncatedLowerBounds(expr.getFullyConverted())
}
/**
* Gets the truncated upper bounds of the fully converted expression.
*/
float getFullyConvertedUpperBounds(Expr expr) {
result = getTruncatedUpperBounds(expr.getFullyConverted())
}
}
private import SimpleRangeAnalysisInternal

Просмотреть файл

@ -0,0 +1,9 @@
/// Adds its arguments (has custom modeling in QL)
int custom_add_function(int a, int b);
int test_extensibility_add(int x) {
if (x >= -10 && x <= 10) {
int result = custom_add_function(x, 100);
return result; // 90 .. 110
}
}

Просмотреть файл

@ -0,0 +1,4 @@
| extensibility.c:5:7:5:7 | x | -2.147483648E9 | 2.147483647E9 |
| extensibility.c:5:19:5:19 | x | -10.0 | 2.147483647E9 |
| extensibility.c:6:38:6:38 | x | -10.0 | 10.0 |
| extensibility.c:7:12:7:17 | result | 90.0 | 110.0 |

Просмотреть файл

@ -0,0 +1,32 @@
import semmle.code.cpp.rangeanalysis.SimpleRangeAnalysis
import experimental.semmle.code.cpp.models.interfaces.SimpleRangeAnalysisExpr
class CustomAddFunctionCall extends SimpleRangeAnalysisExpr, FunctionCall {
CustomAddFunctionCall() { this.getTarget().hasGlobalName("custom_add_function") }
override float getLowerBounds() {
exists(float lower0, float lower1 |
lower0 = getFullyConvertedLowerBounds(this.getArgument(0)) and
lower1 = getFullyConvertedLowerBounds(this.getArgument(1)) and
// Note: this rounds toward 0, not -Inf as it should
result = lower0 + lower1
)
}
override float getUpperBounds() {
exists(float upper0, float upper1 |
upper0 = getFullyConvertedUpperBounds(this.getArgument(0)) and
upper1 = getFullyConvertedUpperBounds(this.getArgument(1)) and
// Note: this rounds toward 0, not Inf as it should
result = upper0 + upper1
)
}
override predicate dependsOnChild(Expr child) { child = this.getAnArgument() }
}
from VariableAccess expr, float lower, float upper
where
lower = lowerBound(expr) and
upper = upperBound(expr)
select expr, lower, upper

Просмотреть файл

@ -0,0 +1,21 @@
edges
| test.cpp:77:16:77:22 | medical | test.cpp:78:24:78:27 | temp |
| test.cpp:81:17:81:20 | call to func | test.cpp:82:24:82:28 | buff5 |
| test.cpp:81:22:81:28 | medical | test.cpp:81:17:81:20 | call to func |
nodes
| test.cpp:57:9:57:18 | theZipcode | semmle.label | theZipcode |
| test.cpp:74:24:74:30 | medical | semmle.label | medical |
| test.cpp:77:16:77:22 | medical | semmle.label | medical |
| test.cpp:78:24:78:27 | temp | semmle.label | temp |
| test.cpp:81:17:81:20 | call to func | semmle.label | call to func |
| test.cpp:81:22:81:28 | medical | semmle.label | medical |
| test.cpp:82:24:82:28 | buff5 | semmle.label | buff5 |
| test.cpp:96:37:96:46 | theZipcode | semmle.label | theZipcode |
| test.cpp:99:42:99:51 | theZipcode | semmle.label | theZipcode |
#select
| test.cpp:57:9:57:18 | theZipcode | This write into the external location 'theZipcode' may contain unencrypted data from $@ | test.cpp:57:9:57:18 | theZipcode | this source. |
| test.cpp:74:24:74:30 | medical | This write into the external location 'medical' may contain unencrypted data from $@ | test.cpp:74:24:74:30 | medical | this source. |
| test.cpp:78:24:78:27 | temp | This write into the external location 'temp' may contain unencrypted data from $@ | test.cpp:77:16:77:22 | medical | this source. |
| test.cpp:82:24:82:28 | buff5 | This write into the external location 'buff5' may contain unencrypted data from $@ | test.cpp:81:22:81:28 | medical | this source. |
| test.cpp:96:37:96:46 | theZipcode | This write into the external location 'theZipcode' may contain unencrypted data from $@ | test.cpp:96:37:96:46 | theZipcode | this source. |
| test.cpp:99:42:99:51 | theZipcode | This write into the external location 'theZipcode' may contain unencrypted data from $@ | test.cpp:99:42:99:51 | theZipcode | this source. |

Просмотреть файл

@ -0,0 +1 @@
experimental/Security/CWE/CWE-359/PrivateCleartextWrite.ql

Просмотреть файл

@ -0,0 +1,105 @@
#define FILE int
#define wchar char
#define size_t int
typedef int streamsize;
size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream);
int fputs(const char *s, FILE *stream);
int fputc(int c, FILE *stream);
int fprintf(FILE *stream, const char *format, ...);
int sprintf(char *s, const char *format, ...);
size_t strlen(const char *s);
namespace std
{
template <class charT>
struct char_traits;
template <class charT, class traits = char_traits<charT>>
class basic_ostream /*: virtual public basic_ios<charT,traits> - not needed for this test */
{
public:
typedef charT char_type;
basic_ostream<charT, traits> &write(const char_type *s, streamsize n);
};
template <class charT, class traits = char_traits<charT>>
class basic_ofstream : public basic_ostream<charT, traits>
{
public:
};
template <class charT, class traits>
basic_ostream<charT, traits> &operator<<(basic_ostream<charT, traits> &, const charT *);
typedef basic_ostream<char> ostream;
typedef basic_ofstream<char> ofstream;
}; // namespace std
using namespace std;
char *encrypt(char *buffer)
{
return buffer;
}
char *func(char *buffer)
{
return buffer;
}
// test for CleartextFileWrite
void file()
{
char *theZipcode = "cleartext zipcode!";
FILE *file;
// BAD: write zipcode to file in cleartext
fputs(theZipcode, file);
// GOOD: encrypt first
char *encrypted = encrypt(theZipcode);
fwrite(encrypted, sizeof(encrypted), 1, file);
}
// test for CleartextBufferWrite
int main(int argc, char **argv)
{
char *medical = "medical";
char *buff1;
char *buff2;
char *buff3;
char *buff4;
// BAD: write medical to buffer in cleartext
sprintf(buff1, "%s", medical);
// BAD: write medical to buffer in cleartext
char *temp = medical;
sprintf(buff2, "%s", temp);
// BAD: write medical to buffer in cleartext
char *buff5 = func(medical);
sprintf(buff3, "%s", buff5);
char *buff6 = encrypt(medical);
// GOOD: encrypt first
sprintf(buff4, "%s", buff6);
}
// test for CleartextFileWrite
void stream()
{
char *theZipcode = "cleartext zipcode!";
ofstream mystream;
// BAD: write zipcode to file in cleartext
mystream << "the zipcode is: " << theZipcode;
// BAD: write zipcode to file in cleartext
(mystream << "the zipcode is: ").write(theZipcode, strlen(theZipcode));
// GOOD: encrypt first
char *encrypted = encrypt(theZipcode);
mystream << "the zipcode is: " << encrypted;
(mystream << "the zipcode is: ").write(encrypted, strlen(encrypted));
}

Просмотреть файл

@ -308,205 +308,230 @@
| movableclass.cpp:65:13:65:18 | call to source | movableclass.cpp:65:13:65:20 | call to MyMovableClass | TAINT |
| movableclass.cpp:65:13:65:20 | call to MyMovableClass | movableclass.cpp:65:8:65:9 | ref arg s3 | TAINT |
| movableclass.cpp:65:13:65:20 | call to MyMovableClass | movableclass.cpp:65:11:65:11 | call to operator= | TAINT |
| stl.cpp:97:12:97:17 | call to source | stl.cpp:101:7:101:7 | a | |
| stl.cpp:98:16:98:20 | 123 | stl.cpp:98:16:98:21 | call to basic_string | TAINT |
| stl.cpp:98:16:98:21 | call to basic_string | stl.cpp:102:7:102:7 | b | |
| stl.cpp:98:16:98:21 | call to basic_string | stl.cpp:104:7:104:7 | b | |
| stl.cpp:99:16:99:21 | call to source | stl.cpp:99:16:99:24 | call to basic_string | TAINT |
| stl.cpp:99:16:99:24 | call to basic_string | stl.cpp:103:7:103:7 | c | |
| stl.cpp:99:16:99:24 | call to basic_string | stl.cpp:105:7:105:7 | c | |
| stl.cpp:104:7:104:7 | b | stl.cpp:104:9:104:13 | call to c_str | TAINT |
| stl.cpp:105:7:105:7 | c | stl.cpp:105:9:105:13 | call to c_str | TAINT |
| stl.cpp:110:20:110:22 | call to basic_stringstream | stl.cpp:113:2:113:4 | ss1 | |
| stl.cpp:110:20:110:22 | call to basic_stringstream | stl.cpp:119:7:119:9 | ss1 | |
| stl.cpp:110:20:110:22 | call to basic_stringstream | stl.cpp:124:7:124:9 | ss1 | |
| stl.cpp:110:25:110:27 | call to basic_stringstream | stl.cpp:114:2:114:4 | ss2 | |
| stl.cpp:110:25:110:27 | call to basic_stringstream | stl.cpp:120:7:120:9 | ss2 | |
| stl.cpp:110:25:110:27 | call to basic_stringstream | stl.cpp:125:7:125:9 | ss2 | |
| stl.cpp:110:30:110:32 | call to basic_stringstream | stl.cpp:115:2:115:4 | ss3 | |
| stl.cpp:110:30:110:32 | call to basic_stringstream | stl.cpp:121:7:121:9 | ss3 | |
| stl.cpp:110:30:110:32 | call to basic_stringstream | stl.cpp:126:7:126:9 | ss3 | |
| stl.cpp:110:35:110:37 | call to basic_stringstream | stl.cpp:116:2:116:4 | ss4 | |
| stl.cpp:110:35:110:37 | call to basic_stringstream | stl.cpp:122:7:122:9 | ss4 | |
| stl.cpp:110:35:110:37 | call to basic_stringstream | stl.cpp:127:7:127:9 | ss4 | |
| stl.cpp:110:40:110:42 | call to basic_stringstream | stl.cpp:117:2:117:4 | ss5 | |
| stl.cpp:110:40:110:42 | call to basic_stringstream | stl.cpp:123:7:123:9 | ss5 | |
| stl.cpp:110:40:110:42 | call to basic_stringstream | stl.cpp:128:7:128:9 | ss5 | |
| stl.cpp:111:16:111:21 | call to source | stl.cpp:111:16:111:24 | call to basic_string | TAINT |
| stl.cpp:111:16:111:24 | call to basic_string | stl.cpp:117:9:117:9 | t | |
| stl.cpp:113:2:113:4 | ref arg ss1 | stl.cpp:119:7:119:9 | ss1 | |
| stl.cpp:113:2:113:4 | ref arg ss1 | stl.cpp:124:7:124:9 | ss1 | |
| stl.cpp:114:2:114:4 | ref arg ss2 | stl.cpp:120:7:120:9 | ss2 | |
| stl.cpp:114:2:114:4 | ref arg ss2 | stl.cpp:125:7:125:9 | ss2 | |
| stl.cpp:115:2:115:4 | ref arg ss3 | stl.cpp:121:7:121:9 | ss3 | |
| stl.cpp:115:2:115:4 | ref arg ss3 | stl.cpp:126:7:126:9 | ss3 | |
| stl.cpp:116:2:116:4 | ref arg ss4 | stl.cpp:122:7:122:9 | ss4 | |
| stl.cpp:116:2:116:4 | ref arg ss4 | stl.cpp:127:7:127:9 | ss4 | |
| stl.cpp:117:2:117:4 | ref arg ss5 | stl.cpp:123:7:123:9 | ss5 | |
| stl.cpp:117:2:117:4 | ref arg ss5 | stl.cpp:128:7:128:9 | ss5 | |
| stl.cpp:131:32:131:37 | source | stl.cpp:136:9:136:14 | source | |
| stl.cpp:133:20:133:22 | call to basic_stringstream | stl.cpp:135:2:135:4 | ss1 | |
| stl.cpp:133:20:133:22 | call to basic_stringstream | stl.cpp:138:7:138:9 | ss1 | |
| stl.cpp:133:20:133:22 | call to basic_stringstream | stl.cpp:140:7:140:9 | ss1 | |
| stl.cpp:133:25:133:27 | call to basic_stringstream | stl.cpp:136:2:136:4 | ss2 | |
| stl.cpp:133:25:133:27 | call to basic_stringstream | stl.cpp:139:7:139:9 | ss2 | |
| stl.cpp:133:25:133:27 | call to basic_stringstream | stl.cpp:141:7:141:9 | ss2 | |
| stl.cpp:135:2:135:4 | ref arg ss1 | stl.cpp:138:7:138:9 | ss1 | |
| stl.cpp:135:2:135:4 | ref arg ss1 | stl.cpp:140:7:140:9 | ss1 | |
| stl.cpp:136:2:136:4 | ref arg ss2 | stl.cpp:139:7:139:9 | ss2 | |
| stl.cpp:136:2:136:4 | ref arg ss2 | stl.cpp:141:7:141:9 | ss2 | |
| stl.cpp:154:16:154:28 | call to basic_string | stl.cpp:155:7:155:11 | path1 | |
| stl.cpp:154:17:154:26 | call to user_input | stl.cpp:154:16:154:28 | call to basic_string | TAINT |
| stl.cpp:155:7:155:11 | path1 | stl.cpp:155:13:155:17 | call to c_str | TAINT |
| stl.cpp:158:10:158:19 | call to user_input | stl.cpp:158:10:158:21 | call to basic_string | TAINT |
| stl.cpp:158:10:158:21 | call to basic_string | stl.cpp:158:2:158:21 | ... = ... | |
| stl.cpp:158:10:158:21 | call to basic_string | stl.cpp:159:7:159:11 | path2 | |
| stl.cpp:159:7:159:11 | path2 | stl.cpp:159:13:159:17 | call to c_str | TAINT |
| stl.cpp:161:15:161:24 | call to user_input | stl.cpp:161:15:161:27 | call to basic_string | TAINT |
| stl.cpp:161:15:161:27 | call to basic_string | stl.cpp:162:7:162:11 | path3 | |
| stl.cpp:162:7:162:11 | path3 | stl.cpp:162:13:162:17 | call to c_str | TAINT |
| stl.cpp:167:19:167:24 | call to source | stl.cpp:170:17:170:18 | cs | |
| stl.cpp:167:19:167:24 | call to source | stl.cpp:172:7:172:8 | cs | |
| stl.cpp:170:17:170:18 | cs | stl.cpp:170:17:170:19 | call to basic_string | TAINT |
| stl.cpp:170:17:170:19 | call to basic_string | stl.cpp:173:7:173:8 | ss | |
| stl.cpp:178:19:178:24 | call to source | stl.cpp:181:17:181:18 | cs | |
| stl.cpp:181:17:181:18 | cs | stl.cpp:181:17:181:19 | call to basic_string | TAINT |
| stl.cpp:181:17:181:19 | call to basic_string | stl.cpp:184:7:184:8 | ss | |
| stl.cpp:181:17:181:19 | call to basic_string | stl.cpp:187:7:187:8 | ss | |
| stl.cpp:184:7:184:8 | ss | stl.cpp:184:10:184:14 | call to c_str | TAINT |
| stl.cpp:184:10:184:14 | call to c_str | stl.cpp:184:2:184:16 | ... = ... | |
| stl.cpp:184:10:184:14 | call to c_str | stl.cpp:186:7:186:8 | cs | |
| stl.cpp:193:18:193:24 | hello | stl.cpp:193:18:193:25 | call to basic_string | TAINT |
| stl.cpp:193:18:193:25 | call to basic_string | stl.cpp:198:8:198:9 | s1 | |
| stl.cpp:194:19:194:26 | call to basic_string | stl.cpp:199:8:199:9 | s2 | |
| stl.cpp:194:20:194:26 | hello | stl.cpp:194:19:194:26 | call to basic_string | TAINT |
| stl.cpp:196:8:196:14 | call to basic_string | stl.cpp:196:3:196:14 | ... = ... | |
| stl.cpp:196:8:196:14 | call to basic_string | stl.cpp:200:8:200:9 | s3 | |
| stl.cpp:196:8:196:14 | hello | stl.cpp:196:8:196:14 | call to basic_string | TAINT |
| stl.cpp:204:18:204:23 | call to source | stl.cpp:204:18:204:26 | call to basic_string | TAINT |
| stl.cpp:204:18:204:26 | call to basic_string | stl.cpp:209:8:209:9 | s1 | |
| stl.cpp:205:19:205:27 | call to basic_string | stl.cpp:210:8:210:9 | s2 | |
| stl.cpp:205:20:205:25 | call to source | stl.cpp:205:19:205:27 | call to basic_string | TAINT |
| stl.cpp:207:8:207:13 | call to source | stl.cpp:207:8:207:15 | call to basic_string | TAINT |
| stl.cpp:207:8:207:15 | call to basic_string | stl.cpp:207:3:207:15 | ... = ... | |
| stl.cpp:207:8:207:15 | call to basic_string | stl.cpp:211:8:211:9 | s3 | |
| stl.cpp:215:15:215:16 | call to basic_string | stl.cpp:216:20:216:21 | s1 | |
| stl.cpp:215:15:215:16 | call to basic_string | stl.cpp:218:8:218:9 | s1 | |
| stl.cpp:215:15:215:16 | call to basic_string | stl.cpp:220:8:220:9 | s1 | |
| stl.cpp:216:20:216:21 | s1 | stl.cpp:221:8:221:9 | s2 | |
| stl.cpp:218:8:218:9 | s1 | stl.cpp:218:3:218:9 | ... = ... | |
| stl.cpp:218:8:218:9 | s1 | stl.cpp:222:8:222:9 | s3 | |
| stl.cpp:226:19:226:40 | call to basic_string | stl.cpp:230:8:230:9 | s1 | |
| stl.cpp:226:32:226:37 | call to source | stl.cpp:226:19:226:40 | call to basic_string | TAINT |
| stl.cpp:228:8:228:28 | call to basic_string | stl.cpp:228:3:228:28 | ... = ... | |
| stl.cpp:228:8:228:28 | call to basic_string | stl.cpp:231:8:231:9 | s2 | |
| stl.cpp:228:20:228:25 | call to source | stl.cpp:228:8:228:28 | call to basic_string | TAINT |
| stl.cpp:238:16:238:21 | call to source | stl.cpp:238:16:238:24 | call to basic_string | TAINT |
| stl.cpp:238:16:238:24 | call to basic_string | stl.cpp:239:15:239:15 | s | |
| stl.cpp:238:16:238:24 | call to basic_string | stl.cpp:243:33:243:33 | s | |
| stl.cpp:238:16:238:24 | call to basic_string | stl.cpp:243:50:243:50 | s | |
| stl.cpp:238:16:238:24 | call to basic_string | stl.cpp:247:16:247:16 | s | |
| stl.cpp:239:15:239:15 | call to begin | stl.cpp:239:15:239:15 | (__begin) | |
| stl.cpp:239:15:239:15 | call to begin | stl.cpp:239:15:239:15 | (__begin) | |
| stl.cpp:239:15:239:15 | call to begin | stl.cpp:239:15:239:15 | (__begin) | |
| stl.cpp:239:15:239:15 | call to end | stl.cpp:239:15:239:15 | (__end) | |
| stl.cpp:239:15:239:15 | call to operator* | stl.cpp:240:8:240:8 | c | |
| stl.cpp:239:15:239:15 | ref arg (__begin) | stl.cpp:239:15:239:15 | (__begin) | |
| stl.cpp:239:15:239:15 | ref arg (__begin) | stl.cpp:239:15:239:15 | (__begin) | |
| stl.cpp:239:15:239:15 | ref arg (__begin) | stl.cpp:239:15:239:15 | (__begin) | |
| stl.cpp:239:15:239:15 | ref arg (__range) | stl.cpp:239:15:239:15 | (__range) | |
| stl.cpp:239:15:239:15 | s | stl.cpp:239:15:239:15 | (__range) | |
| stl.cpp:239:15:239:15 | s | stl.cpp:239:15:239:15 | (__range) | |
| stl.cpp:239:15:239:15 | s | stl.cpp:239:15:239:15 | call to operator* | TAINT |
| stl.cpp:243:33:243:33 | ref arg s | stl.cpp:243:50:243:50 | s | |
| stl.cpp:243:33:243:33 | ref arg s | stl.cpp:247:16:247:16 | s | |
| stl.cpp:243:35:243:39 | call to begin | stl.cpp:243:44:243:45 | it | |
| stl.cpp:243:35:243:39 | call to begin | stl.cpp:243:61:243:62 | it | |
| stl.cpp:243:35:243:39 | call to begin | stl.cpp:244:9:244:10 | it | |
| stl.cpp:243:50:243:50 | ref arg s | stl.cpp:243:50:243:50 | s | |
| stl.cpp:243:50:243:50 | ref arg s | stl.cpp:247:16:247:16 | s | |
| stl.cpp:243:61:243:62 | ref arg it | stl.cpp:243:44:243:45 | it | |
| stl.cpp:243:61:243:62 | ref arg it | stl.cpp:243:61:243:62 | it | |
| stl.cpp:243:61:243:62 | ref arg it | stl.cpp:244:9:244:10 | it | |
| stl.cpp:247:16:247:16 | call to begin | stl.cpp:247:16:247:16 | (__begin) | |
| stl.cpp:247:16:247:16 | call to begin | stl.cpp:247:16:247:16 | (__begin) | |
| stl.cpp:247:16:247:16 | call to begin | stl.cpp:247:16:247:16 | (__begin) | |
| stl.cpp:247:16:247:16 | call to end | stl.cpp:247:16:247:16 | (__end) | |
| stl.cpp:247:16:247:16 | call to operator* | stl.cpp:248:8:248:8 | c | |
| stl.cpp:247:16:247:16 | ref arg (__begin) | stl.cpp:247:16:247:16 | (__begin) | |
| stl.cpp:247:16:247:16 | ref arg (__begin) | stl.cpp:247:16:247:16 | (__begin) | |
| stl.cpp:247:16:247:16 | ref arg (__begin) | stl.cpp:247:16:247:16 | (__begin) | |
| stl.cpp:247:16:247:16 | ref arg (__range) | stl.cpp:247:16:247:16 | (__range) | |
| stl.cpp:247:16:247:16 | s | stl.cpp:247:16:247:16 | (__range) | |
| stl.cpp:247:16:247:16 | s | stl.cpp:247:16:247:16 | (__range) | |
| stl.cpp:247:16:247:16 | s | stl.cpp:247:16:247:16 | call to operator* | TAINT |
| stl.cpp:251:28:251:33 | call to source | stl.cpp:251:28:251:36 | call to basic_string | TAINT |
| stl.cpp:251:28:251:36 | call to basic_string | stl.cpp:252:22:252:28 | const_s | |
| stl.cpp:252:22:252:22 | call to begin | stl.cpp:252:22:252:22 | (__begin) | |
| stl.cpp:252:22:252:22 | call to begin | stl.cpp:252:22:252:22 | (__begin) | |
| stl.cpp:252:22:252:22 | call to begin | stl.cpp:252:22:252:22 | (__begin) | |
| stl.cpp:252:22:252:22 | call to end | stl.cpp:252:22:252:22 | (__end) | |
| stl.cpp:252:22:252:22 | call to operator* | stl.cpp:253:8:253:8 | c | |
| stl.cpp:252:22:252:22 | ref arg (__begin) | stl.cpp:252:22:252:22 | (__begin) | |
| stl.cpp:252:22:252:22 | ref arg (__begin) | stl.cpp:252:22:252:22 | (__begin) | |
| stl.cpp:252:22:252:22 | ref arg (__begin) | stl.cpp:252:22:252:22 | (__begin) | |
| stl.cpp:252:22:252:28 | const_s | stl.cpp:252:22:252:22 | (__range) | |
| stl.cpp:252:22:252:28 | const_s | stl.cpp:252:22:252:22 | (__range) | |
| stl.cpp:252:22:252:28 | const_s | stl.cpp:252:22:252:22 | call to operator* | TAINT |
| stl.cpp:288:43:288:49 | source1 | stl.cpp:292:21:292:27 | source1 | |
| stl.cpp:288:43:288:49 | source1 | stl.cpp:306:33:306:39 | source1 | |
| stl.cpp:292:21:292:27 | source1 | stl.cpp:292:21:292:28 | call to vector | TAINT |
| stl.cpp:292:21:292:28 | call to vector | stl.cpp:294:14:294:14 | v | |
| stl.cpp:292:21:292:28 | call to vector | stl.cpp:298:38:298:38 | v | |
| stl.cpp:292:21:292:28 | call to vector | stl.cpp:298:55:298:55 | v | |
| stl.cpp:292:21:292:28 | call to vector | stl.cpp:302:15:302:15 | v | |
| stl.cpp:294:14:294:14 | call to begin | stl.cpp:294:14:294:14 | (__begin) | |
| stl.cpp:294:14:294:14 | call to begin | stl.cpp:294:14:294:14 | (__begin) | |
| stl.cpp:294:14:294:14 | call to begin | stl.cpp:294:14:294:14 | (__begin) | |
| stl.cpp:294:14:294:14 | call to end | stl.cpp:294:14:294:14 | (__end) | |
| stl.cpp:294:14:294:14 | call to operator* | stl.cpp:295:8:295:8 | x | |
| stl.cpp:294:14:294:14 | ref arg (__begin) | stl.cpp:294:14:294:14 | (__begin) | |
| stl.cpp:294:14:294:14 | ref arg (__begin) | stl.cpp:294:14:294:14 | (__begin) | |
| stl.cpp:294:14:294:14 | ref arg (__begin) | stl.cpp:294:14:294:14 | (__begin) | |
| stl.cpp:294:14:294:14 | ref arg (__range) | stl.cpp:294:14:294:14 | (__range) | |
| stl.cpp:294:14:294:14 | v | stl.cpp:294:14:294:14 | (__range) | |
| stl.cpp:294:14:294:14 | v | stl.cpp:294:14:294:14 | (__range) | |
| stl.cpp:294:14:294:14 | v | stl.cpp:294:14:294:14 | call to operator* | TAINT |
| stl.cpp:298:38:298:38 | ref arg v | stl.cpp:298:55:298:55 | v | |
| stl.cpp:298:38:298:38 | ref arg v | stl.cpp:302:15:302:15 | v | |
| stl.cpp:298:40:298:44 | call to begin | stl.cpp:298:49:298:50 | it | |
| stl.cpp:298:40:298:44 | call to begin | stl.cpp:298:66:298:67 | it | |
| stl.cpp:298:40:298:44 | call to begin | stl.cpp:299:9:299:10 | it | |
| stl.cpp:298:55:298:55 | ref arg v | stl.cpp:298:55:298:55 | v | |
| stl.cpp:298:55:298:55 | ref arg v | stl.cpp:302:15:302:15 | v | |
| stl.cpp:298:66:298:67 | ref arg it | stl.cpp:298:49:298:50 | it | |
| stl.cpp:298:66:298:67 | ref arg it | stl.cpp:298:66:298:67 | it | |
| stl.cpp:298:66:298:67 | ref arg it | stl.cpp:299:9:299:10 | it | |
| stl.cpp:302:15:302:15 | call to begin | stl.cpp:302:15:302:15 | (__begin) | |
| stl.cpp:302:15:302:15 | call to begin | stl.cpp:302:15:302:15 | (__begin) | |
| stl.cpp:302:15:302:15 | call to begin | stl.cpp:302:15:302:15 | (__begin) | |
| stl.cpp:302:15:302:15 | call to end | stl.cpp:302:15:302:15 | (__end) | |
| stl.cpp:302:15:302:15 | call to operator* | stl.cpp:303:8:303:8 | x | |
| stl.cpp:302:15:302:15 | ref arg (__begin) | stl.cpp:302:15:302:15 | (__begin) | |
| stl.cpp:302:15:302:15 | ref arg (__begin) | stl.cpp:302:15:302:15 | (__begin) | |
| stl.cpp:302:15:302:15 | ref arg (__begin) | stl.cpp:302:15:302:15 | (__begin) | |
| stl.cpp:302:15:302:15 | ref arg (__range) | stl.cpp:302:15:302:15 | (__range) | |
| stl.cpp:302:15:302:15 | v | stl.cpp:302:15:302:15 | (__range) | |
| stl.cpp:302:15:302:15 | v | stl.cpp:302:15:302:15 | (__range) | |
| stl.cpp:302:15:302:15 | v | stl.cpp:302:15:302:15 | call to operator* | TAINT |
| stl.cpp:306:33:306:39 | source1 | stl.cpp:306:33:306:40 | call to vector | TAINT |
| stl.cpp:306:33:306:40 | call to vector | stl.cpp:307:21:307:27 | const_v | |
| stl.cpp:307:21:307:21 | call to begin | stl.cpp:307:21:307:21 | (__begin) | |
| stl.cpp:307:21:307:21 | call to begin | stl.cpp:307:21:307:21 | (__begin) | |
| stl.cpp:307:21:307:21 | call to begin | stl.cpp:307:21:307:21 | (__begin) | |
| stl.cpp:307:21:307:21 | call to end | stl.cpp:307:21:307:21 | (__end) | |
| stl.cpp:307:21:307:21 | call to operator* | stl.cpp:308:8:308:8 | x | |
| stl.cpp:307:21:307:21 | ref arg (__begin) | stl.cpp:307:21:307:21 | (__begin) | |
| stl.cpp:307:21:307:21 | ref arg (__begin) | stl.cpp:307:21:307:21 | (__begin) | |
| stl.cpp:307:21:307:21 | ref arg (__begin) | stl.cpp:307:21:307:21 | (__begin) | |
| stl.cpp:307:21:307:27 | const_v | stl.cpp:307:21:307:21 | (__range) | |
| stl.cpp:307:21:307:27 | const_v | stl.cpp:307:21:307:21 | (__range) | |
| stl.cpp:307:21:307:27 | const_v | stl.cpp:307:21:307:21 | call to operator* | TAINT |
| string.cpp:24:12:24:17 | call to source | string.cpp:28:7:28:7 | a | |
| string.cpp:25:16:25:20 | 123 | string.cpp:25:16:25:21 | call to basic_string | TAINT |
| string.cpp:25:16:25:21 | call to basic_string | string.cpp:29:7:29:7 | b | |
| string.cpp:25:16:25:21 | call to basic_string | string.cpp:31:7:31:7 | b | |
| string.cpp:26:16:26:21 | call to source | string.cpp:26:16:26:24 | call to basic_string | TAINT |
| string.cpp:26:16:26:24 | call to basic_string | string.cpp:30:7:30:7 | c | |
| string.cpp:26:16:26:24 | call to basic_string | string.cpp:32:7:32:7 | c | |
| string.cpp:31:7:31:7 | b | string.cpp:31:9:31:13 | call to c_str | TAINT |
| string.cpp:32:7:32:7 | c | string.cpp:32:9:32:13 | call to c_str | TAINT |
| string.cpp:37:16:37:28 | call to basic_string | string.cpp:38:7:38:11 | path1 | |
| string.cpp:37:17:37:26 | call to user_input | string.cpp:37:16:37:28 | call to basic_string | TAINT |
| string.cpp:38:7:38:11 | path1 | string.cpp:38:13:38:17 | call to c_str | TAINT |
| string.cpp:41:10:41:19 | call to user_input | string.cpp:41:10:41:21 | call to basic_string | TAINT |
| string.cpp:41:10:41:21 | call to basic_string | string.cpp:41:2:41:21 | ... = ... | |
| string.cpp:41:10:41:21 | call to basic_string | string.cpp:42:7:42:11 | path2 | |
| string.cpp:42:7:42:11 | path2 | string.cpp:42:13:42:17 | call to c_str | TAINT |
| string.cpp:44:15:44:24 | call to user_input | string.cpp:44:15:44:27 | call to basic_string | TAINT |
| string.cpp:44:15:44:27 | call to basic_string | string.cpp:45:7:45:11 | path3 | |
| string.cpp:45:7:45:11 | path3 | string.cpp:45:13:45:17 | call to c_str | TAINT |
| string.cpp:50:19:50:24 | call to source | string.cpp:53:17:53:18 | cs | |
| string.cpp:50:19:50:24 | call to source | string.cpp:55:7:55:8 | cs | |
| string.cpp:53:17:53:18 | cs | string.cpp:53:17:53:19 | call to basic_string | TAINT |
| string.cpp:53:17:53:19 | call to basic_string | string.cpp:56:7:56:8 | ss | |
| string.cpp:61:19:61:24 | call to source | string.cpp:64:17:64:18 | cs | |
| string.cpp:64:17:64:18 | cs | string.cpp:64:17:64:19 | call to basic_string | TAINT |
| string.cpp:64:17:64:19 | call to basic_string | string.cpp:67:7:67:8 | ss | |
| string.cpp:64:17:64:19 | call to basic_string | string.cpp:70:7:70:8 | ss | |
| string.cpp:67:7:67:8 | ss | string.cpp:67:10:67:14 | call to c_str | TAINT |
| string.cpp:67:10:67:14 | call to c_str | string.cpp:67:2:67:16 | ... = ... | |
| string.cpp:67:10:67:14 | call to c_str | string.cpp:69:7:69:8 | cs | |
| string.cpp:76:18:76:24 | hello | string.cpp:76:18:76:25 | call to basic_string | TAINT |
| string.cpp:76:18:76:25 | call to basic_string | string.cpp:81:8:81:9 | s1 | |
| string.cpp:77:19:77:26 | call to basic_string | string.cpp:82:8:82:9 | s2 | |
| string.cpp:77:20:77:26 | hello | string.cpp:77:19:77:26 | call to basic_string | TAINT |
| string.cpp:79:8:79:14 | call to basic_string | string.cpp:79:3:79:14 | ... = ... | |
| string.cpp:79:8:79:14 | call to basic_string | string.cpp:83:8:83:9 | s3 | |
| string.cpp:79:8:79:14 | hello | string.cpp:79:8:79:14 | call to basic_string | TAINT |
| string.cpp:87:18:87:23 | call to source | string.cpp:87:18:87:26 | call to basic_string | TAINT |
| string.cpp:87:18:87:26 | call to basic_string | string.cpp:92:8:92:9 | s1 | |
| string.cpp:88:19:88:27 | call to basic_string | string.cpp:93:8:93:9 | s2 | |
| string.cpp:88:20:88:25 | call to source | string.cpp:88:19:88:27 | call to basic_string | TAINT |
| string.cpp:90:8:90:13 | call to source | string.cpp:90:8:90:15 | call to basic_string | TAINT |
| string.cpp:90:8:90:15 | call to basic_string | string.cpp:90:3:90:15 | ... = ... | |
| string.cpp:90:8:90:15 | call to basic_string | string.cpp:94:8:94:9 | s3 | |
| string.cpp:98:15:98:16 | call to basic_string | string.cpp:99:20:99:21 | s1 | |
| string.cpp:98:15:98:16 | call to basic_string | string.cpp:101:8:101:9 | s1 | |
| string.cpp:98:15:98:16 | call to basic_string | string.cpp:103:8:103:9 | s1 | |
| string.cpp:99:20:99:21 | s1 | string.cpp:104:8:104:9 | s2 | |
| string.cpp:101:8:101:9 | s1 | string.cpp:101:3:101:9 | ... = ... | |
| string.cpp:101:8:101:9 | s1 | string.cpp:105:8:105:9 | s3 | |
| string.cpp:109:19:109:40 | call to basic_string | string.cpp:113:8:113:9 | s1 | |
| string.cpp:109:32:109:37 | call to source | string.cpp:109:19:109:40 | call to basic_string | TAINT |
| string.cpp:111:8:111:28 | call to basic_string | string.cpp:111:3:111:28 | ... = ... | |
| string.cpp:111:8:111:28 | call to basic_string | string.cpp:114:8:114:9 | s2 | |
| string.cpp:111:20:111:25 | call to source | string.cpp:111:8:111:28 | call to basic_string | TAINT |
| string.cpp:119:16:119:21 | call to source | string.cpp:119:16:119:24 | call to basic_string | TAINT |
| string.cpp:119:16:119:24 | call to basic_string | string.cpp:120:15:120:15 | s | |
| string.cpp:119:16:119:24 | call to basic_string | string.cpp:124:33:124:33 | s | |
| string.cpp:119:16:119:24 | call to basic_string | string.cpp:124:50:124:50 | s | |
| string.cpp:119:16:119:24 | call to basic_string | string.cpp:128:16:128:16 | s | |
| string.cpp:120:15:120:15 | call to begin | string.cpp:120:15:120:15 | (__begin) | |
| string.cpp:120:15:120:15 | call to begin | string.cpp:120:15:120:15 | (__begin) | |
| string.cpp:120:15:120:15 | call to begin | string.cpp:120:15:120:15 | (__begin) | |
| string.cpp:120:15:120:15 | call to end | string.cpp:120:15:120:15 | (__end) | |
| string.cpp:120:15:120:15 | call to operator* | string.cpp:121:8:121:8 | c | |
| string.cpp:120:15:120:15 | ref arg (__begin) | string.cpp:120:15:120:15 | (__begin) | |
| string.cpp:120:15:120:15 | ref arg (__begin) | string.cpp:120:15:120:15 | (__begin) | |
| string.cpp:120:15:120:15 | ref arg (__begin) | string.cpp:120:15:120:15 | (__begin) | |
| string.cpp:120:15:120:15 | ref arg (__range) | string.cpp:120:15:120:15 | (__range) | |
| string.cpp:120:15:120:15 | s | string.cpp:120:15:120:15 | (__range) | |
| string.cpp:120:15:120:15 | s | string.cpp:120:15:120:15 | (__range) | |
| string.cpp:120:15:120:15 | s | string.cpp:120:15:120:15 | call to operator* | TAINT |
| string.cpp:124:33:124:33 | ref arg s | string.cpp:124:50:124:50 | s | |
| string.cpp:124:33:124:33 | ref arg s | string.cpp:128:16:128:16 | s | |
| string.cpp:124:35:124:39 | call to begin | string.cpp:124:44:124:45 | it | |
| string.cpp:124:35:124:39 | call to begin | string.cpp:124:61:124:62 | it | |
| string.cpp:124:35:124:39 | call to begin | string.cpp:125:9:125:10 | it | |
| string.cpp:124:50:124:50 | ref arg s | string.cpp:124:50:124:50 | s | |
| string.cpp:124:50:124:50 | ref arg s | string.cpp:128:16:128:16 | s | |
| string.cpp:124:61:124:62 | ref arg it | string.cpp:124:44:124:45 | it | |
| string.cpp:124:61:124:62 | ref arg it | string.cpp:124:61:124:62 | it | |
| string.cpp:124:61:124:62 | ref arg it | string.cpp:125:9:125:10 | it | |
| string.cpp:128:16:128:16 | call to begin | string.cpp:128:16:128:16 | (__begin) | |
| string.cpp:128:16:128:16 | call to begin | string.cpp:128:16:128:16 | (__begin) | |
| string.cpp:128:16:128:16 | call to begin | string.cpp:128:16:128:16 | (__begin) | |
| string.cpp:128:16:128:16 | call to end | string.cpp:128:16:128:16 | (__end) | |
| string.cpp:128:16:128:16 | call to operator* | string.cpp:129:8:129:8 | c | |
| string.cpp:128:16:128:16 | ref arg (__begin) | string.cpp:128:16:128:16 | (__begin) | |
| string.cpp:128:16:128:16 | ref arg (__begin) | string.cpp:128:16:128:16 | (__begin) | |
| string.cpp:128:16:128:16 | ref arg (__begin) | string.cpp:128:16:128:16 | (__begin) | |
| string.cpp:128:16:128:16 | ref arg (__range) | string.cpp:128:16:128:16 | (__range) | |
| string.cpp:128:16:128:16 | s | string.cpp:128:16:128:16 | (__range) | |
| string.cpp:128:16:128:16 | s | string.cpp:128:16:128:16 | (__range) | |
| string.cpp:128:16:128:16 | s | string.cpp:128:16:128:16 | call to operator* | TAINT |
| string.cpp:132:28:132:33 | call to source | string.cpp:132:28:132:36 | call to basic_string | TAINT |
| string.cpp:132:28:132:36 | call to basic_string | string.cpp:133:22:133:28 | const_s | |
| string.cpp:133:22:133:22 | call to begin | string.cpp:133:22:133:22 | (__begin) | |
| string.cpp:133:22:133:22 | call to begin | string.cpp:133:22:133:22 | (__begin) | |
| string.cpp:133:22:133:22 | call to begin | string.cpp:133:22:133:22 | (__begin) | |
| string.cpp:133:22:133:22 | call to end | string.cpp:133:22:133:22 | (__end) | |
| string.cpp:133:22:133:22 | call to operator* | string.cpp:134:8:134:8 | c | |
| string.cpp:133:22:133:22 | ref arg (__begin) | string.cpp:133:22:133:22 | (__begin) | |
| string.cpp:133:22:133:22 | ref arg (__begin) | string.cpp:133:22:133:22 | (__begin) | |
| string.cpp:133:22:133:22 | ref arg (__begin) | string.cpp:133:22:133:22 | (__begin) | |
| string.cpp:133:22:133:28 | const_s | string.cpp:133:22:133:22 | (__range) | |
| string.cpp:133:22:133:28 | const_s | string.cpp:133:22:133:22 | (__range) | |
| string.cpp:133:22:133:28 | const_s | string.cpp:133:22:133:22 | call to operator* | TAINT |
| string.cpp:140:18:140:24 | hello | string.cpp:140:18:140:25 | call to basic_string | TAINT |
| string.cpp:140:18:140:25 | call to basic_string | string.cpp:143:8:143:9 | s1 | |
| string.cpp:140:18:140:25 | call to basic_string | string.cpp:143:13:143:14 | s1 | |
| string.cpp:140:18:140:25 | call to basic_string | string.cpp:144:8:144:9 | s1 | |
| string.cpp:140:18:140:25 | call to basic_string | string.cpp:145:13:145:14 | s1 | |
| string.cpp:140:18:140:25 | call to basic_string | string.cpp:148:8:148:9 | s1 | |
| string.cpp:140:18:140:25 | call to basic_string | string.cpp:149:8:149:9 | s1 | |
| string.cpp:141:18:141:23 | call to source | string.cpp:141:18:141:26 | call to basic_string | TAINT |
| string.cpp:141:18:141:26 | call to basic_string | string.cpp:144:13:144:14 | s2 | |
| string.cpp:141:18:141:26 | call to basic_string | string.cpp:145:8:145:9 | s2 | |
| string.cpp:141:18:141:26 | call to basic_string | string.cpp:146:8:146:9 | s2 | |
| string.cpp:141:18:141:26 | call to basic_string | string.cpp:146:13:146:14 | s2 | |
| string.cpp:143:8:143:9 | s1 | string.cpp:143:11:143:11 | call to operator+ | TAINT |
| string.cpp:143:13:143:14 | s1 | string.cpp:143:11:143:11 | call to operator+ | TAINT |
| string.cpp:144:8:144:9 | s1 | string.cpp:144:11:144:11 | call to operator+ | TAINT |
| string.cpp:144:13:144:14 | s2 | string.cpp:144:11:144:11 | call to operator+ | TAINT |
| string.cpp:145:8:145:9 | s2 | string.cpp:145:11:145:11 | call to operator+ | TAINT |
| string.cpp:145:13:145:14 | s1 | string.cpp:145:11:145:11 | call to operator+ | TAINT |
| string.cpp:146:8:146:9 | s2 | string.cpp:146:11:146:11 | call to operator+ | TAINT |
| string.cpp:146:13:146:14 | s2 | string.cpp:146:11:146:11 | call to operator+ | TAINT |
| string.cpp:148:8:148:9 | s1 | string.cpp:148:11:148:11 | call to operator+ | TAINT |
| string.cpp:148:13:148:20 | world | string.cpp:148:11:148:11 | call to operator+ | TAINT |
| string.cpp:149:8:149:9 | s1 | string.cpp:149:11:149:11 | call to operator+ | TAINT |
| string.cpp:149:13:149:18 | call to source | string.cpp:149:11:149:11 | call to operator+ | TAINT |
| string.cpp:153:18:153:22 | abc | string.cpp:153:18:153:23 | call to basic_string | TAINT |
| string.cpp:153:18:153:23 | call to basic_string | string.cpp:157:8:157:9 | s3 | |
| string.cpp:153:18:153:23 | call to basic_string | string.cpp:160:8:160:9 | s3 | |
| string.cpp:153:18:153:23 | call to basic_string | string.cpp:164:8:164:9 | s3 | |
| string.cpp:153:18:153:23 | call to basic_string | string.cpp:169:8:169:9 | s3 | |
| string.cpp:153:18:153:23 | call to basic_string | string.cpp:173:8:173:9 | s3 | |
| string.cpp:154:18:154:23 | call to source | string.cpp:154:18:154:26 | call to basic_string | TAINT |
| string.cpp:154:18:154:26 | call to basic_string | string.cpp:157:13:157:14 | s4 | |
| string.cpp:154:18:154:26 | call to basic_string | string.cpp:161:9:161:10 | s4 | |
| string.cpp:154:18:154:26 | call to basic_string | string.cpp:170:13:170:14 | s4 | |
| string.cpp:157:8:157:9 | s3 | string.cpp:157:11:157:11 | call to operator+ | TAINT |
| string.cpp:157:11:157:11 | call to operator+ | string.cpp:157:3:157:14 | ... = ... | |
| string.cpp:157:11:157:11 | call to operator+ | string.cpp:158:8:158:9 | s5 | |
| string.cpp:157:13:157:14 | s4 | string.cpp:157:11:157:11 | call to operator+ | TAINT |
| string.cpp:160:8:160:9 | s3 | string.cpp:160:3:160:9 | ... = ... | |
| string.cpp:160:8:160:9 | s3 | string.cpp:161:3:161:4 | s6 | |
| string.cpp:160:8:160:9 | s3 | string.cpp:162:8:162:9 | s6 | |
| string.cpp:161:3:161:4 | ref arg s6 | string.cpp:162:8:162:9 | s6 | |
| string.cpp:161:9:161:10 | s4 | string.cpp:161:3:161:4 | ref arg s6 | TAINT |
| string.cpp:161:9:161:10 | s4 | string.cpp:161:6:161:6 | call to operator+= | TAINT |
| string.cpp:164:8:164:9 | s3 | string.cpp:164:3:164:9 | ... = ... | |
| string.cpp:164:8:164:9 | s3 | string.cpp:165:3:165:4 | s7 | |
| string.cpp:164:8:164:9 | s3 | string.cpp:166:3:166:4 | s7 | |
| string.cpp:164:8:164:9 | s3 | string.cpp:167:8:167:9 | s7 | |
| string.cpp:165:3:165:4 | ref arg s7 | string.cpp:166:3:166:4 | s7 | |
| string.cpp:165:3:165:4 | ref arg s7 | string.cpp:167:8:167:9 | s7 | |
| string.cpp:165:9:165:14 | call to source | string.cpp:165:3:165:4 | ref arg s7 | TAINT |
| string.cpp:165:9:165:14 | call to source | string.cpp:165:6:165:6 | call to operator+= | TAINT |
| string.cpp:166:3:166:4 | ref arg s7 | string.cpp:167:8:167:9 | s7 | |
| string.cpp:166:9:166:11 | | string.cpp:166:3:166:4 | ref arg s7 | TAINT |
| string.cpp:166:9:166:11 | | string.cpp:166:6:166:6 | call to operator+= | TAINT |
| string.cpp:169:8:169:9 | s3 | string.cpp:169:3:169:9 | ... = ... | |
| string.cpp:169:8:169:9 | s3 | string.cpp:170:3:170:4 | s8 | |
| string.cpp:169:8:169:9 | s3 | string.cpp:171:8:171:9 | s8 | |
| string.cpp:170:3:170:4 | ref arg s8 | string.cpp:171:8:171:9 | s8 | |
| string.cpp:170:13:170:14 | s4 | string.cpp:170:3:170:4 | ref arg s8 | TAINT |
| string.cpp:170:13:170:14 | s4 | string.cpp:170:6:170:11 | call to append | TAINT |
| string.cpp:173:8:173:9 | s3 | string.cpp:173:3:173:9 | ... = ... | |
| string.cpp:173:8:173:9 | s3 | string.cpp:174:3:174:4 | s9 | |
| string.cpp:173:8:173:9 | s3 | string.cpp:175:3:175:4 | s9 | |
| string.cpp:173:8:173:9 | s3 | string.cpp:176:8:176:9 | s9 | |
| string.cpp:174:3:174:4 | ref arg s9 | string.cpp:175:3:175:4 | s9 | |
| string.cpp:174:3:174:4 | ref arg s9 | string.cpp:176:8:176:9 | s9 | |
| string.cpp:174:13:174:18 | call to source | string.cpp:174:3:174:4 | ref arg s9 | TAINT |
| string.cpp:174:13:174:18 | call to source | string.cpp:174:6:174:11 | call to append | TAINT |
| string.cpp:175:3:175:4 | ref arg s9 | string.cpp:176:8:176:9 | s9 | |
| string.cpp:175:13:175:15 | | string.cpp:175:3:175:4 | ref arg s9 | TAINT |
| string.cpp:175:13:175:15 | | string.cpp:175:6:175:11 | call to append | TAINT |
| string.cpp:180:19:180:23 | abc | string.cpp:180:19:180:24 | call to basic_string | TAINT |
| string.cpp:180:19:180:24 | call to basic_string | string.cpp:183:3:183:5 | s10 | |
| string.cpp:180:19:180:24 | call to basic_string | string.cpp:184:8:184:10 | s10 | |
| string.cpp:181:12:181:26 | call to source | string.cpp:183:17:183:17 | c | |
| string.cpp:183:3:183:5 | ref arg s10 | string.cpp:184:8:184:10 | s10 | |
| string.cpp:183:17:183:17 | c | string.cpp:183:3:183:5 | ref arg s10 | TAINT |
| string.cpp:183:17:183:17 | c | string.cpp:183:7:183:12 | call to append | TAINT |
| stringstream.cpp:13:20:13:22 | call to basic_stringstream | stringstream.cpp:16:2:16:4 | ss1 | |
| stringstream.cpp:13:20:13:22 | call to basic_stringstream | stringstream.cpp:22:7:22:9 | ss1 | |
| stringstream.cpp:13:20:13:22 | call to basic_stringstream | stringstream.cpp:27:7:27:9 | ss1 | |
| stringstream.cpp:13:25:13:27 | call to basic_stringstream | stringstream.cpp:17:2:17:4 | ss2 | |
| stringstream.cpp:13:25:13:27 | call to basic_stringstream | stringstream.cpp:23:7:23:9 | ss2 | |
| stringstream.cpp:13:25:13:27 | call to basic_stringstream | stringstream.cpp:28:7:28:9 | ss2 | |
| stringstream.cpp:13:30:13:32 | call to basic_stringstream | stringstream.cpp:18:2:18:4 | ss3 | |
| stringstream.cpp:13:30:13:32 | call to basic_stringstream | stringstream.cpp:24:7:24:9 | ss3 | |
| stringstream.cpp:13:30:13:32 | call to basic_stringstream | stringstream.cpp:29:7:29:9 | ss3 | |
| stringstream.cpp:13:35:13:37 | call to basic_stringstream | stringstream.cpp:19:2:19:4 | ss4 | |
| stringstream.cpp:13:35:13:37 | call to basic_stringstream | stringstream.cpp:25:7:25:9 | ss4 | |
| stringstream.cpp:13:35:13:37 | call to basic_stringstream | stringstream.cpp:30:7:30:9 | ss4 | |
| stringstream.cpp:13:40:13:42 | call to basic_stringstream | stringstream.cpp:20:2:20:4 | ss5 | |
| stringstream.cpp:13:40:13:42 | call to basic_stringstream | stringstream.cpp:26:7:26:9 | ss5 | |
| stringstream.cpp:13:40:13:42 | call to basic_stringstream | stringstream.cpp:31:7:31:9 | ss5 | |
| stringstream.cpp:14:16:14:21 | call to source | stringstream.cpp:14:16:14:24 | call to basic_string | TAINT |
| stringstream.cpp:14:16:14:24 | call to basic_string | stringstream.cpp:20:9:20:9 | t | |
| stringstream.cpp:16:2:16:4 | ref arg ss1 | stringstream.cpp:22:7:22:9 | ss1 | |
| stringstream.cpp:16:2:16:4 | ref arg ss1 | stringstream.cpp:27:7:27:9 | ss1 | |
| stringstream.cpp:17:2:17:4 | ref arg ss2 | stringstream.cpp:23:7:23:9 | ss2 | |
| stringstream.cpp:17:2:17:4 | ref arg ss2 | stringstream.cpp:28:7:28:9 | ss2 | |
| stringstream.cpp:18:2:18:4 | ref arg ss3 | stringstream.cpp:24:7:24:9 | ss3 | |
| stringstream.cpp:18:2:18:4 | ref arg ss3 | stringstream.cpp:29:7:29:9 | ss3 | |
| stringstream.cpp:19:2:19:4 | ref arg ss4 | stringstream.cpp:25:7:25:9 | ss4 | |
| stringstream.cpp:19:2:19:4 | ref arg ss4 | stringstream.cpp:30:7:30:9 | ss4 | |
| stringstream.cpp:20:2:20:4 | ref arg ss5 | stringstream.cpp:26:7:26:9 | ss5 | |
| stringstream.cpp:20:2:20:4 | ref arg ss5 | stringstream.cpp:31:7:31:9 | ss5 | |
| stringstream.cpp:34:32:34:37 | source | stringstream.cpp:39:9:39:14 | source | |
| stringstream.cpp:36:20:36:22 | call to basic_stringstream | stringstream.cpp:38:2:38:4 | ss1 | |
| stringstream.cpp:36:20:36:22 | call to basic_stringstream | stringstream.cpp:41:7:41:9 | ss1 | |
| stringstream.cpp:36:20:36:22 | call to basic_stringstream | stringstream.cpp:43:7:43:9 | ss1 | |
| stringstream.cpp:36:25:36:27 | call to basic_stringstream | stringstream.cpp:39:2:39:4 | ss2 | |
| stringstream.cpp:36:25:36:27 | call to basic_stringstream | stringstream.cpp:42:7:42:9 | ss2 | |
| stringstream.cpp:36:25:36:27 | call to basic_stringstream | stringstream.cpp:44:7:44:9 | ss2 | |
| stringstream.cpp:38:2:38:4 | ref arg ss1 | stringstream.cpp:41:7:41:9 | ss1 | |
| stringstream.cpp:38:2:38:4 | ref arg ss1 | stringstream.cpp:43:7:43:9 | ss1 | |
| stringstream.cpp:39:2:39:4 | ref arg ss2 | stringstream.cpp:42:7:42:9 | ss2 | |
| stringstream.cpp:39:2:39:4 | ref arg ss2 | stringstream.cpp:44:7:44:9 | ss2 | |
| structlikeclass.cpp:5:7:5:7 | Unknown literal | structlikeclass.cpp:5:7:5:7 | constructor init of field v | TAINT |
| structlikeclass.cpp:5:7:5:7 | Unknown literal | structlikeclass.cpp:5:7:5:7 | constructor init of field v | TAINT |
| structlikeclass.cpp:5:7:5:7 | this | structlikeclass.cpp:5:7:5:7 | constructor init of field v [pre-this] | |
@ -1305,3 +1330,57 @@
| taint.cpp:483:18:483:19 | ref arg & ... | taint.cpp:483:19:483:19 | n [inner post update] | |
| taint.cpp:483:19:483:19 | n | taint.cpp:483:18:483:19 | & ... | |
| taint.cpp:483:28:483:34 | source1 | taint.cpp:483:11:483:15 | ref arg & ... | TAINT |
| vector.cpp:8:43:8:49 | source1 | vector.cpp:12:21:12:27 | source1 | |
| vector.cpp:8:43:8:49 | source1 | vector.cpp:26:33:26:39 | source1 | |
| vector.cpp:12:21:12:27 | source1 | vector.cpp:12:21:12:28 | call to vector | TAINT |
| vector.cpp:12:21:12:28 | call to vector | vector.cpp:14:14:14:14 | v | |
| vector.cpp:12:21:12:28 | call to vector | vector.cpp:18:38:18:38 | v | |
| vector.cpp:12:21:12:28 | call to vector | vector.cpp:18:55:18:55 | v | |
| vector.cpp:12:21:12:28 | call to vector | vector.cpp:22:15:22:15 | v | |
| vector.cpp:14:14:14:14 | call to begin | vector.cpp:14:14:14:14 | (__begin) | |
| vector.cpp:14:14:14:14 | call to begin | vector.cpp:14:14:14:14 | (__begin) | |
| vector.cpp:14:14:14:14 | call to begin | vector.cpp:14:14:14:14 | (__begin) | |
| vector.cpp:14:14:14:14 | call to end | vector.cpp:14:14:14:14 | (__end) | |
| vector.cpp:14:14:14:14 | call to operator* | vector.cpp:15:8:15:8 | x | |
| vector.cpp:14:14:14:14 | ref arg (__begin) | vector.cpp:14:14:14:14 | (__begin) | |
| vector.cpp:14:14:14:14 | ref arg (__begin) | vector.cpp:14:14:14:14 | (__begin) | |
| vector.cpp:14:14:14:14 | ref arg (__begin) | vector.cpp:14:14:14:14 | (__begin) | |
| vector.cpp:14:14:14:14 | ref arg (__range) | vector.cpp:14:14:14:14 | (__range) | |
| vector.cpp:14:14:14:14 | v | vector.cpp:14:14:14:14 | (__range) | |
| vector.cpp:14:14:14:14 | v | vector.cpp:14:14:14:14 | (__range) | |
| vector.cpp:14:14:14:14 | v | vector.cpp:14:14:14:14 | call to operator* | TAINT |
| vector.cpp:18:38:18:38 | ref arg v | vector.cpp:18:55:18:55 | v | |
| vector.cpp:18:38:18:38 | ref arg v | vector.cpp:22:15:22:15 | v | |
| vector.cpp:18:40:18:44 | call to begin | vector.cpp:18:49:18:50 | it | |
| vector.cpp:18:40:18:44 | call to begin | vector.cpp:18:66:18:67 | it | |
| vector.cpp:18:40:18:44 | call to begin | vector.cpp:19:9:19:10 | it | |
| vector.cpp:18:55:18:55 | ref arg v | vector.cpp:18:55:18:55 | v | |
| vector.cpp:18:55:18:55 | ref arg v | vector.cpp:22:15:22:15 | v | |
| vector.cpp:18:66:18:67 | ref arg it | vector.cpp:18:49:18:50 | it | |
| vector.cpp:18:66:18:67 | ref arg it | vector.cpp:18:66:18:67 | it | |
| vector.cpp:18:66:18:67 | ref arg it | vector.cpp:19:9:19:10 | it | |
| vector.cpp:22:15:22:15 | call to begin | vector.cpp:22:15:22:15 | (__begin) | |
| vector.cpp:22:15:22:15 | call to begin | vector.cpp:22:15:22:15 | (__begin) | |
| vector.cpp:22:15:22:15 | call to begin | vector.cpp:22:15:22:15 | (__begin) | |
| vector.cpp:22:15:22:15 | call to end | vector.cpp:22:15:22:15 | (__end) | |
| vector.cpp:22:15:22:15 | call to operator* | vector.cpp:23:8:23:8 | x | |
| vector.cpp:22:15:22:15 | ref arg (__begin) | vector.cpp:22:15:22:15 | (__begin) | |
| vector.cpp:22:15:22:15 | ref arg (__begin) | vector.cpp:22:15:22:15 | (__begin) | |
| vector.cpp:22:15:22:15 | ref arg (__begin) | vector.cpp:22:15:22:15 | (__begin) | |
| vector.cpp:22:15:22:15 | ref arg (__range) | vector.cpp:22:15:22:15 | (__range) | |
| vector.cpp:22:15:22:15 | v | vector.cpp:22:15:22:15 | (__range) | |
| vector.cpp:22:15:22:15 | v | vector.cpp:22:15:22:15 | (__range) | |
| vector.cpp:22:15:22:15 | v | vector.cpp:22:15:22:15 | call to operator* | TAINT |
| vector.cpp:26:33:26:39 | source1 | vector.cpp:26:33:26:40 | call to vector | TAINT |
| vector.cpp:26:33:26:40 | call to vector | vector.cpp:27:21:27:27 | const_v | |
| vector.cpp:27:21:27:21 | call to begin | vector.cpp:27:21:27:21 | (__begin) | |
| vector.cpp:27:21:27:21 | call to begin | vector.cpp:27:21:27:21 | (__begin) | |
| vector.cpp:27:21:27:21 | call to begin | vector.cpp:27:21:27:21 | (__begin) | |
| vector.cpp:27:21:27:21 | call to end | vector.cpp:27:21:27:21 | (__end) | |
| vector.cpp:27:21:27:21 | call to operator* | vector.cpp:28:8:28:8 | x | |
| vector.cpp:27:21:27:21 | ref arg (__begin) | vector.cpp:27:21:27:21 | (__begin) | |
| vector.cpp:27:21:27:21 | ref arg (__begin) | vector.cpp:27:21:27:21 | (__begin) | |
| vector.cpp:27:21:27:21 | ref arg (__begin) | vector.cpp:27:21:27:21 | (__begin) | |
| vector.cpp:27:21:27:27 | const_v | vector.cpp:27:21:27:21 | (__range) | |
| vector.cpp:27:21:27:27 | const_v | vector.cpp:27:21:27:21 | (__range) | |
| vector.cpp:27:21:27:27 | const_v | vector.cpp:27:21:27:21 | call to operator* | TAINT |

Просмотреть файл

@ -1,310 +0,0 @@
typedef unsigned long size_t;
namespace std
{
template<class charT> struct char_traits;
typedef size_t streamsize;
struct ptrdiff_t;
template <class iterator_category,
class value_type,
class difference_type = ptrdiff_t,
class pointer_type = value_type*,
class reference_type = value_type&>
struct iterator {
iterator &operator++();
iterator operator++(int);
bool operator==(iterator other) const;
bool operator!=(iterator other) const;
reference_type operator*() const;
};
struct input_iterator_tag {};
struct forward_iterator_tag : public input_iterator_tag {};
struct bidirectional_iterator_tag : public forward_iterator_tag {};
struct random_access_iterator_tag : public bidirectional_iterator_tag {};
template <class T> class allocator {
public:
allocator() throw();
};
template<class charT, class traits = char_traits<charT>, class Allocator = allocator<charT> >
class basic_string {
public:
explicit basic_string(const Allocator& a = Allocator());
basic_string(const charT* s, const Allocator& a = Allocator());
const charT* c_str() const;
typedef std::iterator<random_access_iterator_tag, charT> iterator;
typedef std::iterator<random_access_iterator_tag, const charT> const_iterator;
iterator begin();
iterator end();
const_iterator begin() const;
const_iterator end() const;
const_iterator cbegin() const;
const_iterator cend() const;
};
typedef basic_string<char> string;
template <class charT, class traits = char_traits<charT> >
class basic_istream /*: virtual public basic_ios<charT,traits> - not needed for this test */ {
public:
basic_istream<charT,traits>& operator>>(int& n);
};
template <class charT, class traits = char_traits<charT> >
class basic_ostream /*: virtual public basic_ios<charT,traits> - not needed for this test */ {
public:
typedef charT char_type;
basic_ostream<charT,traits>& write(const char_type* s, streamsize n);
basic_ostream<charT, traits>& operator<<(int n);
};
template<class charT, class traits> basic_ostream<charT,traits>& operator<<(basic_ostream<charT,traits>&, const charT*);
template<class charT, class traits, class Allocator> basic_ostream<charT, traits>& operator<<(basic_ostream<charT, traits>& os, const basic_string<charT, traits, Allocator>& str);
template<class charT, class traits = char_traits<charT>>
class basic_iostream : public basic_istream<charT, traits>, public basic_ostream<charT, traits> {
public:
};
template<class charT, class traits = char_traits<charT>, class Allocator = allocator<charT>>
class basic_stringstream : public basic_iostream<charT, traits> {
public:
explicit basic_stringstream(/*ios_base::openmode which = ios_base::out|ios_base::in - not needed for this test*/);
basic_string<charT, traits, Allocator> str() const;
};
using stringstream = basic_stringstream<char>;
}
char *source();
void sink(const char *s) {};
void sink(const std::string &s) {};
void sink(const std::stringstream &s) {};
void test_string()
{
char *a = source();
std::string b("123");
std::string c(source());
sink(a); // tainted
sink(b);
sink(c); // tainted
sink(b.c_str());
sink(c.c_str()); // tainted
}
void test_stringstream()
{
std::stringstream ss1, ss2, ss3, ss4, ss5;
std::string t(source());
ss1 << "1234";
ss2 << source();
ss3 << "123" << source();
ss4 << source() << "456";
ss5 << t;
sink(ss1);
sink(ss2); // tainted [NOT DETECTED]
sink(ss3); // tainted [NOT DETECTED]
sink(ss4); // tainted [NOT DETECTED]
sink(ss5); // tainted [NOT DETECTED]
sink(ss1.str());
sink(ss2.str()); // tainted [NOT DETECTED]
sink(ss3.str()); // tainted [NOT DETECTED]
sink(ss4.str()); // tainted [NOT DETECTED]
sink(ss5.str()); // tainted [NOT DETECTED]
}
void test_stringstream_int(int source)
{
std::stringstream ss1, ss2;
ss1 << 1234;
ss2 << source;
sink(ss1);
sink(ss2); // tainted [NOT DETECTED]
sink(ss1.str());
sink(ss2.str()); // tainted [NOT DETECTED]
}
using namespace std;
char *user_input() {
return source();
}
void sink(const char *filename, const char *mode);
void test_strings2()
{
string path1 = user_input();
sink(path1.c_str(), "r"); // tainted
string path2;
path2 = user_input();
sink(path2.c_str(), "r"); // tainted
string path3(user_input());
sink(path3.c_str(), "r"); // tainted
}
void test_string3()
{
const char *cs = source();
// convert char * -> std::string
std::string ss(cs);
sink(cs); // tainted
sink(ss); // tainted
}
void test_string4()
{
const char *cs = source();
// convert char * -> std::string
std::string ss(cs);
// convert back std::string -> char *
cs = ss.c_str();
sink(cs); // tainted
sink(ss); // tainted
}
void test_string_constructors_assignments()
{
{
std::string s1("hello");
std::string s2 = "hello";
std::string s3;
s3 = "hello";
sink(s1);
sink(s2);
sink(s3);
}
{
std::string s1(source());
std::string s2 = source();
std::string s3;
s3 = source();
sink(s1); // tainted
sink(s2); // tainted
sink(s3); // tainted
}
{
std::string s1;
std::string s2 = s1;
std::string s3;
s3 = s1;
sink(s1);
sink(s2);
sink(s3);
}
{
std::string s1 = std::string(source());
std::string s2;
s2 = std::string(source());
sink(s1); // tainted
sink(s2); // tainted
}
}
void sink(char) {}
void test_range_based_for_loop_string() {
std::string s(source());
for(char c : s) {
sink(c); // tainted [NOT DETECTED by IR]
}
for(std::string::iterator it = s.begin(); it != s.end(); ++it) {
sink(*it); // tainted [NOT DETECTED]
}
for(char& c : s) {
sink(c); // tainted [NOT DETECTED by IR]
}
const std::string const_s(source());
for(const char& c : const_s) {
sink(c); // tainted [NOT DETECTED by IR]
}
}
namespace std {
template <class T>
class vector {
private:
void *data_;
public:
vector(int size);
T& operator[](int idx);
const T& operator[](int idx) const;
typedef std::iterator<random_access_iterator_tag, T> iterator;
typedef std::iterator<random_access_iterator_tag, const T> const_iterator;
iterator begin() noexcept;
iterator end() noexcept;
const_iterator begin() const noexcept;
const_iterator end() const noexcept;
};
}
void sink(int);
void test_range_based_for_loop_vector(int source1) {
// Tainting the vector by allocating a tainted length. This doesn't represent
// how a vector would typically get tainted, but it allows this test to avoid
// being concerned with std::vector modeling.
std::vector<int> v(source1);
for(int x : v) {
sink(x); // tainted [NOT DETECTED by IR]
}
for(std::vector<int>::iterator it = v.begin(); it != v.end(); ++it) {
sink(*it); // tainted [NOT DETECTED]
}
for(int& x : v) {
sink(x); // tainted [NOT DETECTED by IR]
}
const std::vector<int> const_v(source1);
for(const int& x : const_v) {
sink(x); // tainted [NOT DETECTED by IR]
}
}

Просмотреть файл

@ -0,0 +1,126 @@
typedef unsigned long size_t;
// --- string ---
namespace std
{
template<class charT> struct char_traits;
typedef size_t streamsize;
struct ptrdiff_t;
template <class iterator_category,
class value_type,
class difference_type = ptrdiff_t,
class pointer_type = value_type*,
class reference_type = value_type&>
struct iterator {
iterator &operator++();
iterator operator++(int);
bool operator==(iterator other) const;
bool operator!=(iterator other) const;
reference_type operator*() const;
};
struct input_iterator_tag {};
struct forward_iterator_tag : public input_iterator_tag {};
struct bidirectional_iterator_tag : public forward_iterator_tag {};
struct random_access_iterator_tag : public bidirectional_iterator_tag {};
template <class T> class allocator {
public:
allocator() throw();
typedef size_t size_type;
};
template<class charT, class traits = char_traits<charT>, class Allocator = allocator<charT> >
class basic_string {
public:
typedef typename Allocator::size_type size_type;
explicit basic_string(const Allocator& a = Allocator());
basic_string(const charT* s, const Allocator& a = Allocator());
const charT* c_str() const;
typedef std::iterator<random_access_iterator_tag, charT> iterator;
typedef std::iterator<random_access_iterator_tag, const charT> const_iterator;
iterator begin();
iterator end();
const_iterator begin() const;
const_iterator end() const;
const_iterator cbegin() const;
const_iterator cend() const;
template<class T> basic_string& operator+=(const T& t);
basic_string& operator+=(const charT* s);
basic_string& append(const basic_string& str);
basic_string& append(const charT* s);
basic_string& append(size_type n, charT c);
};
template<class charT, class traits, class Allocator> basic_string<charT, traits, Allocator> operator+(const basic_string<charT, traits, Allocator>& lhs, const basic_string<charT, traits, Allocator>& rhs);
template<class charT, class traits, class Allocator> basic_string<charT, traits, Allocator> operator+(const basic_string<charT, traits, Allocator>& lhs, const charT* rhs);
typedef basic_string<char> string;
template <class charT, class traits = char_traits<charT> >
class basic_istream /*: virtual public basic_ios<charT,traits> - not needed for this test */ {
public:
basic_istream<charT,traits>& operator>>(int& n);
};
template <class charT, class traits = char_traits<charT> >
class basic_ostream /*: virtual public basic_ios<charT,traits> - not needed for this test */ {
public:
typedef charT char_type;
basic_ostream<charT,traits>& write(const char_type* s, streamsize n);
basic_ostream<charT, traits>& operator<<(int n);
};
template<class charT, class traits> basic_ostream<charT,traits>& operator<<(basic_ostream<charT,traits>&, const charT*);
template<class charT, class traits, class Allocator> basic_ostream<charT, traits>& operator<<(basic_ostream<charT, traits>& os, const basic_string<charT, traits, Allocator>& str);
template<class charT, class traits = char_traits<charT>>
class basic_iostream : public basic_istream<charT, traits>, public basic_ostream<charT, traits> {
public:
};
template<class charT, class traits = char_traits<charT>, class Allocator = allocator<charT>>
class basic_stringstream : public basic_iostream<charT, traits> {
public:
explicit basic_stringstream(/*ios_base::openmode which = ios_base::out|ios_base::in - not needed for this test*/);
basic_string<charT, traits, Allocator> str() const;
};
using stringstream = basic_stringstream<char>;
}
// --- vector ---
namespace std {
template <class T>
class vector {
private:
void *data_;
public:
vector(int size);
T& operator[](int idx);
const T& operator[](int idx) const;
typedef std::iterator<random_access_iterator_tag, T> iterator;
typedef std::iterator<random_access_iterator_tag, const T> const_iterator;
iterator begin() noexcept;
iterator end() noexcept;
const_iterator begin() const noexcept;
const_iterator end() const noexcept;
};
}

Просмотреть файл

@ -0,0 +1,186 @@
#include "stl.h"
using namespace std;
char *source();
namespace ns_char
{
char source();
}
char *user_input() {
return source();
}
void sink(const char *s) {};
void sink(const std::string &s) {};
void sink(const char *filename, const char *mode);
void sink(char) {}
void test_string()
{
char *a = source();
std::string b("123");
std::string c(source());
sink(a); // tainted
sink(b);
sink(c); // tainted
sink(b.c_str());
sink(c.c_str()); // tainted
}
void test_strings2()
{
string path1 = user_input();
sink(path1.c_str(), "r"); // tainted
string path2;
path2 = user_input();
sink(path2.c_str(), "r"); // tainted
string path3(user_input());
sink(path3.c_str(), "r"); // tainted
}
void test_string3()
{
const char *cs = source();
// convert char * -> std::string
std::string ss(cs);
sink(cs); // tainted
sink(ss); // tainted
}
void test_string4()
{
const char *cs = source();
// convert char * -> std::string
std::string ss(cs);
// convert back std::string -> char *
cs = ss.c_str();
sink(cs); // tainted
sink(ss); // tainted
}
void test_string_constructors_assignments()
{
{
std::string s1("hello");
std::string s2 = "hello";
std::string s3;
s3 = "hello";
sink(s1);
sink(s2);
sink(s3);
}
{
std::string s1(source());
std::string s2 = source();
std::string s3;
s3 = source();
sink(s1); // tainted
sink(s2); // tainted
sink(s3); // tainted
}
{
std::string s1;
std::string s2 = s1;
std::string s3;
s3 = s1;
sink(s1);
sink(s2);
sink(s3);
}
{
std::string s1 = std::string(source());
std::string s2;
s2 = std::string(source());
sink(s1); // tainted
sink(s2); // tainted
}
}
void test_range_based_for_loop_string() {
std::string s(source());
for(char c : s) {
sink(c); // tainted [NOT DETECTED by IR]
}
for(std::string::iterator it = s.begin(); it != s.end(); ++it) {
sink(*it); // tainted [NOT DETECTED]
}
for(char& c : s) {
sink(c); // tainted [NOT DETECTED by IR]
}
const std::string const_s(source());
for(const char& c : const_s) {
sink(c); // tainted [NOT DETECTED by IR]
}
}
void test_string_append() {
{
std::string s1("hello");
std::string s2(source());
sink(s1 + s1);
sink(s1 + s2); // tainted
sink(s2 + s1); // tainted
sink(s2 + s2); // tainted
sink(s1 + " world");
sink(s1 + source()); // tainted
}
{
std::string s3("abc");
std::string s4(source());
std::string s5, s6, s7, s8, s9;
s5 = s3 + s4;
sink(s5); // tainted
s6 = s3;
s6 += s4;
sink(s6); // tainted
s7 = s3;
s7 += source();
s7 += " ";
sink(s7); // tainted
s8 = s3;
s8.append(s4);
sink(s8); // tainted
s9 = s3;
s9.append(source());
s9.append(" ");
sink(s9); // tainted
}
{
std::string s10("abc");
char c = ns_char::source();
s10.append(1, c);
sink(s10); // tainted
}
}

Просмотреть файл

@ -0,0 +1,45 @@
#include "stl.h"
using namespace std;
char *source();
void sink(const std::string &s) {};
void sink(const std::stringstream &s) {};
void test_stringstream()
{
std::stringstream ss1, ss2, ss3, ss4, ss5;
std::string t(source());
ss1 << "1234";
ss2 << source();
ss3 << "123" << source();
ss4 << source() << "456";
ss5 << t;
sink(ss1);
sink(ss2); // tainted [NOT DETECTED]
sink(ss3); // tainted [NOT DETECTED]
sink(ss4); // tainted [NOT DETECTED]
sink(ss5); // tainted [NOT DETECTED]
sink(ss1.str());
sink(ss2.str()); // tainted [NOT DETECTED]
sink(ss3.str()); // tainted [NOT DETECTED]
sink(ss4.str()); // tainted [NOT DETECTED]
sink(ss5.str()); // tainted [NOT DETECTED]
}
void test_stringstream_int(int source)
{
std::stringstream ss1, ss2;
ss1 << 1234;
ss2 << source;
sink(ss1);
sink(ss2); // tainted [NOT DETECTED]
sink(ss1.str());
sink(ss2.str()); // tainted [NOT DETECTED]
}

Просмотреть файл

@ -32,27 +32,34 @@
| movableclass.cpp:55:8:55:9 | s2 | movableclass.cpp:52:23:52:28 | call to source |
| movableclass.cpp:64:8:64:9 | s2 | movableclass.cpp:23:55:23:60 | call to source |
| movableclass.cpp:65:11:65:11 | call to operator= | movableclass.cpp:65:13:65:18 | call to source |
| stl.cpp:101:7:101:7 | a | stl.cpp:97:12:97:17 | call to source |
| stl.cpp:103:7:103:7 | c | stl.cpp:99:16:99:21 | call to source |
| stl.cpp:105:9:105:13 | call to c_str | stl.cpp:99:16:99:21 | call to source |
| stl.cpp:155:13:155:17 | call to c_str | stl.cpp:147:10:147:15 | call to source |
| stl.cpp:159:13:159:17 | call to c_str | stl.cpp:147:10:147:15 | call to source |
| stl.cpp:162:13:162:17 | call to c_str | stl.cpp:147:10:147:15 | call to source |
| stl.cpp:172:7:172:8 | cs | stl.cpp:167:19:167:24 | call to source |
| stl.cpp:173:7:173:8 | ss | stl.cpp:167:19:167:24 | call to source |
| stl.cpp:186:7:186:8 | cs | stl.cpp:178:19:178:24 | call to source |
| stl.cpp:187:7:187:8 | ss | stl.cpp:178:19:178:24 | call to source |
| stl.cpp:209:8:209:9 | s1 | stl.cpp:204:18:204:23 | call to source |
| stl.cpp:210:8:210:9 | s2 | stl.cpp:205:20:205:25 | call to source |
| stl.cpp:211:8:211:9 | s3 | stl.cpp:207:8:207:13 | call to source |
| stl.cpp:230:8:230:9 | s1 | stl.cpp:226:32:226:37 | call to source |
| stl.cpp:231:8:231:9 | s2 | stl.cpp:228:20:228:25 | call to source |
| stl.cpp:240:8:240:8 | c | stl.cpp:238:16:238:21 | call to source |
| stl.cpp:248:8:248:8 | c | stl.cpp:238:16:238:21 | call to source |
| stl.cpp:253:8:253:8 | c | stl.cpp:251:28:251:33 | call to source |
| stl.cpp:295:8:295:8 | x | stl.cpp:288:43:288:49 | source1 |
| stl.cpp:303:8:303:8 | x | stl.cpp:288:43:288:49 | source1 |
| stl.cpp:308:8:308:8 | x | stl.cpp:288:43:288:49 | source1 |
| string.cpp:28:7:28:7 | a | string.cpp:24:12:24:17 | call to source |
| string.cpp:30:7:30:7 | c | string.cpp:26:16:26:21 | call to source |
| string.cpp:32:9:32:13 | call to c_str | string.cpp:26:16:26:21 | call to source |
| string.cpp:38:13:38:17 | call to c_str | string.cpp:14:10:14:15 | call to source |
| string.cpp:42:13:42:17 | call to c_str | string.cpp:14:10:14:15 | call to source |
| string.cpp:45:13:45:17 | call to c_str | string.cpp:14:10:14:15 | call to source |
| string.cpp:55:7:55:8 | cs | string.cpp:50:19:50:24 | call to source |
| string.cpp:56:7:56:8 | ss | string.cpp:50:19:50:24 | call to source |
| string.cpp:69:7:69:8 | cs | string.cpp:61:19:61:24 | call to source |
| string.cpp:70:7:70:8 | ss | string.cpp:61:19:61:24 | call to source |
| string.cpp:92:8:92:9 | s1 | string.cpp:87:18:87:23 | call to source |
| string.cpp:93:8:93:9 | s2 | string.cpp:88:20:88:25 | call to source |
| string.cpp:94:8:94:9 | s3 | string.cpp:90:8:90:13 | call to source |
| string.cpp:113:8:113:9 | s1 | string.cpp:109:32:109:37 | call to source |
| string.cpp:114:8:114:9 | s2 | string.cpp:111:20:111:25 | call to source |
| string.cpp:121:8:121:8 | c | string.cpp:119:16:119:21 | call to source |
| string.cpp:129:8:129:8 | c | string.cpp:119:16:119:21 | call to source |
| string.cpp:134:8:134:8 | c | string.cpp:132:28:132:33 | call to source |
| string.cpp:144:11:144:11 | call to operator+ | string.cpp:141:18:141:23 | call to source |
| string.cpp:145:11:145:11 | call to operator+ | string.cpp:141:18:141:23 | call to source |
| string.cpp:146:11:146:11 | call to operator+ | string.cpp:141:18:141:23 | call to source |
| string.cpp:149:11:149:11 | call to operator+ | string.cpp:149:13:149:18 | call to source |
| string.cpp:158:8:158:9 | s5 | string.cpp:154:18:154:23 | call to source |
| string.cpp:162:8:162:9 | s6 | string.cpp:154:18:154:23 | call to source |
| string.cpp:167:8:167:9 | s7 | string.cpp:165:9:165:14 | call to source |
| string.cpp:171:8:171:9 | s8 | string.cpp:154:18:154:23 | call to source |
| string.cpp:176:8:176:9 | s9 | string.cpp:174:13:174:18 | call to source |
| string.cpp:184:8:184:10 | s10 | string.cpp:181:12:181:26 | call to source |
| structlikeclass.cpp:35:8:35:9 | s1 | structlikeclass.cpp:29:22:29:27 | call to source |
| structlikeclass.cpp:36:8:36:9 | s2 | structlikeclass.cpp:30:24:30:29 | call to source |
| structlikeclass.cpp:37:8:37:9 | s3 | structlikeclass.cpp:29:22:29:27 | call to source |
@ -159,3 +166,6 @@
| taint.cpp:470:7:470:7 | x | taint.cpp:462:6:462:11 | call to source |
| taint.cpp:471:7:471:7 | y | taint.cpp:462:6:462:11 | call to source |
| taint.cpp:485:7:485:10 | line | taint.cpp:480:26:480:32 | source1 |
| vector.cpp:15:8:15:8 | x | vector.cpp:8:43:8:49 | source1 |
| vector.cpp:23:8:23:8 | x | vector.cpp:8:43:8:49 | source1 |
| vector.cpp:28:8:28:8 | x | vector.cpp:8:43:8:49 | source1 |

Просмотреть файл

@ -30,26 +30,33 @@
| movableclass.cpp:55:8:55:9 | movableclass.cpp:52:23:52:28 | AST only |
| movableclass.cpp:64:8:64:9 | movableclass.cpp:23:55:23:60 | AST only |
| movableclass.cpp:65:11:65:11 | movableclass.cpp:65:13:65:18 | AST only |
| stl.cpp:103:7:103:7 | stl.cpp:99:16:99:21 | AST only |
| stl.cpp:105:9:105:13 | stl.cpp:99:16:99:21 | AST only |
| stl.cpp:155:13:155:17 | stl.cpp:147:10:147:15 | AST only |
| stl.cpp:159:13:159:17 | stl.cpp:147:10:147:15 | AST only |
| stl.cpp:162:13:162:17 | stl.cpp:147:10:147:15 | AST only |
| stl.cpp:172:7:172:8 | stl.cpp:167:19:167:26 | IR only |
| stl.cpp:173:7:173:8 | stl.cpp:167:19:167:24 | AST only |
| stl.cpp:186:7:186:8 | stl.cpp:178:19:178:24 | AST only |
| stl.cpp:187:7:187:8 | stl.cpp:178:19:178:24 | AST only |
| stl.cpp:209:8:209:9 | stl.cpp:204:18:204:23 | AST only |
| stl.cpp:210:8:210:9 | stl.cpp:205:20:205:25 | AST only |
| stl.cpp:211:8:211:9 | stl.cpp:207:8:207:13 | AST only |
| stl.cpp:230:8:230:9 | stl.cpp:226:32:226:37 | AST only |
| stl.cpp:231:8:231:9 | stl.cpp:228:20:228:25 | AST only |
| stl.cpp:240:8:240:8 | stl.cpp:238:16:238:21 | AST only |
| stl.cpp:248:8:248:8 | stl.cpp:238:16:238:21 | AST only |
| stl.cpp:253:8:253:8 | stl.cpp:251:28:251:33 | AST only |
| stl.cpp:295:8:295:8 | stl.cpp:288:43:288:49 | AST only |
| stl.cpp:303:8:303:8 | stl.cpp:288:43:288:49 | AST only |
| stl.cpp:308:8:308:8 | stl.cpp:288:43:288:49 | AST only |
| string.cpp:30:7:30:7 | string.cpp:26:16:26:21 | AST only |
| string.cpp:32:9:32:13 | string.cpp:26:16:26:21 | AST only |
| string.cpp:38:13:38:17 | string.cpp:14:10:14:15 | AST only |
| string.cpp:42:13:42:17 | string.cpp:14:10:14:15 | AST only |
| string.cpp:45:13:45:17 | string.cpp:14:10:14:15 | AST only |
| string.cpp:55:7:55:8 | string.cpp:50:19:50:26 | IR only |
| string.cpp:56:7:56:8 | string.cpp:50:19:50:24 | AST only |
| string.cpp:69:7:69:8 | string.cpp:61:19:61:24 | AST only |
| string.cpp:70:7:70:8 | string.cpp:61:19:61:24 | AST only |
| string.cpp:92:8:92:9 | string.cpp:87:18:87:23 | AST only |
| string.cpp:93:8:93:9 | string.cpp:88:20:88:25 | AST only |
| string.cpp:94:8:94:9 | string.cpp:90:8:90:13 | AST only |
| string.cpp:113:8:113:9 | string.cpp:109:32:109:37 | AST only |
| string.cpp:114:8:114:9 | string.cpp:111:20:111:25 | AST only |
| string.cpp:121:8:121:8 | string.cpp:119:16:119:21 | AST only |
| string.cpp:129:8:129:8 | string.cpp:119:16:119:21 | AST only |
| string.cpp:134:8:134:8 | string.cpp:132:28:132:33 | AST only |
| string.cpp:144:11:144:11 | string.cpp:141:18:141:23 | AST only |
| string.cpp:145:11:145:11 | string.cpp:141:18:141:23 | AST only |
| string.cpp:146:11:146:11 | string.cpp:141:18:141:23 | AST only |
| string.cpp:149:11:149:11 | string.cpp:149:13:149:18 | AST only |
| string.cpp:158:8:158:9 | string.cpp:154:18:154:23 | AST only |
| string.cpp:162:8:162:9 | string.cpp:154:18:154:23 | AST only |
| string.cpp:167:8:167:9 | string.cpp:165:9:165:14 | AST only |
| string.cpp:171:8:171:9 | string.cpp:154:18:154:23 | AST only |
| string.cpp:176:8:176:9 | string.cpp:174:13:174:18 | AST only |
| string.cpp:184:8:184:10 | string.cpp:181:12:181:26 | AST only |
| structlikeclass.cpp:35:8:35:9 | structlikeclass.cpp:29:22:29:27 | AST only |
| structlikeclass.cpp:36:8:36:9 | structlikeclass.cpp:30:24:30:29 | AST only |
| structlikeclass.cpp:37:8:37:9 | structlikeclass.cpp:29:22:29:27 | AST only |
@ -94,3 +101,6 @@
| taint.cpp:446:7:446:7 | taint.cpp:445:14:445:28 | AST only |
| taint.cpp:447:9:447:17 | taint.cpp:445:14:445:28 | AST only |
| taint.cpp:471:7:471:7 | taint.cpp:462:6:462:11 | AST only |
| vector.cpp:15:8:15:8 | vector.cpp:8:43:8:49 | AST only |
| vector.cpp:23:8:23:8 | vector.cpp:8:43:8:49 | AST only |
| vector.cpp:28:8:28:8 | vector.cpp:8:43:8:49 | AST only |

Просмотреть файл

@ -1,10 +1,10 @@
| format.cpp:157:7:157:22 | (int)... | format.cpp:147:12:147:25 | call to source |
| format.cpp:157:7:157:22 | access to array | format.cpp:147:12:147:25 | call to source |
| format.cpp:158:7:158:27 | ... + ... | format.cpp:148:16:148:30 | call to source |
| stl.cpp:101:7:101:7 | (const char *)... | stl.cpp:97:12:97:17 | call to source |
| stl.cpp:101:7:101:7 | a | stl.cpp:97:12:97:17 | call to source |
| stl.cpp:172:7:172:8 | cs | stl.cpp:167:19:167:24 | call to source |
| stl.cpp:172:7:172:8 | cs | stl.cpp:167:19:167:26 | (const char *)... |
| string.cpp:28:7:28:7 | (const char *)... | string.cpp:24:12:24:17 | call to source |
| string.cpp:28:7:28:7 | a | string.cpp:24:12:24:17 | call to source |
| string.cpp:55:7:55:8 | cs | string.cpp:50:19:50:24 | call to source |
| string.cpp:55:7:55:8 | cs | string.cpp:50:19:50:26 | (const char *)... |
| structlikeclass.cpp:38:8:38:9 | s4 | structlikeclass.cpp:33:8:33:13 | call to source |
| structlikeclass.cpp:61:8:61:9 | s2 | structlikeclass.cpp:58:24:58:29 | call to source |
| structlikeclass.cpp:62:8:62:20 | ... = ... | structlikeclass.cpp:62:13:62:18 | call to source |

Просмотреть файл

@ -0,0 +1,30 @@
#include "stl.h"
using namespace std;
void sink(int);
void test_range_based_for_loop_vector(int source1) {
// Tainting the vector by allocating a tainted length. This doesn't represent
// how a vector would typically get tainted, but it allows this test to avoid
// being concerned with std::vector modeling.
std::vector<int> v(source1);
for(int x : v) {
sink(x); // tainted [NOT DETECTED by IR]
}
for(std::vector<int>::iterator it = v.begin(); it != v.end(); ++it) {
sink(*it); // tainted [NOT DETECTED]
}
for(int& x : v) {
sink(x); // tainted [NOT DETECTED by IR]
}
const std::vector<int> const_v(source1);
for(const int& x : const_v) {
sink(x); // tainted [NOT DETECTED by IR]
}
}

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -1,4 +1,4 @@
import semmle.code.cpp.rangeanalysis.SimpleRangeAnalysis
from VariableAccess expr
select expr, lowerBound(expr)
select expr, lowerBound(expr).toString()

Просмотреть файл

@ -422,7 +422,7 @@ void test17() {
out(i); // 50
i = 20 + (j -= 10);
out(i); // 60 [BUG: the analysis thinks it's 2^-31 .. 2^31-1]
out(i); // 60
}
// Tests for unsigned multiplication.
@ -463,3 +463,30 @@ int test_unsigned_mult02(unsigned b) {
return total;
}
unsigned long mult_rounding() {
unsigned long x, y, xy;
x = y = 1000000003UL; // 1e9 + 3
xy = x * y;
return xy; // BUG: upper bound should be >= 1000000006000000009UL
}
unsigned long mult_overflow() {
unsigned long x, y, xy;
x = 274177UL;
y = 67280421310721UL;
xy = x * y;
return xy; // BUG: lower bound should be <= 18446744073709551617UL
}
unsigned long mult_lower_bound(unsigned int ui, unsigned long ul) {
if (ui >= 10) {
unsigned long result = (unsigned long)ui * ui;
return result; // BUG: upper bound should be >= 18446744065119617025 (possibly a pretty-printing bug)
}
if (ul >= 10) {
unsigned long result = ul * ul;
return result; // lower bound is correctly 0 (overflow is possible)
}
return 0;
}

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -1,4 +1,4 @@
import semmle.code.cpp.rangeanalysis.SimpleRangeAnalysis
from VariableAccess expr
select expr, upperBound(expr)
select expr, upperBound(expr).toString()

Просмотреть файл

@ -385,10 +385,39 @@ void bitwise_ands()
void unsigned_mult(unsigned int x, unsigned int y) {
if(x < 13 && y < 35) {
if(x * y > 1024) {} // always false [NOT DETECTED]
if(x * y > 1024) {} // always false
if(x * y < 204) {}
if(x >= 3 && y >= 2) {
if(x * y < 5) {} // always false [NOT DETECTED]
if(x * y < 5) {} // always false
}
}
}
}
void mult_rounding() {
unsigned long x, y, xy;
x = y = 1000000003UL; // 1e9 + 3
xy = 1000000006000000009UL; // x * y, precisely
// Even though the range analysis wrongly considers x*y to be xy - 9, there
// are no PointlessComparison false positives in these tests because alerts
// are suppressed when ulp() < 1, which roughly means that the number is
// larger than 2^53.
if (x * y < xy) {} // always false [NOT DETECTED]
if (x * y > xy) {} // always false [NOT DETECTED]
}
void mult_overflow() {
unsigned long x, y;
// The following two numbers multiply to 2^64 + 1, which is 1 when truncated
// to 64-bit unsigned.
x = 274177UL;
y = 67280421310721UL;
if (x * y == 1) {} // always true [BUG: reported as always false]
// This bug appears to be caused by
// `RangeAnalysisUtils::typeUpperBound(unsigned long)` having a result of
// 2**64 + 384, making the range analysis think that the multiplication can't
// overflow. The correct `typeUpperBound` would be 2**64 - 1, but we can't
// represent that with a QL float or int. We could make `typeUpperBound`
// exclusive instead of inclusive, but there is no exclusive upper bound for
// floats.
}

Просмотреть файл

@ -41,6 +41,9 @@
| PointlessComparison.c:372:6:372:16 | ... >= ... | Comparison is always true because ... >> ... >= 1. |
| PointlessComparison.c:373:6:373:16 | ... >= ... | Comparison is always false because ... >> ... <= 1. |
| PointlessComparison.c:383:6:383:17 | ... >= ... | Comparison is always false because ... & ... <= 2. |
| PointlessComparison.c:388:10:388:21 | ... > ... | Comparison is always false because ... * ... <= 408. |
| PointlessComparison.c:391:12:391:20 | ... < ... | Comparison is always false because ... * ... >= 6. |
| PointlessComparison.c:414:7:414:16 | ... == ... | Comparison is always false because ... * ... >= 18446744073709552000. |
| PointlessComparison.cpp:36:6:36:33 | ... >= ... | Comparison is always false because ... >> ... <= 9223372036854776000. |
| PointlessComparison.cpp:41:6:41:29 | ... >= ... | Comparison is always false because ... >> ... <= 140737488355327.5. |
| PointlessComparison.cpp:42:6:42:29 | ... >= ... | Comparison is always false because ... >> ... <= 140737488355327.5. |

Просмотреть файл

@ -2,7 +2,7 @@
import csharp
private import semmle.code.csharp.frameworks.System
private import semmle.code.csharp.dataflow.DataFlow2
private import semmle.code.csharp.dataflow.DataFlow3
/** The `System.Xml` namespace. */
class SystemXmlNamespace extends Namespace {
@ -163,7 +163,7 @@ class XmlReaderSettingsCreation extends ObjectCreation {
}
}
private class SettingsDataFlowConfig extends DataFlow2::Configuration {
private class SettingsDataFlowConfig extends DataFlow3::Configuration {
SettingsDataFlowConfig() { this = "SettingsDataFlowConfig" }
override predicate isSource(DataFlow::Node source) {

Просмотреть файл

@ -0,0 +1,8 @@
public class XSS extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// BAD: a request parameter is written directly to an error response page
response.sendError(HttpServletResponse.SC_NOT_FOUND,
"The page \"" + request.getParameter("page") + "\" was not found.");
}
}

Просмотреть файл

@ -0,0 +1,12 @@
public class SQLInjection extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
StringBuilder sqlQueryBuilder = new StringBuilder();
sqlQueryBuilder.append("SELECT * FROM user WHERE user_id='");
sqlQueryBuilder.append(request.getParameter("user_id"));
sqlQueryBuilder.append("'");
// ...
}
}

Просмотреть файл

@ -0,0 +1,48 @@
<!DOCTYPE qhelp PUBLIC
"-//Semmle//qhelp//EN"
"qhelp.dtd">
<qhelp>
<overview>
<p>Using unsanitized untrusted data in an external API can cause a variety of security issues. This query reports
all external APIs that are used with untrusted data, along with how frequently the API is used, and how many
unique sources of untrusted data flow to this API. This query is designed primarily to help identify which APIs
may be relevant for security analysis of this application.</p>
<p>An external API is defined as a method call to a method that is not defined in the source code, not overridden
in the source code, and is not modeled as a taint step in the default taint library. External APIs may be from the
Java standard library, third party dependencies or from internal dependencies. The query will report the method
signature with a fully qualified name, along with either <code>[param x]</code>, where <code>x</code> indicates the
position of the parameter receiving the untrusted data or <code>[qualifier]</code> indicating the untrusted data is
used as the qualifier to the method call.</p>
</overview>
<recommendation>
<p>For each result:</p>
<ul>
<li>If the result highlights a known sink, no action is required.</li>
<li>If the result highlights an unknown sink for a problem, then add modeling for the sink to the relevant query.</li>
<li>If the result represents a call to an external API which transfers taint, add the appropriate modeling, and
re-run the query to determine what new results have appeared due to this additional modeling.</li>
</ul>
<p>Otherwise, the result is likely uninteresting. Custom versions of this query can extend the <code>SafeExternalAPIMethod</code>
class to exclude known safe external APIs from future analysis.</p>
</recommendation>
<example>
<p>If the query were to return the API <code>javax.servlet.http.HttpServletResponse.sendError(int, java.lang.String) [param 1]</code>
then we should first consider whether this a security relevant sink. In this case, this is writing to a HTTP response, so we should
consider whether this is an XSS sink. If it is, we should confirm that it is handled by the XSS query.</p>
<p>If the query were to return the API <code>java.lang.StringBuilder.append(java.lang.String) [param 0]</code>, then this should be
reviewed as a possible taint step, because tainted data would flow from the 0th argument to the qualifier of the call.</p>
<p>Note that both examples are correctly handled by the standard taint tracking library and XSS query.</p>
</example>
<references>
</references>
</qhelp>

Просмотреть файл

@ -0,0 +1,18 @@
/**
* @name Frequency counts for external APIs that are used with untrusted data
* @description This reports the external APIs that are used with untrusted data, along with how
* frequently the API is called, and how many unique sources of untrusted data flow
* to it.
* @id java/count-untrusted-data-external-api
* @kind table
* @tags security external/cwe/cwe-20
*/
import java
import semmle.code.java.security.ExternalAPIs
import semmle.code.java.dataflow.DataFlow
from ExternalAPIUsedWithUntrustedData externalAPI
select externalAPI, count(externalAPI.getUntrustedDataNode()) as numberOfUses,
externalAPI.getNumberOfUntrustedSources() as numberOfUntrustedSources order by
numberOfUntrustedSources desc

Просмотреть файл

@ -0,0 +1,57 @@
<!DOCTYPE qhelp PUBLIC
"-//Semmle//qhelp//EN"
"qhelp.dtd">
<qhelp>
<overview>
<p>Using unsanitized untrusted data in an external API can cause a variety of security issues. This query reports
external APIs that use untrusted data. The results are not filtered so that you can audit all examples. The query provides data for security reviews of the application and you can also use it to identify external APIs that should be modeled as either taint steps, or sinks for specific problems.</p>
<p>An external API is defined as a method call to a method that is not defined in the source code, not overridden
in the source code, and is not modeled as a taint step in the default taint library. External APIs may be from the
Java standard library, third-party dependencies or from internal dependencies. The query reports uses of
untrusted data in either the qualifier or as one of the arguments of external APIs.</p>
</overview>
<recommendation>
<p>For each result:</p>
<ul>
<li>If the result highlights a known sink, confirm that the result is reported by the relevant query, or
that the result is a false positive because this data is sanitized.</li>
<li>If the result highlights an unknown sink for a problem, then add modeling for the sink to the relevant query,
and confirm that the result is either found, or is safe due to appropriate sanitization.</li>
<li>If the result represents a call to an external API that transfers taint, add the appropriate modeling, and
re-run the query to determine what new results have appeared due to this additional modeling.</li>
</ul>
<p>Otherwise, the result is likely uninteresting. Custom versions of this query can extend the <code>SafeExternalAPIMethod</code>
class to exclude known safe external APIs from future analysis.</p>
</recommendation>
<example>
<p>In this first example, a request parameter is read from <code>HttpServletRequest</code> and then ultimately used in a call to the
<code>HttpServletResponse.sendError</code> external API:</p>
<sample src="ExternalAPISinkExample.java" />
<p>This is an XSS sink. The XSS query should therefore be reviewed to confirm that this sink is appropriately modeled,
and if it is, to confirm that the query reports this particular result, or that the result is a false positive due to
some existing sanitization.</p>
<p>In this second example, again a request parameter is read from <code>HttpServletRequest</code>.</p>
<sample src="ExternalAPITaintStepExample.java" />
<p>If the query reported the call to <code>StringBuilder.append</code> on line 7, this would suggest that this external API is
not currently modeled as a taint step in the taint tracking library. The next step would be to model this as a taint step, then
re-run the query to determine what additional results might be found. In this example, it seems likely that the result of the
<code>StringBuilder</code> will be executed as an SQL query, potentially leading to an SQL injection vulnerability.</p>
<p>Note that both examples are correctly handled by the standard taint tracking library and XSS query.</p>
</example>
<references>
</references>
</qhelp>

Просмотреть файл

@ -0,0 +1,21 @@
/**
* @name Untrusted data passed to external API
* @description Data provided remotely is used in this external API without sanitization, which could be a security risk.
* @id java/untrusted-data-to-external-api
* @kind path-problem
* @precision low
* @problem.severity error
* @tags security external/cwe/cwe-20
*/
import java
import semmle.code.java.dataflow.FlowSources
import semmle.code.java.dataflow.TaintTracking
import semmle.code.java.security.ExternalAPIs
import DataFlow::PathGraph
from UntrustedDataToExternalAPIConfig config, DataFlow::PathNode source, DataFlow::PathNode sink
where config.hasFlowPath(source, sink)
select sink, source, sink,
"Call to " + sink.getNode().(ExternalAPIDataNode).getMethodDescription() +
" with untrusted data from $@.", source, source.toString()

Просмотреть файл

@ -17,7 +17,7 @@ import PathGraph
*/
private string getACredentialRegex() {
result = "(?i).*challenge|pass(wd|word|code|phrase)(?!.*question).*" or
result = "(?i)(.*username|url).*"
result = "(?i)(.*username|.*secret|url).*"
}
/** Variable keeps sensitive information judging by its name * */
@ -31,8 +31,12 @@ class CredentialExpr extends Expr {
class LoggerType extends RefType {
LoggerType() {
this.hasQualifiedName("org.apache.log4j", "Category") or //Log4J
this.hasQualifiedName("org.apache.logging.log4j", "Logger") or //Log4J 2
this.hasQualifiedName("org.slf4j", "Logger") or //SLF4j and Gradle Logging
this.hasQualifiedName("org.jboss.logging", "BasicLogger") //JBoss Logging
this.hasQualifiedName("org.jboss.logging", "BasicLogger") or //JBoss Logging
this.hasQualifiedName("org.jboss.logging", "Logger") or //JBoss Logging (`org.jboss.logging.Logger` in some implementations like JBoss Application Server 4.0.4 did not implement `BasicLogger`)
this.hasQualifiedName("org.apache.commons.logging", "Log") or //Apache Commons Logging
this.hasQualifiedName("org.scijava.log", "Logger") //SciJava Logging
}
}
@ -42,7 +46,8 @@ predicate isSensitiveLoggingSink(DataFlow::Node sink) {
(
ma.getMethod().hasName("debug") or
ma.getMethod().hasName("trace") or
ma.getMethod().hasName("debugf")
ma.getMethod().hasName("debugf") or
ma.getMethod().hasName("debugv")
) and //Check low priority log levels which are more likely to be real issues to reduce false positives
sink.asExpr() = ma.getAnArgument()
)

Просмотреть файл

@ -1344,10 +1344,7 @@ class VarAccess extends Expr, @varaccess {
*/
predicate isLValue() {
exists(Assignment a | a.getDest() = this) or
exists(PreIncExpr e | e.getExpr() = this) or
exists(PreDecExpr e | e.getExpr() = this) or
exists(PostIncExpr e | e.getExpr() = this) or
exists(PostDecExpr e | e.getExpr() = this)
exists(UnaryAssignExpr e | e.getExpr() = this)
}
/**

Просмотреть файл

@ -0,0 +1,146 @@
/**
* Definitions for reasoning about untrusted data used in APIs defined outside the
* database.
*/
import java
import semmle.code.java.dataflow.FlowSources
import semmle.code.java.dataflow.TaintTracking
/**
* A `Method` that is considered a "safe" external API from a security perspective.
*/
abstract class SafeExternalAPIMethod extends Method { }
/** The default set of "safe" external APIs. */
private class DefaultSafeExternalAPIMethod extends SafeExternalAPIMethod {
DefaultSafeExternalAPIMethod() {
this instanceof EqualsMethod
or
getName().regexpMatch("size|length|compareTo|getClass|lastIndexOf")
or
this.getDeclaringType().hasQualifiedName("org.apache.commons.lang3", "Validate")
or
getQualifiedName() = "Objects.equals"
or
getDeclaringType() instanceof TypeString and getName() = "equals"
or
getDeclaringType().hasQualifiedName("com.google.common.base", "Preconditions")
or
getDeclaringType().getPackage().getName().matches("org.junit%")
or
getDeclaringType().hasQualifiedName("com.google.common.base", "Strings") and
getName() = "isNullOrEmpty"
or
getDeclaringType().hasQualifiedName("org.apache.commons.lang3", "StringUtils") and
getName() = "isNotEmpty"
or
getDeclaringType().hasQualifiedName("java.lang", "Character") and
getName() = "isDigit"
or
getDeclaringType().hasQualifiedName("java.lang", "String") and
getName().regexpMatch("equalsIgnoreCase|regionMatches")
or
getDeclaringType().hasQualifiedName("java.lang", "Boolean") and
getName() = "parseBoolean"
or
getDeclaringType().hasQualifiedName("org.apache.commons.io", "IOUtils") and
getName() = "closeQuietly"
or
getDeclaringType().hasQualifiedName("org.springframework.util", "StringUtils") and
getName().regexpMatch("hasText|isEmpty")
}
}
/** A node representing data being passed to an external API. */
class ExternalAPIDataNode extends DataFlow::Node {
Call call;
int i;
ExternalAPIDataNode() {
(
// Argument to call to a method
this.asExpr() = call.getArgument(i)
or
// Qualifier to call to a method which returns non trivial value
this.asExpr() = call.getQualifier() and
i = -1 and
not call.getCallee().getReturnType() instanceof VoidType and
not call.getCallee().getReturnType() instanceof BooleanType
) and
// Defined outside the source archive
not call.getCallee().fromSource() and
// Not a call to an method which is overridden in source
not exists(Method m |
m.getASourceOverriddenMethod() = call.getCallee().getSourceDeclaration() and
m.fromSource()
) and
// Not already modeled as a taint step
not exists(DataFlow::Node next | TaintTracking::localTaintStep(this, next)) and
// Not a call to a known safe external API
not call.getCallee() instanceof SafeExternalAPIMethod
}
/** Gets the called API `Method`. */
Method getMethod() { result = call.getCallee() }
/** Gets the index which is passed untrusted data (where -1 indicates the qualifier). */
int getIndex() { result = i }
/** Gets the description of the method being called. */
string getMethodDescription() {
result = getMethod().getDeclaringType().getPackage() + "." + getMethod().getQualifiedName()
}
}
/** A configuration for tracking flow from `RemoteFlowSource`s to `ExternalAPIDataNode`s. */
class UntrustedDataToExternalAPIConfig extends TaintTracking::Configuration {
UntrustedDataToExternalAPIConfig() { this = "UntrustedDataToExternalAPIConfig" }
override predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource }
override predicate isSink(DataFlow::Node sink) { sink instanceof ExternalAPIDataNode }
}
/** A node representing untrusted data being passed to an external API. */
class UntrustedExternalAPIDataNode extends ExternalAPIDataNode {
UntrustedExternalAPIDataNode() { any(UntrustedDataToExternalAPIConfig c).hasFlow(_, this) }
/** Gets a source of untrusted data which is passed to this external API data node. */
DataFlow::Node getAnUntrustedSource() {
any(UntrustedDataToExternalAPIConfig c).hasFlow(result, this)
}
}
private newtype TExternalAPI =
TExternalAPIParameter(Method m, int index) {
exists(UntrustedExternalAPIDataNode n |
m = n.getMethod() and
index = n.getIndex()
)
}
/** An external API which is used with untrusted data. */
class ExternalAPIUsedWithUntrustedData extends TExternalAPI {
/** Gets a possibly untrusted use of this external API. */
UntrustedExternalAPIDataNode getUntrustedDataNode() {
this = TExternalAPIParameter(result.getMethod(), result.getIndex())
}
/** Gets the number of untrusted sources used with this external API. */
int getNumberOfUntrustedSources() {
result = count(getUntrustedDataNode().getAnUntrustedSource())
}
/** Gets a textual representation of this element. */
string toString() {
exists(Method m, int index, string indexString |
if index = -1 then indexString = "qualifier" else indexString = "param " + index
|
this = TExternalAPIParameter(m, index) and
result =
m.getDeclaringType().(RefType).getQualifiedName() + "." + m.getSignature() + " [" +
indexString + "]"
)
}
}

Просмотреть файл

@ -97,6 +97,7 @@ class WritingMethod extends Method {
(
this.getName().matches("print%") or
this.getName() = "append" or
this.getName() = "format" or
this.getName() = "write"
)
}

Просмотреть файл

@ -210,6 +210,7 @@ public class AutoBuild {
private final String defaultEncoding;
private ExecutorService threadPool;
private volatile boolean seenCode = false;
private volatile boolean seenFiles = false;
private boolean installDependencies = false;
private int installDependenciesTimeout;
private final VirtualSourceRoot virtualSourceRoot;
@ -472,7 +473,11 @@ public class AutoBuild {
shutdownThreadPool();
}
if (!seenCode) {
warn("No JavaScript or TypeScript code found.");
if (seenFiles) {
warn("Only found JavaScript or TypeScript files that were empty or contained syntax errors.");
} else {
warn("No JavaScript or TypeScript code found.");
}
return -1;
}
return 0;
@ -1201,6 +1206,7 @@ protected DependencyInstallationResult preparePackagesAndDependencies(Set<Path>
long start = logBeginProcess("Extracting " + file);
Integer loc = extractor.extract(f, state);
if (!extractor.getConfig().isExterns() && (loc == null || loc != 0)) seenCode = true;
if (!extractor.getConfig().isExterns()) seenFiles = true;
logEndProcess(start, "Done extracting " + file);
} catch (Throwable t) {
System.err.println("Exception while extracting " + file + ".");

Просмотреть файл

@ -24,5 +24,6 @@ where
// ignore ambient, abstract, and overloaded declarations in TypeScript
f.hasBody() and
g.hasBody()
select f.getId(), "Declaration of " + f.describe() + " conflicts with $@ in the same scope.",
g.getId(), "another declaration"
select f.getIdentifier(),
"Declaration of " + f.describe() + " conflicts with $@ in the same scope.", g.getIdentifier(),
"another declaration"

Просмотреть файл

@ -42,11 +42,11 @@ where
access.isAmbient()
) and
// don't flag function expressions
not exists(FunctionExpr fe | dead = fe.getId()) and
not exists(FunctionExpr fe | dead = fe.getIdentifier()) and
// don't flag function declarations nested inside blocks or other compound statements;
// their meaning is only partially specified by the standard
not exists(FunctionDeclStmt fd, StmtContainer outer |
dead = fd.getId() and outer = fd.getEnclosingContainer()
dead = fd.getIdentifier() and outer = fd.getEnclosingContainer()
|
not fd = outer.getBody().(BlockStmt).getAStmt()
) and

Просмотреть файл

@ -22,6 +22,6 @@ where
not decl.isAmbient() and
not redecl.isAmbient() and
// Redeclaring a namespace extends the previous definition.
not decl = any(NamespaceDeclaration ns).getId() and
not redecl = any(NamespaceDeclaration ns).getId()
not decl = any(NamespaceDeclaration ns).getIdentifier() and
not redecl = any(NamespaceDeclaration ns).getIdentifier()
select redecl, "This variable has already been declared $@.", decl, "here"

Просмотреть файл

@ -93,7 +93,7 @@ predicate isEnumMember(VarDecl decl) { decl = any(EnumMember member).getIdentifi
* "function f", "variable v" or "class c".
*/
string describeVarDecl(VarDecl vd) {
if vd = any(Function f).getId()
if vd = any(Function f).getIdentifier()
then result = "function " + vd.getName()
else
if vd = any(ClassDefinition c).getIdentifier()
@ -115,7 +115,7 @@ class ImportVarDeclProvider extends Stmt {
*/
VarDecl getAVarDecl() {
result = this.(ImportDeclaration).getASpecifier().getLocal() or
result = this.(ImportEqualsDeclaration).getId()
result = this.(ImportEqualsDeclaration).getIdentifier()
}
/**

Просмотреть файл

@ -23,7 +23,7 @@ private import semmle.javascript.dataflow.InferredTypes
* if it is part of a const enum access, so we conservatively silence the alert in that case.
*/
predicate namespaceOrConstEnumAccess(VarAccess e) {
exists(NamespaceDeclaration decl | e.getVariable().getADeclaration() = decl.getId())
exists(NamespaceDeclaration decl | e.getVariable().getADeclaration() = decl.getIdentifier())
or
exists(EnumDeclaration decl | e.getVariable().getADeclaration() = decl.getIdentifier() |
decl.isConst()

Просмотреть файл

@ -43,6 +43,10 @@ where
or
// target is a HTTP URL to a domain on any TLD
target.regexpMatch("(?i)https?://([a-z0-9-]+\\.)+([a-z]+)(:[0-9]+)?/?")
or
// target is a HTTP URL to a domain on any TLD with path elements, and the check is an includes check
check instanceof StringOps::Includes and
target.regexpMatch("(?i)https?://([a-z0-9-]+\\.)+([a-z]+)(:[0-9]+)?/[a-z0-9/_-]+")
) and
(
if check instanceof StringOps::StartsWith

Просмотреть файл

@ -30,15 +30,17 @@ private predicate defn(ControlFlowNode def, Expr lhs, AST::ValueNode rhs) {
or
exists(VariableDeclarator vd | def = vd | lhs = vd.getBindingPattern() and rhs = vd.getInit())
or
exists(Function f | def = f.getId() | lhs = def and rhs = f)
exists(Function f | def = f.getIdentifier() | lhs = def and rhs = f)
or
exists(ClassDefinition c | lhs = c.getIdentifier() | def = c and rhs = c and not c.isAmbient())
or
exists(NamespaceDeclaration n | def = n | lhs = n.getId() and rhs = n)
exists(NamespaceDeclaration n | def = n | lhs = n.getIdentifier() and rhs = n)
or
exists(EnumDeclaration ed | def = ed.getIdentifier() | lhs = def and rhs = ed)
or
exists(ImportEqualsDeclaration i | def = i | lhs = i.getId() and rhs = i.getImportedEntity())
exists(ImportEqualsDeclaration i | def = i |
lhs = i.getIdentifier() and rhs = i.getImportedEntity()
)
or
exists(ImportSpecifier i | def = i | lhs = i.getLocal() and rhs = i)
or
@ -149,7 +151,7 @@ class RValue extends RefExpr {
or
this = any(UpdateExpr u).getOperand().getUnderlyingReference()
or
this = any(NamespaceDeclaration decl).getId()
this = any(NamespaceDeclaration decl).getIdentifier()
}
}

Просмотреть файл

@ -330,7 +330,7 @@ class ExportDefaultDeclaration extends ExportDeclaration, @exportdefaultdeclarat
/** Gets the declaration, if any, exported by this default export. */
VarDecl getADecl() {
exists(ExprOrStmt op | op = getOperand() |
result = op.(FunctionDeclStmt).getId() or
result = op.(FunctionDeclStmt).getIdentifier() or
result = op.(ClassDeclStmt).getIdentifier()
)
}
@ -364,13 +364,13 @@ class ExportNamedDeclaration extends ExportDeclaration, @exportnameddeclaration
Identifier getAnExportedDecl() {
exists(ExprOrStmt op | op = getOperand() |
result = op.(DeclStmt).getADecl().getBindingPattern().getABindingVarRef() or
result = op.(FunctionDeclStmt).getId() or
result = op.(FunctionDeclStmt).getIdentifier() or
result = op.(ClassDeclStmt).getIdentifier() or
result = op.(NamespaceDeclaration).getId() or
result = op.(NamespaceDeclaration).getIdentifier() or
result = op.(EnumDeclaration).getIdentifier() or
result = op.(InterfaceDeclaration).getIdentifier() or
result = op.(TypeAliasDeclaration).getIdentifier() or
result = op.(ImportEqualsDeclaration).getId()
result = op.(ImportEqualsDeclaration).getIdentifier()
)
}

Просмотреть файл

@ -77,8 +77,15 @@ class Function extends @function, Parameterized, TypeParameterized, StmtContaine
result = getDocumentation().getATagByTitle("this").getType()
}
/**
* DEPRECATED: Use `getIdentifier()` instead.
*
* Gets the identifier specifying the name of this function, if any.
*/
deprecated VarDecl getId() { result = getIdentifier() }
/** Gets the identifier specifying the name of this function, if any. */
VarDecl getId() { result = getChildExpr(-1) }
VarDecl getIdentifier() { result = getChildExpr(-1) }
/**
* Gets the name of this function if it has one, or a name inferred from its context.
@ -89,9 +96,9 @@ class Function extends @function, Parameterized, TypeParameterized, StmtContaine
* can be inferred, there is no result.
*/
string getName() {
result = getId().getName()
result = getIdentifier().getName()
or
not exists(getId()) and
not exists(getIdentifier()) and
(
exists(VarDef vd | this = vd.getSource() | result = vd.getTarget().(VarRef).getName())
or
@ -111,7 +118,7 @@ class Function extends @function, Parameterized, TypeParameterized, StmtContaine
}
/** Gets the variable holding this function. */
Variable getVariable() { result = getId().getVariable() }
Variable getVariable() { result = getIdentifier().getVariable() }
/** Gets the `arguments` variable of this function, if any. */
ArgumentsVariable getArgumentsVariable() { result.getFunction() = this }
@ -183,11 +190,11 @@ class Function extends @function, Parameterized, TypeParameterized, StmtContaine
not exists(getAParameter()) and
(
// if the function has a name, the opening parenthesis comes right after it
result = getId().getLastToken().getNextToken()
result = getIdentifier().getLastToken().getNextToken()
or
// otherwise this must be an arrow function with no parameters, so the opening
// parenthesis is the very first token of the function
not exists(getId()) and result = getFirstToken()
not exists(getIdentifier()) and result = getFirstToken()
)
}
@ -309,8 +316,8 @@ class Function extends @function, Parameterized, TypeParameterized, StmtContaine
*/
private string inferNameFromVarDef() {
// in ambiguous cases like `var f = function g() {}`, prefer `g` to `f`
if exists(getId())
then result = "function " + getId().getName()
if exists(getIdentifier())
then result = "function " + getIdentifier().getName()
else
exists(VarDef vd | this = vd.getSource() |
result = "function " + vd.getTarget().(VarRef).getName()

Просмотреть файл

@ -267,7 +267,7 @@ module AccessPath {
or
exists(FunctionDeclStmt fun |
node = DataFlow::valueNode(fun) and
result = fun.getId().(GlobalVarDecl).getName() and
result = fun.getIdentifier().(GlobalVarDecl).getName() and
root.isGlobal()
)
or
@ -285,7 +285,7 @@ module AccessPath {
or
exists(NamespaceDeclaration decl |
node = DataFlow::valueNode(decl) and
result = decl.getId().(GlobalVarDecl).getName() and
result = decl.getIdentifier().(GlobalVarDecl).getName() and
root.isGlobal()
)
}

Просмотреть файл

@ -8,13 +8,16 @@ import javascript
*/
class NamespaceDefinition extends Stmt, @namespacedefinition, AST::ValueNode {
/**
* DEPRECATED: Use `getIdentifier()` instead.
*
* Gets the identifier naming the namespace.
*/
Identifier getId() {
result = this.(NamespaceDeclaration).getId()
or
result = this.(EnumDeclaration).getIdentifier()
}
deprecated Identifier getId() { result = getIdentifier() }
/**
* Gets the identifier naming the namespace.
*/
Identifier getIdentifier() { none() } // Overridden in subtypes.
/**
* Gets unqualified name of the namespace being defined.
@ -29,7 +32,7 @@ class NamespaceDefinition extends Stmt, @namespacedefinition, AST::ValueNode {
* Gets the local namespace name induced by this namespace.
*/
LocalNamespaceName getLocalNamespaceName() {
result = getId().(LocalNamespaceDecl).getLocalNamespaceName()
result = getIdentifier().(LocalNamespaceDecl).getLocalNamespaceName()
}
/**
@ -55,10 +58,10 @@ class NamespaceDefinition extends Stmt, @namespacedefinition, AST::ValueNode {
*/
class NamespaceDeclaration extends NamespaceDefinition, StmtContainer, @namespacedeclaration {
/** Gets the name of this namespace. */
override Identifier getId() { result = getChildExpr(-1) }
override Identifier getIdentifier() { result = getChildExpr(-1) }
/** Gets the name of this namespace as a string. */
override string getName() { result = getId().getName() }
override string getName() { result = getIdentifier().getName() }
/** Gets the `i`th statement in this namespace. */
Stmt getStmt(int i) {
@ -83,7 +86,7 @@ class NamespaceDeclaration extends NamespaceDefinition, StmtContainer, @namespac
predicate isInstantiated() { isInstantiated(this) }
override ControlFlowNode getFirstControlFlowNode() {
if hasDeclareKeyword(this) then result = this else result = getId()
if hasDeclareKeyword(this) then result = this else result = getIdentifier()
}
}
@ -178,13 +181,20 @@ class GlobalAugmentationDeclaration extends Stmt, StmtContainer, @globalaugmenta
/** A TypeScript "import-equals" declaration. */
class ImportEqualsDeclaration extends Stmt, @importequalsdeclaration {
/**
* DEPRECATED: Use `getIdentifier()` instead.
*
* Gets the name under which the imported entity is imported.
*/
deprecated Identifier getId() { result = getIdentifier() }
/** Gets the name under which the imported entity is imported. */
Identifier getId() { result = getChildExpr(0) }
Identifier getIdentifier() { result = getChildExpr(0) }
/** Gets the expression specifying the imported module or entity. */
Expr getImportedEntity() { result = getChildExpr(1) }
override ControlFlowNode getFirstControlFlowNode() { result = getId() }
override ControlFlowNode getFirstControlFlowNode() { result = getIdentifier() }
}
/**
@ -348,7 +358,7 @@ class TypeDecl extends Identifier, TypeRef, LexicalDecl {
this = any(ClassOrInterface ci).getIdentifier() or
this = any(TypeParameter tp).getIdentifier() or
this = any(ImportSpecifier im).getLocal() or
this = any(ImportEqualsDeclaration im).getId() or
this = any(ImportEqualsDeclaration im).getIdentifier() or
this = any(TypeAliasDeclaration td).getIdentifier() or
this = any(EnumDeclaration ed).getIdentifier() or
this = any(EnumMember member).getIdentifier()
@ -1226,8 +1236,8 @@ abstract class NamespaceRef extends ASTNode { }
*/
class LocalNamespaceDecl extends VarDecl, NamespaceRef {
LocalNamespaceDecl() {
any(NamespaceDeclaration nd).getId() = this or
any(ImportEqualsDeclaration im).getId() = this or
any(NamespaceDeclaration nd).getIdentifier() = this or
any(ImportEqualsDeclaration im).getIdentifier() = this or
any(ImportSpecifier im).getLocal() = this or
any(EnumDeclaration ed).getIdentifier() = this
}
@ -1325,7 +1335,7 @@ class ImportVarTypeAccess extends VarTypeAccess, ImportTypeExpr, @importvartypea
*/
class EnumDeclaration extends NamespaceDefinition, @enumdeclaration, AST::ValueNode {
/** Gets the name of this enum, such as `E` in `enum E { A, B }`. */
Identifier getIdentifier() { result = getChildExpr(0) }
override Identifier getIdentifier() { result = getChildExpr(0) }
/** Gets the name of this enum as a string. */
override string getName() { result = getIdentifier().getName() }

Просмотреть файл

@ -312,8 +312,11 @@ class LocalVariable extends Variable {
this = result.getScope().getAVariable()
or
exists(VarDecl d | d = getADeclaration() |
if d = any(FunctionDeclStmt fds).getId()
then exists(FunctionDeclStmt fds | d = fds.getId() | result = fds.getEnclosingContainer())
if d = any(FunctionDeclStmt fds).getIdentifier()
then
exists(FunctionDeclStmt fds | d = fds.getIdentifier() |
result = fds.getEnclosingContainer()
)
else result = d.getContainer()
)
}

Просмотреть файл

@ -111,7 +111,7 @@ private class AnalyzedNamespaceDeclaration extends DataFlow::AnalyzedValueNode {
AbstractValue getPreviousValue() {
exists(AnalyzedSsaDefinition def |
def.getVariable().getAUse() = astNode.getId() and
def.getVariable().getAUse() = astNode.getIdentifier() and
result = def.getAnRhsValue()
)
}

Просмотреть файл

@ -1,5 +1,5 @@
/**
* Provides classes for modelling cryptographic libraries.
* Provides classes for modeling cryptographic libraries.
*/
import javascript

Просмотреть файл

@ -1,5 +1,5 @@
import javascript
query predicate test_getId(Function f, VarDecl res0, string res1) {
res0 = f.getId() and res1 = f.getName()
res0 = f.getIdentifier() and res1 = f.getName()
}

Просмотреть файл

@ -10,7 +10,7 @@ class ResolveCall extends CallExpr {
string getDeclaredValue() {
result = getVariable().getAnAssignedExpr().getStringValue()
or
exists(NamespaceDeclaration decl | decl.getId() = getVariable().getADeclaration() |
exists(NamespaceDeclaration decl | decl.getIdentifier() = getVariable().getADeclaration() |
result = getNamespaceName(decl)
)
}
@ -21,7 +21,8 @@ string getNamespaceName(NamespaceDeclaration decl) {
or
not decl.getStmt(0).(ExprStmt).getExpr() instanceof ConstantString and
result =
"Namespace " + decl.getId() + " on line " + decl.getFirstToken().getLocation().getStartLine()
"Namespace " + decl.getIdentifier() + " on line " +
decl.getFirstToken().getLocation().getStartLine()
}
from ResolveCall resolve

Просмотреть файл

@ -20,3 +20,6 @@
| tst-IncompleteUrlSubstringSanitization.js:63:4:63:33 | x.index ... !== -1 | '$@' can be anywhere in the URL, and arbitrary hosts may come before or after it. | tst-IncompleteUrlSubstringSanitization.js:63:14:63:25 | "secure.com" | secure.com |
| tst-IncompleteUrlSubstringSanitization.js:64:3:64:26 | x.inclu ... e.com") | '$@' can be anywhere in the URL, and arbitrary hosts may come before or after it. | tst-IncompleteUrlSubstringSanitization.js:64:14:64:25 | "secure.com" | secure.com |
| tst-IncompleteUrlSubstringSanitization.js:66:6:66:29 | x.inclu ... e.com") | '$@' can be anywhere in the URL, and arbitrary hosts may come before or after it. | tst-IncompleteUrlSubstringSanitization.js:66:17:66:28 | "secure.com" | secure.com |
| tst-IncompleteUrlSubstringSanitization.js:73:5:73:48 | x.index ... ") >= 0 | '$@' can be anywhere in the URL, and arbitrary hosts may come before or after it. | tst-IncompleteUrlSubstringSanitization.js:73:15:73:42 | "https: ... oo/bar" | https://secure.com/foo/bar |
| tst-IncompleteUrlSubstringSanitization.js:74:5:74:40 | x.index ... ") >= 0 | '$@' can be anywhere in the URL, and arbitrary hosts may come before or after it. | tst-IncompleteUrlSubstringSanitization.js:74:15:74:34 | "https://secure.com" | https://secure.com |
| tst-IncompleteUrlSubstringSanitization.js:75:5:75:52 | x.index ... ") >= 0 | '$@' can be anywhere in the URL, and arbitrary hosts may come before or after it. | tst-IncompleteUrlSubstringSanitization.js:75:15:75:46 | "https: ... ar-baz" | https://secure.com/foo/bar-baz |

Просмотреть файл

@ -67,5 +67,10 @@
} else {
doSomeThingWithTrustedURL(x);
}
}
x.startsWith("https://secure.com/foo/bar"); // OK - a forward slash after the domain makes prefix checks safe.
x.indexOf("https://secure.com/foo/bar") >= 0 // NOT OK - the url can be anywhere in the string.
x.indexOf("https://secure.com") >= 0 // NOT OK
x.indexOf("https://secure.com/foo/bar-baz") >= 0 // NOT OK - the url can be anywhere in the string.
});

Просмотреть файл

@ -26,7 +26,7 @@ predicate all_defined(ModuleValue exporter) {
}
from ImportStar imp, ModuleValue exporter
where import_star(imp, exporter) and not all_defined(exporter)
where import_star(imp, exporter) and not all_defined(exporter) and not exporter.isAbsent()
select imp,
"Import pollutes the enclosing namespace, as the imported module $@ does not define '__all__'.",
exporter, exporter.getName()

Просмотреть файл

@ -97,8 +97,65 @@ predicate simpleLocalFlowStep(Node nodeFrom, Node nodeTo) {
//--------
// Global flow
//--------
/**
* IPA type for DataFlowCallable.
* A callable is either a callable value or a class.
*/
newtype TDataFlowCallable =
TCallableValue(CallableValue callable) or
TClassValue(ClassValue c)
/** Represents a callable */
class DataFlowCallable = CallableValue;
abstract class DataFlowCallable extends TDataFlowCallable {
/** Gets a textual representation of this element. */
abstract string toString();
/** Gets a call to this callable. */
abstract CallNode getACall();
/** Gets the scope of this callable */
abstract Scope getScope();
/** Gets the specified parameter of this callable */
abstract NameNode getParameter(int n);
/** Gets the name of this callable. */
abstract string getName();
}
class DataFlowCallableValue extends DataFlowCallable, TCallableValue {
CallableValue callable;
DataFlowCallableValue() { this = TCallableValue(callable) }
override string toString() { result = callable.toString() }
override CallNode getACall() { result = callable.getACall() }
override Scope getScope() { result = callable.getScope() }
override NameNode getParameter(int n) { result = callable.getParameter(n) }
override string getName() { result = callable.getName() }
}
class DataFlowClassValue extends DataFlowCallable, TClassValue {
ClassValue c;
DataFlowClassValue() { this = TClassValue(c) }
override string toString() { result = c.toString() }
override CallNode getACall() { result = c.getACall() }
override Scope getScope() { result = c.getScope() }
override NameNode getParameter(int n) {
result.getNode() = c.getScope().getInitMethod().getArg(n + 1).asName()
}
override string getName() { result = c.getName() }
}
/** Represents a call to a callable */
class DataFlowCall extends CallNode {

Просмотреть файл

@ -1,4 +1,4 @@
import callGraphConfig
import experimental.dataflow.callGraphConfig
from DataFlow::Node source, DataFlow::Node sink
where exists(CallGraphConfig cfg | cfg.hasFlow(source, sink))

Просмотреть файл

@ -1,4 +1,4 @@
import callGraphConfig
import experimental.dataflow.callGraphConfig
from DataFlow::Node sink
where exists(CallGraphConfig cfg | cfg.isSink(sink))

Просмотреть файл

@ -1,4 +1,4 @@
import callGraphConfig
import experimental.dataflow.callGraphConfig
from DataFlow::Node source
where exists(CallGraphConfig cfg | cfg.isSource(source))

Просмотреть файл

@ -101,3 +101,5 @@ argHasPostUpdate
| test.py:74:17:74:17 | ControlFlowNode for t | ArgumentNode is missing PostUpdateNode. |
| test.py:81:13:81:13 | ControlFlowNode for t | ArgumentNode is missing PostUpdateNode. |
| test.py:86:13:86:13 | ControlFlowNode for t | ArgumentNode is missing PostUpdateNode. |
| test.py:158:15:158:15 | ControlFlowNode for l | ArgumentNode is missing PostUpdateNode. |
| test.py:159:15:159:15 | ControlFlowNode for d | ArgumentNode is missing PostUpdateNode. |

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -0,0 +1,6 @@
| classes.py:19:12:19:31 | ControlFlowNode for Attribute() | classes.py:19:12:19:31 | ControlFlowNode for Attribute() |
| classes.py:174:7:174:22 | ControlFlowNode for set() | classes.py:174:7:174:22 | ControlFlowNode for set() |
| classes.py:178:7:178:28 | ControlFlowNode for frozenset() | classes.py:178:7:178:28 | ControlFlowNode for frozenset() |
| classes.py:182:7:182:26 | ControlFlowNode for dict() | classes.py:182:7:182:26 | ControlFlowNode for dict() |
| classes.py:303:28:303:51 | ControlFlowNode for dict() | classes.py:303:28:303:51 | ControlFlowNode for dict() |
| classes.py:466:12:466:24 | ControlFlowNode for Attribute() | classes.py:466:12:466:24 | ControlFlowNode for Attribute() |

Просмотреть файл

@ -0,0 +1,10 @@
import experimental.dataflow.callGraphConfig
from DataFlow::Node source, DataFlow::Node sink
where
source.getLocation().getFile().getBaseName() = "classes.py" and
sink.getLocation().getFile().getBaseName() = "classes.py" and
exists(CallGraphConfig cfg | cfg.hasFlow(source, sink))
select source, sink
// Ideally, we would just have 1-step paths either from argument to parameter
// or from return to call. This gives a bit more, so should be rewritten.

Просмотреть файл

@ -1,39 +1,167 @@
edges
| test.py:35:9:35:14 | ControlFlowNode for SOURCE | test.py:36:10:36:10 | ControlFlowNode for x |
| test.py:40:9:40:16 | ControlFlowNode for Str | test.py:41:10:41:10 | ControlFlowNode for x |
| test.py:44:9:44:17 | ControlFlowNode for Str | test.py:45:10:45:10 | ControlFlowNode for x |
| test.py:48:9:48:10 | ControlFlowNode for IntegerLiteral | test.py:49:10:49:10 | ControlFlowNode for x |
| test.py:52:9:52:12 | ControlFlowNode for FloatLiteral | test.py:53:10:53:10 | ControlFlowNode for x |
| test.py:61:10:61:15 | ControlFlowNode for SOURCE | test.py:62:10:62:10 | ControlFlowNode for x |
| test.py:238:28:238:33 | ControlFlowNode for SOURCE | test.py:238:10:238:34 | ControlFlowNode for second() |
| test.py:297:12:297:17 | ControlFlowNode for SOURCE | test.py:297:10:297:18 | ControlFlowNode for f() |
| test.py:301:28:301:33 | ControlFlowNode for SOURCE | test.py:301:10:301:34 | ControlFlowNode for second() |
| datamodel.py:13:1:13:6 | GSSA Variable SOURCE | datamodel.py:38:6:38:17 | ControlFlowNode for f() |
| datamodel.py:13:1:13:6 | GSSA Variable SOURCE | datamodel.py:38:6:38:17 | GSSA Variable SOURCE |
| datamodel.py:13:1:13:6 | GSSA Variable SOURCE | datamodel.py:38:8:38:13 | ControlFlowNode for SOURCE |
| datamodel.py:13:10:13:17 | ControlFlowNode for Str | datamodel.py:13:1:13:6 | GSSA Variable SOURCE |
| datamodel.py:38:6:38:17 | GSSA Variable SOURCE | datamodel.py:65:5:65:7 | ControlFlowNode for C() |
| datamodel.py:38:6:38:17 | GSSA Variable SOURCE | datamodel.py:71:6:71:24 | ControlFlowNode for Attribute() |
| datamodel.py:38:6:38:17 | GSSA Variable SOURCE | datamodel.py:71:6:71:24 | GSSA Variable SOURCE |
| datamodel.py:38:6:38:17 | GSSA Variable SOURCE | datamodel.py:71:15:71:20 | ControlFlowNode for SOURCE |
| datamodel.py:38:8:38:13 | ControlFlowNode for SOURCE | datamodel.py:38:6:38:17 | ControlFlowNode for f() |
| datamodel.py:65:1:65:1 | GSSA Variable c | datamodel.py:71:6:71:24 | ControlFlowNode for Attribute() |
| datamodel.py:65:1:65:1 | GSSA Variable c | datamodel.py:71:6:71:24 | GSSA Variable c |
| datamodel.py:65:5:65:7 | ControlFlowNode for C() | datamodel.py:65:1:65:1 | GSSA Variable c |
| datamodel.py:71:6:71:24 | GSSA Variable SOURCE | datamodel.py:72:6:72:27 | ControlFlowNode for Attribute() |
| datamodel.py:71:6:71:24 | GSSA Variable SOURCE | datamodel.py:72:18:72:23 | ControlFlowNode for SOURCE |
| datamodel.py:71:6:71:24 | GSSA Variable SOURCE | datamodel.py:73:6:73:27 | ControlFlowNode for func_obj() |
| datamodel.py:71:6:71:24 | GSSA Variable SOURCE | datamodel.py:80:6:80:26 | ControlFlowNode for Attribute() |
| datamodel.py:71:6:71:24 | GSSA Variable SOURCE | datamodel.py:80:6:80:26 | GSSA Variable SOURCE |
| datamodel.py:71:6:71:24 | GSSA Variable SOURCE | datamodel.py:80:20:80:25 | ControlFlowNode for SOURCE |
| datamodel.py:71:6:71:24 | GSSA Variable c | datamodel.py:72:6:72:27 | ControlFlowNode for Attribute() |
| datamodel.py:71:6:71:24 | GSSA Variable c | datamodel.py:72:6:72:27 | GSSA Variable c |
| datamodel.py:71:15:71:20 | ControlFlowNode for SOURCE | datamodel.py:71:6:71:24 | ControlFlowNode for Attribute() |
| datamodel.py:72:6:72:27 | GSSA Variable c | datamodel.py:73:6:73:27 | ControlFlowNode for func_obj() |
| datamodel.py:72:6:72:27 | GSSA Variable c | datamodel.py:73:6:73:27 | GSSA Variable c |
| datamodel.py:72:18:72:23 | ControlFlowNode for SOURCE | datamodel.py:72:6:72:27 | ControlFlowNode for Attribute() |
| datamodel.py:73:6:73:27 | GSSA Variable c | datamodel.py:80:6:80:26 | ControlFlowNode for Attribute() |
| datamodel.py:73:6:73:27 | GSSA Variable c | datamodel.py:80:6:80:26 | GSSA Variable c |
| datamodel.py:80:6:80:26 | GSSA Variable SOURCE | datamodel.py:81:6:81:26 | ControlFlowNode for Attribute() |
| datamodel.py:80:6:80:26 | GSSA Variable SOURCE | datamodel.py:81:6:81:26 | GSSA Variable SOURCE |
| datamodel.py:80:6:80:26 | GSSA Variable SOURCE | datamodel.py:81:20:81:25 | ControlFlowNode for SOURCE |
| datamodel.py:80:6:80:26 | GSSA Variable c | datamodel.py:81:6:81:26 | ControlFlowNode for Attribute() |
| datamodel.py:80:6:80:26 | GSSA Variable c | datamodel.py:82:6:82:26 | ControlFlowNode for c_func_obj() |
| datamodel.py:80:6:80:26 | GSSA Variable c | datamodel.py:92:8:92:21 | ControlFlowNode for gen() |
| datamodel.py:80:6:80:26 | GSSA Variable c | datamodel.py:93:6:93:20 | ControlFlowNode for Attribute() |
| datamodel.py:80:6:80:26 | GSSA Variable c | datamodel.py:96:9:96:24 | ControlFlowNode for Attribute() |
| datamodel.py:80:6:80:26 | GSSA Variable c | datamodel.py:96:9:96:24 | GSSA Variable c |
| datamodel.py:80:20:80:25 | ControlFlowNode for SOURCE | datamodel.py:80:6:80:26 | ControlFlowNode for Attribute() |
| datamodel.py:81:6:81:26 | GSSA Variable SOURCE | datamodel.py:82:6:82:26 | ControlFlowNode for c_func_obj() |
| datamodel.py:81:6:81:26 | GSSA Variable SOURCE | datamodel.py:92:8:92:21 | ControlFlowNode for gen() |
| datamodel.py:81:6:81:26 | GSSA Variable SOURCE | datamodel.py:92:8:92:21 | GSSA Variable SOURCE |
| datamodel.py:81:20:81:25 | ControlFlowNode for SOURCE | datamodel.py:81:6:81:26 | ControlFlowNode for Attribute() |
| datamodel.py:92:1:92:4 | GSSA Variable iter | datamodel.py:93:6:93:20 | ControlFlowNode for Attribute() |
| datamodel.py:92:1:92:4 | GSSA Variable iter | datamodel.py:93:6:93:20 | GSSA Variable iter |
| datamodel.py:92:8:92:21 | ControlFlowNode for gen() | datamodel.py:92:1:92:4 | GSSA Variable iter |
| datamodel.py:92:8:92:21 | GSSA Variable SOURCE | datamodel.py:93:6:93:20 | ControlFlowNode for Attribute() |
| datamodel.py:92:8:92:21 | GSSA Variable SOURCE | datamodel.py:96:9:96:24 | ControlFlowNode for Attribute() |
| datamodel.py:92:8:92:21 | GSSA Variable SOURCE | datamodel.py:96:9:96:24 | GSSA Variable SOURCE |
| datamodel.py:93:6:93:20 | GSSA Variable iter | datamodel.py:96:9:96:24 | ControlFlowNode for Attribute() |
| datamodel.py:93:6:93:20 | GSSA Variable iter | datamodel.py:97:6:97:21 | ControlFlowNode for Attribute() |
| datamodel.py:93:6:93:20 | GSSA Variable iter | datamodel.py:106:6:106:30 | ControlFlowNode for Attribute() |
| datamodel.py:93:6:93:20 | GSSA Variable iter | datamodel.py:107:6:107:32 | ControlFlowNode for Attribute() |
| datamodel.py:93:6:93:20 | GSSA Variable iter | datamodel.py:119:6:119:30 | ControlFlowNode for Attribute() |
| datamodel.py:96:1:96:5 | GSSA Variable oiter | datamodel.py:97:6:97:21 | ControlFlowNode for Attribute() |
| datamodel.py:96:1:96:5 | GSSA Variable oiter | datamodel.py:97:6:97:21 | GSSA Variable oiter |
| datamodel.py:96:9:96:24 | ControlFlowNode for Attribute() | datamodel.py:96:1:96:5 | GSSA Variable oiter |
| datamodel.py:96:9:96:24 | GSSA Variable SOURCE | datamodel.py:97:6:97:21 | ControlFlowNode for Attribute() |
| datamodel.py:96:9:96:24 | GSSA Variable SOURCE | datamodel.py:106:18:106:29 | GSSA Variable SOURCE |
| datamodel.py:96:9:96:24 | GSSA Variable c | datamodel.py:97:6:97:21 | ControlFlowNode for Attribute() |
| datamodel.py:96:9:96:24 | GSSA Variable c | datamodel.py:106:6:106:30 | ControlFlowNode for Attribute() |
| datamodel.py:96:9:96:24 | GSSA Variable c | datamodel.py:107:18:107:31 | GSSA Variable c |
| datamodel.py:97:6:97:21 | GSSA Variable oiter | datamodel.py:106:6:106:30 | ControlFlowNode for Attribute() |
| datamodel.py:97:6:97:21 | GSSA Variable oiter | datamodel.py:107:6:107:32 | ControlFlowNode for Attribute() |
| datamodel.py:97:6:97:21 | GSSA Variable oiter | datamodel.py:119:6:119:30 | ControlFlowNode for Attribute() |
| datamodel.py:106:18:106:29 | GSSA Variable SOURCE | datamodel.py:106:6:106:30 | ControlFlowNode for Attribute() |
| datamodel.py:106:18:106:29 | GSSA Variable SOURCE | datamodel.py:107:18:107:31 | GSSA Variable SOURCE |
| datamodel.py:107:18:107:31 | GSSA Variable SOURCE | datamodel.py:107:6:107:32 | ControlFlowNode for Attribute() |
| datamodel.py:107:18:107:31 | GSSA Variable SOURCE | datamodel.py:119:18:119:29 | GSSA Variable SOURCE |
| datamodel.py:107:18:107:31 | GSSA Variable c | datamodel.py:107:6:107:32 | ControlFlowNode for Attribute() |
| datamodel.py:107:18:107:31 | GSSA Variable c | datamodel.py:119:6:119:30 | ControlFlowNode for Attribute() |
| datamodel.py:119:18:119:29 | GSSA Variable SOURCE | datamodel.py:119:6:119:30 | ControlFlowNode for Attribute() |
| test.py:43:9:43:14 | ControlFlowNode for SOURCE | test.py:44:10:44:10 | ControlFlowNode for x |
| test.py:48:9:48:16 | ControlFlowNode for Str | test.py:49:10:49:10 | ControlFlowNode for x |
| test.py:52:9:52:17 | ControlFlowNode for Str | test.py:53:10:53:10 | ControlFlowNode for x |
| test.py:56:9:56:10 | ControlFlowNode for IntegerLiteral | test.py:57:10:57:10 | ControlFlowNode for x |
| test.py:60:9:60:12 | ControlFlowNode for FloatLiteral | test.py:61:10:61:10 | ControlFlowNode for x |
| test.py:69:10:69:15 | ControlFlowNode for SOURCE | test.py:70:10:70:10 | ControlFlowNode for x |
| test.py:246:28:246:33 | ControlFlowNode for SOURCE | test.py:246:10:246:34 | ControlFlowNode for second() |
| test.py:305:12:305:17 | ControlFlowNode for SOURCE | test.py:305:10:305:18 | ControlFlowNode for f() |
| test.py:309:28:309:33 | ControlFlowNode for SOURCE | test.py:309:10:309:34 | ControlFlowNode for second() |
nodes
| test.py:35:9:35:14 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE |
| test.py:36:10:36:10 | ControlFlowNode for x | semmle.label | ControlFlowNode for x |
| test.py:40:9:40:16 | ControlFlowNode for Str | semmle.label | ControlFlowNode for Str |
| test.py:41:10:41:10 | ControlFlowNode for x | semmle.label | ControlFlowNode for x |
| test.py:44:9:44:17 | ControlFlowNode for Str | semmle.label | ControlFlowNode for Str |
| test.py:45:10:45:10 | ControlFlowNode for x | semmle.label | ControlFlowNode for x |
| test.py:48:9:48:10 | ControlFlowNode for IntegerLiteral | semmle.label | ControlFlowNode for IntegerLiteral |
| datamodel.py:13:1:13:6 | GSSA Variable SOURCE | semmle.label | GSSA Variable SOURCE |
| datamodel.py:13:10:13:17 | ControlFlowNode for Str | semmle.label | ControlFlowNode for Str |
| datamodel.py:38:6:38:17 | ControlFlowNode for f() | semmle.label | ControlFlowNode for f() |
| datamodel.py:38:6:38:17 | GSSA Variable SOURCE | semmle.label | GSSA Variable SOURCE |
| datamodel.py:38:8:38:13 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE |
| datamodel.py:65:1:65:1 | GSSA Variable c | semmle.label | GSSA Variable c |
| datamodel.py:65:5:65:7 | ControlFlowNode for C() | semmle.label | ControlFlowNode for C() |
| datamodel.py:71:6:71:24 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() |
| datamodel.py:71:6:71:24 | GSSA Variable SOURCE | semmle.label | GSSA Variable SOURCE |
| datamodel.py:71:6:71:24 | GSSA Variable c | semmle.label | GSSA Variable c |
| datamodel.py:71:15:71:20 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE |
| datamodel.py:72:6:72:27 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() |
| datamodel.py:72:6:72:27 | GSSA Variable c | semmle.label | GSSA Variable c |
| datamodel.py:72:18:72:23 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE |
| datamodel.py:73:6:73:27 | ControlFlowNode for func_obj() | semmle.label | ControlFlowNode for func_obj() |
| datamodel.py:73:6:73:27 | GSSA Variable c | semmle.label | GSSA Variable c |
| datamodel.py:80:6:80:26 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() |
| datamodel.py:80:6:80:26 | GSSA Variable SOURCE | semmle.label | GSSA Variable SOURCE |
| datamodel.py:80:6:80:26 | GSSA Variable c | semmle.label | GSSA Variable c |
| datamodel.py:80:20:80:25 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE |
| datamodel.py:81:6:81:26 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() |
| datamodel.py:81:6:81:26 | GSSA Variable SOURCE | semmle.label | GSSA Variable SOURCE |
| datamodel.py:81:20:81:25 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE |
| datamodel.py:82:6:82:26 | ControlFlowNode for c_func_obj() | semmle.label | ControlFlowNode for c_func_obj() |
| datamodel.py:92:1:92:4 | GSSA Variable iter | semmle.label | GSSA Variable iter |
| datamodel.py:92:8:92:21 | ControlFlowNode for gen() | semmle.label | ControlFlowNode for gen() |
| datamodel.py:92:8:92:21 | GSSA Variable SOURCE | semmle.label | GSSA Variable SOURCE |
| datamodel.py:93:6:93:20 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() |
| datamodel.py:93:6:93:20 | GSSA Variable iter | semmle.label | GSSA Variable iter |
| datamodel.py:96:1:96:5 | GSSA Variable oiter | semmle.label | GSSA Variable oiter |
| datamodel.py:96:9:96:24 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() |
| datamodel.py:96:9:96:24 | GSSA Variable SOURCE | semmle.label | GSSA Variable SOURCE |
| datamodel.py:96:9:96:24 | GSSA Variable c | semmle.label | GSSA Variable c |
| datamodel.py:97:6:97:21 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() |
| datamodel.py:97:6:97:21 | GSSA Variable oiter | semmle.label | GSSA Variable oiter |
| datamodel.py:106:6:106:30 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() |
| datamodel.py:106:18:106:29 | GSSA Variable SOURCE | semmle.label | GSSA Variable SOURCE |
| datamodel.py:107:6:107:32 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() |
| datamodel.py:107:18:107:31 | GSSA Variable SOURCE | semmle.label | GSSA Variable SOURCE |
| datamodel.py:107:18:107:31 | GSSA Variable c | semmle.label | GSSA Variable c |
| datamodel.py:119:6:119:30 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() |
| datamodel.py:119:18:119:29 | GSSA Variable SOURCE | semmle.label | GSSA Variable SOURCE |
| test.py:43:9:43:14 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE |
| test.py:44:10:44:10 | ControlFlowNode for x | semmle.label | ControlFlowNode for x |
| test.py:48:9:48:16 | ControlFlowNode for Str | semmle.label | ControlFlowNode for Str |
| test.py:49:10:49:10 | ControlFlowNode for x | semmle.label | ControlFlowNode for x |
| test.py:52:9:52:12 | ControlFlowNode for FloatLiteral | semmle.label | ControlFlowNode for FloatLiteral |
| test.py:52:9:52:17 | ControlFlowNode for Str | semmle.label | ControlFlowNode for Str |
| test.py:53:10:53:10 | ControlFlowNode for x | semmle.label | ControlFlowNode for x |
| test.py:61:10:61:15 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE |
| test.py:62:10:62:10 | ControlFlowNode for x | semmle.label | ControlFlowNode for x |
| test.py:238:10:238:34 | ControlFlowNode for second() | semmle.label | ControlFlowNode for second() |
| test.py:238:28:238:33 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE |
| test.py:297:10:297:18 | ControlFlowNode for f() | semmle.label | ControlFlowNode for f() |
| test.py:297:12:297:17 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE |
| test.py:301:10:301:34 | ControlFlowNode for second() | semmle.label | ControlFlowNode for second() |
| test.py:301:28:301:33 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE |
| test.py:56:9:56:10 | ControlFlowNode for IntegerLiteral | semmle.label | ControlFlowNode for IntegerLiteral |
| test.py:57:10:57:10 | ControlFlowNode for x | semmle.label | ControlFlowNode for x |
| test.py:60:9:60:12 | ControlFlowNode for FloatLiteral | semmle.label | ControlFlowNode for FloatLiteral |
| test.py:61:10:61:10 | ControlFlowNode for x | semmle.label | ControlFlowNode for x |
| test.py:69:10:69:15 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE |
| test.py:70:10:70:10 | ControlFlowNode for x | semmle.label | ControlFlowNode for x |
| test.py:246:10:246:34 | ControlFlowNode for second() | semmle.label | ControlFlowNode for second() |
| test.py:246:28:246:33 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE |
| test.py:305:10:305:18 | ControlFlowNode for f() | semmle.label | ControlFlowNode for f() |
| test.py:305:12:305:17 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE |
| test.py:309:10:309:34 | ControlFlowNode for second() | semmle.label | ControlFlowNode for second() |
| test.py:309:28:309:33 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE |
#select
| test.py:36:10:36:10 | ControlFlowNode for x | test.py:35:9:35:14 | ControlFlowNode for SOURCE | test.py:36:10:36:10 | ControlFlowNode for x | <message> |
| test.py:41:10:41:10 | ControlFlowNode for x | test.py:40:9:40:16 | ControlFlowNode for Str | test.py:41:10:41:10 | ControlFlowNode for x | <message> |
| test.py:45:10:45:10 | ControlFlowNode for x | test.py:44:9:44:17 | ControlFlowNode for Str | test.py:45:10:45:10 | ControlFlowNode for x | <message> |
| test.py:49:10:49:10 | ControlFlowNode for x | test.py:48:9:48:10 | ControlFlowNode for IntegerLiteral | test.py:49:10:49:10 | ControlFlowNode for x | <message> |
| test.py:53:10:53:10 | ControlFlowNode for x | test.py:52:9:52:12 | ControlFlowNode for FloatLiteral | test.py:53:10:53:10 | ControlFlowNode for x | <message> |
| test.py:62:10:62:10 | ControlFlowNode for x | test.py:61:10:61:15 | ControlFlowNode for SOURCE | test.py:62:10:62:10 | ControlFlowNode for x | <message> |
| test.py:238:10:238:34 | ControlFlowNode for second() | test.py:238:28:238:33 | ControlFlowNode for SOURCE | test.py:238:10:238:34 | ControlFlowNode for second() | <message> |
| test.py:297:10:297:18 | ControlFlowNode for f() | test.py:297:12:297:17 | ControlFlowNode for SOURCE | test.py:297:10:297:18 | ControlFlowNode for f() | <message> |
| test.py:301:10:301:34 | ControlFlowNode for second() | test.py:301:28:301:33 | ControlFlowNode for SOURCE | test.py:301:10:301:34 | ControlFlowNode for second() | <message> |
| datamodel.py:38:6:38:17 | ControlFlowNode for f() | datamodel.py:13:10:13:17 | ControlFlowNode for Str | datamodel.py:38:6:38:17 | ControlFlowNode for f() | <message> |
| datamodel.py:38:6:38:17 | ControlFlowNode for f() | datamodel.py:38:8:38:13 | ControlFlowNode for SOURCE | datamodel.py:38:6:38:17 | ControlFlowNode for f() | <message> |
| datamodel.py:71:6:71:24 | ControlFlowNode for Attribute() | datamodel.py:13:10:13:17 | ControlFlowNode for Str | datamodel.py:71:6:71:24 | ControlFlowNode for Attribute() | <message> |
| datamodel.py:71:6:71:24 | ControlFlowNode for Attribute() | datamodel.py:71:15:71:20 | ControlFlowNode for SOURCE | datamodel.py:71:6:71:24 | ControlFlowNode for Attribute() | <message> |
| datamodel.py:72:6:72:27 | ControlFlowNode for Attribute() | datamodel.py:13:10:13:17 | ControlFlowNode for Str | datamodel.py:72:6:72:27 | ControlFlowNode for Attribute() | <message> |
| datamodel.py:72:6:72:27 | ControlFlowNode for Attribute() | datamodel.py:72:18:72:23 | ControlFlowNode for SOURCE | datamodel.py:72:6:72:27 | ControlFlowNode for Attribute() | <message> |
| datamodel.py:73:6:73:27 | ControlFlowNode for func_obj() | datamodel.py:13:10:13:17 | ControlFlowNode for Str | datamodel.py:73:6:73:27 | ControlFlowNode for func_obj() | <message> |
| datamodel.py:80:6:80:26 | ControlFlowNode for Attribute() | datamodel.py:13:10:13:17 | ControlFlowNode for Str | datamodel.py:80:6:80:26 | ControlFlowNode for Attribute() | <message> |
| datamodel.py:80:6:80:26 | ControlFlowNode for Attribute() | datamodel.py:80:20:80:25 | ControlFlowNode for SOURCE | datamodel.py:80:6:80:26 | ControlFlowNode for Attribute() | <message> |
| datamodel.py:81:6:81:26 | ControlFlowNode for Attribute() | datamodel.py:13:10:13:17 | ControlFlowNode for Str | datamodel.py:81:6:81:26 | ControlFlowNode for Attribute() | <message> |
| datamodel.py:81:6:81:26 | ControlFlowNode for Attribute() | datamodel.py:81:20:81:25 | ControlFlowNode for SOURCE | datamodel.py:81:6:81:26 | ControlFlowNode for Attribute() | <message> |
| datamodel.py:82:6:82:26 | ControlFlowNode for c_func_obj() | datamodel.py:13:10:13:17 | ControlFlowNode for Str | datamodel.py:82:6:82:26 | ControlFlowNode for c_func_obj() | <message> |
| datamodel.py:93:6:93:20 | ControlFlowNode for Attribute() | datamodel.py:13:10:13:17 | ControlFlowNode for Str | datamodel.py:93:6:93:20 | ControlFlowNode for Attribute() | <message> |
| datamodel.py:97:6:97:21 | ControlFlowNode for Attribute() | datamodel.py:13:10:13:17 | ControlFlowNode for Str | datamodel.py:97:6:97:21 | ControlFlowNode for Attribute() | <message> |
| datamodel.py:106:6:106:30 | ControlFlowNode for Attribute() | datamodel.py:13:10:13:17 | ControlFlowNode for Str | datamodel.py:106:6:106:30 | ControlFlowNode for Attribute() | <message> |
| datamodel.py:107:6:107:32 | ControlFlowNode for Attribute() | datamodel.py:13:10:13:17 | ControlFlowNode for Str | datamodel.py:107:6:107:32 | ControlFlowNode for Attribute() | <message> |
| datamodel.py:119:6:119:30 | ControlFlowNode for Attribute() | datamodel.py:13:10:13:17 | ControlFlowNode for Str | datamodel.py:119:6:119:30 | ControlFlowNode for Attribute() | <message> |
| test.py:44:10:44:10 | ControlFlowNode for x | test.py:43:9:43:14 | ControlFlowNode for SOURCE | test.py:44:10:44:10 | ControlFlowNode for x | <message> |
| test.py:49:10:49:10 | ControlFlowNode for x | test.py:48:9:48:16 | ControlFlowNode for Str | test.py:49:10:49:10 | ControlFlowNode for x | <message> |
| test.py:53:10:53:10 | ControlFlowNode for x | test.py:52:9:52:17 | ControlFlowNode for Str | test.py:53:10:53:10 | ControlFlowNode for x | <message> |
| test.py:57:10:57:10 | ControlFlowNode for x | test.py:56:9:56:10 | ControlFlowNode for IntegerLiteral | test.py:57:10:57:10 | ControlFlowNode for x | <message> |
| test.py:61:10:61:10 | ControlFlowNode for x | test.py:60:9:60:12 | ControlFlowNode for FloatLiteral | test.py:61:10:61:10 | ControlFlowNode for x | <message> |
| test.py:70:10:70:10 | ControlFlowNode for x | test.py:69:10:69:15 | ControlFlowNode for SOURCE | test.py:70:10:70:10 | ControlFlowNode for x | <message> |
| test.py:246:10:246:34 | ControlFlowNode for second() | test.py:246:28:246:33 | ControlFlowNode for SOURCE | test.py:246:10:246:34 | ControlFlowNode for second() | <message> |
| test.py:305:10:305:18 | ControlFlowNode for f() | test.py:305:12:305:17 | ControlFlowNode for SOURCE | test.py:305:10:305:18 | ControlFlowNode for f() | <message> |
| test.py:309:10:309:34 | ControlFlowNode for second() | test.py:309:28:309:33 | ControlFlowNode for SOURCE | test.py:309:10:309:34 | ControlFlowNode for second() | <message> |

Просмотреть файл

@ -0,0 +1,159 @@
# User-defined methods, both instance methods and class methods, can be called in many non-standard ways
# i.e. differently from simply `c.f()` or `C.f()`. For example, a user-defined `__await__` method on a
# class `C` will be called by the syntactic construct `await c` when `c` is an instance of `C`.
#
# These tests are based on the first part of https://docs.python.org/3/reference/datamodel.html.
# A thorough covering of methods in that document is found in classes.py.
#
# Intended sources should be the variable `SOURCE` and intended sinks should be
# arguments to the function `SINK` (see python/ql/test/experimental/dataflow/testConfig.qll).
# These are defined so that we can evaluate the test code.
NONSOURCE = "not a source"
SOURCE = "source"
def is_source(x):
return x == "source" or x == b"source" or x == 42 or x == 42.0 or x == 42j
def SINK(x):
if is_source(x):
print("OK")
else:
print("Unexpected flow", x)
def SINK_F(x):
if is_source(x):
print("Unexpected flow", x)
else:
print("OK")
# Callable types
# These are the types to which the function call operation (see section Calls) can be applied:
# User-defined functions
# A user-defined function object is created by a function definition (see section Function definitions). It should be called with an argument list containing the same number of items as the function's formal parameter list.
def f(a, b):
return a
SINK(f(SOURCE, 3))
# Instance methods
# An instance method object combines a class, a class instance and any callable object (normally a user-defined function).
class C(object):
def method(self, x, cls):
assert cls is self.__class__
return x
@classmethod
def classmethod(cls, x):
return x
@staticmethod
def staticmethod(x):
return x
def gen(self, x, count):
n = count
while n > 0:
yield x
n -= 1
async def coro(self, x):
return x
c = C()
# When an instance method object is created by retrieving a user-defined function object from a class via one of its instances, its __self__ attribute is the instance, and the method object is said to be bound. The new methods __func__ attribute is the original function object.
func_obj = c.method.__func__
# When an instance method object is called, the underlying function (__func__) is called, inserting the class instance (__self__) in front of the argument list. For instance, when C is a class which contains a definition for a function f(), and x is an instance of C, calling x.f(1) is equivalent to calling C.f(x, 1).
SINK(c.method(SOURCE, C))
SINK(C.method(c, SOURCE, C))
SINK(func_obj(c, SOURCE, C))
# When an instance method object is created by retrieving a class method object from a class or instance, its __self__ attribute is the class itself, and its __func__ attribute is the function object underlying the class method.
c_func_obj = C.classmethod.__func__
# When an instance method object is derived from a class method object, the “class instance” stored in __self__ will actually be the class itself, so that calling either x.f(1) or C.f(1) is equivalent to calling f(C,1) where f is the underlying function.
SINK(c.classmethod(SOURCE))
SINK(C.classmethod(SOURCE))
SINK(c_func_obj(C, SOURCE))
# Generator functions
# A function or method which uses the yield statement (see section The yield statement) is called a generator function. Such a function, when called, always returns an iterator object which can be used to execute the body of the function: calling the iterators iterator.__next__() method will cause the function to execute until it provides a value using the yield statement. When the function executes a return statement or falls off the end, a StopIteration exception is raised and the iterator will have reached the end of the set of values to be returned.
def gen(x, count):
n = count
while n > 0:
yield x
n -= 1
iter = gen(SOURCE, 1)
SINK(iter.__next__())
# SINK_F(iter.__next__()) # throws StopIteration, FP
oiter = c.gen(SOURCE, 1)
SINK(oiter.__next__())
# SINK_F(oiter.__next__()) # throws StopIteration, FP
# Coroutine functions
# A function or method which is defined using async def is called a coroutine function. Such a function, when called, returns a coroutine object. It may contain await expressions, as well as async with and async for statements. See also the Coroutine Objects section.
async def coro(x):
return x
import asyncio
SINK(asyncio.run(coro(SOURCE)))
SINK(asyncio.run(c.coro(SOURCE)))
class A:
def __await__(self):
# yield SOURCE -- see https://groups.google.com/g/dev-python/c/_lrrc-vp9TI?pli=1
return (yield from asyncio.coroutine(lambda: SOURCE)())
async def agen(x):
a = A()
return await a
SINK(asyncio.run(agen(SOURCE)))
# Asynchronous generator functions
# A function or method which is defined using async def and which uses the yield statement is called a asynchronous generator function. Such a function, when called, returns an asynchronous iterator object which can be used in an async for statement to execute the body of the function.
# Calling the asynchronous iterators aiterator.__anext__() method will return an awaitable which when awaited will execute until it provides a value using the yield expression. When the function executes an empty return statement or falls off the end, a StopAsyncIteration exception is raised and the asynchronous iterator will have reached the end of the set of values to be yielded.
# Built-in functions
# A built-in function object is a wrapper around a C function. Examples of built-in functions are len() and math.sin() (math is a standard built-in module). The number and type of the arguments are determined by the C function. Special read-only attributes: __doc__ is the functions documentation string, or None if unavailable; __name__ is the functions name; __self__ is set to None (but see the next item); __module__ is the name of the module the function was defined in or None if unavailable.
# Built-in methods
# This is really a different disguise of a built-in function, this time containing an object passed to the C function as an implicit extra argument. An example of a built-in method is alist.append(), assuming alist is a list object. In this case, the special read-only attribute __self__ is set to the object denoted by alist.
# Classes
# Classes are callable. These objects normally act as factories for new instances of themselves, but variations are possible for class types that override __new__(). The arguments of the call are passed to __new__() and, in the typical case, to __init__() to initialize the new instance.
# Class Instances
# Instances of arbitrary classes can be made callable by defining a __call__() method in their class.
# If a class sets __iter__() to None, calling iter() on its instances will raise a TypeError (without falling back to __getitem__()).
# 3.3.1. Basic customization
class Customized:
a = NONSOURCE
b = NONSOURCE
def __new__(cls):
cls.a = SOURCE
return super().__new__(cls)
def __init__(self):
self.b = SOURCE
# testing __new__ and __init__
customized = Customized()
SINK(Customized.a)
SINK_F(Customized.b)
SINK(customized.a)
SINK(customized.b)

Просмотреть файл

@ -1,7 +1,7 @@
| test.py:24:5:24:5 | SSA variable x | test.py:23:1:23:33 | Exit node for Function test_tuple_with_local_flow |
| test.py:24:5:24:5 | SSA variable x | test.py:25:9:25:9 | ControlFlowNode for x |
| test.py:24:10:24:26 | ControlFlowNode for Tuple | test.py:24:5:24:5 | SSA variable x |
| test.py:25:5:25:5 | SSA variable y | test.py:26:5:26:11 | SSA variable y |
| test.py:25:5:25:5 | SSA variable y | test.py:26:10:26:10 | ControlFlowNode for y |
| test.py:25:9:25:12 | ControlFlowNode for Subscript | test.py:25:5:25:5 | SSA variable y |
| test.py:26:5:26:11 | SSA variable y | test.py:23:1:23:33 | Exit node for Function test_tuple_with_local_flow |
| test.py:32:5:32:5 | SSA variable x | test.py:31:1:31:33 | Exit node for Function test_tuple_with_local_flow |
| test.py:32:5:32:5 | SSA variable x | test.py:33:9:33:9 | ControlFlowNode for x |
| test.py:32:10:32:26 | ControlFlowNode for Tuple | test.py:32:5:32:5 | SSA variable x |
| test.py:33:5:33:5 | SSA variable y | test.py:34:5:34:11 | SSA variable y |
| test.py:33:5:33:5 | SSA variable y | test.py:34:10:34:10 | ControlFlowNode for y |
| test.py:33:9:33:12 | ControlFlowNode for Subscript | test.py:33:5:33:5 | SSA variable y |
| test.py:34:5:34:11 | SSA variable y | test.py:31:1:31:33 | Exit node for Function test_tuple_with_local_flow |

Просмотреть файл

@ -6,19 +6,27 @@
#
# Functions whose name ends with "_with_local_flow" will also be tested for local flow.
#
# All functions starting with "test_" should run and either
# - print a source (sources are defined in testConfig.qll).
# - print "Unexpected flow: " and a non-source
# (The idea is to later write a script to autimatically confirm this.)
# All functions starting with "test_" should run and print `"OK"`.
# This can be checked by running validTest.py.
# These are defined so that we can evaluate the test code.
NONSOURCE = "not a source"
SOURCE = "source"
def is_source(x):
return x == "source" or x == b"source" or x == 42 or x == 42.0 or x == 42j
def SINK(x):
print(x)
if is_source(x):
print("OK")
else:
print("Unexpected flow", x)
def SINK_F(x):
print("Unexpected flow: ", x)
if is_source(x):
print("Unexpected flow", x)
else:
print("OK")
def test_tuple_with_local_flow():
x = (NONSOURCE, SOURCE)

Просмотреть файл

@ -0,0 +1,49 @@
def check_output(s, f):
if s == "OK\n":
pass
else:
raise RuntimeError("Function failed", s, f)
def check_test_function(f):
from io import StringIO
import sys
capturer = StringIO()
old_stdout = sys.stdout
sys.stdout = capturer
f()
sys.stdout = old_stdout
check_output(capturer.getvalue(), f)
def check_async_test_function(f):
from io import StringIO
import sys
import asyncio
capturer = StringIO()
old_stdout = sys.stdout
sys.stdout = capturer
asyncio.run(f())
sys.stdout = old_stdout
check_output(capturer.getvalue(), f)
def check_tests_valid(testFile):
import importlib
tests = importlib.import_module(testFile)
for i in dir(tests):
# print("Considering", i)
if i.startswith("test_"):
item = getattr(tests,i)
if callable(item):
print("Checking", testFile, item)
check_test_function(item)
elif i.startswith("atest_"):
item = getattr(tests,i)
if callable(item):
print("Checking", testFile, item)
check_async_test_function(item)
if __name__ == '__main__':
check_tests_valid("classes")
check_tests_valid("test")

Просмотреть файл

@ -1,2 +1,3 @@
| imports_test.py:21:1:21:20 | from module import * | Using 'from ... import *' pollutes the namespace |
| imports_test.py:22:1:22:32 | from module_without_all import * | Using 'from ... import *' pollutes the namespace |
| imports_test.py:65:1:65:40 | from module_that_does_not_exist import * | Using 'from ... import *' pollutes the namespace |

Просмотреть файл

@ -61,3 +61,5 @@ import module1 as different
#Use it
different
# FP reported in https://github.com/github/codeql/issues/4003
from module_that_does_not_exist import *