mirror of
https://github.com/github/codeql.git
synced 2025-12-20 18:56:32 +01:00
Merge remote-tracking branch 'upstream/master' into dataflow-partial-chi
Conflicts: cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll cpp/ql/test/library-tests/dataflow/DefaultTaintTracking/tainted.expected
This commit is contained in:
@@ -8,6 +8,7 @@ The following changes in version 1.24 affect C/C++ analysis in all applications.
|
|||||||
|
|
||||||
| **Query** | **Tags** | **Purpose** |
|
| **Query** | **Tags** | **Purpose** |
|
||||||
|-----------------------------|-----------|--------------------------------------------------------------------|
|
|-----------------------------|-----------|--------------------------------------------------------------------|
|
||||||
|
| Implicit function declarations (`cpp/Likely Bugs/Underspecified Functions/ImplicitFunctionDeclaration.ql`) | correctness, maintainability | This query finds calls to undeclared functions that are compiled by a C compiler. Results are shown on LGTM by default. |
|
||||||
|
|
||||||
## Changes to existing queries
|
## Changes to existing queries
|
||||||
|
|
||||||
@@ -39,4 +40,4 @@ The following changes in version 1.24 affect C/C++ analysis in all applications.
|
|||||||
* The taint tracking library (`semmle.code.cpp.dataflow.TaintTracking`) has had
|
* The taint tracking library (`semmle.code.cpp.dataflow.TaintTracking`) has had
|
||||||
the following improvements:
|
the following improvements:
|
||||||
* The library now models data flow through `strdup` and similar functions.
|
* The library now models data flow through `strdup` and similar functions.
|
||||||
|
* The library now models data flow through formatting functions such as `sprintf`.
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ The following changes in version 1.24 affect C# analysis in all applications.
|
|||||||
| **Query** | **Expected impact** | **Change** |
|
| **Query** | **Expected impact** | **Change** |
|
||||||
|------------------------------|------------------------|-----------------------------------|
|
|------------------------------|------------------------|-----------------------------------|
|
||||||
| Useless assignment to local variable (`cs/useless-assignment-to-local`) | Fewer false positive results | Results have been removed when the variable is named `_` in a `foreach` statement. |
|
| Useless assignment to local variable (`cs/useless-assignment-to-local`) | Fewer false positive results | Results have been removed when the variable is named `_` in a `foreach` statement. |
|
||||||
|
| Dereferenced variable may be null (`cs/dereferenced-value-may-be-null`) | More results | Results are reported from parameters with a default value of `null`. |
|
||||||
|
|
||||||
## Removal of old queries
|
## Removal of old queries
|
||||||
|
|
||||||
|
|||||||
@@ -10,15 +10,25 @@ The following changes in version 1.24 affect Java analysis in all applications.
|
|||||||
|
|
||||||
| **Query** | **Tags** | **Purpose** |
|
| **Query** | **Tags** | **Purpose** |
|
||||||
|-----------------------------|-----------|--------------------------------------------------------------------|
|
|-----------------------------|-----------|--------------------------------------------------------------------|
|
||||||
|
| Disabled Spring CSRF protection (`java/spring-disabled-csrf-protection`) | security, external/cwe/cwe-352 | Finds disabled Cross-Site Request Forgery (CSRF) protection in Spring. |
|
||||||
| Failure to use HTTPS or SFTP URL in Maven artifact upload/download (`java/maven/non-https-url`) | security, external/cwe/cwe-300, external/cwe/cwe-319, external/cwe/cwe-494, external/cwe/cwe-829 | Finds use of insecure protocols during Maven dependency resolution. Results are shown on LGTM by default. |
|
| Failure to use HTTPS or SFTP URL in Maven artifact upload/download (`java/maven/non-https-url`) | security, external/cwe/cwe-300, external/cwe/cwe-319, external/cwe/cwe-494, external/cwe/cwe-829 | Finds use of insecure protocols during Maven dependency resolution. Results are shown on LGTM by default. |
|
||||||
|
| Left shift by more than the type width (`java/lshift-larger-than-type-width`) | correctness | Finds left shifts of ints by 32 bits or more and left shifts of longs by 64 bits or more. Results are shown on LGTM by default. |
|
||||||
|
| Suspicious date format (`java/suspicious-date-format`) | correctness | Finds date format patterns that use placeholders that are likely to be incorrect. |
|
||||||
|
|
||||||
## Changes to existing queries
|
## Changes to existing queries
|
||||||
|
|
||||||
| **Query** | **Expected impact** | **Change** |
|
| **Query** | **Expected impact** | **Change** |
|
||||||
|------------------------------|------------------------|-----------------------------------|
|
|------------------------------|------------------------|-----------------------------------|
|
||||||
| Dereferenced variable may be null (`java/dereferenced-value-may-be-null`) | Fewer false positives | Final fields with a non-null initializer are no longer reported. |
|
| Dereferenced variable may be null (`java/dereferenced-value-may-be-null`) | Fewer false positives | Final fields with a non-null initializer are no longer reported. |
|
||||||
| Expression always evaluates to the same value (`java/evaluation-to-constant`) | Fewer false positives | Expressions of the form `0 * x` are usually intended and no longer reported. |
|
| Expression always evaluates to the same value (`java/evaluation-to-constant`) | Fewer false positives | Expressions of the form `0 * x` are usually intended and no longer reported. Also left shift of ints by 32 bits and longs by 64 bits are no longer reported as they are not constant, these results are instead reported by the new query `java/lshift-larger-than-type-width`. |
|
||||||
| Useless null check (`java/useless-null-check`) | More true positives | Useless checks on final fields with a non-null initializer are now reported. |
|
| Useless null check (`java/useless-null-check`) | More true positives | Useless checks on final fields with a non-null initializer are now reported. |
|
||||||
|
|
||||||
## Changes to libraries
|
## Changes to libraries
|
||||||
|
|
||||||
|
* Identification of test classes has been improved. Previously, one of the
|
||||||
|
match conditions would classify any class with a name containing the string
|
||||||
|
"Test" as a test class, but now this matching has been replaced with one that
|
||||||
|
looks for the occurrence of actual unit-test annotations. This affects the
|
||||||
|
general file classification mechanism and thus suppression of alerts, and
|
||||||
|
also any security queries using taint tracking, as test classes act as
|
||||||
|
default barriers stopping taint flow.
|
||||||
|
|||||||
@@ -13,6 +13,11 @@
|
|||||||
- [react](https://www.npmjs.com/package/react)
|
- [react](https://www.npmjs.com/package/react)
|
||||||
- [typeahead.js](https://www.npmjs.com/package/typeahead.js)
|
- [typeahead.js](https://www.npmjs.com/package/typeahead.js)
|
||||||
- [Handlebars](https://www.npmjs.com/package/handlebars)
|
- [Handlebars](https://www.npmjs.com/package/handlebars)
|
||||||
|
- [Electron](https://electronjs.org/)
|
||||||
|
- [Node.js](https://nodejs.org/)
|
||||||
|
- [Socket.IO](https://socket.io/)
|
||||||
|
- [ws](https://github.com/websockets/ws)
|
||||||
|
- [WebSocket](https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API)
|
||||||
|
|
||||||
## New queries
|
## New queries
|
||||||
|
|
||||||
@@ -33,7 +38,9 @@
|
|||||||
| Unbound event handler receiver (`js/unbound-event-handler-receiver`) | Fewer false positive results | This query now recognizes additional ways event handler receivers can be bound. |
|
| Unbound event handler receiver (`js/unbound-event-handler-receiver`) | Fewer false positive results | This query now recognizes additional ways event handler receivers can be bound. |
|
||||||
| Expression has no effect (`js/useless-expression`) | Fewer false positive results | The query now recognizes block-level flow type annotations and ignores the first statement of a try block. |
|
| Expression has no effect (`js/useless-expression`) | Fewer false positive results | The query now recognizes block-level flow type annotations and ignores the first statement of a try block. |
|
||||||
| Use of call stack introspection in strict mode (`js/strict-mode-call-stack-introspection`) | Fewer false positive results | The query no longer flags expression statements. |
|
| Use of call stack introspection in strict mode (`js/strict-mode-call-stack-introspection`) | Fewer false positive results | The query no longer flags expression statements. |
|
||||||
|
| Missing CSRF middleware (`js/missing-token-validation`) | Fewer false positive results | The query reports fewer duplicates and only flags handlers that explicitly access cookie data. |
|
||||||
|
|
||||||
## Changes to libraries
|
## Changes to libraries
|
||||||
|
|
||||||
* The predicates `RegExpTerm.getSuccessor` and `RegExpTerm.getPredecessor` have been changed to reflect textual, not operational, matching order. This only makes a difference in lookbehind assertions, which are operationally matched backwards. Previously, `getSuccessor` would mimick this, so in an assertion `(?<=ab)` the term `b` would be considered the predecessor, not the successor, of `a`. Textually, however, `a` is still matched before `b`, and this is the order we now follow.
|
* The predicates `RegExpTerm.getSuccessor` and `RegExpTerm.getPredecessor` have been changed to reflect textual, not operational, matching order. This only makes a difference in lookbehind assertions, which are operationally matched backwards. Previously, `getSuccessor` would mimick this, so in an assertion `(?<=ab)` the term `b` would be considered the predecessor, not the successor, of `a`. Textually, however, `a` is still matched before `b`, and this is the order we now follow.
|
||||||
|
* An extensible model of the `EventEmitter` pattern has been implemented.
|
||||||
|
|||||||
@@ -18,6 +18,7 @@
|
|||||||
+ semmlecode-cpp-queries/Likely Bugs/Likely Typos/ExprHasNoEffect.ql: /Correctness/Common Errors
|
+ semmlecode-cpp-queries/Likely Bugs/Likely Typos/ExprHasNoEffect.ql: /Correctness/Common Errors
|
||||||
+ semmlecode-cpp-queries/Likely Bugs/Underspecified Functions/TooFewArguments.ql: /Correctness/Common Errors
|
+ semmlecode-cpp-queries/Likely Bugs/Underspecified Functions/TooFewArguments.ql: /Correctness/Common Errors
|
||||||
+ semmlecode-cpp-queries/Likely Bugs/Underspecified Functions/TooManyArguments.ql: /Correctness/Common Errors
|
+ semmlecode-cpp-queries/Likely Bugs/Underspecified Functions/TooManyArguments.ql: /Correctness/Common Errors
|
||||||
|
+ semmlecode-cpp-queries/Likely Bugs/Underspecified Functions/ImplicitFunctionDeclaration.ql: /Correctness/Common Errors
|
||||||
+ semmlecode-cpp-queries/Likely Bugs/Likely Typos/ShortCircuitBitMask.ql: /Correctness/Common Errors
|
+ semmlecode-cpp-queries/Likely Bugs/Likely Typos/ShortCircuitBitMask.ql: /Correctness/Common Errors
|
||||||
+ semmlecode-cpp-queries/Likely Bugs/Likely Typos/MissingEnumCaseInSwitch.ql: /Correctness/Common Errors
|
+ semmlecode-cpp-queries/Likely Bugs/Likely Typos/MissingEnumCaseInSwitch.ql: /Correctness/Common Errors
|
||||||
+ semmlecode-cpp-queries/Likely Bugs/Arithmetic/FloatComparison.ql: /Correctness/Common Errors
|
+ semmlecode-cpp-queries/Likely Bugs/Arithmetic/FloatComparison.ql: /Correctness/Common Errors
|
||||||
|
|||||||
@@ -19,6 +19,7 @@
|
|||||||
+ semmlecode-cpp-queries/Likely Bugs/Likely Typos/ExprHasNoEffect.ql: /Correctness/Common Errors
|
+ semmlecode-cpp-queries/Likely Bugs/Likely Typos/ExprHasNoEffect.ql: /Correctness/Common Errors
|
||||||
+ semmlecode-cpp-queries/Likely Bugs/Underspecified Functions/TooFewArguments.ql: /Correctness/Common Errors
|
+ semmlecode-cpp-queries/Likely Bugs/Underspecified Functions/TooFewArguments.ql: /Correctness/Common Errors
|
||||||
+ semmlecode-cpp-queries/Likely Bugs/Underspecified Functions/TooManyArguments.ql: /Correctness/Common Errors
|
+ semmlecode-cpp-queries/Likely Bugs/Underspecified Functions/TooManyArguments.ql: /Correctness/Common Errors
|
||||||
|
+ semmlecode-cpp-queries/Likely Bugs/Underspecified Functions/ImplicitFunctionDeclaration.ql: /Correctness/Common Errors
|
||||||
+ semmlecode-cpp-queries/Likely Bugs/Likely Typos/ShortCircuitBitMask.ql: /Correctness/Common Errors
|
+ semmlecode-cpp-queries/Likely Bugs/Likely Typos/ShortCircuitBitMask.ql: /Correctness/Common Errors
|
||||||
+ semmlecode-cpp-queries/Likely Bugs/Likely Typos/MissingEnumCaseInSwitch.ql: /Correctness/Common Errors
|
+ semmlecode-cpp-queries/Likely Bugs/Likely Typos/MissingEnumCaseInSwitch.ql: /Correctness/Common Errors
|
||||||
+ semmlecode-cpp-queries/Likely Bugs/Arithmetic/FloatComparison.ql: /Correctness/Common Errors
|
+ semmlecode-cpp-queries/Likely Bugs/Arithmetic/FloatComparison.ql: /Correctness/Common Errors
|
||||||
|
|||||||
@@ -0,0 +1,8 @@
|
|||||||
|
/* '#include <stdlib.h>' was forgotton */
|
||||||
|
|
||||||
|
int main(void) {
|
||||||
|
/* 'int malloc()' assumed */
|
||||||
|
unsigned char *p = malloc(100);
|
||||||
|
*p = 'a';
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
<!DOCTYPE qhelp PUBLIC
|
||||||
|
"-//Semmle//qhelp//EN"
|
||||||
|
"qhelp.dtd">
|
||||||
|
<qhelp>
|
||||||
|
|
||||||
|
|
||||||
|
<overview>
|
||||||
|
<p>A function is called without a prior function declaration or definition.
|
||||||
|
When this happens, the compiler generates an implicit declaration of the function,
|
||||||
|
specifying an integer return type and no parameters.
|
||||||
|
If the implicit declaration does not match the true signature of the function, the
|
||||||
|
function may behave unpredictably.</p>
|
||||||
|
|
||||||
|
<p>This may indicate a misspelled function name, or that the required header containing
|
||||||
|
the function declaration has not been included.</p>
|
||||||
|
|
||||||
|
</overview>
|
||||||
|
<recommendation>
|
||||||
|
<p>Provide an explicit declaration of the function before invoking it.</p>
|
||||||
|
|
||||||
|
</recommendation>
|
||||||
|
<example><sample src="ImplicitFunctionDeclaration.c" />
|
||||||
|
|
||||||
|
</example>
|
||||||
|
|
||||||
|
<references>
|
||||||
|
<li>SEI CERT C Coding Standard: <a href="https://wiki.sei.cmu.edu/confluence/display/c/DCL31-C.+Declare+identifiers+before+using+them">DCL31-C. Declare identifiers before using them</a></li>
|
||||||
|
</references>
|
||||||
|
</qhelp>
|
||||||
@@ -0,0 +1,48 @@
|
|||||||
|
/**
|
||||||
|
* @name Implicit function declaration
|
||||||
|
* @description An implicitly declared function is assumed to take no
|
||||||
|
* arguments and return an integer. If this assumption does not hold, it
|
||||||
|
* may lead to unpredictable behavior.
|
||||||
|
* @kind problem
|
||||||
|
* @problem.severity warning
|
||||||
|
* @precision high
|
||||||
|
* @id cpp/implicit-function-declaration
|
||||||
|
* @tags correctness
|
||||||
|
* maintainability
|
||||||
|
*/
|
||||||
|
|
||||||
|
import cpp
|
||||||
|
import MistypedFunctionArguments
|
||||||
|
import TooFewArguments
|
||||||
|
import TooManyArguments
|
||||||
|
import semmle.code.cpp.commons.Exclusions
|
||||||
|
|
||||||
|
predicate locInfo(Locatable e, File file, int line, int col) {
|
||||||
|
e.getFile() = file and
|
||||||
|
e.getLocation().getStartLine() = line and
|
||||||
|
e.getLocation().getStartColumn() = col
|
||||||
|
}
|
||||||
|
|
||||||
|
predicate sameLocation(FunctionDeclarationEntry fde, FunctionCall fc) {
|
||||||
|
exists(File file, int line, int col |
|
||||||
|
locInfo(fde, file, line, col) and
|
||||||
|
locInfo(fc, file, line, col)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
predicate isCompiledAsC(File f) {
|
||||||
|
f.compiledAsC()
|
||||||
|
or
|
||||||
|
exists(File src | isCompiledAsC(src) | src.getAnIncludedFile() = f)
|
||||||
|
}
|
||||||
|
|
||||||
|
from FunctionDeclarationEntry fdeIm, FunctionCall fc
|
||||||
|
where
|
||||||
|
isCompiledAsC(fdeIm.getFile()) and
|
||||||
|
not isFromMacroDefinition(fc) and
|
||||||
|
fdeIm.isImplicit() and
|
||||||
|
sameLocation(fdeIm, fc) and
|
||||||
|
not mistypedFunctionArguments(fc, _, _) and
|
||||||
|
not tooFewArguments(fc, _) and
|
||||||
|
not tooManyArguments(fc, _)
|
||||||
|
select fc, "Function call implicitly declares '" + fdeIm.getName() + "'."
|
||||||
@@ -12,95 +12,10 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import cpp
|
import cpp
|
||||||
|
import MistypedFunctionArguments
|
||||||
predicate arithTypesMatch(Type arg, Type parm) {
|
|
||||||
arg = parm
|
|
||||||
or
|
|
||||||
arg.getSize() = parm.getSize() and
|
|
||||||
(
|
|
||||||
arg instanceof IntegralOrEnumType and
|
|
||||||
parm instanceof IntegralOrEnumType
|
|
||||||
or
|
|
||||||
arg instanceof FloatingPointType and
|
|
||||||
parm instanceof FloatingPointType
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
pragma[inline]
|
|
||||||
predicate nestedPointerArgTypeMayBeUsed(Type arg, Type parm) {
|
|
||||||
// arithmetic types
|
|
||||||
arithTypesMatch(arg, parm)
|
|
||||||
or
|
|
||||||
// conversion to/from pointers to void is allowed
|
|
||||||
arg instanceof VoidType
|
|
||||||
or
|
|
||||||
parm instanceof VoidType
|
|
||||||
}
|
|
||||||
|
|
||||||
pragma[inline]
|
|
||||||
predicate pointerArgTypeMayBeUsed(Type arg, Type parm) {
|
|
||||||
nestedPointerArgTypeMayBeUsed(arg, parm)
|
|
||||||
or
|
|
||||||
// nested pointers
|
|
||||||
nestedPointerArgTypeMayBeUsed(arg.(PointerType).getBaseType().getUnspecifiedType(),
|
|
||||||
parm.(PointerType).getBaseType().getUnspecifiedType())
|
|
||||||
or
|
|
||||||
nestedPointerArgTypeMayBeUsed(arg.(ArrayType).getBaseType().getUnspecifiedType(),
|
|
||||||
parm.(PointerType).getBaseType().getUnspecifiedType())
|
|
||||||
}
|
|
||||||
|
|
||||||
pragma[inline]
|
|
||||||
predicate argTypeMayBeUsed(Type arg, Type parm) {
|
|
||||||
// arithmetic types
|
|
||||||
arithTypesMatch(arg, parm)
|
|
||||||
or
|
|
||||||
// pointers to compatible types
|
|
||||||
pointerArgTypeMayBeUsed(arg.(PointerType).getBaseType().getUnspecifiedType(),
|
|
||||||
parm.(PointerType).getBaseType().getUnspecifiedType())
|
|
||||||
or
|
|
||||||
pointerArgTypeMayBeUsed(arg.(ArrayType).getBaseType().getUnspecifiedType(),
|
|
||||||
parm.(PointerType).getBaseType().getUnspecifiedType())
|
|
||||||
or
|
|
||||||
// C11 arrays
|
|
||||||
pointerArgTypeMayBeUsed(arg.(PointerType).getBaseType().getUnspecifiedType(),
|
|
||||||
parm.(ArrayType).getBaseType().getUnspecifiedType())
|
|
||||||
or
|
|
||||||
pointerArgTypeMayBeUsed(arg.(ArrayType).getBaseType().getUnspecifiedType(),
|
|
||||||
parm.(ArrayType).getBaseType().getUnspecifiedType())
|
|
||||||
}
|
|
||||||
|
|
||||||
// This predicate holds whenever expression `arg` may be used to initialize
|
|
||||||
// function parameter `parm` without need for run-time conversion.
|
|
||||||
pragma[inline]
|
|
||||||
predicate argMayBeUsed(Expr arg, Parameter parm) {
|
|
||||||
argTypeMayBeUsed(arg.getFullyConverted().getUnspecifiedType(), parm.getUnspecifiedType())
|
|
||||||
}
|
|
||||||
|
|
||||||
// True if function was ()-declared, but not (void)-declared or K&R-defined
|
|
||||||
predicate hasZeroParamDecl(Function f) {
|
|
||||||
exists(FunctionDeclarationEntry fde | fde = f.getADeclarationEntry() |
|
|
||||||
not fde.hasVoidParamList() and fde.getNumberOfParameters() = 0 and not fde.isDefinition()
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
// True if this file (or header) was compiled as a C file
|
|
||||||
predicate isCompiledAsC(File f) {
|
|
||||||
f.compiledAsC()
|
|
||||||
or
|
|
||||||
exists(File src | isCompiledAsC(src) | src.getAnIncludedFile() = f)
|
|
||||||
}
|
|
||||||
|
|
||||||
from FunctionCall fc, Function f, Parameter p
|
from FunctionCall fc, Function f, Parameter p
|
||||||
where
|
where mistypedFunctionArguments(fc, f, p)
|
||||||
f = fc.getTarget() and
|
|
||||||
p = f.getAParameter() and
|
|
||||||
hasZeroParamDecl(f) and
|
|
||||||
isCompiledAsC(f.getFile()) and
|
|
||||||
not f.isVarargs() and
|
|
||||||
not f instanceof BuiltInFunction and
|
|
||||||
p.getIndex() < fc.getNumberOfArguments() and
|
|
||||||
// Parameter p and its corresponding call argument must have mismatched types
|
|
||||||
not argMayBeUsed(fc.getArgument(p.getIndex()), p)
|
|
||||||
select fc, "Calling $@: argument $@ of type $@ is incompatible with parameter $@.", f, f.toString(),
|
select fc, "Calling $@: argument $@ of type $@ is incompatible with parameter $@.", f, f.toString(),
|
||||||
fc.getArgument(p.getIndex()) as arg, arg.toString(),
|
fc.getArgument(p.getIndex()) as arg, arg.toString(),
|
||||||
arg.getExplicitlyConverted().getUnspecifiedType() as atype, atype.toString(), p, p.getTypedName()
|
arg.getExplicitlyConverted().getUnspecifiedType() as atype, atype.toString(), p, p.getTypedName()
|
||||||
|
|||||||
@@ -0,0 +1,96 @@
|
|||||||
|
/**
|
||||||
|
* Provides the implementation of the MistypedFunctionArguments query. The
|
||||||
|
* query is implemented as a library, so that we can avoid producing
|
||||||
|
* duplicate results in other similar queries.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import cpp
|
||||||
|
|
||||||
|
private predicate arithTypesMatch(Type arg, Type parm) {
|
||||||
|
arg = parm
|
||||||
|
or
|
||||||
|
arg.getSize() = parm.getSize() and
|
||||||
|
(
|
||||||
|
arg instanceof IntegralOrEnumType and
|
||||||
|
parm instanceof IntegralOrEnumType
|
||||||
|
or
|
||||||
|
arg instanceof FloatingPointType and
|
||||||
|
parm instanceof FloatingPointType
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
pragma[inline]
|
||||||
|
private predicate nestedPointerArgTypeMayBeUsed(Type arg, Type parm) {
|
||||||
|
// arithmetic types
|
||||||
|
arithTypesMatch(arg, parm)
|
||||||
|
or
|
||||||
|
// conversion to/from pointers to void is allowed
|
||||||
|
arg instanceof VoidType
|
||||||
|
or
|
||||||
|
parm instanceof VoidType
|
||||||
|
}
|
||||||
|
|
||||||
|
pragma[inline]
|
||||||
|
private predicate pointerArgTypeMayBeUsed(Type arg, Type parm) {
|
||||||
|
nestedPointerArgTypeMayBeUsed(arg, parm)
|
||||||
|
or
|
||||||
|
// nested pointers
|
||||||
|
nestedPointerArgTypeMayBeUsed(arg.(PointerType).getBaseType().getUnspecifiedType(),
|
||||||
|
parm.(PointerType).getBaseType().getUnspecifiedType())
|
||||||
|
or
|
||||||
|
nestedPointerArgTypeMayBeUsed(arg.(ArrayType).getBaseType().getUnspecifiedType(),
|
||||||
|
parm.(PointerType).getBaseType().getUnspecifiedType())
|
||||||
|
}
|
||||||
|
|
||||||
|
pragma[inline]
|
||||||
|
private predicate argTypeMayBeUsed(Type arg, Type parm) {
|
||||||
|
// arithmetic types
|
||||||
|
arithTypesMatch(arg, parm)
|
||||||
|
or
|
||||||
|
// pointers to compatible types
|
||||||
|
pointerArgTypeMayBeUsed(arg.(PointerType).getBaseType().getUnspecifiedType(),
|
||||||
|
parm.(PointerType).getBaseType().getUnspecifiedType())
|
||||||
|
or
|
||||||
|
pointerArgTypeMayBeUsed(arg.(ArrayType).getBaseType().getUnspecifiedType(),
|
||||||
|
parm.(PointerType).getBaseType().getUnspecifiedType())
|
||||||
|
or
|
||||||
|
// C11 arrays
|
||||||
|
pointerArgTypeMayBeUsed(arg.(PointerType).getBaseType().getUnspecifiedType(),
|
||||||
|
parm.(ArrayType).getBaseType().getUnspecifiedType())
|
||||||
|
or
|
||||||
|
pointerArgTypeMayBeUsed(arg.(ArrayType).getBaseType().getUnspecifiedType(),
|
||||||
|
parm.(ArrayType).getBaseType().getUnspecifiedType())
|
||||||
|
}
|
||||||
|
|
||||||
|
// This predicate holds whenever expression `arg` may be used to initialize
|
||||||
|
// function parameter `parm` without need for run-time conversion.
|
||||||
|
pragma[inline]
|
||||||
|
private predicate argMayBeUsed(Expr arg, Parameter parm) {
|
||||||
|
argTypeMayBeUsed(arg.getFullyConverted().getUnspecifiedType(), parm.getUnspecifiedType())
|
||||||
|
}
|
||||||
|
|
||||||
|
// True if function was ()-declared, but not (void)-declared or K&R-defined
|
||||||
|
private predicate hasZeroParamDecl(Function f) {
|
||||||
|
exists(FunctionDeclarationEntry fde | fde = f.getADeclarationEntry() |
|
||||||
|
not fde.hasVoidParamList() and fde.getNumberOfParameters() = 0 and not fde.isDefinition()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
// True if this file (or header) was compiled as a C file
|
||||||
|
private predicate isCompiledAsC(File f) {
|
||||||
|
f.compiledAsC()
|
||||||
|
or
|
||||||
|
exists(File src | isCompiledAsC(src) | src.getAnIncludedFile() = f)
|
||||||
|
}
|
||||||
|
|
||||||
|
predicate mistypedFunctionArguments(FunctionCall fc, Function f, Parameter p) {
|
||||||
|
f = fc.getTarget() and
|
||||||
|
p = f.getAParameter() and
|
||||||
|
hasZeroParamDecl(f) and
|
||||||
|
isCompiledAsC(f.getFile()) and
|
||||||
|
not f.isVarargs() and
|
||||||
|
not f instanceof BuiltInFunction and
|
||||||
|
p.getIndex() < fc.getNumberOfArguments() and
|
||||||
|
// Parameter p and its corresponding call argument must have mismatched types
|
||||||
|
not argMayBeUsed(fc.getArgument(p.getIndex()), p)
|
||||||
|
}
|
||||||
@@ -15,31 +15,8 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import cpp
|
import cpp
|
||||||
|
import TooFewArguments
|
||||||
// True if function was ()-declared, but not (void)-declared or K&R-defined
|
|
||||||
predicate hasZeroParamDecl(Function f) {
|
|
||||||
exists(FunctionDeclarationEntry fde | fde = f.getADeclarationEntry() |
|
|
||||||
not fde.hasVoidParamList() and fde.getNumberOfParameters() = 0 and not fde.isDefinition()
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
// True if this file (or header) was compiled as a C file
|
|
||||||
predicate isCompiledAsC(File f) {
|
|
||||||
f.compiledAsC()
|
|
||||||
or
|
|
||||||
exists(File src | isCompiledAsC(src) | src.getAnIncludedFile() = f)
|
|
||||||
}
|
|
||||||
|
|
||||||
from FunctionCall fc, Function f
|
from FunctionCall fc, Function f
|
||||||
where
|
where tooFewArguments(fc, f)
|
||||||
f = fc.getTarget() and
|
|
||||||
not f.isVarargs() and
|
|
||||||
not f instanceof BuiltInFunction and
|
|
||||||
hasZeroParamDecl(f) and
|
|
||||||
isCompiledAsC(f.getFile()) and
|
|
||||||
// There is an explicit declaration of the function whose parameter count is larger
|
|
||||||
// than the number of call arguments
|
|
||||||
exists(FunctionDeclarationEntry fde | fde = f.getADeclarationEntry() |
|
|
||||||
fde.getNumberOfParameters() > fc.getNumberOfArguments()
|
|
||||||
)
|
|
||||||
select fc, "This call has fewer arguments than required by $@.", f, f.toString()
|
select fc, "This call has fewer arguments than required by $@.", f, f.toString()
|
||||||
|
|||||||
@@ -0,0 +1,34 @@
|
|||||||
|
/**
|
||||||
|
* Provides the implementation of the TooFewArguments query. The
|
||||||
|
* query is implemented as a library, so that we can avoid producing
|
||||||
|
* duplicate results in other similar queries.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import cpp
|
||||||
|
|
||||||
|
// True if function was ()-declared, but not (void)-declared or K&R-defined
|
||||||
|
private predicate hasZeroParamDecl(Function f) {
|
||||||
|
exists(FunctionDeclarationEntry fde | fde = f.getADeclarationEntry() |
|
||||||
|
not fde.hasVoidParamList() and fde.getNumberOfParameters() = 0 and not fde.isDefinition()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
// True if this file (or header) was compiled as a C file
|
||||||
|
private predicate isCompiledAsC(File f) {
|
||||||
|
f.compiledAsC()
|
||||||
|
or
|
||||||
|
exists(File src | isCompiledAsC(src) | src.getAnIncludedFile() = f)
|
||||||
|
}
|
||||||
|
|
||||||
|
predicate tooFewArguments(FunctionCall fc, Function f) {
|
||||||
|
f = fc.getTarget() and
|
||||||
|
not f.isVarargs() and
|
||||||
|
not f instanceof BuiltInFunction and
|
||||||
|
hasZeroParamDecl(f) and
|
||||||
|
isCompiledAsC(f.getFile()) and
|
||||||
|
// There is an explicit declaration of the function whose parameter count is larger
|
||||||
|
// than the number of call arguments
|
||||||
|
exists(FunctionDeclarationEntry fde | fde = f.getADeclarationEntry() |
|
||||||
|
fde.getNumberOfParameters() > fc.getNumberOfArguments()
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -12,35 +12,8 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import cpp
|
import cpp
|
||||||
|
import TooManyArguments
|
||||||
// True if function was ()-declared, but not (void)-declared or K&R-defined
|
|
||||||
// or implicitly declared (i.e., lacking a prototype)
|
|
||||||
predicate hasZeroParamDecl(Function f) {
|
|
||||||
exists(FunctionDeclarationEntry fde | fde = f.getADeclarationEntry() |
|
|
||||||
not fde.isImplicit() and
|
|
||||||
not fde.hasVoidParamList() and
|
|
||||||
fde.getNumberOfParameters() = 0 and
|
|
||||||
not fde.isDefinition()
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
// True if this file (or header) was compiled as a C file
|
|
||||||
predicate isCompiledAsC(File f) {
|
|
||||||
f.compiledAsC()
|
|
||||||
or
|
|
||||||
exists(File src | isCompiledAsC(src) | src.getAnIncludedFile() = f)
|
|
||||||
}
|
|
||||||
|
|
||||||
from FunctionCall fc, Function f
|
from FunctionCall fc, Function f
|
||||||
where
|
where tooManyArguments(fc, f)
|
||||||
f = fc.getTarget() and
|
|
||||||
not f.isVarargs() and
|
|
||||||
hasZeroParamDecl(f) and
|
|
||||||
isCompiledAsC(f.getFile()) and
|
|
||||||
exists(f.getBlock()) and
|
|
||||||
// There must not exist a declaration with the number of parameters
|
|
||||||
// at least as large as the number of call arguments
|
|
||||||
not exists(FunctionDeclarationEntry fde | fde = f.getADeclarationEntry() |
|
|
||||||
fde.getNumberOfParameters() >= fc.getNumberOfArguments()
|
|
||||||
)
|
|
||||||
select fc, "This call has more arguments than required by $@.", f, f.toString()
|
select fc, "This call has more arguments than required by $@.", f, f.toString()
|
||||||
|
|||||||
@@ -0,0 +1,38 @@
|
|||||||
|
/**
|
||||||
|
* Provides the implementation of the TooManyArguments query. The
|
||||||
|
* query is implemented as a library, so that we can avoid producing
|
||||||
|
* duplicate results in other similar queries.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import cpp
|
||||||
|
|
||||||
|
// True if function was ()-declared, but not (void)-declared or K&R-defined
|
||||||
|
// or implicitly declared (i.e., lacking a prototype)
|
||||||
|
private predicate hasZeroParamDecl(Function f) {
|
||||||
|
exists(FunctionDeclarationEntry fde | fde = f.getADeclarationEntry() |
|
||||||
|
not fde.isImplicit() and
|
||||||
|
not fde.hasVoidParamList() and
|
||||||
|
fde.getNumberOfParameters() = 0 and
|
||||||
|
not fde.isDefinition()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
// True if this file (or header) was compiled as a C file
|
||||||
|
private predicate isCompiledAsC(File f) {
|
||||||
|
f.compiledAsC()
|
||||||
|
or
|
||||||
|
exists(File src | isCompiledAsC(src) | src.getAnIncludedFile() = f)
|
||||||
|
}
|
||||||
|
|
||||||
|
predicate tooManyArguments(FunctionCall fc, Function f) {
|
||||||
|
f = fc.getTarget() and
|
||||||
|
not f.isVarargs() and
|
||||||
|
hasZeroParamDecl(f) and
|
||||||
|
isCompiledAsC(f.getFile()) and
|
||||||
|
exists(f.getBlock()) and
|
||||||
|
// There must not exist a declaration with the number of parameters
|
||||||
|
// at least as large as the number of call arguments
|
||||||
|
not exists(FunctionDeclarationEntry fde | fde = f.getADeclarationEntry() |
|
||||||
|
fde.getNumberOfParameters() >= fc.getNumberOfArguments()
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -163,5 +163,8 @@ class Parameter extends LocalScopeVariable, @parameter {
|
|||||||
* An `int` that is a parameter index for some function. This is needed for binding in certain cases.
|
* An `int` that is a parameter index for some function. This is needed for binding in certain cases.
|
||||||
*/
|
*/
|
||||||
class ParameterIndex extends int {
|
class ParameterIndex extends int {
|
||||||
ParameterIndex() { exists(Parameter p | this = p.getIndex()) }
|
ParameterIndex() {
|
||||||
|
exists(Parameter p | this = p.getIndex()) or
|
||||||
|
exists(Call c | exists(c.getArgument(this))) // permit indexing varargs
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -139,12 +139,6 @@ abstract class Configuration extends string {
|
|||||||
partialFlow(source, node, this) and
|
partialFlow(source, node, this) and
|
||||||
dist = node.getSourceDistance()
|
dist = node.getSourceDistance()
|
||||||
}
|
}
|
||||||
|
|
||||||
/** DEPRECATED: use `hasFlow` instead. */
|
|
||||||
deprecated predicate hasFlowForward(Node source, Node sink) { hasFlow(source, sink) }
|
|
||||||
|
|
||||||
/** DEPRECATED: use `hasFlow` instead. */
|
|
||||||
deprecated predicate hasFlowBackward(Node source, Node sink) { hasFlow(source, sink) }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -139,12 +139,6 @@ abstract class Configuration extends string {
|
|||||||
partialFlow(source, node, this) and
|
partialFlow(source, node, this) and
|
||||||
dist = node.getSourceDistance()
|
dist = node.getSourceDistance()
|
||||||
}
|
}
|
||||||
|
|
||||||
/** DEPRECATED: use `hasFlow` instead. */
|
|
||||||
deprecated predicate hasFlowForward(Node source, Node sink) { hasFlow(source, sink) }
|
|
||||||
|
|
||||||
/** DEPRECATED: use `hasFlow` instead. */
|
|
||||||
deprecated predicate hasFlowBackward(Node source, Node sink) { hasFlow(source, sink) }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -139,12 +139,6 @@ abstract class Configuration extends string {
|
|||||||
partialFlow(source, node, this) and
|
partialFlow(source, node, this) and
|
||||||
dist = node.getSourceDistance()
|
dist = node.getSourceDistance()
|
||||||
}
|
}
|
||||||
|
|
||||||
/** DEPRECATED: use `hasFlow` instead. */
|
|
||||||
deprecated predicate hasFlowForward(Node source, Node sink) { hasFlow(source, sink) }
|
|
||||||
|
|
||||||
/** DEPRECATED: use `hasFlow` instead. */
|
|
||||||
deprecated predicate hasFlowBackward(Node source, Node sink) { hasFlow(source, sink) }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -139,12 +139,6 @@ abstract class Configuration extends string {
|
|||||||
partialFlow(source, node, this) and
|
partialFlow(source, node, this) and
|
||||||
dist = node.getSourceDistance()
|
dist = node.getSourceDistance()
|
||||||
}
|
}
|
||||||
|
|
||||||
/** DEPRECATED: use `hasFlow` instead. */
|
|
||||||
deprecated predicate hasFlowForward(Node source, Node sink) { hasFlow(source, sink) }
|
|
||||||
|
|
||||||
/** DEPRECATED: use `hasFlow` instead. */
|
|
||||||
deprecated predicate hasFlowBackward(Node source, Node sink) { hasFlow(source, sink) }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -139,12 +139,6 @@ abstract class Configuration extends string {
|
|||||||
partialFlow(source, node, this) and
|
partialFlow(source, node, this) and
|
||||||
dist = node.getSourceDistance()
|
dist = node.getSourceDistance()
|
||||||
}
|
}
|
||||||
|
|
||||||
/** DEPRECATED: use `hasFlow` instead. */
|
|
||||||
deprecated predicate hasFlowForward(Node source, Node sink) { hasFlow(source, sink) }
|
|
||||||
|
|
||||||
/** DEPRECATED: use `hasFlow` instead. */
|
|
||||||
deprecated predicate hasFlowBackward(Node source, Node sink) { hasFlow(source, sink) }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -282,8 +282,6 @@ class DataFlowExpr = Expr;
|
|||||||
|
|
||||||
class DataFlowType = Type;
|
class DataFlowType = Type;
|
||||||
|
|
||||||
class DataFlowLocation = Location;
|
|
||||||
|
|
||||||
/** A function call relevant for data flow. */
|
/** A function call relevant for data flow. */
|
||||||
class DataFlowCall extends Expr {
|
class DataFlowCall extends Expr {
|
||||||
DataFlowCall() { this instanceof Call }
|
DataFlowCall() { this instanceof Call }
|
||||||
|
|||||||
@@ -68,9 +68,11 @@ predicate localAdditionalTaintStep(DataFlow::Node nodeFrom, DataFlow::Node nodeT
|
|||||||
)
|
)
|
||||||
or
|
or
|
||||||
// Taint can flow through modeled functions
|
// Taint can flow through modeled functions
|
||||||
|
exprToExprStep(nodeFrom.asExpr(), nodeTo.asExpr())
|
||||||
|
or
|
||||||
exprToDefinitionByReferenceStep(nodeFrom.asExpr(), nodeTo.asDefiningArgument())
|
exprToDefinitionByReferenceStep(nodeFrom.asExpr(), nodeTo.asDefiningArgument())
|
||||||
or
|
or
|
||||||
exprToExprStep(nodeFrom.asExpr(), nodeTo.asExpr())
|
exprToPartialDefinitionStep(nodeFrom.asExpr(), nodeTo.asPartialDefinition())
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -130,14 +132,24 @@ private predicate exprToExprStep(Expr exprIn, Expr exprOut) {
|
|||||||
// dest_ptr = strdup(tainted_ptr)
|
// dest_ptr = strdup(tainted_ptr)
|
||||||
inModel.isParameterDeref(argInIndex) and
|
inModel.isParameterDeref(argInIndex) and
|
||||||
exprIn = call.getArgument(argInIndex)
|
exprIn = call.getArgument(argInIndex)
|
||||||
|
or
|
||||||
|
inModel.isParameter(argInIndex) and
|
||||||
|
exprIn = call.getArgument(argInIndex)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
or
|
or
|
||||||
exists(TaintFunction f, Call call, FunctionOutput outModel |
|
exists(TaintFunction f, Call call, FunctionInput inModel, FunctionOutput outModel |
|
||||||
call.getTarget() = f and
|
call.getTarget() = f and
|
||||||
|
(
|
||||||
exprOut = call and
|
exprOut = call and
|
||||||
outModel.isReturnValueDeref() and
|
outModel.isReturnValueDeref()
|
||||||
exists(int argInIndex, FunctionInput inModel | f.hasTaintFlow(inModel, outModel) |
|
or
|
||||||
|
exprOut = call and
|
||||||
|
outModel.isReturnValue()
|
||||||
|
) and
|
||||||
|
f.hasTaintFlow(inModel, outModel) and
|
||||||
|
(
|
||||||
|
exists(int argInIndex |
|
||||||
inModel.isParameterDeref(argInIndex) and
|
inModel.isParameterDeref(argInIndex) and
|
||||||
exprIn = call.getArgument(argInIndex)
|
exprIn = call.getArgument(argInIndex)
|
||||||
or
|
or
|
||||||
@@ -147,6 +159,10 @@ private predicate exprToExprStep(Expr exprIn, Expr exprOut) {
|
|||||||
inModel.isParameter(argInIndex) and
|
inModel.isParameter(argInIndex) and
|
||||||
exprIn = call.getArgument(argInIndex)
|
exprIn = call.getArgument(argInIndex)
|
||||||
)
|
)
|
||||||
|
or
|
||||||
|
inModel.isQualifierObject() and
|
||||||
|
exprIn = call.getQualifier()
|
||||||
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -160,14 +176,46 @@ private predicate exprToDefinitionByReferenceStep(Expr exprIn, Expr argOut) {
|
|||||||
// memcpy(&dest_var, tainted_ptr, len)
|
// memcpy(&dest_var, tainted_ptr, len)
|
||||||
inModel.isParameterDeref(argInIndex) and
|
inModel.isParameterDeref(argInIndex) and
|
||||||
exprIn = call.getArgument(argInIndex)
|
exprIn = call.getArgument(argInIndex)
|
||||||
|
or
|
||||||
|
inModel.isParameter(argInIndex) and
|
||||||
|
exprIn = call.getArgument(argInIndex)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
or
|
or
|
||||||
exists(TaintFunction f, Call call, FunctionOutput outModel, int argOutIndex |
|
exists(
|
||||||
|
TaintFunction f, Call call, FunctionInput inModel, FunctionOutput outModel, int argOutIndex
|
||||||
|
|
|
||||||
call.getTarget() = f and
|
call.getTarget() = f and
|
||||||
argOut = call.getArgument(argOutIndex) and
|
argOut = call.getArgument(argOutIndex) and
|
||||||
outModel.isParameterDeref(argOutIndex) and
|
outModel.isParameterDeref(argOutIndex) and
|
||||||
exists(int argInIndex, FunctionInput inModel | f.hasTaintFlow(inModel, outModel) |
|
f.hasTaintFlow(inModel, outModel) and
|
||||||
|
(
|
||||||
|
exists(int argInIndex |
|
||||||
|
inModel.isParameterDeref(argInIndex) and
|
||||||
|
exprIn = call.getArgument(argInIndex)
|
||||||
|
or
|
||||||
|
inModel.isParameterDeref(argInIndex) and
|
||||||
|
call.passesByReference(argInIndex, exprIn)
|
||||||
|
or
|
||||||
|
inModel.isParameter(argInIndex) and
|
||||||
|
exprIn = call.getArgument(argInIndex)
|
||||||
|
)
|
||||||
|
or
|
||||||
|
inModel.isQualifierObject() and
|
||||||
|
exprIn = call.getQualifier()
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
private predicate exprToPartialDefinitionStep(Expr exprIn, Expr exprOut) {
|
||||||
|
exists(TaintFunction f, Call call, FunctionInput inModel, FunctionOutput outModel |
|
||||||
|
call.getTarget() = f and
|
||||||
|
(
|
||||||
|
exprOut = call.getQualifier() and
|
||||||
|
outModel.isQualifierObject()
|
||||||
|
) and
|
||||||
|
f.hasTaintFlow(inModel, outModel) and
|
||||||
|
exists(int argInIndex |
|
||||||
inModel.isParameterDeref(argInIndex) and
|
inModel.isParameterDeref(argInIndex) and
|
||||||
exprIn = call.getArgument(argInIndex)
|
exprIn = call.getArgument(argInIndex)
|
||||||
or
|
or
|
||||||
|
|||||||
@@ -21,33 +21,30 @@ private predicate predictableInstruction(Instruction instr) {
|
|||||||
predictableInstruction(instr.(UnaryInstruction).getUnary())
|
predictableInstruction(instr.(UnaryInstruction).getUnary())
|
||||||
}
|
}
|
||||||
|
|
||||||
private predicate userInputInstruction(Instruction instr) {
|
private class DefaultTaintTrackingCfg extends DataFlow::Configuration {
|
||||||
|
DefaultTaintTrackingCfg() { this = "DefaultTaintTrackingCfg" }
|
||||||
|
|
||||||
|
override predicate isSource(DataFlow::Node source) {
|
||||||
exists(CallInstruction ci, WriteSideEffectInstruction wsei |
|
exists(CallInstruction ci, WriteSideEffectInstruction wsei |
|
||||||
userInputArgument(ci.getConvertedResultExpression(), wsei.getIndex()) and
|
userInputArgument(ci.getConvertedResultExpression(), wsei.getIndex()) and
|
||||||
instr = wsei and
|
source.asInstruction() = wsei and
|
||||||
wsei.getPrimaryInstruction() = ci
|
wsei.getPrimaryInstruction() = ci
|
||||||
)
|
)
|
||||||
or
|
or
|
||||||
userInputReturned(instr.getConvertedResultExpression())
|
userInputReturned(source.asExpr())
|
||||||
or
|
or
|
||||||
isUserInput(instr.getConvertedResultExpression(), _)
|
isUserInput(source.asExpr(), _)
|
||||||
or
|
or
|
||||||
instr.getConvertedResultExpression() instanceof EnvironmentRead
|
source.asExpr() instanceof EnvironmentRead
|
||||||
or
|
or
|
||||||
instr
|
source
|
||||||
|
.asInstruction()
|
||||||
.(LoadInstruction)
|
.(LoadInstruction)
|
||||||
.getSourceAddress()
|
.getSourceAddress()
|
||||||
.(VariableAddressInstruction)
|
.(VariableAddressInstruction)
|
||||||
.getASTVariable()
|
.getASTVariable()
|
||||||
.hasName("argv") and
|
.hasName("argv") and
|
||||||
instr.getEnclosingFunction().hasGlobalName("main")
|
source.asInstruction().getEnclosingFunction().hasGlobalName("main")
|
||||||
}
|
|
||||||
|
|
||||||
private class DefaultTaintTrackingCfg extends DataFlow::Configuration {
|
|
||||||
DefaultTaintTrackingCfg() { this = "DefaultTaintTrackingCfg" }
|
|
||||||
|
|
||||||
override predicate isSource(DataFlow::Node source) {
|
|
||||||
userInputInstruction(source.asInstruction())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override predicate isSink(DataFlow::Node sink) { any() }
|
override predicate isSink(DataFlow::Node sink) { any() }
|
||||||
|
|||||||
@@ -83,10 +83,24 @@ private module VirtualDispatch {
|
|||||||
)
|
)
|
||||||
or
|
or
|
||||||
// Flow through global variable
|
// Flow through global variable
|
||||||
exists(StoreInstruction store, Variable var |
|
exists(StoreInstruction store |
|
||||||
store = src.asInstruction() and
|
store = src.asInstruction() and
|
||||||
|
(
|
||||||
|
exists(Variable var |
|
||||||
var = store.getDestinationAddress().(VariableAddressInstruction).getASTVariable() and
|
var = store.getDestinationAddress().(VariableAddressInstruction).getASTVariable() and
|
||||||
this.flowsFromGlobal(var) and
|
this.flowsFromGlobal(var)
|
||||||
|
)
|
||||||
|
or
|
||||||
|
exists(Variable var, FieldAccess a |
|
||||||
|
var = store
|
||||||
|
.getDestinationAddress()
|
||||||
|
.(FieldAddressInstruction)
|
||||||
|
.getObjectAddress()
|
||||||
|
.(VariableAddressInstruction)
|
||||||
|
.getASTVariable() and
|
||||||
|
this.flowsFromGlobalUnionField(var, a)
|
||||||
|
)
|
||||||
|
) and
|
||||||
allowFromArg = true
|
allowFromArg = true
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -97,6 +111,19 @@ private module VirtualDispatch {
|
|||||||
load.getSourceAddress().(VariableAddressInstruction).getASTVariable() = var
|
load.getSourceAddress().(VariableAddressInstruction).getASTVariable() = var
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private predicate flowsFromGlobalUnionField(Variable var, FieldAccess a) {
|
||||||
|
a.getTarget().getDeclaringType() instanceof Union and
|
||||||
|
exists(LoadInstruction load |
|
||||||
|
this.flowsFrom(DataFlow::instructionNode(load), _) and
|
||||||
|
load
|
||||||
|
.getSourceAddress()
|
||||||
|
.(FieldAddressInstruction)
|
||||||
|
.getObjectAddress()
|
||||||
|
.(VariableAddressInstruction)
|
||||||
|
.getASTVariable() = var
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Call through a function pointer. */
|
/** Call through a function pointer. */
|
||||||
|
|||||||
@@ -139,12 +139,6 @@ abstract class Configuration extends string {
|
|||||||
partialFlow(source, node, this) and
|
partialFlow(source, node, this) and
|
||||||
dist = node.getSourceDistance()
|
dist = node.getSourceDistance()
|
||||||
}
|
}
|
||||||
|
|
||||||
/** DEPRECATED: use `hasFlow` instead. */
|
|
||||||
deprecated predicate hasFlowForward(Node source, Node sink) { hasFlow(source, sink) }
|
|
||||||
|
|
||||||
/** DEPRECATED: use `hasFlow` instead. */
|
|
||||||
deprecated predicate hasFlowBackward(Node source, Node sink) { hasFlow(source, sink) }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -139,12 +139,6 @@ abstract class Configuration extends string {
|
|||||||
partialFlow(source, node, this) and
|
partialFlow(source, node, this) and
|
||||||
dist = node.getSourceDistance()
|
dist = node.getSourceDistance()
|
||||||
}
|
}
|
||||||
|
|
||||||
/** DEPRECATED: use `hasFlow` instead. */
|
|
||||||
deprecated predicate hasFlowForward(Node source, Node sink) { hasFlow(source, sink) }
|
|
||||||
|
|
||||||
/** DEPRECATED: use `hasFlow` instead. */
|
|
||||||
deprecated predicate hasFlowBackward(Node source, Node sink) { hasFlow(source, sink) }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -139,12 +139,6 @@ abstract class Configuration extends string {
|
|||||||
partialFlow(source, node, this) and
|
partialFlow(source, node, this) and
|
||||||
dist = node.getSourceDistance()
|
dist = node.getSourceDistance()
|
||||||
}
|
}
|
||||||
|
|
||||||
/** DEPRECATED: use `hasFlow` instead. */
|
|
||||||
deprecated predicate hasFlowForward(Node source, Node sink) { hasFlow(source, sink) }
|
|
||||||
|
|
||||||
/** DEPRECATED: use `hasFlow` instead. */
|
|
||||||
deprecated predicate hasFlowBackward(Node source, Node sink) { hasFlow(source, sink) }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -139,12 +139,6 @@ abstract class Configuration extends string {
|
|||||||
partialFlow(source, node, this) and
|
partialFlow(source, node, this) and
|
||||||
dist = node.getSourceDistance()
|
dist = node.getSourceDistance()
|
||||||
}
|
}
|
||||||
|
|
||||||
/** DEPRECATED: use `hasFlow` instead. */
|
|
||||||
deprecated predicate hasFlowForward(Node source, Node sink) { hasFlow(source, sink) }
|
|
||||||
|
|
||||||
/** DEPRECATED: use `hasFlow` instead. */
|
|
||||||
deprecated predicate hasFlowBackward(Node source, Node sink) { hasFlow(source, sink) }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -191,8 +191,6 @@ class DataFlowExpr = Expr;
|
|||||||
|
|
||||||
class DataFlowType = Type;
|
class DataFlowType = Type;
|
||||||
|
|
||||||
class DataFlowLocation = Location;
|
|
||||||
|
|
||||||
/** A function call relevant for data flow. */
|
/** A function call relevant for data flow. */
|
||||||
class DataFlowCall extends CallInstruction {
|
class DataFlowCall extends CallInstruction {
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -55,6 +55,9 @@ class Node extends TIRDataFlowNode {
|
|||||||
*/
|
*/
|
||||||
Expr asConvertedExpr() { result = instr.getConvertedResultExpression() }
|
Expr asConvertedExpr() { result = instr.getConvertedResultExpression() }
|
||||||
|
|
||||||
|
/** Gets the argument that defines this `DefinitionByReferenceNode`, if any. */
|
||||||
|
Expr asDefiningArgument() { result = this.(DefinitionByReferenceNode).getArgument() }
|
||||||
|
|
||||||
/** Gets the parameter corresponding to this node, if any. */
|
/** Gets the parameter corresponding to this node, if any. */
|
||||||
Parameter asParameter() { result = instr.(InitializeParameterInstruction).getParameter() }
|
Parameter asParameter() { result = instr.(InitializeParameterInstruction).getParameter() }
|
||||||
|
|
||||||
@@ -268,6 +271,8 @@ private predicate simpleInstructionLocalFlowStep(Instruction iFrom, Instruction
|
|||||||
// Treat all conversions as flow, even conversions between different numeric types.
|
// Treat all conversions as flow, even conversions between different numeric types.
|
||||||
iTo.(ConvertInstruction).getUnary() = iFrom
|
iTo.(ConvertInstruction).getUnary() = iFrom
|
||||||
or
|
or
|
||||||
|
iTo.(CheckedConvertOrNullInstruction).getUnary() = iFrom
|
||||||
|
or
|
||||||
iTo.(InheritanceConversionInstruction).getUnary() = iFrom
|
iTo.(InheritanceConversionInstruction).getUnary() = iFrom
|
||||||
or
|
or
|
||||||
// A chi instruction represents a point where a new value (the _partial_
|
// A chi instruction represents a point where a new value (the _partial_
|
||||||
|
|||||||
@@ -947,6 +947,10 @@ class ConvertInstruction extends UnaryInstruction {
|
|||||||
ConvertInstruction() { getOpcode() instanceof Opcode::Convert }
|
ConvertInstruction() { getOpcode() instanceof Opcode::Convert }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class CheckedConvertOrNullInstruction extends UnaryInstruction {
|
||||||
|
CheckedConvertOrNullInstruction() { getOpcode() instanceof Opcode::CheckedConvertOrNull }
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents an instruction that converts between two addresses
|
* Represents an instruction that converts between two addresses
|
||||||
* related by inheritance.
|
* related by inheritance.
|
||||||
|
|||||||
@@ -96,6 +96,10 @@ private predicate operandIsPropagated(Operand operand, IntValue bitOffset) {
|
|||||||
bitOffset = Ints::mul(convert.getDerivation().getByteOffset(), 8)
|
bitOffset = Ints::mul(convert.getDerivation().getByteOffset(), 8)
|
||||||
)
|
)
|
||||||
or
|
or
|
||||||
|
// Conversion using dynamic_cast results in an unknown offset
|
||||||
|
instr instanceof CheckedConvertOrNullInstruction and
|
||||||
|
bitOffset = Ints::unknown()
|
||||||
|
or
|
||||||
// Converting to a derived class subtracts the offset of the base class.
|
// Converting to a derived class subtracts the offset of the base class.
|
||||||
exists(ConvertToDerivedInstruction convert |
|
exists(ConvertToDerivedInstruction convert |
|
||||||
convert = instr and
|
convert = instr and
|
||||||
|
|||||||
@@ -947,6 +947,10 @@ class ConvertInstruction extends UnaryInstruction {
|
|||||||
ConvertInstruction() { getOpcode() instanceof Opcode::Convert }
|
ConvertInstruction() { getOpcode() instanceof Opcode::Convert }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class CheckedConvertOrNullInstruction extends UnaryInstruction {
|
||||||
|
CheckedConvertOrNullInstruction() { getOpcode() instanceof Opcode::CheckedConvertOrNull }
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents an instruction that converts between two addresses
|
* Represents an instruction that converts between two addresses
|
||||||
* related by inheritance.
|
* related by inheritance.
|
||||||
|
|||||||
@@ -947,6 +947,10 @@ class ConvertInstruction extends UnaryInstruction {
|
|||||||
ConvertInstruction() { getOpcode() instanceof Opcode::Convert }
|
ConvertInstruction() { getOpcode() instanceof Opcode::Convert }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class CheckedConvertOrNullInstruction extends UnaryInstruction {
|
||||||
|
CheckedConvertOrNullInstruction() { getOpcode() instanceof Opcode::CheckedConvertOrNull }
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents an instruction that converts between two addresses
|
* Represents an instruction that converts between two addresses
|
||||||
* related by inheritance.
|
* related by inheritance.
|
||||||
|
|||||||
@@ -96,6 +96,10 @@ private predicate operandIsPropagated(Operand operand, IntValue bitOffset) {
|
|||||||
bitOffset = Ints::mul(convert.getDerivation().getByteOffset(), 8)
|
bitOffset = Ints::mul(convert.getDerivation().getByteOffset(), 8)
|
||||||
)
|
)
|
||||||
or
|
or
|
||||||
|
// Conversion using dynamic_cast results in an unknown offset
|
||||||
|
instr instanceof CheckedConvertOrNullInstruction and
|
||||||
|
bitOffset = Ints::unknown()
|
||||||
|
or
|
||||||
// Converting to a derived class subtracts the offset of the base class.
|
// Converting to a derived class subtracts the offset of the base class.
|
||||||
exists(ConvertToDerivedInstruction convert |
|
exists(ConvertToDerivedInstruction convert |
|
||||||
convert = instr and
|
convert = instr and
|
||||||
|
|||||||
@@ -83,6 +83,11 @@ class PureStrFunction extends AliasFunction, ArrayFunction, TaintFunction, SideE
|
|||||||
override predicate hasOnlySpecificReadSideEffects() { none() }
|
override predicate hasOnlySpecificReadSideEffects() { none() }
|
||||||
|
|
||||||
override predicate hasOnlySpecificWriteSideEffects() { any() }
|
override predicate hasOnlySpecificWriteSideEffects() { any() }
|
||||||
|
|
||||||
|
override predicate hasSpecificReadSideEffect(ParameterIndex i, boolean buffer) {
|
||||||
|
getParameter(i).getUnspecifiedType() instanceof PointerType and
|
||||||
|
buffer = true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class PureFunction extends TaintFunction, SideEffectFunction {
|
class PureFunction extends TaintFunction, SideEffectFunction {
|
||||||
|
|||||||
@@ -47,20 +47,11 @@ class StrcpyFunction extends ArrayFunction, DataFlowFunction, TaintFunction {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override predicate hasDataFlow(FunctionInput input, FunctionOutput output) {
|
override predicate hasDataFlow(FunctionInput input, FunctionOutput output) {
|
||||||
(
|
|
||||||
// These always copy the full value of the input buffer to the output
|
|
||||||
// buffer
|
|
||||||
this.hasName("strcpy") or
|
|
||||||
this.hasName("_mbscpy") or
|
|
||||||
this.hasName("wcscpy")
|
|
||||||
) and
|
|
||||||
(
|
|
||||||
input.isParameterDeref(1) and
|
input.isParameterDeref(1) and
|
||||||
output.isParameterDeref(0)
|
output.isParameterDeref(0)
|
||||||
or
|
or
|
||||||
input.isParameterDeref(1) and
|
input.isParameterDeref(1) and
|
||||||
output.isReturnValueDeref()
|
output.isReturnValueDeref()
|
||||||
)
|
|
||||||
or
|
or
|
||||||
input.isParameter(0) and
|
input.isParameter(0) and
|
||||||
output.isReturnValue()
|
output.isReturnValue()
|
||||||
@@ -77,10 +68,7 @@ class StrcpyFunction extends ArrayFunction, DataFlowFunction, TaintFunction {
|
|||||||
this.hasName("wcsncpy") or
|
this.hasName("wcsncpy") or
|
||||||
this.hasName("_wcsncpy_l")
|
this.hasName("_wcsncpy_l")
|
||||||
) and
|
) and
|
||||||
(
|
input.isParameter(2) and
|
||||||
input.isParameter(2) or
|
|
||||||
input.isParameterDeref(1)
|
|
||||||
) and
|
|
||||||
(
|
(
|
||||||
output.isParameterDeref(0) or
|
output.isParameterDeref(0) or
|
||||||
output.isReturnValueDeref()
|
output.isReturnValueDeref()
|
||||||
|
|||||||
@@ -9,17 +9,14 @@ import semmle.code.cpp.models.interfaces.Taint
|
|||||||
class StrdupFunction extends AllocationFunction, ArrayFunction, DataFlowFunction {
|
class StrdupFunction extends AllocationFunction, ArrayFunction, DataFlowFunction {
|
||||||
StrdupFunction() {
|
StrdupFunction() {
|
||||||
exists(string name |
|
exists(string name |
|
||||||
hasGlobalOrStdName(name) and
|
hasGlobalName(name) and
|
||||||
(
|
(
|
||||||
// strdup(str)
|
// strdup(str)
|
||||||
name = "strdup"
|
name = "strdup"
|
||||||
or
|
or
|
||||||
// wcsdup(str)
|
// wcsdup(str)
|
||||||
name = "wcsdup"
|
name = "wcsdup"
|
||||||
)
|
|
||||||
or
|
or
|
||||||
hasGlobalName(name) and
|
|
||||||
(
|
|
||||||
// _strdup(str)
|
// _strdup(str)
|
||||||
name = "_strdup"
|
name = "_strdup"
|
||||||
or
|
or
|
||||||
@@ -37,9 +34,32 @@ class StrdupFunction extends AllocationFunction, ArrayFunction, DataFlowFunction
|
|||||||
override predicate hasArrayWithNullTerminator(int bufParam) { bufParam = 0 }
|
override predicate hasArrayWithNullTerminator(int bufParam) { bufParam = 0 }
|
||||||
|
|
||||||
override predicate hasDataFlow(FunctionInput input, FunctionOutput output) {
|
override predicate hasDataFlow(FunctionInput input, FunctionOutput output) {
|
||||||
// These always copy the full value of the input buffer to the result
|
|
||||||
// buffer
|
|
||||||
input.isParameterDeref(0) and
|
input.isParameterDeref(0) and
|
||||||
output.isReturnValueDeref()
|
output.isReturnValueDeref()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A `strndup` style allocation function.
|
||||||
|
*/
|
||||||
|
class StrndupFunction extends AllocationFunction, ArrayFunction, DataFlowFunction {
|
||||||
|
StrndupFunction() {
|
||||||
|
exists(string name |
|
||||||
|
hasGlobalName(name) and
|
||||||
|
// strndup(str, maxlen)
|
||||||
|
name = "strndup"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
override predicate hasArrayInput(int bufParam) { bufParam = 0 }
|
||||||
|
|
||||||
|
override predicate hasArrayWithNullTerminator(int bufParam) { bufParam = 0 }
|
||||||
|
|
||||||
|
override predicate hasDataFlow(FunctionInput input, FunctionOutput output) {
|
||||||
|
(
|
||||||
|
input.isParameterDeref(0) or
|
||||||
|
input.isParameter(1)
|
||||||
|
) and
|
||||||
|
output.isReturnValueDeref()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -12,8 +12,8 @@ import FunctionInputsAndOutputs
|
|||||||
import semmle.code.cpp.models.Models
|
import semmle.code.cpp.models.Models
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A library function for which a value is copied from a parameter or qualifier
|
* A library function for which a value is or may be copied from a parameter
|
||||||
* to an output buffer, return value, or qualifier.
|
* or qualifier to an output buffer, return value, or qualifier.
|
||||||
*
|
*
|
||||||
* Note that this does not include partial copying of values or partial writes
|
* Note that this does not include partial copying of values or partial writes
|
||||||
* to destinations; that is covered by `TaintModel.qll`.
|
* to destinations; that is covered by `TaintModel.qll`.
|
||||||
|
|||||||
@@ -6,7 +6,8 @@
|
|||||||
* `FormattingFunction` to match the flow within that function.
|
* `FormattingFunction` to match the flow within that function.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import semmle.code.cpp.Function
|
import semmle.code.cpp.models.interfaces.ArrayFunction
|
||||||
|
import semmle.code.cpp.models.interfaces.Taint
|
||||||
|
|
||||||
private Type stripTopLevelSpecifiersOnly(Type t) {
|
private Type stripTopLevelSpecifiersOnly(Type t) {
|
||||||
result = stripTopLevelSpecifiersOnly(t.(SpecifiedType).getBaseType())
|
result = stripTopLevelSpecifiersOnly(t.(SpecifiedType).getBaseType())
|
||||||
@@ -39,7 +40,7 @@ private Type getAFormatterWideTypeOrDefault() {
|
|||||||
/**
|
/**
|
||||||
* A standard library function that uses a `printf`-like formatting string.
|
* A standard library function that uses a `printf`-like formatting string.
|
||||||
*/
|
*/
|
||||||
abstract class FormattingFunction extends Function {
|
abstract class FormattingFunction extends ArrayFunction, TaintFunction {
|
||||||
/** Gets the position at which the format parameter occurs. */
|
/** Gets the position at which the format parameter occurs. */
|
||||||
abstract int getFormatParameterIndex();
|
abstract int getFormatParameterIndex();
|
||||||
|
|
||||||
@@ -133,4 +134,33 @@ abstract class FormattingFunction extends Function {
|
|||||||
* Gets the position of the buffer size argument, if any.
|
* Gets the position of the buffer size argument, if any.
|
||||||
*/
|
*/
|
||||||
int getSizeParameterIndex() { none() }
|
int getSizeParameterIndex() { none() }
|
||||||
|
|
||||||
|
override predicate hasArrayWithNullTerminator(int bufParam) {
|
||||||
|
bufParam = getFormatParameterIndex()
|
||||||
|
}
|
||||||
|
|
||||||
|
override predicate hasArrayWithVariableSize(int bufParam, int countParam) {
|
||||||
|
bufParam = getOutputParameterIndex() and
|
||||||
|
countParam = getSizeParameterIndex()
|
||||||
|
}
|
||||||
|
|
||||||
|
override predicate hasArrayWithUnknownSize(int bufParam) {
|
||||||
|
bufParam = getOutputParameterIndex() and
|
||||||
|
not exists(getSizeParameterIndex())
|
||||||
|
}
|
||||||
|
|
||||||
|
override predicate hasArrayInput(int bufParam) { bufParam = getFormatParameterIndex() }
|
||||||
|
|
||||||
|
override predicate hasArrayOutput(int bufParam) { bufParam = getOutputParameterIndex() }
|
||||||
|
|
||||||
|
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
|
||||||
|
exists(int arg |
|
||||||
|
(
|
||||||
|
arg = getFormatParameterIndex() or
|
||||||
|
arg >= getFirstFormatArgumentIndex()
|
||||||
|
) and
|
||||||
|
input.isParameterDeref(arg) and
|
||||||
|
output.isParameterDeref(getOutputParameterIndex())
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,7 +16,9 @@ import semmle.code.cpp.models.Models
|
|||||||
* from a parameter or qualifier to an output buffer, return value, or qualifier.
|
* from a parameter or qualifier to an output buffer, return value, or qualifier.
|
||||||
*
|
*
|
||||||
* Note that this does not include direct copying of values; that is covered by
|
* Note that this does not include direct copying of values; that is covered by
|
||||||
* DataFlowModel.qll
|
* DataFlowModel.qll. If a value is sometimes copied in full, and sometimes
|
||||||
|
* altered (for example copying a string with `strncpy`), this is also considered
|
||||||
|
* data flow.
|
||||||
*/
|
*/
|
||||||
abstract class TaintFunction extends Function {
|
abstract class TaintFunction extends Function {
|
||||||
abstract predicate hasTaintFlow(FunctionInput input, FunctionOutput output);
|
abstract predicate hasTaintFlow(FunctionInput input, FunctionOutput output);
|
||||||
|
|||||||
@@ -0,0 +1,13 @@
|
|||||||
|
| stackVariableReachability.c:11:2:11:2 | a | ... + ... |
|
||||||
|
| stackVariableReachability.c:11:6:11:6 | a | 10 |
|
||||||
|
| stackVariableReachability.c:12:2:12:2 | a | 40 |
|
||||||
|
| stackVariableReachability.c:13:2:13:2 | a | 40 |
|
||||||
|
| stackVariableReachability.c:14:4:14:4 | a | 40 |
|
||||||
|
| stackVariableReachability.c:15:2:15:2 | a | call to f |
|
||||||
|
| stackVariableReachability.c:15:8:15:8 | a | 40 |
|
||||||
|
| stackVariableReachability.c:16:2:16:2 | a | call to f |
|
||||||
|
| stackVariableReachability.c:19:3:19:3 | b | 50 |
|
||||||
|
| stackVariableReachability.c:21:3:21:3 | b | 60 |
|
||||||
|
| stackVariableReachability.c:23:2:23:2 | c | b |
|
||||||
|
| stackVariableReachability.c:23:6:23:6 | b | 50, 60 |
|
||||||
|
| stackVariableReachability.c:24:2:24:2 | c | 50, 60, b |
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
import cpp
|
||||||
|
import semmle.code.cpp.controlflow.StackVariableReachability
|
||||||
|
|
||||||
|
class MyStackVariableReachability extends StackVariableReachabilityWithReassignment {
|
||||||
|
MyStackVariableReachability() { this = "MyStackVariableReachability" }
|
||||||
|
|
||||||
|
override predicate isSourceActual(ControlFlowNode node, StackVariable v) {
|
||||||
|
exprDefinition(v, _, node)
|
||||||
|
}
|
||||||
|
|
||||||
|
override predicate isSinkActual(ControlFlowNode node, StackVariable v) {
|
||||||
|
node.(VariableAccess).getTarget() = v
|
||||||
|
}
|
||||||
|
|
||||||
|
override predicate isBarrier(ControlFlowNode node, StackVariable v) { exprDefinition(v, _, node) }
|
||||||
|
}
|
||||||
|
|
||||||
|
from MyStackVariableReachability svr, ControlFlowNode sink
|
||||||
|
select sink, strictconcat(Expr source | svr.reaches(source, _, sink) | source.toString(), ", ")
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
|
||||||
|
int cond();
|
||||||
|
int f(int x);
|
||||||
|
|
||||||
|
void test(int p)
|
||||||
|
{
|
||||||
|
int a = 10;
|
||||||
|
int b = 20;
|
||||||
|
int c = 30;
|
||||||
|
|
||||||
|
a = a + 1;
|
||||||
|
a = 40;
|
||||||
|
a++;
|
||||||
|
++a;
|
||||||
|
a = f(a);
|
||||||
|
a;
|
||||||
|
|
||||||
|
if (cond()) {
|
||||||
|
b = 50;
|
||||||
|
} else {
|
||||||
|
b = 60;
|
||||||
|
}
|
||||||
|
c = b;
|
||||||
|
c;
|
||||||
|
}
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
| stackVariableReachability.c:11:2:11:2 | a | ... + ... |
|
||||||
|
| stackVariableReachability.c:11:6:11:6 | a | 10 |
|
||||||
|
| stackVariableReachability.c:12:2:12:2 | a | 40 |
|
||||||
|
| stackVariableReachability.c:13:2:13:2 | a | 40 |
|
||||||
|
| stackVariableReachability.c:14:4:14:4 | a | 40 |
|
||||||
|
| stackVariableReachability.c:15:2:15:2 | a | call to f |
|
||||||
|
| stackVariableReachability.c:15:8:15:8 | a | 40 |
|
||||||
|
| stackVariableReachability.c:16:2:16:2 | a | call to f |
|
||||||
|
| stackVariableReachability.c:19:3:19:3 | b | 50 |
|
||||||
|
| stackVariableReachability.c:21:3:21:3 | b | 60 |
|
||||||
|
| stackVariableReachability.c:23:2:23:2 | c | b |
|
||||||
|
| stackVariableReachability.c:23:6:23:6 | b | 50, 60 |
|
||||||
|
| stackVariableReachability.c:24:2:24:2 | c | b |
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
import cpp
|
||||||
|
import semmle.code.cpp.controlflow.StackVariableReachability
|
||||||
|
|
||||||
|
class MyStackVariableReachability extends StackVariableReachability {
|
||||||
|
MyStackVariableReachability() { this = "MyStackVariableReachability" }
|
||||||
|
|
||||||
|
override predicate isSource(ControlFlowNode node, StackVariable v) { exprDefinition(v, _, node) }
|
||||||
|
|
||||||
|
override predicate isSink(ControlFlowNode node, StackVariable v) {
|
||||||
|
node.(VariableAccess).getTarget() = v
|
||||||
|
}
|
||||||
|
|
||||||
|
override predicate isBarrier(ControlFlowNode node, StackVariable v) { exprDefinition(v, _, node) }
|
||||||
|
}
|
||||||
|
|
||||||
|
from MyStackVariableReachability svr, ControlFlowNode sink
|
||||||
|
select sink, strictconcat(Expr source | svr.reaches(source, _, sink) | source.toString(), ", ")
|
||||||
@@ -10,8 +10,8 @@ void sink(const char *);
|
|||||||
void sink(int);
|
void sink(int);
|
||||||
|
|
||||||
int main(int argc, char *argv[]) {
|
int main(int argc, char *argv[]) {
|
||||||
int taintedInt = atoi(getenv("VAR"));
|
|
||||||
taintedInt++; // BUG: `taintedInt` isn't marked as tainted. Only `++` is.
|
|
||||||
|
|
||||||
sink(_strdup(getenv("VAR")));
|
sink(_strdup(getenv("VAR")));
|
||||||
sink(strdup(getenv("VAR")));
|
sink(strdup(getenv("VAR")));
|
||||||
@@ -39,3 +39,42 @@ void test_indirect_arg_to_model() {
|
|||||||
inet_addr_retval a = inet_addr((const char *)&env_pointer);
|
inet_addr_retval a = inet_addr((const char *)&env_pointer);
|
||||||
sink(a);
|
sink(a);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class B {
|
||||||
|
public:
|
||||||
|
virtual void f(const char*) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
class D1 : public B {};
|
||||||
|
|
||||||
|
class D2 : public D1 {
|
||||||
|
public:
|
||||||
|
void f(const char* p) override {}
|
||||||
|
};
|
||||||
|
|
||||||
|
class D3 : public D2 {
|
||||||
|
public:
|
||||||
|
void f(const char* p) override {
|
||||||
|
sink(p);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
void test_dynamic_cast() {
|
||||||
|
B* b = new D3();
|
||||||
|
b->f(getenv("VAR")); // tainted
|
||||||
|
|
||||||
|
((D2*)b)->f(getenv("VAR")); // tainted
|
||||||
|
static_cast<D2*>(b)->f(getenv("VAR")); // tainted
|
||||||
|
dynamic_cast<D2*>(b)->f(getenv("VAR")); // tainted
|
||||||
|
reinterpret_cast<D2*>(b)->f(getenv("VAR")); // tainted
|
||||||
|
|
||||||
|
B* b2 = new D2();
|
||||||
|
b2->f(getenv("VAR"));
|
||||||
|
|
||||||
|
((D2*)b2)->f(getenv("VAR"));
|
||||||
|
static_cast<D2*>(b2)->f(getenv("VAR"));
|
||||||
|
dynamic_cast<D2*>(b2)->f(getenv("VAR"));
|
||||||
|
reinterpret_cast<D2*>(b2)->f(getenv("VAR"));
|
||||||
|
|
||||||
|
dynamic_cast<D3*>(b2)->f(getenv("VAR")); // tainted [FALSE POSITIVE]
|
||||||
|
}
|
||||||
@@ -1,21 +1,17 @@
|
|||||||
| defaulttainttracking.cpp:13:25:13:30 | call to getenv | defaulttainttracking.cpp:1:22:1:25 | nptr |
|
|
||||||
| defaulttainttracking.cpp:13:25:13:30 | call to getenv | defaulttainttracking.cpp:13:7:13:16 | taintedInt |
|
|
||||||
| defaulttainttracking.cpp:13:25:13:30 | call to getenv | defaulttainttracking.cpp:13:20:13:23 | call to atoi |
|
|
||||||
| defaulttainttracking.cpp:13:25:13:30 | call to getenv | defaulttainttracking.cpp:13:25:13:30 | call to getenv |
|
|
||||||
| defaulttainttracking.cpp:13:25:13:30 | call to getenv | defaulttainttracking.cpp:13:25:13:37 | (const char *)... |
|
|
||||||
| defaulttainttracking.cpp:13:25:13:30 | call to getenv | defaulttainttracking.cpp:14:3:14:14 | ... ++ |
|
|
||||||
| defaulttainttracking.cpp:16:16:16:21 | call to getenv | defaulttainttracking.cpp:6:15:6:24 | p#0 |
|
| defaulttainttracking.cpp:16:16:16:21 | call to getenv | defaulttainttracking.cpp:6:15:6:24 | p#0 |
|
||||||
| defaulttainttracking.cpp:16:16:16:21 | call to getenv | defaulttainttracking.cpp:9:11:9:20 | p#0 |
|
| defaulttainttracking.cpp:16:16:16:21 | call to getenv | defaulttainttracking.cpp:9:11:9:20 | p#0 |
|
||||||
| defaulttainttracking.cpp:16:16:16:21 | call to getenv | defaulttainttracking.cpp:16:8:16:14 | call to _strdup |
|
| defaulttainttracking.cpp:16:16:16:21 | call to getenv | defaulttainttracking.cpp:16:8:16:14 | call to _strdup |
|
||||||
| defaulttainttracking.cpp:16:16:16:21 | call to getenv | defaulttainttracking.cpp:16:8:16:29 | (const char *)... |
|
| defaulttainttracking.cpp:16:16:16:21 | call to getenv | defaulttainttracking.cpp:16:8:16:29 | (const char *)... |
|
||||||
| defaulttainttracking.cpp:16:16:16:21 | call to getenv | defaulttainttracking.cpp:16:16:16:21 | call to getenv |
|
| defaulttainttracking.cpp:16:16:16:21 | call to getenv | defaulttainttracking.cpp:16:16:16:21 | call to getenv |
|
||||||
| defaulttainttracking.cpp:16:16:16:21 | call to getenv | defaulttainttracking.cpp:16:16:16:28 | (const char *)... |
|
| defaulttainttracking.cpp:16:16:16:21 | call to getenv | defaulttainttracking.cpp:16:16:16:28 | (const char *)... |
|
||||||
|
| defaulttainttracking.cpp:16:16:16:21 | call to getenv | test_diff.cpp:1:11:1:20 | p#0 |
|
||||||
| defaulttainttracking.cpp:17:15:17:20 | call to getenv | defaulttainttracking.cpp:5:14:5:23 | p#0 |
|
| defaulttainttracking.cpp:17:15:17:20 | call to getenv | defaulttainttracking.cpp:5:14:5:23 | p#0 |
|
||||||
| defaulttainttracking.cpp:17:15:17:20 | call to getenv | defaulttainttracking.cpp:9:11:9:20 | p#0 |
|
| defaulttainttracking.cpp:17:15:17:20 | call to getenv | defaulttainttracking.cpp:9:11:9:20 | p#0 |
|
||||||
| defaulttainttracking.cpp:17:15:17:20 | call to getenv | defaulttainttracking.cpp:17:8:17:13 | call to strdup |
|
| defaulttainttracking.cpp:17:15:17:20 | call to getenv | defaulttainttracking.cpp:17:8:17:13 | call to strdup |
|
||||||
| defaulttainttracking.cpp:17:15:17:20 | call to getenv | defaulttainttracking.cpp:17:8:17:28 | (const char *)... |
|
| defaulttainttracking.cpp:17:15:17:20 | call to getenv | defaulttainttracking.cpp:17:8:17:28 | (const char *)... |
|
||||||
| defaulttainttracking.cpp:17:15:17:20 | call to getenv | defaulttainttracking.cpp:17:15:17:20 | call to getenv |
|
| defaulttainttracking.cpp:17:15:17:20 | call to getenv | defaulttainttracking.cpp:17:15:17:20 | call to getenv |
|
||||||
| defaulttainttracking.cpp:17:15:17:20 | call to getenv | defaulttainttracking.cpp:17:15:17:27 | (const char *)... |
|
| defaulttainttracking.cpp:17:15:17:20 | call to getenv | defaulttainttracking.cpp:17:15:17:27 | (const char *)... |
|
||||||
|
| defaulttainttracking.cpp:17:15:17:20 | call to getenv | test_diff.cpp:1:11:1:20 | p#0 |
|
||||||
| defaulttainttracking.cpp:18:27:18:32 | call to getenv | defaulttainttracking.cpp:7:26:7:35 | p#0 |
|
| defaulttainttracking.cpp:18:27:18:32 | call to getenv | defaulttainttracking.cpp:7:26:7:35 | p#0 |
|
||||||
| defaulttainttracking.cpp:18:27:18:32 | call to getenv | defaulttainttracking.cpp:18:27:18:32 | call to getenv |
|
| defaulttainttracking.cpp:18:27:18:32 | call to getenv | defaulttainttracking.cpp:18:27:18:32 | call to getenv |
|
||||||
| defaulttainttracking.cpp:18:27:18:32 | call to getenv | defaulttainttracking.cpp:18:27:18:39 | (const char *)... |
|
| defaulttainttracking.cpp:18:27:18:32 | call to getenv | defaulttainttracking.cpp:18:27:18:39 | (const char *)... |
|
||||||
@@ -26,6 +22,7 @@
|
|||||||
| defaulttainttracking.cpp:22:20:22:25 | call to getenv | defaulttainttracking.cpp:22:20:22:25 | call to getenv |
|
| defaulttainttracking.cpp:22:20:22:25 | call to getenv | defaulttainttracking.cpp:22:20:22:25 | call to getenv |
|
||||||
| defaulttainttracking.cpp:22:20:22:25 | call to getenv | defaulttainttracking.cpp:22:20:22:32 | (const char *)... |
|
| defaulttainttracking.cpp:22:20:22:25 | call to getenv | defaulttainttracking.cpp:22:20:22:32 | (const char *)... |
|
||||||
| defaulttainttracking.cpp:22:20:22:25 | call to getenv | defaulttainttracking.cpp:24:8:24:10 | buf |
|
| defaulttainttracking.cpp:22:20:22:25 | call to getenv | defaulttainttracking.cpp:24:8:24:10 | buf |
|
||||||
|
| defaulttainttracking.cpp:22:20:22:25 | call to getenv | test_diff.cpp:1:11:1:20 | p#0 |
|
||||||
| defaulttainttracking.cpp:38:25:38:30 | call to getenv | defaulttainttracking.cpp:32:11:32:26 | p#0 |
|
| defaulttainttracking.cpp:38:25:38:30 | call to getenv | defaulttainttracking.cpp:32:11:32:26 | p#0 |
|
||||||
| defaulttainttracking.cpp:38:25:38:30 | call to getenv | defaulttainttracking.cpp:38:11:38:21 | env_pointer |
|
| defaulttainttracking.cpp:38:25:38:30 | call to getenv | defaulttainttracking.cpp:38:11:38:21 | env_pointer |
|
||||||
| defaulttainttracking.cpp:38:25:38:30 | call to getenv | defaulttainttracking.cpp:38:25:38:30 | call to getenv |
|
| defaulttainttracking.cpp:38:25:38:30 | call to getenv | defaulttainttracking.cpp:38:25:38:30 | call to getenv |
|
||||||
@@ -34,3 +31,162 @@
|
|||||||
| defaulttainttracking.cpp:38:25:38:30 | call to getenv | defaulttainttracking.cpp:39:26:39:34 | call to inet_addr |
|
| defaulttainttracking.cpp:38:25:38:30 | call to getenv | defaulttainttracking.cpp:39:26:39:34 | call to inet_addr |
|
||||||
| defaulttainttracking.cpp:38:25:38:30 | call to getenv | defaulttainttracking.cpp:39:50:39:61 | & ... |
|
| defaulttainttracking.cpp:38:25:38:30 | call to getenv | defaulttainttracking.cpp:39:50:39:61 | & ... |
|
||||||
| defaulttainttracking.cpp:38:25:38:30 | call to getenv | defaulttainttracking.cpp:40:10:40:10 | a |
|
| defaulttainttracking.cpp:38:25:38:30 | call to getenv | defaulttainttracking.cpp:40:10:40:10 | a |
|
||||||
|
| defaulttainttracking.cpp:64:10:64:15 | call to getenv | defaulttainttracking.cpp:9:11:9:20 | p#0 |
|
||||||
|
| defaulttainttracking.cpp:64:10:64:15 | call to getenv | defaulttainttracking.cpp:45:20:45:29 | p#0 |
|
||||||
|
| defaulttainttracking.cpp:64:10:64:15 | call to getenv | defaulttainttracking.cpp:52:24:52:24 | p |
|
||||||
|
| defaulttainttracking.cpp:64:10:64:15 | call to getenv | defaulttainttracking.cpp:57:24:57:24 | p |
|
||||||
|
| defaulttainttracking.cpp:64:10:64:15 | call to getenv | defaulttainttracking.cpp:58:14:58:14 | p |
|
||||||
|
| defaulttainttracking.cpp:64:10:64:15 | call to getenv | defaulttainttracking.cpp:64:10:64:15 | call to getenv |
|
||||||
|
| defaulttainttracking.cpp:64:10:64:15 | call to getenv | defaulttainttracking.cpp:64:10:64:22 | (const char *)... |
|
||||||
|
| defaulttainttracking.cpp:64:10:64:15 | call to getenv | test_diff.cpp:1:11:1:20 | p#0 |
|
||||||
|
| defaulttainttracking.cpp:66:17:66:22 | call to getenv | defaulttainttracking.cpp:9:11:9:20 | p#0 |
|
||||||
|
| defaulttainttracking.cpp:66:17:66:22 | call to getenv | defaulttainttracking.cpp:52:24:52:24 | p |
|
||||||
|
| defaulttainttracking.cpp:66:17:66:22 | call to getenv | defaulttainttracking.cpp:57:24:57:24 | p |
|
||||||
|
| defaulttainttracking.cpp:66:17:66:22 | call to getenv | defaulttainttracking.cpp:58:14:58:14 | p |
|
||||||
|
| defaulttainttracking.cpp:66:17:66:22 | call to getenv | defaulttainttracking.cpp:66:17:66:22 | call to getenv |
|
||||||
|
| defaulttainttracking.cpp:66:17:66:22 | call to getenv | defaulttainttracking.cpp:66:17:66:29 | (const char *)... |
|
||||||
|
| defaulttainttracking.cpp:66:17:66:22 | call to getenv | test_diff.cpp:1:11:1:20 | p#0 |
|
||||||
|
| defaulttainttracking.cpp:67:28:67:33 | call to getenv | defaulttainttracking.cpp:9:11:9:20 | p#0 |
|
||||||
|
| defaulttainttracking.cpp:67:28:67:33 | call to getenv | defaulttainttracking.cpp:52:24:52:24 | p |
|
||||||
|
| defaulttainttracking.cpp:67:28:67:33 | call to getenv | defaulttainttracking.cpp:57:24:57:24 | p |
|
||||||
|
| defaulttainttracking.cpp:67:28:67:33 | call to getenv | defaulttainttracking.cpp:58:14:58:14 | p |
|
||||||
|
| defaulttainttracking.cpp:67:28:67:33 | call to getenv | defaulttainttracking.cpp:67:28:67:33 | call to getenv |
|
||||||
|
| defaulttainttracking.cpp:67:28:67:33 | call to getenv | defaulttainttracking.cpp:67:28:67:40 | (const char *)... |
|
||||||
|
| defaulttainttracking.cpp:67:28:67:33 | call to getenv | test_diff.cpp:1:11:1:20 | p#0 |
|
||||||
|
| defaulttainttracking.cpp:68:29:68:34 | call to getenv | defaulttainttracking.cpp:9:11:9:20 | p#0 |
|
||||||
|
| defaulttainttracking.cpp:68:29:68:34 | call to getenv | defaulttainttracking.cpp:52:24:52:24 | p |
|
||||||
|
| defaulttainttracking.cpp:68:29:68:34 | call to getenv | defaulttainttracking.cpp:57:24:57:24 | p |
|
||||||
|
| defaulttainttracking.cpp:68:29:68:34 | call to getenv | defaulttainttracking.cpp:58:14:58:14 | p |
|
||||||
|
| defaulttainttracking.cpp:68:29:68:34 | call to getenv | defaulttainttracking.cpp:68:29:68:34 | call to getenv |
|
||||||
|
| defaulttainttracking.cpp:68:29:68:34 | call to getenv | defaulttainttracking.cpp:68:29:68:41 | (const char *)... |
|
||||||
|
| defaulttainttracking.cpp:68:29:68:34 | call to getenv | test_diff.cpp:1:11:1:20 | p#0 |
|
||||||
|
| defaulttainttracking.cpp:69:33:69:38 | call to getenv | defaulttainttracking.cpp:9:11:9:20 | p#0 |
|
||||||
|
| defaulttainttracking.cpp:69:33:69:38 | call to getenv | defaulttainttracking.cpp:52:24:52:24 | p |
|
||||||
|
| defaulttainttracking.cpp:69:33:69:38 | call to getenv | defaulttainttracking.cpp:57:24:57:24 | p |
|
||||||
|
| defaulttainttracking.cpp:69:33:69:38 | call to getenv | defaulttainttracking.cpp:58:14:58:14 | p |
|
||||||
|
| defaulttainttracking.cpp:69:33:69:38 | call to getenv | defaulttainttracking.cpp:69:33:69:38 | call to getenv |
|
||||||
|
| defaulttainttracking.cpp:69:33:69:38 | call to getenv | defaulttainttracking.cpp:69:33:69:45 | (const char *)... |
|
||||||
|
| defaulttainttracking.cpp:69:33:69:38 | call to getenv | test_diff.cpp:1:11:1:20 | p#0 |
|
||||||
|
| defaulttainttracking.cpp:72:11:72:16 | call to getenv | defaulttainttracking.cpp:45:20:45:29 | p#0 |
|
||||||
|
| defaulttainttracking.cpp:72:11:72:16 | call to getenv | defaulttainttracking.cpp:52:24:52:24 | p |
|
||||||
|
| defaulttainttracking.cpp:72:11:72:16 | call to getenv | defaulttainttracking.cpp:72:11:72:16 | call to getenv |
|
||||||
|
| defaulttainttracking.cpp:72:11:72:16 | call to getenv | defaulttainttracking.cpp:72:11:72:23 | (const char *)... |
|
||||||
|
| defaulttainttracking.cpp:74:18:74:23 | call to getenv | defaulttainttracking.cpp:52:24:52:24 | p |
|
||||||
|
| defaulttainttracking.cpp:74:18:74:23 | call to getenv | defaulttainttracking.cpp:74:18:74:23 | call to getenv |
|
||||||
|
| defaulttainttracking.cpp:74:18:74:23 | call to getenv | defaulttainttracking.cpp:74:18:74:30 | (const char *)... |
|
||||||
|
| defaulttainttracking.cpp:75:29:75:34 | call to getenv | defaulttainttracking.cpp:52:24:52:24 | p |
|
||||||
|
| defaulttainttracking.cpp:75:29:75:34 | call to getenv | defaulttainttracking.cpp:75:29:75:34 | call to getenv |
|
||||||
|
| defaulttainttracking.cpp:75:29:75:34 | call to getenv | defaulttainttracking.cpp:75:29:75:41 | (const char *)... |
|
||||||
|
| defaulttainttracking.cpp:76:30:76:35 | call to getenv | defaulttainttracking.cpp:52:24:52:24 | p |
|
||||||
|
| defaulttainttracking.cpp:76:30:76:35 | call to getenv | defaulttainttracking.cpp:76:30:76:35 | call to getenv |
|
||||||
|
| defaulttainttracking.cpp:76:30:76:35 | call to getenv | defaulttainttracking.cpp:76:30:76:42 | (const char *)... |
|
||||||
|
| defaulttainttracking.cpp:77:34:77:39 | call to getenv | defaulttainttracking.cpp:52:24:52:24 | p |
|
||||||
|
| defaulttainttracking.cpp:77:34:77:39 | call to getenv | defaulttainttracking.cpp:77:34:77:39 | call to getenv |
|
||||||
|
| defaulttainttracking.cpp:77:34:77:39 | call to getenv | defaulttainttracking.cpp:77:34:77:46 | (const char *)... |
|
||||||
|
| defaulttainttracking.cpp:79:30:79:35 | call to getenv | defaulttainttracking.cpp:9:11:9:20 | p#0 |
|
||||||
|
| defaulttainttracking.cpp:79:30:79:35 | call to getenv | defaulttainttracking.cpp:57:24:57:24 | p |
|
||||||
|
| defaulttainttracking.cpp:79:30:79:35 | call to getenv | defaulttainttracking.cpp:58:14:58:14 | p |
|
||||||
|
| defaulttainttracking.cpp:79:30:79:35 | call to getenv | defaulttainttracking.cpp:79:30:79:35 | call to getenv |
|
||||||
|
| defaulttainttracking.cpp:79:30:79:35 | call to getenv | defaulttainttracking.cpp:79:30:79:42 | (const char *)... |
|
||||||
|
| defaulttainttracking.cpp:79:30:79:35 | call to getenv | test_diff.cpp:1:11:1:20 | p#0 |
|
||||||
|
| test_diff.cpp:92:10:92:13 | argv | defaulttainttracking.cpp:9:11:9:20 | p#0 |
|
||||||
|
| test_diff.cpp:92:10:92:13 | argv | test_diff.cpp:1:11:1:20 | p#0 |
|
||||||
|
| test_diff.cpp:92:10:92:13 | argv | test_diff.cpp:92:10:92:13 | argv |
|
||||||
|
| test_diff.cpp:92:10:92:13 | argv | test_diff.cpp:92:10:92:16 | (const char *)... |
|
||||||
|
| test_diff.cpp:92:10:92:13 | argv | test_diff.cpp:92:10:92:16 | access to array |
|
||||||
|
| test_diff.cpp:94:32:94:35 | argv | defaulttainttracking.cpp:10:11:10:13 | p#0 |
|
||||||
|
| test_diff.cpp:94:32:94:35 | argv | test_diff.cpp:2:11:2:13 | p#0 |
|
||||||
|
| test_diff.cpp:94:32:94:35 | argv | test_diff.cpp:94:10:94:36 | reinterpret_cast<int>... |
|
||||||
|
| test_diff.cpp:94:32:94:35 | argv | test_diff.cpp:94:32:94:35 | argv |
|
||||||
|
| test_diff.cpp:96:26:96:29 | argv | defaulttainttracking.cpp:9:11:9:20 | p#0 |
|
||||||
|
| test_diff.cpp:96:26:96:29 | argv | test_diff.cpp:1:11:1:20 | p#0 |
|
||||||
|
| test_diff.cpp:96:26:96:29 | argv | test_diff.cpp:16:39:16:39 | a |
|
||||||
|
| test_diff.cpp:96:26:96:29 | argv | test_diff.cpp:17:10:17:10 | a |
|
||||||
|
| test_diff.cpp:96:26:96:29 | argv | test_diff.cpp:96:26:96:29 | argv |
|
||||||
|
| test_diff.cpp:96:26:96:29 | argv | test_diff.cpp:96:26:96:32 | (const char *)... |
|
||||||
|
| test_diff.cpp:96:26:96:29 | argv | test_diff.cpp:96:26:96:32 | access to array |
|
||||||
|
| test_diff.cpp:98:18:98:21 | argv | defaulttainttracking.cpp:9:11:9:20 | p#0 |
|
||||||
|
| test_diff.cpp:98:18:98:21 | argv | test_diff.cpp:1:11:1:20 | p#0 |
|
||||||
|
| test_diff.cpp:98:18:98:21 | argv | test_diff.cpp:16:39:16:39 | a |
|
||||||
|
| test_diff.cpp:98:18:98:21 | argv | test_diff.cpp:17:10:17:10 | a |
|
||||||
|
| test_diff.cpp:98:18:98:21 | argv | test_diff.cpp:98:13:98:13 | p |
|
||||||
|
| test_diff.cpp:98:18:98:21 | argv | test_diff.cpp:98:17:98:21 | & ... |
|
||||||
|
| test_diff.cpp:98:18:98:21 | argv | test_diff.cpp:98:18:98:21 | argv |
|
||||||
|
| test_diff.cpp:98:18:98:21 | argv | test_diff.cpp:100:10:100:14 | (const char *)... |
|
||||||
|
| test_diff.cpp:98:18:98:21 | argv | test_diff.cpp:100:10:100:14 | * ... |
|
||||||
|
| test_diff.cpp:98:18:98:21 | argv | test_diff.cpp:100:11:100:11 | p |
|
||||||
|
| test_diff.cpp:98:18:98:21 | argv | test_diff.cpp:100:11:100:14 | access to array |
|
||||||
|
| test_diff.cpp:98:18:98:21 | argv | test_diff.cpp:102:26:102:30 | (const char *)... |
|
||||||
|
| test_diff.cpp:98:18:98:21 | argv | test_diff.cpp:102:26:102:30 | * ... |
|
||||||
|
| test_diff.cpp:98:18:98:21 | argv | test_diff.cpp:102:27:102:27 | p |
|
||||||
|
| test_diff.cpp:98:18:98:21 | argv | test_diff.cpp:102:27:102:30 | access to array |
|
||||||
|
| test_diff.cpp:104:12:104:15 | argv | defaulttainttracking.cpp:9:11:9:20 | p#0 |
|
||||||
|
| test_diff.cpp:104:12:104:15 | argv | test_diff.cpp:1:11:1:20 | p#0 |
|
||||||
|
| test_diff.cpp:104:12:104:15 | argv | test_diff.cpp:104:10:104:20 | (const char *)... |
|
||||||
|
| test_diff.cpp:104:12:104:15 | argv | test_diff.cpp:104:10:104:20 | * ... |
|
||||||
|
| test_diff.cpp:104:12:104:15 | argv | test_diff.cpp:104:11:104:20 | (...) |
|
||||||
|
| test_diff.cpp:104:12:104:15 | argv | test_diff.cpp:104:12:104:15 | argv |
|
||||||
|
| test_diff.cpp:104:12:104:15 | argv | test_diff.cpp:104:12:104:19 | ... + ... |
|
||||||
|
| test_diff.cpp:108:10:108:13 | argv | defaulttainttracking.cpp:9:11:9:20 | p#0 |
|
||||||
|
| test_diff.cpp:108:10:108:13 | argv | test_diff.cpp:1:11:1:20 | p#0 |
|
||||||
|
| test_diff.cpp:108:10:108:13 | argv | test_diff.cpp:24:20:24:29 | p#0 |
|
||||||
|
| test_diff.cpp:108:10:108:13 | argv | test_diff.cpp:29:24:29:24 | p |
|
||||||
|
| test_diff.cpp:108:10:108:13 | argv | test_diff.cpp:30:14:30:14 | p |
|
||||||
|
| test_diff.cpp:108:10:108:13 | argv | test_diff.cpp:108:10:108:13 | argv |
|
||||||
|
| test_diff.cpp:108:10:108:13 | argv | test_diff.cpp:108:10:108:16 | (const char *)... |
|
||||||
|
| test_diff.cpp:108:10:108:13 | argv | test_diff.cpp:108:10:108:16 | access to array |
|
||||||
|
| test_diff.cpp:111:10:111:13 | argv | test_diff.cpp:24:20:24:29 | p#0 |
|
||||||
|
| test_diff.cpp:111:10:111:13 | argv | test_diff.cpp:36:24:36:24 | p |
|
||||||
|
| test_diff.cpp:111:10:111:13 | argv | test_diff.cpp:111:10:111:13 | argv |
|
||||||
|
| test_diff.cpp:111:10:111:13 | argv | test_diff.cpp:111:10:111:16 | (const char *)... |
|
||||||
|
| test_diff.cpp:111:10:111:13 | argv | test_diff.cpp:111:10:111:16 | access to array |
|
||||||
|
| test_diff.cpp:115:11:115:14 | argv | defaulttainttracking.cpp:9:11:9:20 | p#0 |
|
||||||
|
| test_diff.cpp:115:11:115:14 | argv | test_diff.cpp:1:11:1:20 | p#0 |
|
||||||
|
| test_diff.cpp:115:11:115:14 | argv | test_diff.cpp:24:20:24:29 | p#0 |
|
||||||
|
| test_diff.cpp:115:11:115:14 | argv | test_diff.cpp:41:24:41:24 | p |
|
||||||
|
| test_diff.cpp:115:11:115:14 | argv | test_diff.cpp:42:14:42:14 | p |
|
||||||
|
| test_diff.cpp:115:11:115:14 | argv | test_diff.cpp:52:24:52:24 | p |
|
||||||
|
| test_diff.cpp:115:11:115:14 | argv | test_diff.cpp:53:37:53:37 | p |
|
||||||
|
| test_diff.cpp:115:11:115:14 | argv | test_diff.cpp:115:11:115:14 | argv |
|
||||||
|
| test_diff.cpp:115:11:115:14 | argv | test_diff.cpp:115:11:115:17 | (const char *)... |
|
||||||
|
| test_diff.cpp:115:11:115:14 | argv | test_diff.cpp:115:11:115:17 | access to array |
|
||||||
|
| test_diff.cpp:118:26:118:29 | argv | test_diff.cpp:60:24:60:24 | p |
|
||||||
|
| test_diff.cpp:118:26:118:29 | argv | test_diff.cpp:61:34:61:34 | p |
|
||||||
|
| test_diff.cpp:118:26:118:29 | argv | test_diff.cpp:88:24:88:24 | p |
|
||||||
|
| test_diff.cpp:118:26:118:29 | argv | test_diff.cpp:118:26:118:29 | argv |
|
||||||
|
| test_diff.cpp:118:26:118:29 | argv | test_diff.cpp:118:26:118:32 | (const char *)... |
|
||||||
|
| test_diff.cpp:118:26:118:29 | argv | test_diff.cpp:118:26:118:32 | access to array |
|
||||||
|
| test_diff.cpp:121:23:121:26 | argv | defaulttainttracking.cpp:9:11:9:20 | p#0 |
|
||||||
|
| test_diff.cpp:121:23:121:26 | argv | test_diff.cpp:1:11:1:20 | p#0 |
|
||||||
|
| test_diff.cpp:121:23:121:26 | argv | test_diff.cpp:60:24:60:24 | p |
|
||||||
|
| test_diff.cpp:121:23:121:26 | argv | test_diff.cpp:61:34:61:34 | p |
|
||||||
|
| test_diff.cpp:121:23:121:26 | argv | test_diff.cpp:67:24:67:24 | p |
|
||||||
|
| test_diff.cpp:121:23:121:26 | argv | test_diff.cpp:68:14:68:14 | p |
|
||||||
|
| test_diff.cpp:121:23:121:26 | argv | test_diff.cpp:121:23:121:26 | argv |
|
||||||
|
| test_diff.cpp:121:23:121:26 | argv | test_diff.cpp:121:23:121:29 | (const char *)... |
|
||||||
|
| test_diff.cpp:121:23:121:26 | argv | test_diff.cpp:121:23:121:29 | access to array |
|
||||||
|
| test_diff.cpp:124:19:124:22 | argv | defaulttainttracking.cpp:9:11:9:20 | p#0 |
|
||||||
|
| test_diff.cpp:124:19:124:22 | argv | test_diff.cpp:1:11:1:20 | p#0 |
|
||||||
|
| test_diff.cpp:124:19:124:22 | argv | test_diff.cpp:24:20:24:29 | p#0 |
|
||||||
|
| test_diff.cpp:124:19:124:22 | argv | test_diff.cpp:76:24:76:24 | p |
|
||||||
|
| test_diff.cpp:124:19:124:22 | argv | test_diff.cpp:81:24:81:24 | p |
|
||||||
|
| test_diff.cpp:124:19:124:22 | argv | test_diff.cpp:82:14:82:14 | p |
|
||||||
|
| test_diff.cpp:124:19:124:22 | argv | test_diff.cpp:124:19:124:22 | argv |
|
||||||
|
| test_diff.cpp:124:19:124:22 | argv | test_diff.cpp:124:19:124:25 | (const char *)... |
|
||||||
|
| test_diff.cpp:124:19:124:22 | argv | test_diff.cpp:124:19:124:25 | access to array |
|
||||||
|
| test_diff.cpp:126:43:126:46 | argv | defaulttainttracking.cpp:9:11:9:20 | p#0 |
|
||||||
|
| test_diff.cpp:126:43:126:46 | argv | test_diff.cpp:1:11:1:20 | p#0 |
|
||||||
|
| test_diff.cpp:126:43:126:46 | argv | test_diff.cpp:76:24:76:24 | p |
|
||||||
|
| test_diff.cpp:126:43:126:46 | argv | test_diff.cpp:81:24:81:24 | p |
|
||||||
|
| test_diff.cpp:126:43:126:46 | argv | test_diff.cpp:82:14:82:14 | p |
|
||||||
|
| test_diff.cpp:126:43:126:46 | argv | test_diff.cpp:126:43:126:46 | argv |
|
||||||
|
| test_diff.cpp:126:43:126:46 | argv | test_diff.cpp:126:43:126:49 | (const char *)... |
|
||||||
|
| test_diff.cpp:126:43:126:46 | argv | test_diff.cpp:126:43:126:49 | access to array |
|
||||||
|
| test_diff.cpp:128:44:128:47 | argv | defaulttainttracking.cpp:9:11:9:20 | p#0 |
|
||||||
|
| test_diff.cpp:128:44:128:47 | argv | test_diff.cpp:1:11:1:20 | p#0 |
|
||||||
|
| test_diff.cpp:128:44:128:47 | argv | test_diff.cpp:76:24:76:24 | p |
|
||||||
|
| test_diff.cpp:128:44:128:47 | argv | test_diff.cpp:81:24:81:24 | p |
|
||||||
|
| test_diff.cpp:128:44:128:47 | argv | test_diff.cpp:82:14:82:14 | p |
|
||||||
|
| test_diff.cpp:128:44:128:47 | argv | test_diff.cpp:128:44:128:47 | argv |
|
||||||
|
| test_diff.cpp:128:44:128:47 | argv | test_diff.cpp:128:44:128:50 | (const char *)... |
|
||||||
|
| test_diff.cpp:128:44:128:47 | argv | test_diff.cpp:128:44:128:50 | access to array |
|
||||||
|
|||||||
@@ -0,0 +1,129 @@
|
|||||||
|
void sink(const char *);
|
||||||
|
void sink(int);
|
||||||
|
|
||||||
|
struct S {
|
||||||
|
void(*f)(const char*);
|
||||||
|
|
||||||
|
void apply(char* p) {
|
||||||
|
f(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
void (*get())(const char*) {
|
||||||
|
return f;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
void calls_sink_with_argv(const char* a) {
|
||||||
|
sink(a);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern int i;
|
||||||
|
|
||||||
|
class BaseWithPureVirtual {
|
||||||
|
public:
|
||||||
|
virtual void f(const char*) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
class DerivedCallsSink : public BaseWithPureVirtual {
|
||||||
|
public:
|
||||||
|
void f(const char* p) override {
|
||||||
|
sink(p);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class DerivedDoesNotCallSink : public BaseWithPureVirtual {
|
||||||
|
public:
|
||||||
|
void f(const char* p) override {}
|
||||||
|
};
|
||||||
|
|
||||||
|
class DerivedCallsSinkDiamond1 : virtual public BaseWithPureVirtual {
|
||||||
|
public:
|
||||||
|
void f(const char* p) override {
|
||||||
|
sink(p);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class DerivedDoesNotCallSinkDiamond2 : virtual public BaseWithPureVirtual {
|
||||||
|
public:
|
||||||
|
void f(const char* p) override {}
|
||||||
|
};
|
||||||
|
|
||||||
|
class DerivesMultiple : public DerivedCallsSinkDiamond1, public DerivedDoesNotCallSinkDiamond2 {
|
||||||
|
void f(const char* p) override {
|
||||||
|
DerivedCallsSinkDiamond1::f(p);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
class CRTP {
|
||||||
|
public:
|
||||||
|
void f(const char* p) {
|
||||||
|
static_cast<T*>(this)->g(p);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class CRTPCallsSink : public CRTP<CRTPCallsSink> {
|
||||||
|
public:
|
||||||
|
void g(const char* p) {
|
||||||
|
sink(p);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class Derived1 : public BaseWithPureVirtual {};
|
||||||
|
|
||||||
|
class Derived2 : public Derived1 {
|
||||||
|
public:
|
||||||
|
void f(const char* p) override {}
|
||||||
|
};
|
||||||
|
|
||||||
|
class Derived3 : public Derived2 {
|
||||||
|
public:
|
||||||
|
void f(const char* p) override {
|
||||||
|
sink(p);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class CRTPDoesNotCallSink : public CRTP<CRTPDoesNotCallSink> {
|
||||||
|
public:
|
||||||
|
void g(const char* p) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
int main(int argc, char *argv[]) {
|
||||||
|
sink(argv[0]);
|
||||||
|
|
||||||
|
sink(reinterpret_cast<int>(argv));
|
||||||
|
|
||||||
|
calls_sink_with_argv(argv[1]);
|
||||||
|
|
||||||
|
char*** p = &argv;
|
||||||
|
|
||||||
|
sink(*p[0]);
|
||||||
|
|
||||||
|
calls_sink_with_argv(*p[i]);
|
||||||
|
|
||||||
|
sink(*(argv + 1));
|
||||||
|
|
||||||
|
BaseWithPureVirtual* b = new DerivedCallsSink;
|
||||||
|
|
||||||
|
b->f(argv[1]);
|
||||||
|
|
||||||
|
b = new DerivedDoesNotCallSink;
|
||||||
|
b->f(argv[0]); // no flow [FALSE POSITIVE by AST]
|
||||||
|
|
||||||
|
BaseWithPureVirtual* b2 = new DerivesMultiple;
|
||||||
|
|
||||||
|
b2->f(argv[i]);
|
||||||
|
|
||||||
|
CRTP<CRTPDoesNotCallSink> crtp_not_call_sink;
|
||||||
|
crtp_not_call_sink.f(argv[0]);
|
||||||
|
|
||||||
|
CRTP<CRTPCallsSink> crtp_calls_sink;
|
||||||
|
crtp_calls_sink.f(argv[0]);
|
||||||
|
|
||||||
|
Derived1* calls_sink = new Derived3;
|
||||||
|
calls_sink->f(argv[1]);
|
||||||
|
|
||||||
|
static_cast<Derived2*>(calls_sink)->f(argv[1]);
|
||||||
|
|
||||||
|
dynamic_cast<Derived2*>(calls_sink)->f(argv[1]); // flow [NOT DETECTED by IR]
|
||||||
|
}
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
| defaulttainttracking.cpp:16:16:16:21 | call to getenv | defaulttainttracking.cpp:9:11:9:20 | p#0 | IR only |
|
||||||
|
| defaulttainttracking.cpp:16:16:16:21 | call to getenv | defaulttainttracking.cpp:16:8:16:14 | call to _strdup | IR only |
|
||||||
|
| defaulttainttracking.cpp:16:16:16:21 | call to getenv | defaulttainttracking.cpp:16:8:16:29 | (const char *)... | IR only |
|
||||||
|
| defaulttainttracking.cpp:16:16:16:21 | call to getenv | test_diff.cpp:1:11:1:20 | p#0 | IR only |
|
||||||
|
| defaulttainttracking.cpp:22:20:22:25 | call to getenv | defaulttainttracking.cpp:3:21:3:22 | s1 | AST only |
|
||||||
|
| defaulttainttracking.cpp:22:20:22:25 | call to getenv | defaulttainttracking.cpp:21:8:21:10 | buf | AST only |
|
||||||
|
| defaulttainttracking.cpp:22:20:22:25 | call to getenv | defaulttainttracking.cpp:22:15:22:17 | buf | AST only |
|
||||||
|
| defaulttainttracking.cpp:38:25:38:30 | call to getenv | defaulttainttracking.cpp:31:40:31:53 | dotted_address | AST only |
|
||||||
|
| defaulttainttracking.cpp:38:25:38:30 | call to getenv | defaulttainttracking.cpp:39:36:39:61 | (const char *)... | AST only |
|
||||||
|
| defaulttainttracking.cpp:38:25:38:30 | call to getenv | defaulttainttracking.cpp:39:51:39:61 | env_pointer | AST only |
|
||||||
|
| defaulttainttracking.cpp:64:10:64:15 | call to getenv | defaulttainttracking.cpp:52:24:52:24 | p | IR only |
|
||||||
|
| test_diff.cpp:104:12:104:15 | argv | test_diff.cpp:104:11:104:20 | (...) | IR only |
|
||||||
|
| test_diff.cpp:108:10:108:13 | argv | test_diff.cpp:36:24:36:24 | p | AST only |
|
||||||
|
| test_diff.cpp:111:10:111:13 | argv | defaulttainttracking.cpp:9:11:9:20 | p#0 | AST only |
|
||||||
|
| test_diff.cpp:111:10:111:13 | argv | test_diff.cpp:1:11:1:20 | p#0 | AST only |
|
||||||
|
| test_diff.cpp:111:10:111:13 | argv | test_diff.cpp:29:24:29:24 | p | AST only |
|
||||||
|
| test_diff.cpp:111:10:111:13 | argv | test_diff.cpp:30:14:30:14 | p | AST only |
|
||||||
|
| test_diff.cpp:124:19:124:22 | argv | test_diff.cpp:76:24:76:24 | p | IR only |
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
import cpp
|
||||||
|
import semmle.code.cpp.security.Security
|
||||||
|
import semmle.code.cpp.security.TaintTracking as ASTTaintTracking
|
||||||
|
import semmle.code.cpp.ir.dataflow.DefaultTaintTracking as IRDefaultTaintTracking
|
||||||
|
|
||||||
|
predicate astFlow(Expr source, Element sink) { ASTTaintTracking::tainted(source, sink) }
|
||||||
|
|
||||||
|
predicate irFlow(Expr source, Element sink) { IRDefaultTaintTracking::tainted(source, sink) }
|
||||||
|
|
||||||
|
from Expr source, Element sink, string note
|
||||||
|
where
|
||||||
|
astFlow(source, sink) and
|
||||||
|
not irFlow(source, sink) and
|
||||||
|
note = "AST only"
|
||||||
|
or
|
||||||
|
irFlow(source, sink) and
|
||||||
|
not astFlow(source, sink) and
|
||||||
|
note = "IR only"
|
||||||
|
select source, sink, note
|
||||||
@@ -130,3 +130,46 @@ namespace virtual_inheritance {
|
|||||||
sink(topRef.isSource()); // flow [NOT DETECTED]
|
sink(topRef.isSource()); // flow [NOT DETECTED]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
union union_with_sink_fun_ptrs {
|
||||||
|
SinkFunctionType f;
|
||||||
|
SinkFunctionType g;
|
||||||
|
} u;
|
||||||
|
|
||||||
|
void call_sink_through_union_field_f(SinkFunctionType func) {
|
||||||
|
func(source());
|
||||||
|
}
|
||||||
|
|
||||||
|
void call_sink_through_union_field_g(SinkFunctionType func) {
|
||||||
|
func(source());
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_global_union_field_f() {
|
||||||
|
u.f = callSink;
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_call_sink_through_union() {
|
||||||
|
set_global_union_field_f();
|
||||||
|
call_sink_through_union_field_f(u.f);
|
||||||
|
call_sink_through_union_field_g(u.g);
|
||||||
|
}
|
||||||
|
|
||||||
|
union { union_with_sink_fun_ptrs u; } u2;
|
||||||
|
|
||||||
|
void call_sink_through_union_field_u_g(SinkFunctionType func) {
|
||||||
|
func(source());
|
||||||
|
}
|
||||||
|
|
||||||
|
void call_sink_through_union_field_u_f(SinkFunctionType func) {
|
||||||
|
func(source());
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_global_union_field_u_f() {
|
||||||
|
u2.u.f = callSink;
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_call_sink_through_union_2() {
|
||||||
|
set_global_union_field_u_f();
|
||||||
|
call_sink_through_union_field_u_f(u2.u.f); // flow [NOT DETECTED]
|
||||||
|
call_sink_through_union_field_u_g(u2.u.g); // flow [NOT DETECTED]
|
||||||
|
}
|
||||||
@@ -17,6 +17,8 @@
|
|||||||
| dispatch.cpp:73:14:73:19 | dispatch.cpp:23:38:23:38 | IR only |
|
| dispatch.cpp:73:14:73:19 | dispatch.cpp:23:38:23:38 | IR only |
|
||||||
| dispatch.cpp:81:13:81:18 | dispatch.cpp:23:38:23:38 | IR only |
|
| dispatch.cpp:81:13:81:18 | dispatch.cpp:23:38:23:38 | IR only |
|
||||||
| dispatch.cpp:107:17:107:22 | dispatch.cpp:96:8:96:8 | IR only |
|
| dispatch.cpp:107:17:107:22 | dispatch.cpp:96:8:96:8 | IR only |
|
||||||
|
| dispatch.cpp:140:8:140:13 | dispatch.cpp:96:8:96:8 | IR only |
|
||||||
|
| dispatch.cpp:144:8:144:13 | dispatch.cpp:96:8:96:8 | IR only |
|
||||||
| lambdas.cpp:8:10:8:15 | lambdas.cpp:14:3:14:6 | AST only |
|
| lambdas.cpp:8:10:8:15 | lambdas.cpp:14:3:14:6 | AST only |
|
||||||
| lambdas.cpp:8:10:8:15 | lambdas.cpp:18:8:18:8 | AST only |
|
| lambdas.cpp:8:10:8:15 | lambdas.cpp:18:8:18:8 | AST only |
|
||||||
| lambdas.cpp:8:10:8:15 | lambdas.cpp:21:3:21:6 | AST only |
|
| lambdas.cpp:8:10:8:15 | lambdas.cpp:21:3:21:6 | AST only |
|
||||||
|
|||||||
@@ -30,6 +30,8 @@
|
|||||||
| dispatch.cpp:55:22:55:30 | call to isSource1 | dispatch.cpp:22:37:22:42 | call to source |
|
| dispatch.cpp:55:22:55:30 | call to isSource1 | dispatch.cpp:22:37:22:42 | call to source |
|
||||||
| dispatch.cpp:58:28:58:36 | call to isSource1 | dispatch.cpp:22:37:22:42 | call to source |
|
| dispatch.cpp:58:28:58:36 | call to isSource1 | dispatch.cpp:22:37:22:42 | call to source |
|
||||||
| dispatch.cpp:96:8:96:8 | x | dispatch.cpp:107:17:107:22 | call to source |
|
| dispatch.cpp:96:8:96:8 | x | dispatch.cpp:107:17:107:22 | call to source |
|
||||||
|
| dispatch.cpp:96:8:96:8 | x | dispatch.cpp:140:8:140:13 | call to source |
|
||||||
|
| dispatch.cpp:96:8:96:8 | x | dispatch.cpp:144:8:144:13 | call to source |
|
||||||
| lambdas.cpp:35:8:35:8 | a | lambdas.cpp:8:10:8:15 | call to source |
|
| lambdas.cpp:35:8:35:8 | a | lambdas.cpp:8:10:8:15 | call to source |
|
||||||
| test.cpp:7:8:7:9 | t1 | test.cpp:6:12:6:17 | call to source |
|
| test.cpp:7:8:7:9 | t1 | test.cpp:6:12:6:17 | call to source |
|
||||||
| test.cpp:9:8:9:9 | t1 | test.cpp:6:12:6:17 | call to source |
|
| test.cpp:9:8:9:9 | t1 | test.cpp:6:12:6:17 | call to source |
|
||||||
|
|||||||
@@ -0,0 +1,54 @@
|
|||||||
|
| test.cpp:23:23:23:28 | call to getenv | test.cpp:8:24:8:25 | s1 | |
|
||||||
|
| test.cpp:23:23:23:28 | call to getenv | test.cpp:23:14:23:19 | envStr | |
|
||||||
|
| test.cpp:23:23:23:28 | call to getenv | test.cpp:23:23:23:28 | call to getenv | |
|
||||||
|
| test.cpp:23:23:23:28 | call to getenv | test.cpp:23:23:23:40 | (const char *)... | |
|
||||||
|
| test.cpp:23:23:23:28 | call to getenv | test.cpp:25:6:25:29 | ! ... | |
|
||||||
|
| test.cpp:23:23:23:28 | call to getenv | test.cpp:25:7:25:12 | call to strcmp | |
|
||||||
|
| test.cpp:23:23:23:28 | call to getenv | test.cpp:25:7:25:29 | (bool)... | |
|
||||||
|
| test.cpp:23:23:23:28 | call to getenv | test.cpp:25:14:25:19 | envStr | |
|
||||||
|
| test.cpp:23:23:23:28 | call to getenv | test.cpp:29:6:29:28 | ! ... | |
|
||||||
|
| test.cpp:23:23:23:28 | call to getenv | test.cpp:29:7:29:12 | call to strcmp | |
|
||||||
|
| test.cpp:23:23:23:28 | call to getenv | test.cpp:29:7:29:28 | (bool)... | |
|
||||||
|
| test.cpp:23:23:23:28 | call to getenv | test.cpp:29:14:29:19 | envStr | |
|
||||||
|
| test.cpp:38:23:38:28 | call to getenv | test.cpp:8:24:8:25 | s1 | |
|
||||||
|
| test.cpp:38:23:38:28 | call to getenv | test.cpp:38:14:38:19 | envStr | |
|
||||||
|
| test.cpp:38:23:38:28 | call to getenv | test.cpp:38:23:38:28 | call to getenv | |
|
||||||
|
| test.cpp:38:23:38:28 | call to getenv | test.cpp:38:23:38:40 | (const char *)... | |
|
||||||
|
| test.cpp:38:23:38:28 | call to getenv | test.cpp:40:14:40:19 | envStr | |
|
||||||
|
| test.cpp:49:23:49:28 | call to getenv | test.cpp:8:24:8:25 | s1 | envStrGlobal |
|
||||||
|
| test.cpp:49:23:49:28 | call to getenv | test.cpp:45:13:45:24 | envStrGlobal | |
|
||||||
|
| test.cpp:49:23:49:28 | call to getenv | test.cpp:45:13:45:24 | envStrGlobal | envStrGlobal |
|
||||||
|
| test.cpp:49:23:49:28 | call to getenv | test.cpp:49:14:49:19 | envStr | |
|
||||||
|
| test.cpp:49:23:49:28 | call to getenv | test.cpp:49:23:49:28 | call to getenv | |
|
||||||
|
| test.cpp:49:23:49:28 | call to getenv | test.cpp:49:23:49:40 | (const char *)... | |
|
||||||
|
| test.cpp:49:23:49:28 | call to getenv | test.cpp:50:15:50:24 | envStr_ptr | |
|
||||||
|
| test.cpp:49:23:49:28 | call to getenv | test.cpp:50:15:50:24 | envStr_ptr | envStrGlobal |
|
||||||
|
| test.cpp:49:23:49:28 | call to getenv | test.cpp:50:28:50:40 | & ... | envStrGlobal |
|
||||||
|
| test.cpp:49:23:49:28 | call to getenv | test.cpp:50:29:50:40 | envStrGlobal | envStrGlobal |
|
||||||
|
| test.cpp:49:23:49:28 | call to getenv | test.cpp:52:2:52:12 | * ... | |
|
||||||
|
| test.cpp:49:23:49:28 | call to getenv | test.cpp:52:3:52:12 | envStr_ptr | |
|
||||||
|
| test.cpp:49:23:49:28 | call to getenv | test.cpp:52:16:52:21 | envStr | |
|
||||||
|
| test.cpp:49:23:49:28 | call to getenv | test.cpp:54:6:54:35 | ! ... | envStrGlobal |
|
||||||
|
| test.cpp:49:23:49:28 | call to getenv | test.cpp:54:7:54:12 | call to strcmp | envStrGlobal |
|
||||||
|
| test.cpp:49:23:49:28 | call to getenv | test.cpp:54:7:54:35 | (bool)... | envStrGlobal |
|
||||||
|
| test.cpp:49:23:49:28 | call to getenv | test.cpp:54:14:54:25 | envStrGlobal | envStrGlobal |
|
||||||
|
| test.cpp:60:29:60:34 | call to getenv | test.cpp:10:27:10:27 | s | |
|
||||||
|
| test.cpp:60:29:60:34 | call to getenv | test.cpp:60:18:60:25 | userName | |
|
||||||
|
| test.cpp:60:29:60:34 | call to getenv | test.cpp:60:29:60:34 | call to getenv | |
|
||||||
|
| test.cpp:60:29:60:34 | call to getenv | test.cpp:60:29:60:47 | (const char *)... | |
|
||||||
|
| test.cpp:60:29:60:34 | call to getenv | test.cpp:64:25:64:32 | userName | |
|
||||||
|
| test.cpp:68:28:68:33 | call to getenv | test.cpp:11:20:11:21 | s1 | |
|
||||||
|
| test.cpp:68:28:68:33 | call to getenv | test.cpp:11:36:11:37 | s2 | |
|
||||||
|
| test.cpp:68:28:68:33 | call to getenv | test.cpp:67:7:67:13 | copying | |
|
||||||
|
| test.cpp:68:28:68:33 | call to getenv | test.cpp:68:17:68:24 | userName | |
|
||||||
|
| test.cpp:68:28:68:33 | call to getenv | test.cpp:68:28:68:33 | call to getenv | |
|
||||||
|
| test.cpp:68:28:68:33 | call to getenv | test.cpp:68:28:68:46 | (const char *)... | |
|
||||||
|
| test.cpp:68:28:68:33 | call to getenv | test.cpp:69:10:69:13 | copy | |
|
||||||
|
| test.cpp:68:28:68:33 | call to getenv | test.cpp:70:5:70:10 | call to strcpy | |
|
||||||
|
| test.cpp:68:28:68:33 | call to getenv | test.cpp:70:12:70:15 | copy | |
|
||||||
|
| test.cpp:68:28:68:33 | call to getenv | test.cpp:70:18:70:25 | userName | |
|
||||||
|
| test.cpp:68:28:68:33 | call to getenv | test.cpp:71:12:71:15 | copy | |
|
||||||
|
| test.cpp:75:20:75:25 | call to getenv | test.cpp:15:22:15:25 | nptr | |
|
||||||
|
| test.cpp:75:20:75:25 | call to getenv | test.cpp:75:15:75:18 | call to atoi | |
|
||||||
|
| test.cpp:75:20:75:25 | call to getenv | test.cpp:75:20:75:25 | call to getenv | |
|
||||||
|
| test.cpp:75:20:75:25 | call to getenv | test.cpp:75:20:75:45 | (const char *)... | |
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
import semmle.code.cpp.security.TaintTracking
|
||||||
|
|
||||||
|
from Expr source, Element tainted, string globalVar
|
||||||
|
where
|
||||||
|
taintedIncludingGlobalVars(source, tainted, globalVar) and
|
||||||
|
not tainted.getLocation().getFile().getExtension() = "h"
|
||||||
|
select source, tainted, globalVar
|
||||||
78
cpp/ql/test/library-tests/dataflow/security-taint/test.cpp
Normal file
78
cpp/ql/test/library-tests/dataflow/security-taint/test.cpp
Normal file
@@ -0,0 +1,78 @@
|
|||||||
|
// Test for the general-purpose taint-tracking
|
||||||
|
// mechanism that is used by several of the security queries.
|
||||||
|
|
||||||
|
///// Library functions //////
|
||||||
|
|
||||||
|
typedef unsigned long size_t;
|
||||||
|
|
||||||
|
int strcmp(const char *s1, const char *s2);
|
||||||
|
char *getenv(const char *name);
|
||||||
|
size_t strlen(const char *s);
|
||||||
|
char *strcpy(char *s1, const char *s2);
|
||||||
|
|
||||||
|
void *malloc(size_t size);
|
||||||
|
|
||||||
|
int atoi(const char *nptr);
|
||||||
|
|
||||||
|
//// Test code /////
|
||||||
|
|
||||||
|
bool isAdmin = false;
|
||||||
|
|
||||||
|
void test1()
|
||||||
|
{
|
||||||
|
const char *envStr = getenv("USERINFO");
|
||||||
|
|
||||||
|
if (!strcmp(envStr, "admin")) {
|
||||||
|
isAdmin = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!strcmp(envStr, "none")) {
|
||||||
|
isAdmin = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extern const char *specialUser;
|
||||||
|
|
||||||
|
void test2()
|
||||||
|
{
|
||||||
|
const char *envStr = getenv("USERINFO");
|
||||||
|
|
||||||
|
if (!strcmp(envStr, specialUser)) {
|
||||||
|
isAdmin = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *envStrGlobal;
|
||||||
|
|
||||||
|
void test3()
|
||||||
|
{
|
||||||
|
const char *envStr = getenv("USERINFO");
|
||||||
|
const char **envStr_ptr = &envStrGlobal;
|
||||||
|
|
||||||
|
*envStr_ptr = envStr;
|
||||||
|
|
||||||
|
if (!strcmp(envStrGlobal, "admin")) {
|
||||||
|
isAdmin = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void bugWithBinop() {
|
||||||
|
const char *userName = getenv("USER_NAME");
|
||||||
|
|
||||||
|
// The following is tainted, but should not cause
|
||||||
|
// the whole program to be considered tainted.
|
||||||
|
int bytes = strlen(userName) + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
char* copying() {
|
||||||
|
const char *userName = getenv("USER_NAME");
|
||||||
|
char copy[1024];
|
||||||
|
strcpy(copy, userName);
|
||||||
|
return copy; // copy should be tainted
|
||||||
|
}
|
||||||
|
|
||||||
|
void guard() {
|
||||||
|
int len = atoi(getenv("FOOBAZ_BRANCHING"));
|
||||||
|
if (len > 1000) return;
|
||||||
|
char **node = (char **) malloc(len * sizeof(char *));
|
||||||
|
}
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
import cpp
|
import cpp
|
||||||
import semmle.code.cpp.dataflow.TaintTracking
|
import semmle.code.cpp.dataflow.TaintTracking
|
||||||
|
import semmle.code.cpp.models.interfaces.Taint
|
||||||
|
|
||||||
/** Common data flow configuration to be used by tests. */
|
/** Common data flow configuration to be used by tests. */
|
||||||
class TestAllocationConfig extends TaintTracking::Configuration {
|
class TestAllocationConfig extends TaintTracking::Configuration {
|
||||||
@@ -25,3 +26,39 @@ class TestAllocationConfig extends TaintTracking::Configuration {
|
|||||||
barrier.asExpr().(VariableAccess).getTarget().hasName("sanitizer")
|
barrier.asExpr().(VariableAccess).getTarget().hasName("sanitizer")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class SetMemberFunction extends TaintFunction {
|
||||||
|
SetMemberFunction() { this.hasName("setMember") }
|
||||||
|
|
||||||
|
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
|
||||||
|
input.isParameter(0) and
|
||||||
|
output.isQualifierObject()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class GetMemberFunction extends TaintFunction {
|
||||||
|
GetMemberFunction() { this.hasName("getMember") }
|
||||||
|
|
||||||
|
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
|
||||||
|
input.isQualifierObject() and
|
||||||
|
output.isReturnValue()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class SetStringFunction extends TaintFunction {
|
||||||
|
SetStringFunction() { this.hasName("setString") }
|
||||||
|
|
||||||
|
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
|
||||||
|
input.isParameterDeref(0) and
|
||||||
|
output.isQualifierObject()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class GetStringFunction extends TaintFunction {
|
||||||
|
GetStringFunction() { this.hasName("getString") }
|
||||||
|
|
||||||
|
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
|
||||||
|
input.isQualifierObject() and
|
||||||
|
output.isReturnValueDeref()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
134
cpp/ql/test/library-tests/dataflow/taint-tests/format.cpp
Normal file
134
cpp/ql/test/library-tests/dataflow/taint-tests/format.cpp
Normal file
@@ -0,0 +1,134 @@
|
|||||||
|
|
||||||
|
typedef unsigned long size_t;
|
||||||
|
typedef struct {} FILE;
|
||||||
|
|
||||||
|
int snprintf(char *s, size_t n, const char *format, ...);
|
||||||
|
int sprintf(char *s, const char *format, ...);
|
||||||
|
int swprintf(wchar_t *s, size_t n, const wchar_t *format, ...);
|
||||||
|
|
||||||
|
typedef void *va_list;
|
||||||
|
#define va_start(ap, parmN)
|
||||||
|
#define va_end(ap)
|
||||||
|
#define va_arg(ap, type) ((type)0)
|
||||||
|
|
||||||
|
int vsnprintf(char *s, size_t n, const char *format, va_list arg);
|
||||||
|
|
||||||
|
int mysprintf(char *s, size_t n, const char *format, ...)
|
||||||
|
{
|
||||||
|
va_list args;
|
||||||
|
va_start(args, format);
|
||||||
|
vsnprintf(s, n, format, args);
|
||||||
|
va_end(args);
|
||||||
|
}
|
||||||
|
|
||||||
|
int sscanf(const char *s, const char *format, ...);
|
||||||
|
|
||||||
|
// ----------
|
||||||
|
|
||||||
|
int source();
|
||||||
|
void sink(...) {};
|
||||||
|
|
||||||
|
namespace string
|
||||||
|
{
|
||||||
|
char *source();
|
||||||
|
};
|
||||||
|
|
||||||
|
namespace wstring
|
||||||
|
{
|
||||||
|
wchar_t *source();
|
||||||
|
};
|
||||||
|
|
||||||
|
// ----------
|
||||||
|
|
||||||
|
void test1()
|
||||||
|
{
|
||||||
|
{
|
||||||
|
char buffer[256] = {0};
|
||||||
|
sink(snprintf(buffer, 256, "%s", "Hello."));
|
||||||
|
sink(buffer);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
char buffer[256] = {0};
|
||||||
|
sink(snprintf(buffer, 256, "%s", string::source()));
|
||||||
|
sink(buffer); // tainted
|
||||||
|
}
|
||||||
|
{
|
||||||
|
char buffer[256] = {0};
|
||||||
|
sink(snprintf(buffer, 256, string::source(), "Hello."));
|
||||||
|
sink(buffer); // tainted
|
||||||
|
}
|
||||||
|
{
|
||||||
|
char buffer[256] = {0};
|
||||||
|
sink(snprintf(buffer, 256, "%s %s %s", "a", "b", string::source()));
|
||||||
|
sink(buffer); // tainted
|
||||||
|
}
|
||||||
|
{
|
||||||
|
char buffer[256] = {0};
|
||||||
|
sink(snprintf(buffer, 256, "%.*s", 10, string::source()));
|
||||||
|
sink(buffer); // tainted
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
char buffer[256] = {0};
|
||||||
|
sink(snprintf(buffer, 256, "%i", 0));
|
||||||
|
sink(buffer);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
char buffer[256] = {0};
|
||||||
|
sink(snprintf(buffer, 256, "%i", source()));
|
||||||
|
sink(buffer); // tainted
|
||||||
|
}
|
||||||
|
{
|
||||||
|
char buffer[256] = {0};
|
||||||
|
sink(snprintf(buffer, 256, "%.*s", source(), "Hello."));
|
||||||
|
sink(buffer); // tainted
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
char buffer[256] = {0};
|
||||||
|
sink(snprintf(buffer, 256, "%p", string::source()));
|
||||||
|
sink(buffer); // tainted (debatable)
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
char buffer[256] = {0};
|
||||||
|
sink(sprintf(buffer, "%s", string::source()));
|
||||||
|
sink(buffer); // tainted
|
||||||
|
}
|
||||||
|
{
|
||||||
|
char buffer[256] = {0};
|
||||||
|
sink(sprintf(buffer, "%ls", wstring::source()));
|
||||||
|
sink(buffer); // tainted
|
||||||
|
}
|
||||||
|
{
|
||||||
|
wchar_t wbuffer[256] = {0};
|
||||||
|
sink(swprintf(wbuffer, 256, L"%s", wstring::source()));
|
||||||
|
sink(wbuffer); // tainted
|
||||||
|
}
|
||||||
|
{
|
||||||
|
char buffer[256] = {0};
|
||||||
|
sink(mysprintf(buffer, 256, "%s", string::source()));
|
||||||
|
sink(buffer); // tainted [NOT DETECTED - implement UserDefinedFormattingFunction.getOutputParameterIndex()]
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
int i = 0;
|
||||||
|
sink(sscanf("123", "%i", &i));
|
||||||
|
sink(i);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
int i = 0;
|
||||||
|
sink(sscanf(string::source(), "%i", &i));
|
||||||
|
sink(i); // tainted [NOT DETECTED]
|
||||||
|
}
|
||||||
|
{
|
||||||
|
char buffer[256] = {0};
|
||||||
|
sink(sscanf("Hello.", "%s", &buffer));
|
||||||
|
sink(buffer);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
char buffer[256] = {0};
|
||||||
|
sink(sscanf(string::source(), "%s", &buffer));
|
||||||
|
sink(buffer); // tainted [NOT DETECTED]
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -3,6 +3,108 @@
|
|||||||
| file://:0:0:0:0 | p#0 | file://:0:0:0:0 | p#0 | |
|
| file://:0:0:0:0 | p#0 | file://:0:0:0:0 | p#0 | |
|
||||||
| file://:0:0:0:0 | p#0 | file://:0:0:0:0 | p#0 | |
|
| file://:0:0:0:0 | p#0 | file://:0:0:0:0 | p#0 | |
|
||||||
| file://:0:0:0:0 | p#0 | file://:0:0:0:0 | p#0 | |
|
| file://:0:0:0:0 | p#0 | file://:0:0:0:0 | p#0 | |
|
||||||
|
| format.cpp:16:21:16:21 | s | format.cpp:20:13:20:13 | s | |
|
||||||
|
| format.cpp:16:31:16:31 | n | format.cpp:20:16:20:16 | n | |
|
||||||
|
| format.cpp:16:46:16:51 | format | format.cpp:20:19:20:24 | format | |
|
||||||
|
| format.cpp:18:10:18:13 | args | format.cpp:20:27:20:30 | args | |
|
||||||
|
| format.cpp:46:21:46:24 | {...} | format.cpp:47:17:47:22 | buffer | |
|
||||||
|
| format.cpp:46:21:46:24 | {...} | format.cpp:48:8:48:13 | buffer | |
|
||||||
|
| format.cpp:46:23:46:23 | 0 | format.cpp:46:21:46:24 | {...} | TAINT |
|
||||||
|
| format.cpp:47:17:47:22 | ref arg buffer | format.cpp:48:8:48:13 | buffer | |
|
||||||
|
| format.cpp:47:30:47:33 | %s | format.cpp:47:17:47:22 | ref arg buffer | TAINT |
|
||||||
|
| format.cpp:47:36:47:43 | Hello. | format.cpp:47:17:47:22 | ref arg buffer | TAINT |
|
||||||
|
| format.cpp:51:21:51:24 | {...} | format.cpp:52:17:52:22 | buffer | |
|
||||||
|
| format.cpp:51:21:51:24 | {...} | format.cpp:53:8:53:13 | buffer | |
|
||||||
|
| format.cpp:51:23:51:23 | 0 | format.cpp:51:21:51:24 | {...} | TAINT |
|
||||||
|
| format.cpp:52:17:52:22 | ref arg buffer | format.cpp:53:8:53:13 | buffer | |
|
||||||
|
| format.cpp:52:30:52:33 | %s | format.cpp:52:17:52:22 | ref arg buffer | TAINT |
|
||||||
|
| format.cpp:52:36:52:49 | call to source | format.cpp:52:17:52:22 | ref arg buffer | TAINT |
|
||||||
|
| format.cpp:56:21:56:24 | {...} | format.cpp:57:17:57:22 | buffer | |
|
||||||
|
| format.cpp:56:21:56:24 | {...} | format.cpp:58:8:58:13 | buffer | |
|
||||||
|
| format.cpp:56:23:56:23 | 0 | format.cpp:56:21:56:24 | {...} | TAINT |
|
||||||
|
| format.cpp:57:17:57:22 | ref arg buffer | format.cpp:58:8:58:13 | buffer | |
|
||||||
|
| format.cpp:57:30:57:43 | call to source | format.cpp:57:17:57:22 | ref arg buffer | TAINT |
|
||||||
|
| format.cpp:57:48:57:55 | Hello. | format.cpp:57:17:57:22 | ref arg buffer | TAINT |
|
||||||
|
| format.cpp:61:21:61:24 | {...} | format.cpp:62:17:62:22 | buffer | |
|
||||||
|
| format.cpp:61:21:61:24 | {...} | format.cpp:63:8:63:13 | buffer | |
|
||||||
|
| format.cpp:61:23:61:23 | 0 | format.cpp:61:21:61:24 | {...} | TAINT |
|
||||||
|
| format.cpp:62:17:62:22 | ref arg buffer | format.cpp:63:8:63:13 | buffer | |
|
||||||
|
| format.cpp:62:30:62:39 | %s %s %s | format.cpp:62:17:62:22 | ref arg buffer | TAINT |
|
||||||
|
| format.cpp:62:42:62:44 | a | format.cpp:62:17:62:22 | ref arg buffer | TAINT |
|
||||||
|
| format.cpp:62:47:62:49 | b | format.cpp:62:17:62:22 | ref arg buffer | TAINT |
|
||||||
|
| format.cpp:62:52:62:65 | call to source | format.cpp:62:17:62:22 | ref arg buffer | TAINT |
|
||||||
|
| format.cpp:66:21:66:24 | {...} | format.cpp:67:17:67:22 | buffer | |
|
||||||
|
| format.cpp:66:21:66:24 | {...} | format.cpp:68:8:68:13 | buffer | |
|
||||||
|
| format.cpp:66:23:66:23 | 0 | format.cpp:66:21:66:24 | {...} | TAINT |
|
||||||
|
| format.cpp:67:17:67:22 | ref arg buffer | format.cpp:68:8:68:13 | buffer | |
|
||||||
|
| format.cpp:67:30:67:35 | %.*s | format.cpp:67:17:67:22 | ref arg buffer | TAINT |
|
||||||
|
| format.cpp:67:38:67:39 | 10 | format.cpp:67:17:67:22 | ref arg buffer | TAINT |
|
||||||
|
| format.cpp:67:42:67:55 | call to source | format.cpp:67:17:67:22 | ref arg buffer | TAINT |
|
||||||
|
| format.cpp:72:21:72:24 | {...} | format.cpp:73:17:73:22 | buffer | |
|
||||||
|
| format.cpp:72:21:72:24 | {...} | format.cpp:74:8:74:13 | buffer | |
|
||||||
|
| format.cpp:72:23:72:23 | 0 | format.cpp:72:21:72:24 | {...} | TAINT |
|
||||||
|
| format.cpp:73:17:73:22 | ref arg buffer | format.cpp:74:8:74:13 | buffer | |
|
||||||
|
| format.cpp:73:30:73:33 | %i | format.cpp:73:17:73:22 | ref arg buffer | TAINT |
|
||||||
|
| format.cpp:73:36:73:36 | 0 | format.cpp:73:17:73:22 | ref arg buffer | TAINT |
|
||||||
|
| format.cpp:77:21:77:24 | {...} | format.cpp:78:17:78:22 | buffer | |
|
||||||
|
| format.cpp:77:21:77:24 | {...} | format.cpp:79:8:79:13 | buffer | |
|
||||||
|
| format.cpp:77:23:77:23 | 0 | format.cpp:77:21:77:24 | {...} | TAINT |
|
||||||
|
| format.cpp:78:17:78:22 | ref arg buffer | format.cpp:79:8:79:13 | buffer | |
|
||||||
|
| format.cpp:78:30:78:33 | %i | format.cpp:78:17:78:22 | ref arg buffer | TAINT |
|
||||||
|
| format.cpp:78:36:78:41 | call to source | format.cpp:78:17:78:22 | ref arg buffer | TAINT |
|
||||||
|
| format.cpp:82:21:82:24 | {...} | format.cpp:83:17:83:22 | buffer | |
|
||||||
|
| format.cpp:82:21:82:24 | {...} | format.cpp:84:8:84:13 | buffer | |
|
||||||
|
| format.cpp:82:23:82:23 | 0 | format.cpp:82:21:82:24 | {...} | TAINT |
|
||||||
|
| format.cpp:83:17:83:22 | ref arg buffer | format.cpp:84:8:84:13 | buffer | |
|
||||||
|
| format.cpp:83:30:83:35 | %.*s | format.cpp:83:17:83:22 | ref arg buffer | TAINT |
|
||||||
|
| format.cpp:83:38:83:43 | call to source | format.cpp:83:17:83:22 | ref arg buffer | TAINT |
|
||||||
|
| format.cpp:83:48:83:55 | Hello. | format.cpp:83:17:83:22 | ref arg buffer | TAINT |
|
||||||
|
| format.cpp:88:21:88:24 | {...} | format.cpp:89:17:89:22 | buffer | |
|
||||||
|
| format.cpp:88:21:88:24 | {...} | format.cpp:90:8:90:13 | buffer | |
|
||||||
|
| format.cpp:88:23:88:23 | 0 | format.cpp:88:21:88:24 | {...} | TAINT |
|
||||||
|
| format.cpp:89:17:89:22 | ref arg buffer | format.cpp:90:8:90:13 | buffer | |
|
||||||
|
| format.cpp:89:30:89:33 | %p | format.cpp:89:17:89:22 | ref arg buffer | TAINT |
|
||||||
|
| format.cpp:89:36:89:49 | call to source | format.cpp:89:17:89:22 | ref arg buffer | TAINT |
|
||||||
|
| format.cpp:94:21:94:24 | {...} | format.cpp:95:16:95:21 | buffer | |
|
||||||
|
| format.cpp:94:21:94:24 | {...} | format.cpp:96:8:96:13 | buffer | |
|
||||||
|
| format.cpp:94:23:94:23 | 0 | format.cpp:94:21:94:24 | {...} | TAINT |
|
||||||
|
| format.cpp:95:16:95:21 | ref arg buffer | format.cpp:96:8:96:13 | buffer | |
|
||||||
|
| format.cpp:95:24:95:27 | %s | format.cpp:95:16:95:21 | ref arg buffer | TAINT |
|
||||||
|
| format.cpp:95:30:95:43 | call to source | format.cpp:95:16:95:21 | ref arg buffer | TAINT |
|
||||||
|
| format.cpp:99:21:99:24 | {...} | format.cpp:100:16:100:21 | buffer | |
|
||||||
|
| format.cpp:99:21:99:24 | {...} | format.cpp:101:8:101:13 | buffer | |
|
||||||
|
| format.cpp:99:23:99:23 | 0 | format.cpp:99:21:99:24 | {...} | TAINT |
|
||||||
|
| format.cpp:100:16:100:21 | ref arg buffer | format.cpp:101:8:101:13 | buffer | |
|
||||||
|
| format.cpp:100:24:100:28 | %ls | format.cpp:100:16:100:21 | ref arg buffer | TAINT |
|
||||||
|
| format.cpp:100:31:100:45 | call to source | format.cpp:100:16:100:21 | ref arg buffer | TAINT |
|
||||||
|
| format.cpp:104:25:104:28 | {...} | format.cpp:105:17:105:23 | wbuffer | |
|
||||||
|
| format.cpp:104:25:104:28 | {...} | format.cpp:106:8:106:14 | wbuffer | |
|
||||||
|
| format.cpp:104:27:104:27 | 0 | format.cpp:104:25:104:28 | {...} | TAINT |
|
||||||
|
| format.cpp:105:17:105:23 | ref arg wbuffer | format.cpp:106:8:106:14 | wbuffer | |
|
||||||
|
| format.cpp:105:31:105:35 | %s | format.cpp:105:17:105:23 | ref arg wbuffer | TAINT |
|
||||||
|
| format.cpp:105:38:105:52 | call to source | format.cpp:105:17:105:23 | ref arg wbuffer | TAINT |
|
||||||
|
| format.cpp:109:21:109:24 | {...} | format.cpp:110:18:110:23 | buffer | |
|
||||||
|
| format.cpp:109:21:109:24 | {...} | format.cpp:111:8:111:13 | buffer | |
|
||||||
|
| format.cpp:109:23:109:23 | 0 | format.cpp:109:21:109:24 | {...} | TAINT |
|
||||||
|
| format.cpp:110:18:110:23 | ref arg buffer | format.cpp:111:8:111:13 | buffer | |
|
||||||
|
| format.cpp:115:10:115:11 | 0 | format.cpp:116:29:116:29 | i | |
|
||||||
|
| format.cpp:115:10:115:11 | 0 | format.cpp:117:8:117:8 | i | |
|
||||||
|
| format.cpp:116:28:116:29 | ref arg & ... | format.cpp:117:8:117:8 | i | |
|
||||||
|
| format.cpp:116:29:116:29 | i | format.cpp:116:28:116:29 | & ... | |
|
||||||
|
| format.cpp:120:10:120:11 | 0 | format.cpp:121:40:121:40 | i | |
|
||||||
|
| format.cpp:120:10:120:11 | 0 | format.cpp:122:8:122:8 | i | |
|
||||||
|
| format.cpp:121:39:121:40 | ref arg & ... | format.cpp:122:8:122:8 | i | |
|
||||||
|
| format.cpp:121:40:121:40 | i | format.cpp:121:39:121:40 | & ... | |
|
||||||
|
| format.cpp:125:21:125:24 | {...} | format.cpp:126:32:126:37 | buffer | |
|
||||||
|
| format.cpp:125:21:125:24 | {...} | format.cpp:127:8:127:13 | buffer | |
|
||||||
|
| format.cpp:125:23:125:23 | 0 | format.cpp:125:21:125:24 | {...} | TAINT |
|
||||||
|
| format.cpp:126:31:126:37 | ref arg & ... | format.cpp:127:8:127:13 | buffer | |
|
||||||
|
| format.cpp:126:32:126:37 | buffer | format.cpp:126:31:126:37 | & ... | |
|
||||||
|
| format.cpp:130:21:130:24 | {...} | format.cpp:131:40:131:45 | buffer | |
|
||||||
|
| format.cpp:130:21:130:24 | {...} | format.cpp:132:8:132:13 | buffer | |
|
||||||
|
| format.cpp:130:23:130:23 | 0 | format.cpp:130:21:130:24 | {...} | TAINT |
|
||||||
|
| format.cpp:131:39:131:45 | ref arg & ... | format.cpp:132:8:132:13 | buffer | |
|
||||||
|
| format.cpp:131:40:131:45 | buffer | format.cpp:131:39:131:45 | & ... | |
|
||||||
| taint.cpp:4:27:4:33 | source1 | taint.cpp:6:13:6:19 | source1 | |
|
| taint.cpp:4:27:4:33 | source1 | taint.cpp:6:13:6:19 | source1 | |
|
||||||
| taint.cpp:4:40:4:45 | clean1 | taint.cpp:5:8:5:13 | clean1 | |
|
| taint.cpp:4:40:4:45 | clean1 | taint.cpp:5:8:5:13 | clean1 | |
|
||||||
| taint.cpp:4:40:4:45 | clean1 | taint.cpp:6:3:6:8 | clean1 | |
|
| taint.cpp:4:40:4:45 | clean1 | taint.cpp:6:3:6:8 | clean1 | |
|
||||||
@@ -337,9 +439,13 @@
|
|||||||
| taint.cpp:370:13:370:26 | hello, world | taint.cpp:370:6:370:11 | call to strdup | TAINT |
|
| taint.cpp:370:13:370:26 | hello, world | taint.cpp:370:6:370:11 | call to strdup | TAINT |
|
||||||
| taint.cpp:371:6:371:12 | call to strndup | taint.cpp:371:2:371:25 | ... = ... | |
|
| taint.cpp:371:6:371:12 | call to strndup | taint.cpp:371:2:371:25 | ... = ... | |
|
||||||
| taint.cpp:371:6:371:12 | call to strndup | taint.cpp:374:7:374:7 | c | |
|
| taint.cpp:371:6:371:12 | call to strndup | taint.cpp:374:7:374:7 | c | |
|
||||||
|
| taint.cpp:371:14:371:19 | source | taint.cpp:371:6:371:12 | call to strndup | TAINT |
|
||||||
|
| taint.cpp:371:22:371:24 | 100 | taint.cpp:371:6:371:12 | call to strndup | TAINT |
|
||||||
| taint.cpp:377:23:377:28 | source | taint.cpp:381:30:381:35 | source | |
|
| taint.cpp:377:23:377:28 | source | taint.cpp:381:30:381:35 | source | |
|
||||||
| taint.cpp:381:6:381:12 | call to strndup | taint.cpp:381:2:381:36 | ... = ... | |
|
| taint.cpp:381:6:381:12 | call to strndup | taint.cpp:381:2:381:36 | ... = ... | |
|
||||||
| taint.cpp:381:6:381:12 | call to strndup | taint.cpp:382:7:382:7 | a | |
|
| taint.cpp:381:6:381:12 | call to strndup | taint.cpp:382:7:382:7 | a | |
|
||||||
|
| taint.cpp:381:14:381:27 | hello, world | taint.cpp:381:6:381:12 | call to strndup | TAINT |
|
||||||
|
| taint.cpp:381:30:381:35 | source | taint.cpp:381:6:381:12 | call to strndup | TAINT |
|
||||||
| taint.cpp:385:27:385:32 | source | taint.cpp:389:13:389:18 | source | |
|
| taint.cpp:385:27:385:32 | source | taint.cpp:389:13:389:18 | source | |
|
||||||
| taint.cpp:389:6:389:11 | call to wcsdup | taint.cpp:389:2:389:19 | ... = ... | |
|
| taint.cpp:389:6:389:11 | call to wcsdup | taint.cpp:389:2:389:19 | ... = ... | |
|
||||||
| taint.cpp:389:6:389:11 | call to wcsdup | taint.cpp:391:7:391:7 | a | |
|
| taint.cpp:389:6:389:11 | call to wcsdup | taint.cpp:391:7:391:7 | a | |
|
||||||
@@ -347,3 +453,62 @@
|
|||||||
| taint.cpp:390:6:390:11 | call to wcsdup | taint.cpp:390:2:390:28 | ... = ... | |
|
| taint.cpp:390:6:390:11 | call to wcsdup | taint.cpp:390:2:390:28 | ... = ... | |
|
||||||
| taint.cpp:390:6:390:11 | call to wcsdup | taint.cpp:392:7:392:7 | b | |
|
| taint.cpp:390:6:390:11 | call to wcsdup | taint.cpp:392:7:392:7 | b | |
|
||||||
| taint.cpp:390:13:390:27 | hello, world | taint.cpp:390:6:390:11 | call to wcsdup | TAINT |
|
| taint.cpp:390:13:390:27 | hello, world | taint.cpp:390:6:390:11 | call to wcsdup | TAINT |
|
||||||
|
| taint.cpp:417:13:417:14 | call to MyClass2 | taint.cpp:420:7:420:7 | a | |
|
||||||
|
| taint.cpp:417:13:417:14 | call to MyClass2 | taint.cpp:421:7:421:7 | a | |
|
||||||
|
| taint.cpp:417:13:417:14 | call to MyClass2 | taint.cpp:422:2:422:2 | a | |
|
||||||
|
| taint.cpp:417:13:417:14 | call to MyClass2 | taint.cpp:423:7:423:7 | a | |
|
||||||
|
| taint.cpp:417:13:417:14 | call to MyClass2 | taint.cpp:424:7:424:7 | a | |
|
||||||
|
| taint.cpp:417:19:417:20 | call to MyClass2 | taint.cpp:426:7:426:7 | b | |
|
||||||
|
| taint.cpp:417:19:417:20 | call to MyClass2 | taint.cpp:427:7:427:7 | b | |
|
||||||
|
| taint.cpp:417:19:417:20 | call to MyClass2 | taint.cpp:428:2:428:2 | b | |
|
||||||
|
| taint.cpp:417:19:417:20 | call to MyClass2 | taint.cpp:429:7:429:7 | b | |
|
||||||
|
| taint.cpp:417:19:417:20 | call to MyClass2 | taint.cpp:430:7:430:7 | b | |
|
||||||
|
| taint.cpp:417:19:417:20 | call to MyClass2 | taint.cpp:431:7:431:7 | b | |
|
||||||
|
| taint.cpp:418:13:418:15 | call to MyClass3 | taint.cpp:443:7:443:7 | d | |
|
||||||
|
| taint.cpp:418:13:418:15 | call to MyClass3 | taint.cpp:444:7:444:7 | d | |
|
||||||
|
| taint.cpp:418:13:418:15 | call to MyClass3 | taint.cpp:445:2:445:2 | d | |
|
||||||
|
| taint.cpp:418:13:418:15 | call to MyClass3 | taint.cpp:446:7:446:7 | d | |
|
||||||
|
| taint.cpp:418:13:418:15 | call to MyClass3 | taint.cpp:447:7:447:7 | d | |
|
||||||
|
| taint.cpp:421:7:421:7 | a [post update] | taint.cpp:422:2:422:2 | a | |
|
||||||
|
| taint.cpp:421:7:421:7 | a [post update] | taint.cpp:423:7:423:7 | a | |
|
||||||
|
| taint.cpp:421:7:421:7 | a [post update] | taint.cpp:424:7:424:7 | a | |
|
||||||
|
| taint.cpp:422:2:422:2 | a [post update] | taint.cpp:423:7:423:7 | a | |
|
||||||
|
| taint.cpp:422:2:422:2 | a [post update] | taint.cpp:424:7:424:7 | a | |
|
||||||
|
| taint.cpp:427:7:427:7 | b [post update] | taint.cpp:428:2:428:2 | b | |
|
||||||
|
| taint.cpp:427:7:427:7 | b [post update] | taint.cpp:429:7:429:7 | b | |
|
||||||
|
| taint.cpp:427:7:427:7 | b [post update] | taint.cpp:430:7:430:7 | b | |
|
||||||
|
| taint.cpp:427:7:427:7 | b [post update] | taint.cpp:431:7:431:7 | b | |
|
||||||
|
| taint.cpp:428:2:428:2 | b [post update] | taint.cpp:429:7:429:7 | b | |
|
||||||
|
| taint.cpp:428:2:428:2 | b [post update] | taint.cpp:430:7:430:7 | b | |
|
||||||
|
| taint.cpp:428:2:428:2 | b [post update] | taint.cpp:431:7:431:7 | b | |
|
||||||
|
| taint.cpp:428:2:428:20 | ... = ... | taint.cpp:430:9:430:14 | member | |
|
||||||
|
| taint.cpp:428:13:428:18 | call to source | taint.cpp:428:2:428:20 | ... = ... | |
|
||||||
|
| taint.cpp:433:6:433:20 | call to MyClass2 | taint.cpp:433:6:433:20 | new | |
|
||||||
|
| taint.cpp:433:6:433:20 | new | taint.cpp:433:2:433:20 | ... = ... | |
|
||||||
|
| taint.cpp:433:6:433:20 | new | taint.cpp:435:7:435:7 | c | |
|
||||||
|
| taint.cpp:433:6:433:20 | new | taint.cpp:436:7:436:7 | c | |
|
||||||
|
| taint.cpp:433:6:433:20 | new | taint.cpp:437:2:437:2 | c | |
|
||||||
|
| taint.cpp:433:6:433:20 | new | taint.cpp:438:7:438:7 | c | |
|
||||||
|
| taint.cpp:433:6:433:20 | new | taint.cpp:439:7:439:7 | c | |
|
||||||
|
| taint.cpp:433:6:433:20 | new | taint.cpp:441:9:441:9 | c | |
|
||||||
|
| taint.cpp:435:7:435:7 | ref arg c | taint.cpp:436:7:436:7 | c | |
|
||||||
|
| taint.cpp:435:7:435:7 | ref arg c | taint.cpp:437:2:437:2 | c | |
|
||||||
|
| taint.cpp:435:7:435:7 | ref arg c | taint.cpp:438:7:438:7 | c | |
|
||||||
|
| taint.cpp:435:7:435:7 | ref arg c | taint.cpp:439:7:439:7 | c | |
|
||||||
|
| taint.cpp:435:7:435:7 | ref arg c | taint.cpp:441:9:441:9 | c | |
|
||||||
|
| taint.cpp:436:7:436:7 | c [post update] | taint.cpp:437:2:437:2 | c | |
|
||||||
|
| taint.cpp:436:7:436:7 | c [post update] | taint.cpp:438:7:438:7 | c | |
|
||||||
|
| taint.cpp:436:7:436:7 | c [post update] | taint.cpp:439:7:439:7 | c | |
|
||||||
|
| taint.cpp:436:7:436:7 | c [post update] | taint.cpp:441:9:441:9 | c | |
|
||||||
|
| taint.cpp:437:2:437:2 | c [post update] | taint.cpp:438:7:438:7 | c | |
|
||||||
|
| taint.cpp:437:2:437:2 | c [post update] | taint.cpp:439:7:439:7 | c | |
|
||||||
|
| taint.cpp:437:2:437:2 | c [post update] | taint.cpp:441:9:441:9 | c | |
|
||||||
|
| taint.cpp:438:7:438:7 | ref arg c | taint.cpp:439:7:439:7 | c | |
|
||||||
|
| taint.cpp:438:7:438:7 | ref arg c | taint.cpp:441:9:441:9 | c | |
|
||||||
|
| taint.cpp:439:7:439:7 | c [post update] | taint.cpp:441:9:441:9 | c | |
|
||||||
|
| taint.cpp:441:9:441:9 | c | taint.cpp:441:2:441:9 | delete | TAINT |
|
||||||
|
| taint.cpp:444:7:444:7 | d [post update] | taint.cpp:445:2:445:2 | d | |
|
||||||
|
| taint.cpp:444:7:444:7 | d [post update] | taint.cpp:446:7:446:7 | d | |
|
||||||
|
| taint.cpp:444:7:444:7 | d [post update] | taint.cpp:447:7:447:7 | d | |
|
||||||
|
| taint.cpp:445:2:445:2 | d [post update] | taint.cpp:446:7:446:7 | d | |
|
||||||
|
| taint.cpp:445:2:445:2 | d [post update] | taint.cpp:447:7:447:7 | d | |
|
||||||
|
|||||||
@@ -371,7 +371,7 @@ void test_strdup(char *source)
|
|||||||
c = strndup(source, 100);
|
c = strndup(source, 100);
|
||||||
sink(a); // tainted
|
sink(a); // tainted
|
||||||
sink(b);
|
sink(b);
|
||||||
sink(c); // tainted [NOT DETECTED]
|
sink(c); // tainted
|
||||||
}
|
}
|
||||||
|
|
||||||
void test_strndup(int source)
|
void test_strndup(int source)
|
||||||
@@ -379,7 +379,7 @@ void test_strndup(int source)
|
|||||||
char *a;
|
char *a;
|
||||||
|
|
||||||
a = strndup("hello, world", source);
|
a = strndup("hello, world", source);
|
||||||
sink(a);
|
sink(a); // tainted
|
||||||
}
|
}
|
||||||
|
|
||||||
void test_wcsdup(wchar_t *source)
|
void test_wcsdup(wchar_t *source)
|
||||||
@@ -391,3 +391,58 @@ void test_wcsdup(wchar_t *source)
|
|||||||
sink(a); // tainted
|
sink(a); // tainted
|
||||||
sink(b);
|
sink(b);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// --- qualifiers ---
|
||||||
|
|
||||||
|
class MyClass2 {
|
||||||
|
public:
|
||||||
|
MyClass2(int value);
|
||||||
|
void setMember(int value);
|
||||||
|
int getMember();
|
||||||
|
|
||||||
|
int member;
|
||||||
|
};
|
||||||
|
|
||||||
|
class MyClass3 {
|
||||||
|
public:
|
||||||
|
MyClass3(const char *string);
|
||||||
|
void setString(const char *string);
|
||||||
|
const char *getString();
|
||||||
|
|
||||||
|
const char *buffer;
|
||||||
|
};
|
||||||
|
|
||||||
|
void test_qualifiers()
|
||||||
|
{
|
||||||
|
MyClass2 a(0), b(0), *c;
|
||||||
|
MyClass3 d("");
|
||||||
|
|
||||||
|
sink(a);
|
||||||
|
sink(a.getMember());
|
||||||
|
a.setMember(source());
|
||||||
|
sink(a); // tainted
|
||||||
|
sink(a.getMember()); // tainted
|
||||||
|
|
||||||
|
sink(b);
|
||||||
|
sink(b.getMember());
|
||||||
|
b.member = source();
|
||||||
|
sink(b); // tainted
|
||||||
|
sink(b.member); // tainted
|
||||||
|
sink(b.getMember());
|
||||||
|
|
||||||
|
c = new MyClass2(0);
|
||||||
|
|
||||||
|
sink(c);
|
||||||
|
sink(c->getMember());
|
||||||
|
c->setMember(source());
|
||||||
|
sink(c); // tainted (deref)
|
||||||
|
sink(c->getMember()); // tainted
|
||||||
|
|
||||||
|
delete c;
|
||||||
|
|
||||||
|
sink(d);
|
||||||
|
sink(d.getString());
|
||||||
|
d.setString(strings::source());
|
||||||
|
sink(d); // tainted
|
||||||
|
sink(d.getString()); // tainted
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,3 +1,13 @@
|
|||||||
|
| format.cpp:53:8:53:13 | buffer | format.cpp:52:36:52:49 | call to source |
|
||||||
|
| format.cpp:58:8:58:13 | buffer | format.cpp:57:30:57:43 | call to source |
|
||||||
|
| format.cpp:63:8:63:13 | buffer | format.cpp:62:52:62:65 | call to source |
|
||||||
|
| format.cpp:68:8:68:13 | buffer | format.cpp:67:42:67:55 | call to source |
|
||||||
|
| format.cpp:79:8:79:13 | buffer | format.cpp:78:36:78:41 | call to source |
|
||||||
|
| format.cpp:84:8:84:13 | buffer | format.cpp:83:38:83:43 | call to source |
|
||||||
|
| format.cpp:90:8:90:13 | buffer | format.cpp:89:36:89:49 | call to source |
|
||||||
|
| format.cpp:96:8:96:13 | buffer | format.cpp:95:30:95:43 | call to source |
|
||||||
|
| format.cpp:101:8:101:13 | buffer | format.cpp:100:31:100:45 | call to source |
|
||||||
|
| format.cpp:106:8:106:14 | wbuffer | format.cpp:105:38:105:52 | call to source |
|
||||||
| taint.cpp:8:8:8:13 | clean1 | taint.cpp:4:27:4:33 | source1 |
|
| taint.cpp:8:8:8:13 | clean1 | taint.cpp:4:27:4:33 | source1 |
|
||||||
| taint.cpp:16:8:16:14 | source1 | taint.cpp:12:22:12:27 | call to source |
|
| taint.cpp:16:8:16:14 | source1 | taint.cpp:12:22:12:27 | call to source |
|
||||||
| taint.cpp:17:8:17:16 | ++ ... | taint.cpp:12:22:12:27 | call to source |
|
| taint.cpp:17:8:17:16 | ++ ... | taint.cpp:12:22:12:27 | call to source |
|
||||||
@@ -38,4 +48,13 @@
|
|||||||
| taint.cpp:351:7:351:7 | a | taint.cpp:330:6:330:11 | call to source |
|
| taint.cpp:351:7:351:7 | a | taint.cpp:330:6:330:11 | call to source |
|
||||||
| taint.cpp:352:7:352:7 | b | taint.cpp:330:6:330:11 | call to source |
|
| taint.cpp:352:7:352:7 | b | taint.cpp:330:6:330:11 | call to source |
|
||||||
| taint.cpp:372:7:372:7 | a | taint.cpp:365:24:365:29 | source |
|
| taint.cpp:372:7:372:7 | a | taint.cpp:365:24:365:29 | source |
|
||||||
|
| taint.cpp:374:7:374:7 | c | taint.cpp:365:24:365:29 | source |
|
||||||
|
| taint.cpp:382:7:382:7 | a | taint.cpp:377:23:377:28 | source |
|
||||||
| taint.cpp:391:7:391:7 | a | taint.cpp:385:27:385:32 | source |
|
| taint.cpp:391:7:391:7 | a | taint.cpp:385:27:385:32 | source |
|
||||||
|
| taint.cpp:423:7:423:7 | a | taint.cpp:422:14:422:19 | call to source |
|
||||||
|
| taint.cpp:424:9:424:17 | call to getMember | taint.cpp:422:14:422:19 | call to source |
|
||||||
|
| taint.cpp:430:9:430:14 | member | taint.cpp:428:13:428:18 | call to source |
|
||||||
|
| taint.cpp:438:7:438:7 | c | taint.cpp:437:15:437:20 | call to source |
|
||||||
|
| taint.cpp:439:10:439:18 | call to getMember | taint.cpp:437:15:437:20 | call to source |
|
||||||
|
| taint.cpp:446:7:446:7 | d | taint.cpp:445:14:445:28 | call to source |
|
||||||
|
| taint.cpp:447:9:447:17 | call to getString | taint.cpp:445:14:445:28 | call to source |
|
||||||
|
|||||||
@@ -1,3 +1,13 @@
|
|||||||
|
| format.cpp:53:8:53:13 | format.cpp:52:36:52:49 | AST only |
|
||||||
|
| format.cpp:58:8:58:13 | format.cpp:57:30:57:43 | AST only |
|
||||||
|
| format.cpp:63:8:63:13 | format.cpp:62:52:62:65 | AST only |
|
||||||
|
| format.cpp:68:8:68:13 | format.cpp:67:42:67:55 | AST only |
|
||||||
|
| format.cpp:79:8:79:13 | format.cpp:78:36:78:41 | AST only |
|
||||||
|
| format.cpp:84:8:84:13 | format.cpp:83:38:83:43 | AST only |
|
||||||
|
| format.cpp:90:8:90:13 | format.cpp:89:36:89:49 | AST only |
|
||||||
|
| format.cpp:96:8:96:13 | format.cpp:95:30:95:43 | AST only |
|
||||||
|
| format.cpp:101:8:101:13 | format.cpp:100:31:100:45 | AST only |
|
||||||
|
| format.cpp:106:8:106:14 | format.cpp:105:38:105:52 | AST only |
|
||||||
| taint.cpp:41:7:41:13 | taint.cpp:35:12:35:17 | AST only |
|
| taint.cpp:41:7:41:13 | taint.cpp:35:12:35:17 | AST only |
|
||||||
| taint.cpp:42:7:42:13 | taint.cpp:35:12:35:17 | AST only |
|
| taint.cpp:42:7:42:13 | taint.cpp:35:12:35:17 | AST only |
|
||||||
| taint.cpp:43:7:43:13 | taint.cpp:37:22:37:27 | AST only |
|
| taint.cpp:43:7:43:13 | taint.cpp:37:22:37:27 | AST only |
|
||||||
@@ -26,4 +36,13 @@
|
|||||||
| taint.cpp:351:7:351:7 | taint.cpp:330:6:330:11 | AST only |
|
| taint.cpp:351:7:351:7 | taint.cpp:330:6:330:11 | AST only |
|
||||||
| taint.cpp:352:7:352:7 | taint.cpp:330:6:330:11 | AST only |
|
| taint.cpp:352:7:352:7 | taint.cpp:330:6:330:11 | AST only |
|
||||||
| taint.cpp:372:7:372:7 | taint.cpp:365:24:365:29 | AST only |
|
| taint.cpp:372:7:372:7 | taint.cpp:365:24:365:29 | AST only |
|
||||||
|
| taint.cpp:374:7:374:7 | taint.cpp:365:24:365:29 | AST only |
|
||||||
|
| taint.cpp:382:7:382:7 | taint.cpp:377:23:377:28 | AST only |
|
||||||
| taint.cpp:391:7:391:7 | taint.cpp:385:27:385:32 | AST only |
|
| taint.cpp:391:7:391:7 | taint.cpp:385:27:385:32 | AST only |
|
||||||
|
| taint.cpp:423:7:423:7 | taint.cpp:422:14:422:19 | AST only |
|
||||||
|
| taint.cpp:424:9:424:17 | taint.cpp:422:14:422:19 | AST only |
|
||||||
|
| taint.cpp:429:7:429:7 | taint.cpp:428:13:428:18 | IR only |
|
||||||
|
| taint.cpp:438:7:438:7 | taint.cpp:437:15:437:20 | AST only |
|
||||||
|
| taint.cpp:439:10:439:18 | taint.cpp:437:15:437:20 | AST only |
|
||||||
|
| 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 |
|
||||||
|
|||||||
@@ -20,3 +20,5 @@
|
|||||||
| taint.cpp:291:7:291:7 | y | taint.cpp:275:6:275:11 | call to source |
|
| taint.cpp:291:7:291:7 | y | taint.cpp:275:6:275:11 | call to source |
|
||||||
| taint.cpp:337:7:337:7 | t | taint.cpp:330:6:330:11 | call to source |
|
| taint.cpp:337:7:337:7 | t | taint.cpp:330:6:330:11 | call to source |
|
||||||
| taint.cpp:350:7:350:7 | t | taint.cpp:330:6:330:11 | call to source |
|
| taint.cpp:350:7:350:7 | t | taint.cpp:330:6:330:11 | call to source |
|
||||||
|
| taint.cpp:429:7:429:7 | b | taint.cpp:428:13:428:18 | call to source |
|
||||||
|
| taint.cpp:430:9:430:14 | member | taint.cpp:428:13:428:18 | call to source |
|
||||||
|
|||||||
@@ -1 +0,0 @@
|
|||||||
| Test for deprecated library StackVariableReachability. |
|
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
import cpp
|
|
||||||
import semmle.code.cpp.controlflow.StackVariableReachability
|
|
||||||
|
|
||||||
select "Test for deprecated library StackVariableReachability."
|
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
| unused_functions.c:16:13:16:27 | unused_function | Static function unused_function is unreachable | unused_functions.c:16:13:16:27 | unused_function | unused_function |
|
|
||||||
| unused_functions.c:20:13:20:28 | unused_function2 | Static function unused_function2 is unreachable ($@ must be removed at the same time) | unused_functions.c:24:13:24:28 | unused_function3 | unused_function3 |
|
|
||||||
| unused_functions.c:24:13:24:28 | unused_function3 | Static function unused_function3 is unreachable | unused_functions.c:24:13:24:28 | unused_function3 | unused_function3 |
|
|
||||||
| unused_functions.c:63:13:63:14 | h4 | Static function h4 is unreachable | unused_functions.c:63:13:63:14 | h4 | h4 |
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
Best Practices/Unused Entities/UnusedStaticFunctions.ql
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
| unused_mut.c:5:13:5:31 | mut_unused_function | Static function mut_unused_function is unreachable ($@ must be removed at the same time) | unused_mut.c:9:13:9:32 | mut_unused_function2 | mut_unused_function2 |
|
|
||||||
| unused_mut.c:9:13:9:32 | mut_unused_function2 | Static function mut_unused_function2 is unreachable ($@ must be removed at the same time) | unused_mut.c:5:13:5:31 | mut_unused_function | mut_unused_function |
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
Best Practices/Unused Entities/UnusedStaticFunctions.ql
|
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -1 +0,0 @@
|
|||||||
semmle/code/cpp/ir/implementation/aliased_ssa/PrintIR.ql
|
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -1 +0,0 @@
|
|||||||
semmle/code/cpp/ir/implementation/unaliased_ssa/PrintIR.ql
|
|
||||||
@@ -850,23 +850,26 @@ ssa.cpp:
|
|||||||
# 199| r199_8(char *) = Convert : r199_7
|
# 199| r199_8(char *) = Convert : r199_7
|
||||||
# 199| r199_9(int) = Call : func:r199_2, 0:r199_5, 1:r199_8
|
# 199| r199_9(int) = Call : func:r199_2, 0:r199_5, 1:r199_8
|
||||||
# 199| v199_10(void) = ^CallReadSideEffect : ~m198_13
|
# 199| v199_10(void) = ^CallReadSideEffect : ~m198_13
|
||||||
# 199| m199_11(int) = Store : &:r199_1, r199_9
|
# 199| v199_11(void) = ^BufferReadSideEffect[0] : &:r199_5, ~m198_13
|
||||||
|
# 199| v199_12(void) = ^BufferReadSideEffect[1] : &:r199_8, ~m198_13
|
||||||
|
# 199| m199_13(int) = Store : &:r199_1, r199_9
|
||||||
# 200| r200_1(glval<unknown>) = FunctionAddress[strlen] :
|
# 200| r200_1(glval<unknown>) = FunctionAddress[strlen] :
|
||||||
# 200| r200_2(glval<char *>) = VariableAddress[str1] :
|
# 200| r200_2(glval<char *>) = VariableAddress[str1] :
|
||||||
# 200| r200_3(char *) = Load : &:r200_2, m198_5
|
# 200| r200_3(char *) = Load : &:r200_2, m198_5
|
||||||
# 200| r200_4(char *) = Convert : r200_3
|
# 200| r200_4(char *) = Convert : r200_3
|
||||||
# 200| r200_5(int) = Call : func:r200_1, 0:r200_4
|
# 200| r200_5(int) = Call : func:r200_1, 0:r200_4
|
||||||
# 200| v200_6(void) = ^CallReadSideEffect : ~m198_13
|
# 200| v200_6(void) = ^CallReadSideEffect : ~m198_13
|
||||||
# 200| r200_7(glval<int>) = VariableAddress[ret] :
|
# 200| v200_7(void) = ^BufferReadSideEffect[0] : &:r200_4, ~m198_13
|
||||||
# 200| r200_8(int) = Load : &:r200_7, m199_11
|
# 200| r200_8(glval<int>) = VariableAddress[ret] :
|
||||||
# 200| r200_9(int) = Add : r200_8, r200_5
|
# 200| r200_9(int) = Load : &:r200_8, m199_13
|
||||||
# 200| m200_10(int) = Store : &:r200_7, r200_9
|
# 200| r200_10(int) = Add : r200_9, r200_5
|
||||||
|
# 200| m200_11(int) = Store : &:r200_8, r200_10
|
||||||
# 201| r201_1(glval<unknown>) = FunctionAddress[abs] :
|
# 201| r201_1(glval<unknown>) = FunctionAddress[abs] :
|
||||||
# 201| r201_2(glval<int>) = VariableAddress[x] :
|
# 201| r201_2(glval<int>) = VariableAddress[x] :
|
||||||
# 201| r201_3(int) = Load : &:r201_2, m198_15
|
# 201| r201_3(int) = Load : &:r201_2, m198_15
|
||||||
# 201| r201_4(int) = Call : func:r201_1, 0:r201_3
|
# 201| r201_4(int) = Call : func:r201_1, 0:r201_3
|
||||||
# 201| r201_5(glval<int>) = VariableAddress[ret] :
|
# 201| r201_5(glval<int>) = VariableAddress[ret] :
|
||||||
# 201| r201_6(int) = Load : &:r201_5, m200_10
|
# 201| r201_6(int) = Load : &:r201_5, m200_11
|
||||||
# 201| r201_7(int) = Add : r201_6, r201_4
|
# 201| r201_7(int) = Add : r201_6, r201_4
|
||||||
# 201| m201_8(int) = Store : &:r201_5, r201_7
|
# 201| m201_8(int) = Store : &:r201_5, r201_7
|
||||||
# 202| r202_1(glval<int>) = VariableAddress[#return] :
|
# 202| r202_1(glval<int>) = VariableAddress[#return] :
|
||||||
|
|||||||
@@ -847,23 +847,26 @@ ssa.cpp:
|
|||||||
# 199| r199_8(char *) = Convert : r199_7
|
# 199| r199_8(char *) = Convert : r199_7
|
||||||
# 199| r199_9(int) = Call : func:r199_2, 0:r199_5, 1:r199_8
|
# 199| r199_9(int) = Call : func:r199_2, 0:r199_5, 1:r199_8
|
||||||
# 199| v199_10(void) = ^CallReadSideEffect : ~m198_13
|
# 199| v199_10(void) = ^CallReadSideEffect : ~m198_13
|
||||||
# 199| m199_11(int) = Store : &:r199_1, r199_9
|
# 199| v199_11(void) = ^BufferReadSideEffect[0] : &:r199_5, ~m198_13
|
||||||
|
# 199| v199_12(void) = ^BufferReadSideEffect[1] : &:r199_8, ~m198_13
|
||||||
|
# 199| m199_13(int) = Store : &:r199_1, r199_9
|
||||||
# 200| r200_1(glval<unknown>) = FunctionAddress[strlen] :
|
# 200| r200_1(glval<unknown>) = FunctionAddress[strlen] :
|
||||||
# 200| r200_2(glval<char *>) = VariableAddress[str1] :
|
# 200| r200_2(glval<char *>) = VariableAddress[str1] :
|
||||||
# 200| r200_3(char *) = Load : &:r200_2, m198_5
|
# 200| r200_3(char *) = Load : &:r200_2, m198_5
|
||||||
# 200| r200_4(char *) = Convert : r200_3
|
# 200| r200_4(char *) = Convert : r200_3
|
||||||
# 200| r200_5(int) = Call : func:r200_1, 0:r200_4
|
# 200| r200_5(int) = Call : func:r200_1, 0:r200_4
|
||||||
# 200| v200_6(void) = ^CallReadSideEffect : ~m198_13
|
# 200| v200_6(void) = ^CallReadSideEffect : ~m198_13
|
||||||
# 200| r200_7(glval<int>) = VariableAddress[ret] :
|
# 200| v200_7(void) = ^BufferReadSideEffect[0] : &:r200_4, ~m198_13
|
||||||
# 200| r200_8(int) = Load : &:r200_7, m199_11
|
# 200| r200_8(glval<int>) = VariableAddress[ret] :
|
||||||
# 200| r200_9(int) = Add : r200_8, r200_5
|
# 200| r200_9(int) = Load : &:r200_8, m199_13
|
||||||
# 200| m200_10(int) = Store : &:r200_7, r200_9
|
# 200| r200_10(int) = Add : r200_9, r200_5
|
||||||
|
# 200| m200_11(int) = Store : &:r200_8, r200_10
|
||||||
# 201| r201_1(glval<unknown>) = FunctionAddress[abs] :
|
# 201| r201_1(glval<unknown>) = FunctionAddress[abs] :
|
||||||
# 201| r201_2(glval<int>) = VariableAddress[x] :
|
# 201| r201_2(glval<int>) = VariableAddress[x] :
|
||||||
# 201| r201_3(int) = Load : &:r201_2, m198_15
|
# 201| r201_3(int) = Load : &:r201_2, m198_15
|
||||||
# 201| r201_4(int) = Call : func:r201_1, 0:r201_3
|
# 201| r201_4(int) = Call : func:r201_1, 0:r201_3
|
||||||
# 201| r201_5(glval<int>) = VariableAddress[ret] :
|
# 201| r201_5(glval<int>) = VariableAddress[ret] :
|
||||||
# 201| r201_6(int) = Load : &:r201_5, m200_10
|
# 201| r201_6(int) = Load : &:r201_5, m200_11
|
||||||
# 201| r201_7(int) = Add : r201_6, r201_4
|
# 201| r201_7(int) = Add : r201_6, r201_4
|
||||||
# 201| m201_8(int) = Store : &:r201_5, r201_7
|
# 201| m201_8(int) = Store : &:r201_5, r201_7
|
||||||
# 202| r202_1(glval<int>) = VariableAddress[#return] :
|
# 202| r202_1(glval<int>) = VariableAddress[#return] :
|
||||||
|
|||||||
@@ -808,23 +808,26 @@ ssa.cpp:
|
|||||||
# 199| r199_8(char *) = Convert : r199_7
|
# 199| r199_8(char *) = Convert : r199_7
|
||||||
# 199| r199_9(int) = Call : func:r199_2, 0:r199_5, 1:r199_8
|
# 199| r199_9(int) = Call : func:r199_2, 0:r199_5, 1:r199_8
|
||||||
# 199| v199_10(void) = ^CallReadSideEffect : ~mu198_3
|
# 199| v199_10(void) = ^CallReadSideEffect : ~mu198_3
|
||||||
# 199| m199_11(int) = Store : &:r199_1, r199_9
|
# 199| v199_11(void) = ^BufferReadSideEffect[0] : &:r199_5, ~mu198_3
|
||||||
|
# 199| v199_12(void) = ^BufferReadSideEffect[1] : &:r199_8, ~mu198_3
|
||||||
|
# 199| m199_13(int) = Store : &:r199_1, r199_9
|
||||||
# 200| r200_1(glval<unknown>) = FunctionAddress[strlen] :
|
# 200| r200_1(glval<unknown>) = FunctionAddress[strlen] :
|
||||||
# 200| r200_2(glval<char *>) = VariableAddress[str1] :
|
# 200| r200_2(glval<char *>) = VariableAddress[str1] :
|
||||||
# 200| r200_3(char *) = Load : &:r200_2, m198_5
|
# 200| r200_3(char *) = Load : &:r200_2, m198_5
|
||||||
# 200| r200_4(char *) = Convert : r200_3
|
# 200| r200_4(char *) = Convert : r200_3
|
||||||
# 200| r200_5(int) = Call : func:r200_1, 0:r200_4
|
# 200| r200_5(int) = Call : func:r200_1, 0:r200_4
|
||||||
# 200| v200_6(void) = ^CallReadSideEffect : ~mu198_3
|
# 200| v200_6(void) = ^CallReadSideEffect : ~mu198_3
|
||||||
# 200| r200_7(glval<int>) = VariableAddress[ret] :
|
# 200| v200_7(void) = ^BufferReadSideEffect[0] : &:r200_4, ~mu198_3
|
||||||
# 200| r200_8(int) = Load : &:r200_7, m199_11
|
# 200| r200_8(glval<int>) = VariableAddress[ret] :
|
||||||
# 200| r200_9(int) = Add : r200_8, r200_5
|
# 200| r200_9(int) = Load : &:r200_8, m199_13
|
||||||
# 200| m200_10(int) = Store : &:r200_7, r200_9
|
# 200| r200_10(int) = Add : r200_9, r200_5
|
||||||
|
# 200| m200_11(int) = Store : &:r200_8, r200_10
|
||||||
# 201| r201_1(glval<unknown>) = FunctionAddress[abs] :
|
# 201| r201_1(glval<unknown>) = FunctionAddress[abs] :
|
||||||
# 201| r201_2(glval<int>) = VariableAddress[x] :
|
# 201| r201_2(glval<int>) = VariableAddress[x] :
|
||||||
# 201| r201_3(int) = Load : &:r201_2, m198_13
|
# 201| r201_3(int) = Load : &:r201_2, m198_13
|
||||||
# 201| r201_4(int) = Call : func:r201_1, 0:r201_3
|
# 201| r201_4(int) = Call : func:r201_1, 0:r201_3
|
||||||
# 201| r201_5(glval<int>) = VariableAddress[ret] :
|
# 201| r201_5(glval<int>) = VariableAddress[ret] :
|
||||||
# 201| r201_6(int) = Load : &:r201_5, m200_10
|
# 201| r201_6(int) = Load : &:r201_5, m200_11
|
||||||
# 201| r201_7(int) = Add : r201_6, r201_4
|
# 201| r201_7(int) = Add : r201_6, r201_4
|
||||||
# 201| m201_8(int) = Store : &:r201_5, r201_7
|
# 201| m201_8(int) = Store : &:r201_5, r201_7
|
||||||
# 202| r202_1(glval<int>) = VariableAddress[#return] :
|
# 202| r202_1(glval<int>) = VariableAddress[#return] :
|
||||||
|
|||||||
@@ -808,23 +808,26 @@ ssa.cpp:
|
|||||||
# 199| r199_8(char *) = Convert : r199_7
|
# 199| r199_8(char *) = Convert : r199_7
|
||||||
# 199| r199_9(int) = Call : func:r199_2, 0:r199_5, 1:r199_8
|
# 199| r199_9(int) = Call : func:r199_2, 0:r199_5, 1:r199_8
|
||||||
# 199| v199_10(void) = ^CallReadSideEffect : ~mu198_3
|
# 199| v199_10(void) = ^CallReadSideEffect : ~mu198_3
|
||||||
# 199| m199_11(int) = Store : &:r199_1, r199_9
|
# 199| v199_11(void) = ^BufferReadSideEffect[0] : &:r199_5, ~mu198_3
|
||||||
|
# 199| v199_12(void) = ^BufferReadSideEffect[1] : &:r199_8, ~mu198_3
|
||||||
|
# 199| m199_13(int) = Store : &:r199_1, r199_9
|
||||||
# 200| r200_1(glval<unknown>) = FunctionAddress[strlen] :
|
# 200| r200_1(glval<unknown>) = FunctionAddress[strlen] :
|
||||||
# 200| r200_2(glval<char *>) = VariableAddress[str1] :
|
# 200| r200_2(glval<char *>) = VariableAddress[str1] :
|
||||||
# 200| r200_3(char *) = Load : &:r200_2, m198_5
|
# 200| r200_3(char *) = Load : &:r200_2, m198_5
|
||||||
# 200| r200_4(char *) = Convert : r200_3
|
# 200| r200_4(char *) = Convert : r200_3
|
||||||
# 200| r200_5(int) = Call : func:r200_1, 0:r200_4
|
# 200| r200_5(int) = Call : func:r200_1, 0:r200_4
|
||||||
# 200| v200_6(void) = ^CallReadSideEffect : ~mu198_3
|
# 200| v200_6(void) = ^CallReadSideEffect : ~mu198_3
|
||||||
# 200| r200_7(glval<int>) = VariableAddress[ret] :
|
# 200| v200_7(void) = ^BufferReadSideEffect[0] : &:r200_4, ~mu198_3
|
||||||
# 200| r200_8(int) = Load : &:r200_7, m199_11
|
# 200| r200_8(glval<int>) = VariableAddress[ret] :
|
||||||
# 200| r200_9(int) = Add : r200_8, r200_5
|
# 200| r200_9(int) = Load : &:r200_8, m199_13
|
||||||
# 200| m200_10(int) = Store : &:r200_7, r200_9
|
# 200| r200_10(int) = Add : r200_9, r200_5
|
||||||
|
# 200| m200_11(int) = Store : &:r200_8, r200_10
|
||||||
# 201| r201_1(glval<unknown>) = FunctionAddress[abs] :
|
# 201| r201_1(glval<unknown>) = FunctionAddress[abs] :
|
||||||
# 201| r201_2(glval<int>) = VariableAddress[x] :
|
# 201| r201_2(glval<int>) = VariableAddress[x] :
|
||||||
# 201| r201_3(int) = Load : &:r201_2, m198_13
|
# 201| r201_3(int) = Load : &:r201_2, m198_13
|
||||||
# 201| r201_4(int) = Call : func:r201_1, 0:r201_3
|
# 201| r201_4(int) = Call : func:r201_1, 0:r201_3
|
||||||
# 201| r201_5(glval<int>) = VariableAddress[ret] :
|
# 201| r201_5(glval<int>) = VariableAddress[ret] :
|
||||||
# 201| r201_6(int) = Load : &:r201_5, m200_10
|
# 201| r201_6(int) = Load : &:r201_5, m200_11
|
||||||
# 201| r201_7(int) = Add : r201_6, r201_4
|
# 201| r201_7(int) = Add : r201_6, r201_4
|
||||||
# 201| m201_8(int) = Store : &:r201_5, r201_7
|
# 201| m201_8(int) = Store : &:r201_5, r201_7
|
||||||
# 202| r202_1(glval<int>) = VariableAddress[#return] :
|
# 202| r202_1(glval<int>) = VariableAddress[#return] :
|
||||||
|
|||||||
@@ -108,7 +108,7 @@ instructionWithoutSuccessor
|
|||||||
| stmt_in_type.cpp:5:53:5:53 | Constant: 1 |
|
| stmt_in_type.cpp:5:53:5:53 | Constant: 1 |
|
||||||
| vla.c:5:9:5:14 | Uninitialized: definition of matrix |
|
| vla.c:5:9:5:14 | Uninitialized: definition of matrix |
|
||||||
| vla.c:5:16:5:19 | Load: argc |
|
| vla.c:5:16:5:19 | Load: argc |
|
||||||
| vla.c:5:22:5:25 | CallReadSideEffect: call to atoi |
|
| vla.c:5:27:5:33 | BufferReadSideEffect: (const char *)... |
|
||||||
| vla.c:11:6:11:16 | UnmodeledDefinition: vla_typedef |
|
| vla.c:11:6:11:16 | UnmodeledDefinition: vla_typedef |
|
||||||
| vla.c:12:33:12:44 | Add: ... + ... |
|
| vla.c:12:33:12:44 | Add: ... + ... |
|
||||||
| vla.c:12:50:12:62 | Mul: ... * ... |
|
| vla.c:12:50:12:62 | Mul: ... * ... |
|
||||||
|
|||||||
@@ -1,3 +1,9 @@
|
|||||||
|
| unused_functions.c:16:13:16:27 | unused_function | Static function unused_function is unreachable | unused_functions.c:16:13:16:27 | unused_function | unused_function |
|
||||||
|
| unused_functions.c:20:13:20:28 | unused_function2 | Static function unused_function2 is unreachable ($@ must be removed at the same time) | unused_functions.c:24:13:24:28 | unused_function3 | unused_function3 |
|
||||||
|
| unused_functions.c:24:13:24:28 | unused_function3 | Static function unused_function3 is unreachable | unused_functions.c:24:13:24:28 | unused_function3 | unused_function3 |
|
||||||
|
| unused_functions.c:63:13:63:14 | h4 | Static function h4 is unreachable | unused_functions.c:63:13:63:14 | h4 | h4 |
|
||||||
|
| unused_mut.c:5:13:5:31 | mut_unused_function | Static function mut_unused_function is unreachable ($@ must be removed at the same time) | unused_mut.c:9:13:9:32 | mut_unused_function2 | mut_unused_function2 |
|
||||||
|
| unused_mut.c:9:13:9:32 | mut_unused_function2 | Static function mut_unused_function2 is unreachable ($@ must be removed at the same time) | unused_mut.c:5:13:5:31 | mut_unused_function | mut_unused_function |
|
||||||
| unused_static_functions.cpp:19:13:19:14 | f2 | Static function f2 is unreachable | unused_static_functions.cpp:19:13:19:14 | f2 | f2 |
|
| unused_static_functions.cpp:19:13:19:14 | f2 | Static function f2 is unreachable | unused_static_functions.cpp:19:13:19:14 | f2 | f2 |
|
||||||
| unused_static_functions.cpp:33:13:33:14 | f5 | Static function f5 is unreachable ($@ must be removed at the same time) | unused_static_functions.cpp:34:13:34:14 | f6 | f6 |
|
| unused_static_functions.cpp:33:13:33:14 | f5 | Static function f5 is unreachable ($@ must be removed at the same time) | unused_static_functions.cpp:34:13:34:14 | f6 | f6 |
|
||||||
| unused_static_functions.cpp:34:13:34:14 | f6 | Static function f6 is unreachable ($@ must be removed at the same time) | unused_static_functions.cpp:33:13:33:14 | f5 | f5 |
|
| unused_static_functions.cpp:34:13:34:14 | f6 | Static function f6 is unreachable ($@ must be removed at the same time) | unused_static_functions.cpp:33:13:33:14 | f5 | f5 |
|
||||||
|
|||||||
@@ -1,3 +1,10 @@
|
|||||||
|
| test2.c:28:19:28:20 | 41 | Potential buffer-overflow: 'buffer' has size 40 not 41. |
|
||||||
|
| test2.c:29:26:29:27 | 43 | Potential buffer-overflow: 'buffer' has size 40 not 43. |
|
||||||
|
| test2.c:31:26:31:27 | 44 | Potential buffer-overflow: 'buffer' has size 40 not 44. |
|
||||||
|
| test2.c:32:25:32:26 | 45 | Potential buffer-overflow: 'buffer' has size 40 not 45. |
|
||||||
|
| test2.c:33:26:33:27 | 46 | Potential buffer-overflow: 'buffer' has size 40 not 46. |
|
||||||
|
| test2.c:34:22:34:23 | 47 | Potential buffer-overflow: 'buffer' has size 40 not 47. |
|
||||||
|
| test2.c:35:23:35:24 | 48 | Potential buffer-overflow: 'buffer' has size 40 not 48. |
|
||||||
| test.c:14:9:14:13 | access to array | Potential buffer-overflow: 'xs' has size 5 but 'xs[5]' is accessed here. |
|
| test.c:14:9:14:13 | access to array | Potential buffer-overflow: 'xs' has size 5 but 'xs[5]' is accessed here. |
|
||||||
| test.c:15:9:15:13 | access to array | Potential buffer-overflow: 'xs' has size 5 but 'xs[6]' is accessed here. |
|
| test.c:15:9:15:13 | access to array | Potential buffer-overflow: 'xs' has size 5 but 'xs[6]' is accessed here. |
|
||||||
| test.c:20:9:20:18 | access to array | Potential buffer-overflow: 'ys' has size 5 but 'ys[5]' is accessed here. |
|
| test.c:20:9:20:18 | access to array | Potential buffer-overflow: 'ys' has size 5 but 'ys[5]' is accessed here. |
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
| test.c:22:2:22:8 | call to strncpy | Potentially unsafe call to strncpy; third argument should be size of destination. |
|
||||||
|
| test.c:33:2:33:8 | call to strncpy | Potentially unsafe call to strncpy; third argument should be size of destination. |
|
||||||
| test.cpp:19:2:19:8 | call to strncpy | Potentially unsafe call to strncpy; third argument should be size of destination. |
|
| test.cpp:19:2:19:8 | call to strncpy | Potentially unsafe call to strncpy; third argument should be size of destination. |
|
||||||
| test.cpp:20:2:20:8 | call to strncpy | Potentially unsafe call to strncpy; third argument should be size of destination. |
|
| test.cpp:20:2:20:8 | call to strncpy | Potentially unsafe call to strncpy; third argument should be size of destination. |
|
||||||
| test.cpp:21:2:21:8 | call to strncpy | Potentially unsafe call to strncpy; third argument should be size of destination. |
|
| test.cpp:21:2:21:8 | call to strncpy | Potentially unsafe call to strncpy; third argument should be size of destination. |
|
||||||
|
|||||||
@@ -0,0 +1,9 @@
|
|||||||
|
| test.c:28:3:28:12 | call to undeclared | Function call implicitly declares 'undeclared'. |
|
||||||
|
| test.c:31:3:31:19 | call to not_yet_declared1 | Function call implicitly declares 'not_yet_declared1'. |
|
||||||
|
| test.c:32:3:32:19 | call to not_yet_declared2 | Function call implicitly declares 'not_yet_declared2'. |
|
||||||
|
| test.c:43:3:43:27 | call to not_declared_defined_with | Function call implicitly declares 'not_declared_defined_with'. |
|
||||||
|
| test.c:54:3:54:21 | call to defined_with_double | Function call implicitly declares 'defined_with_double'. |
|
||||||
|
| test.c:66:3:66:22 | call to defined_with_ptr_ptr | Function call implicitly declares 'defined_with_ptr_ptr'. |
|
||||||
|
| test.c:68:3:68:22 | call to defined_with_ptr_arr | Function call implicitly declares 'defined_with_ptr_arr'. |
|
||||||
|
| test.c:132:3:132:22 | call to implicit_declaration | Function call implicitly declares 'implicit_declaration'. |
|
||||||
|
| test.c:133:3:133:30 | call to implicit_declaration_k_and_r | Function call implicitly declares 'implicit_declaration_k_and_r'. |
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
Likely Bugs/Underspecified Functions/ImplicitFunctionDeclaration.ql
|
||||||
@@ -25,11 +25,11 @@ void test(int *argv[]) {
|
|||||||
declared_void(); // GOOD
|
declared_void(); // GOOD
|
||||||
declared_with(1); // GOOD
|
declared_with(1); // GOOD
|
||||||
|
|
||||||
undeclared(); // GOOD
|
undeclared(); // BAD (GOOD for everything except cpp/implicit-function-declaration)
|
||||||
undeclared(1); // GOOD
|
undeclared(1); // GOOD
|
||||||
|
|
||||||
not_yet_declared1(1); // GOOD
|
not_yet_declared1(1); // BAD (GOOD for everything except for cpp/implicit-function-declaration)
|
||||||
not_yet_declared2(1); // GOOD
|
not_yet_declared2(1); // BAD (GOOD for everything except for cpp/implicit-function-declaration)
|
||||||
not_yet_declared2(ca); // BAD
|
not_yet_declared2(ca); // BAD
|
||||||
not_yet_declared2(); // BAD
|
not_yet_declared2(); // BAD
|
||||||
|
|
||||||
@@ -40,7 +40,7 @@ void test(int *argv[]) {
|
|||||||
declared_empty_defined_with(&x); // BAD
|
declared_empty_defined_with(&x); // BAD
|
||||||
declared_empty_defined_with(3, &x); // BAD
|
declared_empty_defined_with(3, &x); // BAD
|
||||||
|
|
||||||
not_declared_defined_with(-1, 0, 2U); // GOOD
|
not_declared_defined_with(-1, 0, 2U); // BAD (GOOD for everything except for cpp/implicit-function-declaration)
|
||||||
not_declared_defined_with(4LL, 0, 2.5e9f); // BAD
|
not_declared_defined_with(4LL, 0, 2.5e9f); // BAD
|
||||||
|
|
||||||
declared_with_pointers(pv, ca); // GOOD
|
declared_with_pointers(pv, ca); // GOOD
|
||||||
@@ -51,7 +51,7 @@ void test(int *argv[]) {
|
|||||||
defined_with_float(2.f); // BAD
|
defined_with_float(2.f); // BAD
|
||||||
defined_with_float(2.0); // BAD
|
defined_with_float(2.0); // BAD
|
||||||
|
|
||||||
defined_with_double(2.f); // GOOD
|
defined_with_double(2.f); // BAD (GOOD for everything except for cpp/implicit-function-declaration)
|
||||||
defined_with_double('c'); // BAD
|
defined_with_double('c'); // BAD
|
||||||
|
|
||||||
defined_with_long_long('c'); // BAD
|
defined_with_long_long('c'); // BAD
|
||||||
@@ -63,9 +63,9 @@ void test(int *argv[]) {
|
|||||||
k_and_r_func(2.5, &s); // GOOD
|
k_and_r_func(2.5, &s); // GOOD
|
||||||
|
|
||||||
int (*parameterName)[2];
|
int (*parameterName)[2];
|
||||||
defined_with_ptr_ptr(parameterName); // GOOD
|
defined_with_ptr_ptr(parameterName); // // BAD (GOOD for everything except for cpp/implicit-function-declaration)
|
||||||
defined_with_ptr_ptr(argv); // GOOD
|
defined_with_ptr_ptr(argv); // GOOD
|
||||||
defined_with_ptr_arr(parameterName); // GOOD
|
defined_with_ptr_arr(parameterName); // // BAD (GOOD for everything except for cpp/implicit-function-declaration)
|
||||||
defined_with_ptr_arr(argv); // GOOD
|
defined_with_ptr_arr(argv); // GOOD
|
||||||
|
|
||||||
declared_and_defined_empty(); // GOOD
|
declared_and_defined_empty(); // GOOD
|
||||||
@@ -124,3 +124,15 @@ int call_k_and_r(int i) {
|
|||||||
int will_be_k_and_r(val)
|
int will_be_k_and_r(val)
|
||||||
int val;
|
int val;
|
||||||
{ return val + 1; }
|
{ return val + 1; }
|
||||||
|
|
||||||
|
extern int extern_definition(double, double*);
|
||||||
|
|
||||||
|
void test_implicit_function_declaration(int x, double d) {
|
||||||
|
int y;
|
||||||
|
implicit_declaration(1, 2); // BAD
|
||||||
|
implicit_declaration_k_and_r(1, 2); // BAD
|
||||||
|
|
||||||
|
implicit_declaration(1, 2); // GOOD (no longer an implicit declaration)
|
||||||
|
|
||||||
|
y = extern_definition(3.0f, &d); // GOOD
|
||||||
|
}
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
void implicit_declaration(int x) {}
|
||||||
|
|
||||||
|
int implicit_declaration_k_and_r(x) int x;
|
||||||
|
{
|
||||||
|
return x;
|
||||||
|
}
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
| test.c:28:19:28:20 | 41 | Potential buffer-overflow: 'buffer' has size 40 not 41. |
|
|
||||||
| test.c:29:26:29:27 | 43 | Potential buffer-overflow: 'buffer' has size 40 not 43. |
|
|
||||||
| test.c:31:26:31:27 | 44 | Potential buffer-overflow: 'buffer' has size 40 not 44. |
|
|
||||||
| test.c:32:25:32:26 | 45 | Potential buffer-overflow: 'buffer' has size 40 not 45. |
|
|
||||||
| test.c:33:26:33:27 | 46 | Potential buffer-overflow: 'buffer' has size 40 not 46. |
|
|
||||||
| test.c:34:22:34:23 | 47 | Potential buffer-overflow: 'buffer' has size 40 not 47. |
|
|
||||||
| test.c:35:23:35:24 | 48 | Potential buffer-overflow: 'buffer' has size 40 not 48. |
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
Critical/OverflowStatic.ql
|
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user