mirror of
https://github.com/github/codeql.git
synced 2025-12-21 03:06:31 +01:00
Merge remote-tracking branch 'upstream/master' into dbartol/VarArgIR
This commit is contained in:
@@ -19,15 +19,19 @@ class ConstantZero extends Expr {
|
||||
* Holds if `candidate` is an expression such that if it's unsigned then we
|
||||
* want an alert at `ge`.
|
||||
*/
|
||||
private predicate lookForUnsignedAt(GEExpr ge, Expr candidate) {
|
||||
// Base case: `candidate >= 0`
|
||||
ge.getRightOperand() instanceof ConstantZero and
|
||||
candidate = ge.getLeftOperand().getFullyConverted() and
|
||||
// left operand was a signed or unsigned IntegralType before conversions
|
||||
private predicate lookForUnsignedAt(RelationalOperation ge, Expr candidate) {
|
||||
// Base case: `candidate >= 0` (or `0 <= candidate`)
|
||||
(
|
||||
ge instanceof GEExpr or
|
||||
ge instanceof LEExpr
|
||||
) and
|
||||
ge.getLesserOperand() instanceof ConstantZero and
|
||||
candidate = ge.getGreaterOperand().getFullyConverted() and
|
||||
// left/greater operand was a signed or unsigned IntegralType before conversions
|
||||
// (not a pointer, checking a pointer >= 0 is an entirely different mistake)
|
||||
// (not an enum, as the fully converted type of an enum is compiler dependent
|
||||
// so checking an enum >= 0 is always reasonable)
|
||||
ge.getLeftOperand().getUnderlyingType() instanceof IntegralType
|
||||
ge.getGreaterOperand().getUnderlyingType() instanceof IntegralType
|
||||
or
|
||||
// Recursive case: `...(largerType)candidate >= 0`
|
||||
exists(Conversion conversion |
|
||||
@@ -37,7 +41,7 @@ private predicate lookForUnsignedAt(GEExpr ge, Expr candidate) {
|
||||
)
|
||||
}
|
||||
|
||||
class UnsignedGEZero extends GEExpr {
|
||||
class UnsignedGEZero extends ComparisonOperation {
|
||||
UnsignedGEZero() {
|
||||
exists(Expr ue |
|
||||
lookForUnsignedAt(this, ue) and
|
||||
|
||||
@@ -0,0 +1,138 @@
|
||||
#include <stdlib.h>
|
||||
#include <sys/param.h>
|
||||
#include <unistd.h>
|
||||
#include <pwd.h>
|
||||
|
||||
void callSetuidAndCheck(int uid) {
|
||||
if (setuid(uid) != 0) {
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
void callSetgidAndCheck(int gid) {
|
||||
if (setgid(gid) != 0) {
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
/// Correct ways to drop priv.
|
||||
|
||||
void correctDropPrivInline() {
|
||||
if (setgroups(0, NULL)) {
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (setgid(-2) != 0) {
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (setuid(-2) != 0) {
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
void correctDropPrivInScope() {
|
||||
{
|
||||
if (setgroups(0, NULL)) {
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
if (setgid(-2) != 0) {
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
if (setuid(-2) != 0) {
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void correctOrderForInitgroups() {
|
||||
struct passwd *pw = getpwuid(0);
|
||||
if (pw) {
|
||||
if (initgroups(pw->pw_name, -2)) {
|
||||
exit(1);
|
||||
}
|
||||
} else {
|
||||
// Unhandled.
|
||||
}
|
||||
int rc = setuid(-2);
|
||||
if (rc) {
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
void correctDropPrivInScopeParent() {
|
||||
{
|
||||
callSetgidAndCheck(-2);
|
||||
}
|
||||
correctOrderForInitgroups();
|
||||
}
|
||||
|
||||
void incorrectNoReturnCodeCheck() {
|
||||
int user = -2;
|
||||
if (user) {
|
||||
if (user) {
|
||||
int rc = setgid(user);
|
||||
(void)rc;
|
||||
initgroups("nobody", user);
|
||||
}
|
||||
if (user) {
|
||||
setuid(user);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void correctDropPrivInFunctionCall() {
|
||||
if (setgroups(0, NULL)) {
|
||||
exit(1);
|
||||
}
|
||||
|
||||
callSetgidAndCheck(-2);
|
||||
callSetuidAndCheck(-2);
|
||||
}
|
||||
|
||||
/// Incorrect, out of order gid and uid.
|
||||
/// Calling uid before gid will fail.
|
||||
|
||||
void incorrectDropPrivOutOfOrderInline() {
|
||||
if (setuid(-2) != 0) {
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (setgid(-2) != 0) {
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
void incorrectDropPrivOutOfOrderInScope() {
|
||||
{
|
||||
if (setuid(-2) != 0) {
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
setgid(-2);
|
||||
}
|
||||
|
||||
void incorrectDropPrivOutOfOrderWithFunction() {
|
||||
callSetuidAndCheck(-2);
|
||||
|
||||
if (setgid(-2) != 0) {
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
void incorrectDropPrivOutOfOrderWithFunction2() {
|
||||
callSetuidAndCheck(-2);
|
||||
callSetgidAndCheck(-2);
|
||||
}
|
||||
|
||||
void incorrectDropPrivNoCheck() {
|
||||
setgid(-2);
|
||||
setuid(-2);
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
<!DOCTYPE qhelp PUBLIC
|
||||
"-//Semmle//qhelp//EN"
|
||||
"qhelp.dtd">
|
||||
<qhelp>
|
||||
<overview>
|
||||
<p>The code attempts to drop privilege in an incorrect order by
|
||||
erroneous dropping user privilege before groups. This has security
|
||||
impact if the return codes are not checked.</p>
|
||||
|
||||
<p>False positives include code performing negative checks, making
|
||||
sure that setgid or setgroups does not work, meaning permissions are
|
||||
dropped. Additionally, other forms of sandboxing may be present removing
|
||||
any residual risk, for example a dedicated user namespace.</p>
|
||||
|
||||
</overview>
|
||||
<recommendation>
|
||||
|
||||
<p>Set the new group ID, then set the target user's intended groups by
|
||||
dropping previous supplemental source groups and initializing target
|
||||
groups, and finally set the target user.</p>
|
||||
|
||||
</recommendation>
|
||||
<example>
|
||||
<p>The following example demonstrates out of order calls.</p>
|
||||
<sample src="PrivilegeDroppingOutoforder.c" />
|
||||
|
||||
</example>
|
||||
<references>
|
||||
|
||||
<li>CERT C Coding Standard:
|
||||
<a href="https://wiki.sei.cmu.edu/confluence/display/c/POS37-C.+Ensure+that+privilege+relinquishment+is+successful">POS37-C. Ensure that privilege relinquishment is successful</a>.
|
||||
</li>
|
||||
|
||||
</references>
|
||||
</qhelp>
|
||||
@@ -0,0 +1,101 @@
|
||||
/**
|
||||
* @name LinuxPrivilegeDroppingOutoforder
|
||||
* @description A syscall commonly associated with privilege dropping is being called out of order.
|
||||
* Normally a process drops group ID and sets supplimental groups for the target user
|
||||
* before setting the target user ID. This can have security impact if the return code
|
||||
* from these methods is not checked.
|
||||
* @kind problem
|
||||
* @problem.severity recommendation
|
||||
* @id cpp/drop-linux-privileges-outoforder
|
||||
* @tags security
|
||||
* external/cwe/cwe-273
|
||||
* @precision medium
|
||||
*/
|
||||
|
||||
import cpp
|
||||
|
||||
predicate argumentMayBeRoot(Expr e) {
|
||||
e.getValue() = "0" or
|
||||
e.(VariableAccess).getTarget().getName().toLowerCase().matches("%root%")
|
||||
}
|
||||
|
||||
class SetuidLikeFunctionCall extends FunctionCall {
|
||||
SetuidLikeFunctionCall() {
|
||||
(getTarget().hasGlobalName("setuid") or getTarget().hasGlobalName("setresuid")) and
|
||||
// setuid/setresuid with the root user are false positives.
|
||||
not argumentMayBeRoot(getArgument(0))
|
||||
}
|
||||
}
|
||||
|
||||
class SetuidLikeWrapperCall extends FunctionCall {
|
||||
SetuidLikeFunctionCall baseCall;
|
||||
|
||||
SetuidLikeWrapperCall() {
|
||||
this = baseCall
|
||||
or
|
||||
exists(SetuidLikeWrapperCall fc |
|
||||
this.getTarget() = fc.getEnclosingFunction() and
|
||||
baseCall = fc.getBaseCall()
|
||||
)
|
||||
}
|
||||
|
||||
SetuidLikeFunctionCall getBaseCall() { result = baseCall }
|
||||
}
|
||||
|
||||
class CallBeforeSetuidFunctionCall extends FunctionCall {
|
||||
CallBeforeSetuidFunctionCall() {
|
||||
(
|
||||
getTarget().hasGlobalName("setgid") or
|
||||
getTarget().hasGlobalName("setresgid") or
|
||||
// Compatibility may require skipping initgroups and setgroups return checks.
|
||||
// A stricter best practice is to check the result and errnor for EPERM.
|
||||
getTarget().hasGlobalName("initgroups") or
|
||||
getTarget().hasGlobalName("setgroups")
|
||||
) and
|
||||
// setgid/setresgid/etc with the root group are false positives.
|
||||
not argumentMayBeRoot(getArgument(0))
|
||||
}
|
||||
}
|
||||
|
||||
class CallBeforeSetuidWrapperCall extends FunctionCall {
|
||||
CallBeforeSetuidFunctionCall baseCall;
|
||||
|
||||
CallBeforeSetuidWrapperCall() {
|
||||
this = baseCall
|
||||
or
|
||||
exists(CallBeforeSetuidWrapperCall fc |
|
||||
this.getTarget() = fc.getEnclosingFunction() and
|
||||
baseCall = fc.getBaseCall()
|
||||
)
|
||||
}
|
||||
|
||||
CallBeforeSetuidFunctionCall getBaseCall() { result = baseCall }
|
||||
}
|
||||
|
||||
predicate setuidBeforeSetgid(
|
||||
SetuidLikeWrapperCall setuidWrapper, CallBeforeSetuidWrapperCall setgidWrapper
|
||||
) {
|
||||
setgidWrapper.getAPredecessor+() = setuidWrapper
|
||||
}
|
||||
|
||||
predicate isAccessed(FunctionCall fc) {
|
||||
exists(Variable v | v.getAnAssignedValue() = fc)
|
||||
or
|
||||
exists(Operation c | fc = c.getAChild() | c.isCondition())
|
||||
or
|
||||
// ignore pattern where result is intentionally ignored by a cast to void.
|
||||
fc.hasExplicitConversion()
|
||||
}
|
||||
|
||||
from Function func, CallBeforeSetuidFunctionCall fc, SetuidLikeFunctionCall setuid
|
||||
where
|
||||
setuidBeforeSetgid(setuid, fc) and
|
||||
// Require the call return code to be used in a condition or assigned.
|
||||
// This introduces false negatives where the return is checked but then
|
||||
// errno == EPERM allows execution to continue.
|
||||
not isAccessed(fc) and
|
||||
func = fc.getEnclosingFunction()
|
||||
select fc,
|
||||
"This function is called within " + func + ", and potentially after " +
|
||||
"$@, and may not succeed. Be sure to check the return code and errno, otherwise permissions " +
|
||||
"may not be dropped.", setuid, setuid.getTarget().getName()
|
||||
@@ -381,10 +381,10 @@ class StaticStorageDurationVariable extends Variable {
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if the initializer for this variable is evaluated at compile time.
|
||||
* Holds if the initializer for this variable is evaluated at runtime.
|
||||
*/
|
||||
predicate hasConstantInitialization() {
|
||||
not runtimeExprInStaticInitializer(this.getInitializer().getExpr())
|
||||
predicate hasDynamicInitialization() {
|
||||
runtimeExprInStaticInitializer(this.getInitializer().getExpr())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -409,6 +409,11 @@ private predicate inStaticInitializer(Expr e) {
|
||||
inStaticInitializer(e.getParent())
|
||||
}
|
||||
|
||||
/**
|
||||
* A C++ local variable declared as `static`.
|
||||
*/
|
||||
class StaticLocalVariable extends LocalVariable, StaticStorageDurationVariable { }
|
||||
|
||||
/**
|
||||
* A C/C++ variable which has global scope or namespace scope. For example the
|
||||
* variables `a` and `b` in the following code:
|
||||
|
||||
@@ -441,9 +441,9 @@ private Node getControlOrderChildSparse(Node n, int i) {
|
||||
* thus should not have control flow computed.
|
||||
*/
|
||||
private predicate skipInitializer(Initializer init) {
|
||||
exists(LocalVariable local |
|
||||
exists(StaticLocalVariable local |
|
||||
init = local.getInitializer() and
|
||||
local.(StaticStorageDurationVariable).hasConstantInitialization()
|
||||
not local.hasDynamicInitialization()
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -76,6 +76,8 @@ private class DefaultTaintTrackingCfg extends DataFlow::Configuration {
|
||||
}
|
||||
|
||||
override predicate isBarrier(DataFlow::Node node) { nodeIsBarrier(node) }
|
||||
|
||||
override predicate isBarrierIn(DataFlow::Node node) { nodeIsBarrierIn(node) }
|
||||
}
|
||||
|
||||
private class ToGlobalVarTaintTrackingCfg extends DataFlow::Configuration {
|
||||
@@ -96,6 +98,8 @@ private class ToGlobalVarTaintTrackingCfg extends DataFlow::Configuration {
|
||||
}
|
||||
|
||||
override predicate isBarrier(DataFlow::Node node) { nodeIsBarrier(node) }
|
||||
|
||||
override predicate isBarrierIn(DataFlow::Node node) { nodeIsBarrierIn(node) }
|
||||
}
|
||||
|
||||
private class FromGlobalVarTaintTrackingCfg extends DataFlow2::Configuration {
|
||||
@@ -119,6 +123,8 @@ private class FromGlobalVarTaintTrackingCfg extends DataFlow2::Configuration {
|
||||
}
|
||||
|
||||
override predicate isBarrier(DataFlow::Node node) { nodeIsBarrier(node) }
|
||||
|
||||
override predicate isBarrierIn(DataFlow::Node node) { nodeIsBarrierIn(node) }
|
||||
}
|
||||
|
||||
private predicate readsVariable(LoadInstruction load, Variable var) {
|
||||
@@ -153,6 +159,11 @@ private predicate nodeIsBarrier(DataFlow::Node node) {
|
||||
)
|
||||
}
|
||||
|
||||
private predicate nodeIsBarrierIn(DataFlow::Node node) {
|
||||
// don't use dataflow into taint sources, as this leads to duplicate results.
|
||||
node = getNodeForSource(any(Expr e))
|
||||
}
|
||||
|
||||
private predicate instructionTaintStep(Instruction i1, Instruction i2) {
|
||||
// Expressions computed from tainted data are also tainted
|
||||
exists(CallInstruction call, int argIndex | call = i2 |
|
||||
|
||||
@@ -23,7 +23,8 @@ class IRVariable extends TIRVariable {
|
||||
IRVariable() {
|
||||
this = TIRUserVariable(_, _, func) or
|
||||
this = TIRTempVariable(func, _, _, _) or
|
||||
this = TIRStringLiteral(func, _, _, _)
|
||||
this = TIRStringLiteral(func, _, _, _) or
|
||||
this = TIRDynamicInitializationFlag(func, _, _)
|
||||
}
|
||||
|
||||
string toString() { none() }
|
||||
@@ -149,7 +150,8 @@ class IRGeneratedVariable extends IRVariable {
|
||||
|
||||
IRGeneratedVariable() {
|
||||
this = TIRTempVariable(func, ast, _, type) or
|
||||
this = TIRStringLiteral(func, ast, type, _)
|
||||
this = TIRStringLiteral(func, ast, type, _) or
|
||||
this = TIRDynamicInitializationFlag(func, ast, type)
|
||||
}
|
||||
|
||||
final override Language::LanguageType getLanguageType() { result = type }
|
||||
@@ -208,7 +210,7 @@ class IRReturnVariable extends IRTempVariable {
|
||||
class IRThrowVariable extends IRTempVariable {
|
||||
IRThrowVariable() { tag = ThrowTempVar() }
|
||||
|
||||
override string getBaseString() { result = "#throw" }
|
||||
final override string getBaseString() { result = "#throw" }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -236,7 +238,30 @@ class IRStringLiteral extends IRGeneratedVariable, TIRStringLiteral {
|
||||
result = "String: " + getLocationString() + "=" + Language::getStringLiteralText(literal)
|
||||
}
|
||||
|
||||
override string getBaseString() { result = "#string" }
|
||||
final override string getBaseString() { result = "#string" }
|
||||
|
||||
final Language::StringLiteral getLiteral() { result = literal }
|
||||
}
|
||||
|
||||
/**
|
||||
* A variable generated to track whether a specific non-stack variable has been initialized. This is
|
||||
* used to model the runtime initialization of static local variables in C++, as well as static
|
||||
* fields in C#.
|
||||
*/
|
||||
class IRDynamicInitializationFlag extends IRGeneratedVariable, TIRDynamicInitializationFlag {
|
||||
Language::Variable var;
|
||||
|
||||
IRDynamicInitializationFlag() {
|
||||
this = TIRDynamicInitializationFlag(func, var, type) and ast = var
|
||||
}
|
||||
|
||||
final override string toString() { result = var.toString() + "#init" }
|
||||
|
||||
final Language::Variable getVariable() { result = var }
|
||||
|
||||
final override string getUniqueId() {
|
||||
result = "Init: " + getVariable().toString() + " " + getVariable().getLocation().toString()
|
||||
}
|
||||
|
||||
final override string getBaseString() { result = "#init:" + var.toString() + ":" }
|
||||
}
|
||||
|
||||
@@ -10,6 +10,11 @@ newtype TIRVariable =
|
||||
) {
|
||||
Construction::hasTempVariable(func, ast, tag, type)
|
||||
} or
|
||||
TIRDynamicInitializationFlag(
|
||||
Language::Function func, Language::Variable var, Language::LanguageType type
|
||||
) {
|
||||
Construction::hasDynamicInitializationFlag(func, var, type)
|
||||
} or
|
||||
TIRStringLiteral(
|
||||
Language::Function func, Language::AST ast, Language::LanguageType type,
|
||||
Language::StringLiteral literal
|
||||
|
||||
@@ -23,7 +23,8 @@ class IRVariable extends TIRVariable {
|
||||
IRVariable() {
|
||||
this = TIRUserVariable(_, _, func) or
|
||||
this = TIRTempVariable(func, _, _, _) or
|
||||
this = TIRStringLiteral(func, _, _, _)
|
||||
this = TIRStringLiteral(func, _, _, _) or
|
||||
this = TIRDynamicInitializationFlag(func, _, _)
|
||||
}
|
||||
|
||||
string toString() { none() }
|
||||
@@ -149,7 +150,8 @@ class IRGeneratedVariable extends IRVariable {
|
||||
|
||||
IRGeneratedVariable() {
|
||||
this = TIRTempVariable(func, ast, _, type) or
|
||||
this = TIRStringLiteral(func, ast, type, _)
|
||||
this = TIRStringLiteral(func, ast, type, _) or
|
||||
this = TIRDynamicInitializationFlag(func, ast, type)
|
||||
}
|
||||
|
||||
final override Language::LanguageType getLanguageType() { result = type }
|
||||
@@ -208,7 +210,7 @@ class IRReturnVariable extends IRTempVariable {
|
||||
class IRThrowVariable extends IRTempVariable {
|
||||
IRThrowVariable() { tag = ThrowTempVar() }
|
||||
|
||||
override string getBaseString() { result = "#throw" }
|
||||
final override string getBaseString() { result = "#throw" }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -236,7 +238,30 @@ class IRStringLiteral extends IRGeneratedVariable, TIRStringLiteral {
|
||||
result = "String: " + getLocationString() + "=" + Language::getStringLiteralText(literal)
|
||||
}
|
||||
|
||||
override string getBaseString() { result = "#string" }
|
||||
final override string getBaseString() { result = "#string" }
|
||||
|
||||
final Language::StringLiteral getLiteral() { result = literal }
|
||||
}
|
||||
|
||||
/**
|
||||
* A variable generated to track whether a specific non-stack variable has been initialized. This is
|
||||
* used to model the runtime initialization of static local variables in C++, as well as static
|
||||
* fields in C#.
|
||||
*/
|
||||
class IRDynamicInitializationFlag extends IRGeneratedVariable, TIRDynamicInitializationFlag {
|
||||
Language::Variable var;
|
||||
|
||||
IRDynamicInitializationFlag() {
|
||||
this = TIRDynamicInitializationFlag(func, var, type) and ast = var
|
||||
}
|
||||
|
||||
final override string toString() { result = var.toString() + "#init" }
|
||||
|
||||
final Language::Variable getVariable() { result = var }
|
||||
|
||||
final override string getUniqueId() {
|
||||
result = "Init: " + getVariable().toString() + " " + getVariable().getLocation().toString()
|
||||
}
|
||||
|
||||
final override string getBaseString() { result = "#init:" + var.toString() + ":" }
|
||||
}
|
||||
|
||||
@@ -51,6 +51,13 @@ private module Cached {
|
||||
getTypeForPRValue(literal.getType()) = type
|
||||
}
|
||||
|
||||
cached
|
||||
predicate hasDynamicInitializationFlag(Function func, StaticLocalVariable var, CppType type) {
|
||||
var.getFunction() = func and
|
||||
var.hasDynamicInitialization() and
|
||||
type = getBoolType()
|
||||
}
|
||||
|
||||
cached
|
||||
predicate hasModeledMemoryResult(Instruction instruction) { none() }
|
||||
|
||||
|
||||
@@ -8,6 +8,11 @@ newtype TInstructionTag =
|
||||
InitializerStoreTag() or
|
||||
InitializerIndirectAddressTag() or
|
||||
InitializerIndirectStoreTag() or
|
||||
DynamicInitializationFlagAddressTag() or
|
||||
DynamicInitializationFlagLoadTag() or
|
||||
DynamicInitializationConditionalBranchTag() or
|
||||
DynamicInitializationFlagConstantTag() or
|
||||
DynamicInitializationFlagStoreTag() or
|
||||
ZeroPadStringConstantTag() or
|
||||
ZeroPadStringElementIndexTag() or
|
||||
ZeroPadStringElementAddressTag() or
|
||||
@@ -186,4 +191,14 @@ string getInstructionTagId(TInstructionTag tag) {
|
||||
tag = AsmTag() and result = "Asm"
|
||||
or
|
||||
exists(int index | tag = AsmInputTag(index) and result = "AsmInputTag(" + index + ")")
|
||||
or
|
||||
tag = DynamicInitializationFlagAddressTag() and result = "DynInitFlagAddr"
|
||||
or
|
||||
tag = DynamicInitializationFlagLoadTag() and result = "DynInitFlagLoad"
|
||||
or
|
||||
tag = DynamicInitializationConditionalBranchTag() and result = "DynInitCondBranch"
|
||||
or
|
||||
tag = DynamicInitializationFlagConstantTag() and result = "DynInitFlagConst"
|
||||
or
|
||||
tag = DynamicInitializationFlagStoreTag() and result = "DynInitFlagStore"
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ private import semmle.code.cpp.ir.internal.IRUtilities
|
||||
private import InstructionTag
|
||||
private import TranslatedElement
|
||||
private import TranslatedExpr
|
||||
private import TranslatedFunction
|
||||
private import TranslatedInitialization
|
||||
|
||||
/**
|
||||
@@ -66,17 +67,172 @@ abstract class TranslatedLocalVariableDeclaration extends TranslatedVariableInit
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents the IR translation of a local variable declaration within a declaration statement.
|
||||
* The IR translation of a local variable declaration within a declaration statement.
|
||||
*/
|
||||
class TranslatedVariableDeclarationEntry extends TranslatedLocalVariableDeclaration,
|
||||
class TranslatedAutoVariableDeclarationEntry extends TranslatedLocalVariableDeclaration,
|
||||
TranslatedDeclarationEntry {
|
||||
LocalVariable var;
|
||||
StackVariable var;
|
||||
|
||||
TranslatedVariableDeclarationEntry() { var = entry.getDeclaration() }
|
||||
TranslatedAutoVariableDeclarationEntry() { var = entry.getDeclaration() }
|
||||
|
||||
override LocalVariable getVariable() { result = var }
|
||||
}
|
||||
|
||||
/**
|
||||
* The IR translation of the declaration of a static local variable.
|
||||
* This element generates the logic that determines whether or not the variable has already been
|
||||
* initialized, and if not, invokes the initializer and sets the dynamic initialization flag for the
|
||||
* variable. The actual initialization code is handled in
|
||||
* `TranslatedStaticLocalVariableInitialization`, which is a child of this element.
|
||||
*
|
||||
* The generated code to do the initialization only once is:
|
||||
* ```
|
||||
* Block 1
|
||||
* r1225_1(glval<bool>) = VariableAddress[c#init] :
|
||||
* r1225_2(bool) = Load : &:r1225_1, ~mu1222_4
|
||||
* v1225_3(void) = ConditionalBranch : r1225_2
|
||||
* False -> Block 2
|
||||
* True -> Block 3
|
||||
*
|
||||
* Block 2
|
||||
* r1225_4(glval<int>) = VariableAddress[c] :
|
||||
* <actual initialization of `c`>
|
||||
* r1225_8(bool) = Constant[1] :
|
||||
* mu1225_9(bool) = Store : &:r1225_1, r1225_8
|
||||
* Goto -> Block 3
|
||||
*
|
||||
* Block 3
|
||||
* ```
|
||||
*
|
||||
* Note that the flag variable, `c#init`, is assumed to be zero-initialized at program startup, just
|
||||
* like any other variable with static storage duration.
|
||||
*/
|
||||
class TranslatedStaticLocalVariableDeclarationEntry extends TranslatedDeclarationEntry {
|
||||
StaticLocalVariable var;
|
||||
|
||||
TranslatedStaticLocalVariableDeclarationEntry() { var = entry.getDeclaration() }
|
||||
|
||||
final override TranslatedElement getChild(int id) { id = 0 and result = getInitialization() }
|
||||
|
||||
final override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType type) {
|
||||
tag = DynamicInitializationFlagAddressTag() and
|
||||
opcode instanceof Opcode::VariableAddress and
|
||||
type = getBoolGLValueType()
|
||||
or
|
||||
tag = DynamicInitializationFlagLoadTag() and
|
||||
opcode instanceof Opcode::Load and
|
||||
type = getBoolType()
|
||||
or
|
||||
tag = DynamicInitializationConditionalBranchTag() and
|
||||
opcode instanceof Opcode::ConditionalBranch and
|
||||
type = getVoidType()
|
||||
or
|
||||
tag = DynamicInitializationFlagConstantTag() and
|
||||
opcode instanceof Opcode::Constant and
|
||||
type = getBoolType()
|
||||
or
|
||||
tag = DynamicInitializationFlagStoreTag() and
|
||||
opcode instanceof Opcode::Store and
|
||||
type = getBoolType()
|
||||
}
|
||||
|
||||
final override Instruction getFirstInstruction() {
|
||||
result = getInstruction(DynamicInitializationFlagAddressTag())
|
||||
}
|
||||
|
||||
final override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
|
||||
tag = DynamicInitializationFlagAddressTag() and
|
||||
kind instanceof GotoEdge and
|
||||
result = getInstruction(DynamicInitializationFlagLoadTag())
|
||||
or
|
||||
tag = DynamicInitializationFlagLoadTag() and
|
||||
kind instanceof GotoEdge and
|
||||
result = getInstruction(DynamicInitializationConditionalBranchTag())
|
||||
or
|
||||
tag = DynamicInitializationConditionalBranchTag() and
|
||||
(
|
||||
kind instanceof TrueEdge and
|
||||
result = getParent().getChildSuccessor(this)
|
||||
or
|
||||
kind instanceof FalseEdge and
|
||||
result = getInitialization().getFirstInstruction()
|
||||
)
|
||||
or
|
||||
tag = DynamicInitializationFlagConstantTag() and
|
||||
kind instanceof GotoEdge and
|
||||
result = getInstruction(DynamicInitializationFlagStoreTag())
|
||||
or
|
||||
tag = DynamicInitializationFlagStoreTag() and
|
||||
kind instanceof GotoEdge and
|
||||
result = getParent().getChildSuccessor(this)
|
||||
}
|
||||
|
||||
final override Instruction getChildSuccessor(TranslatedElement child) {
|
||||
child = getInitialization() and
|
||||
result = getInstruction(DynamicInitializationFlagConstantTag())
|
||||
}
|
||||
|
||||
final override IRDynamicInitializationFlag getInstructionVariable(InstructionTag tag) {
|
||||
tag = DynamicInitializationFlagAddressTag() and
|
||||
result.getVariable() = var
|
||||
}
|
||||
|
||||
final override string getInstructionConstantValue(InstructionTag tag) {
|
||||
tag = DynamicInitializationFlagConstantTag() and result = "1"
|
||||
}
|
||||
|
||||
final override Instruction getInstructionOperand(InstructionTag tag, OperandTag operandTag) {
|
||||
tag = DynamicInitializationFlagLoadTag() and
|
||||
(
|
||||
operandTag instanceof AddressOperandTag and
|
||||
result = getInstruction(DynamicInitializationFlagAddressTag())
|
||||
or
|
||||
operandTag instanceof LoadOperandTag and
|
||||
result = getTranslatedFunction(var.getFunction()).getUnmodeledDefinitionInstruction()
|
||||
)
|
||||
or
|
||||
tag = DynamicInitializationConditionalBranchTag() and
|
||||
operandTag instanceof ConditionOperandTag and
|
||||
result = getInstruction(DynamicInitializationFlagLoadTag())
|
||||
or
|
||||
tag = DynamicInitializationFlagStoreTag() and
|
||||
(
|
||||
operandTag instanceof AddressOperandTag and
|
||||
result = getInstruction(DynamicInitializationFlagAddressTag())
|
||||
or
|
||||
operandTag instanceof StoreValueOperandTag and
|
||||
result = getInstruction(DynamicInitializationFlagConstantTag())
|
||||
)
|
||||
}
|
||||
|
||||
private TranslatedStaticLocalVariableInitialization getInitialization() {
|
||||
result.getVariable() = var
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The initialization of a static local variable. This element will only exist for a static variable
|
||||
* with a dynamic initializer.
|
||||
*/
|
||||
class TranslatedStaticLocalVariableInitialization extends TranslatedElement,
|
||||
TranslatedLocalVariableDeclaration, TTranslatedStaticLocalVariableInitialization {
|
||||
VariableDeclarationEntry entry;
|
||||
StaticLocalVariable var;
|
||||
|
||||
TranslatedStaticLocalVariableInitialization() {
|
||||
this = TTranslatedStaticLocalVariableInitialization(entry) and
|
||||
var = entry.getDeclaration()
|
||||
}
|
||||
|
||||
final override string toString() { result = "init: " + entry.toString() }
|
||||
|
||||
final override Locatable getAST() { result = entry }
|
||||
|
||||
final override LocalVariable getVariable() { result = var }
|
||||
|
||||
final override Function getFunction() { result = var.getFunction() }
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the `TranslatedRangeBasedForVariableDeclaration` that represents the declaration of
|
||||
* `var`.
|
||||
|
||||
@@ -54,7 +54,7 @@ private predicate ignoreExprAndDescendants(Expr expr) {
|
||||
// Otherwise the initializer does not run in function scope.
|
||||
exists(Initializer init, StaticStorageDurationVariable var |
|
||||
init = var.getInitializer() and
|
||||
var.hasConstantInitialization() and
|
||||
not var.hasDynamicInitialization() and
|
||||
expr = init.getExpr().getFullyConverted()
|
||||
)
|
||||
or
|
||||
@@ -256,6 +256,26 @@ predicate hasTranslatedLoad(Expr expr) {
|
||||
not ignoreLoad(expr)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if the specified `DeclarationEntry` needs an IR translation. An IR translation is only
|
||||
* necessary for automatic local variables, or for static local variables with dynamic
|
||||
* initialization.
|
||||
*/
|
||||
private predicate translateDeclarationEntry(DeclarationEntry entry) {
|
||||
exists(DeclStmt declStmt, LocalVariable var |
|
||||
translateStmt(declStmt) and
|
||||
declStmt.getADeclarationEntry() = entry and
|
||||
// Only declarations of local variables need to be translated to IR.
|
||||
var = entry.getDeclaration() and
|
||||
(
|
||||
not var.isStatic()
|
||||
or
|
||||
// Ignore static variables unless they have a dynamic initializer.
|
||||
var.(StaticLocalVariable).hasDynamicInitialization()
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
newtype TTranslatedElement =
|
||||
// An expression that is not being consumed as a condition
|
||||
TTranslatedValueExpr(Expr expr) {
|
||||
@@ -396,13 +416,12 @@ newtype TTranslatedElement =
|
||||
)
|
||||
} or
|
||||
// A local declaration
|
||||
TTranslatedDeclarationEntry(DeclarationEntry entry) {
|
||||
exists(DeclStmt declStmt |
|
||||
translateStmt(declStmt) and
|
||||
declStmt.getADeclarationEntry() = entry and
|
||||
// Only declarations of local variables need to be translated to IR.
|
||||
entry.getDeclaration() instanceof LocalVariable
|
||||
)
|
||||
TTranslatedDeclarationEntry(DeclarationEntry entry) { translateDeclarationEntry(entry) } or
|
||||
// The dynamic initialization of a static local variable. This is a separate object from the
|
||||
// declaration entry.
|
||||
TTranslatedStaticLocalVariableInitialization(DeclarationEntry entry) {
|
||||
translateDeclarationEntry(entry) and
|
||||
entry.getDeclaration() instanceof StaticLocalVariable
|
||||
} or
|
||||
// A compiler-generated variable to implement a range-based for loop. These don't have a
|
||||
// `DeclarationEntry` in the database, so we have to go by the `Variable` itself.
|
||||
|
||||
@@ -115,10 +115,14 @@ abstract class TranslatedVariableInitialization extends TranslatedElement, Initi
|
||||
* evaluating the initializer.
|
||||
*/
|
||||
final predicate hasUninitializedInstruction() {
|
||||
not exists(getInitialization()) or
|
||||
getInitialization() instanceof TranslatedListInitialization or
|
||||
getInitialization() instanceof TranslatedConstructorInitialization or
|
||||
getInitialization().(TranslatedStringLiteralInitialization).zeroInitRange(_, _)
|
||||
(
|
||||
not exists(getInitialization()) or
|
||||
getInitialization() instanceof TranslatedListInitialization or
|
||||
getInitialization() instanceof TranslatedConstructorInitialization or
|
||||
getInitialization().(TranslatedStringLiteralInitialization).zeroInitRange(_, _)
|
||||
) and
|
||||
// Variables with static or thread-local storage duration are zero-initialized at program startup.
|
||||
getIRVariable() instanceof IRAutomaticVariable
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -23,7 +23,8 @@ class IRVariable extends TIRVariable {
|
||||
IRVariable() {
|
||||
this = TIRUserVariable(_, _, func) or
|
||||
this = TIRTempVariable(func, _, _, _) or
|
||||
this = TIRStringLiteral(func, _, _, _)
|
||||
this = TIRStringLiteral(func, _, _, _) or
|
||||
this = TIRDynamicInitializationFlag(func, _, _)
|
||||
}
|
||||
|
||||
string toString() { none() }
|
||||
@@ -149,7 +150,8 @@ class IRGeneratedVariable extends IRVariable {
|
||||
|
||||
IRGeneratedVariable() {
|
||||
this = TIRTempVariable(func, ast, _, type) or
|
||||
this = TIRStringLiteral(func, ast, type, _)
|
||||
this = TIRStringLiteral(func, ast, type, _) or
|
||||
this = TIRDynamicInitializationFlag(func, ast, type)
|
||||
}
|
||||
|
||||
final override Language::LanguageType getLanguageType() { result = type }
|
||||
@@ -208,7 +210,7 @@ class IRReturnVariable extends IRTempVariable {
|
||||
class IRThrowVariable extends IRTempVariable {
|
||||
IRThrowVariable() { tag = ThrowTempVar() }
|
||||
|
||||
override string getBaseString() { result = "#throw" }
|
||||
final override string getBaseString() { result = "#throw" }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -236,7 +238,30 @@ class IRStringLiteral extends IRGeneratedVariable, TIRStringLiteral {
|
||||
result = "String: " + getLocationString() + "=" + Language::getStringLiteralText(literal)
|
||||
}
|
||||
|
||||
override string getBaseString() { result = "#string" }
|
||||
final override string getBaseString() { result = "#string" }
|
||||
|
||||
final Language::StringLiteral getLiteral() { result = literal }
|
||||
}
|
||||
|
||||
/**
|
||||
* A variable generated to track whether a specific non-stack variable has been initialized. This is
|
||||
* used to model the runtime initialization of static local variables in C++, as well as static
|
||||
* fields in C#.
|
||||
*/
|
||||
class IRDynamicInitializationFlag extends IRGeneratedVariable, TIRDynamicInitializationFlag {
|
||||
Language::Variable var;
|
||||
|
||||
IRDynamicInitializationFlag() {
|
||||
this = TIRDynamicInitializationFlag(func, var, type) and ast = var
|
||||
}
|
||||
|
||||
final override string toString() { result = var.toString() + "#init" }
|
||||
|
||||
final Language::Variable getVariable() { result = var }
|
||||
|
||||
final override string getUniqueId() {
|
||||
result = "Init: " + getVariable().toString() + " " + getVariable().getLocation().toString()
|
||||
}
|
||||
|
||||
final override string getBaseString() { result = "#init:" + var.toString() + ":" }
|
||||
}
|
||||
|
||||
@@ -363,6 +363,11 @@ CppPRValueType getIntType() {
|
||||
*/
|
||||
CppPRValueType getBoolType() { exists(BoolType type | result.hasType(type, false)) }
|
||||
|
||||
/**
|
||||
* Gets the `CppType` that represents a glvalue of type `bool`.
|
||||
*/
|
||||
CppType getBoolGLValueType() { exists(BoolType type | result.hasType(type, true)) }
|
||||
|
||||
/**
|
||||
* Gets the `CppType` that represents a glvalue of function type.
|
||||
*/
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
private import implementations.Allocation
|
||||
private import implementations.Deallocation
|
||||
private import implementations.Fread
|
||||
private import implementations.Gets
|
||||
private import implementations.IdentityFunction
|
||||
private import implementations.Inet
|
||||
private import implementations.Memcpy
|
||||
|
||||
45
cpp/ql/src/semmle/code/cpp/models/implementations/Gets.qll
Normal file
45
cpp/ql/src/semmle/code/cpp/models/implementations/Gets.qll
Normal file
@@ -0,0 +1,45 @@
|
||||
import semmle.code.cpp.models.interfaces.DataFlow
|
||||
import semmle.code.cpp.models.interfaces.Taint
|
||||
import semmle.code.cpp.models.interfaces.ArrayFunction
|
||||
import semmle.code.cpp.models.interfaces.Alias
|
||||
import semmle.code.cpp.models.interfaces.SideEffect
|
||||
|
||||
/**
|
||||
* The standard functions `gets` and `fgets`.
|
||||
*/
|
||||
class GetsFunction extends DataFlowFunction, TaintFunction, ArrayFunction, AliasFunction,
|
||||
SideEffectFunction {
|
||||
GetsFunction() {
|
||||
exists(string name | hasGlobalOrStdName(name) |
|
||||
name = "gets" or // gets(str)
|
||||
name = "fgets" or // fgets(str, num, stream)
|
||||
name = "fgetws" // fgetws(wstr, num, stream)
|
||||
)
|
||||
}
|
||||
|
||||
override predicate hasDataFlow(FunctionInput input, FunctionOutput output) {
|
||||
input.isParameter(0) and
|
||||
output.isReturnValue()
|
||||
}
|
||||
|
||||
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
|
||||
input.isParameter(2) and
|
||||
output.isParameterDeref(0)
|
||||
}
|
||||
|
||||
override predicate parameterNeverEscapes(int index) { index = 2 }
|
||||
|
||||
override predicate parameterEscapesOnlyViaReturn(int index) { index = 0 }
|
||||
|
||||
override predicate parameterIsAlwaysReturned(int index) { index = 0 }
|
||||
|
||||
override predicate hasOnlySpecificReadSideEffects() { any() }
|
||||
|
||||
override predicate hasOnlySpecificWriteSideEffects() { any() }
|
||||
|
||||
override predicate hasSpecificWriteSideEffect(ParameterIndex i, boolean buffer, boolean mustWrite) {
|
||||
i = 0 and
|
||||
buffer = true and
|
||||
mustWrite = true
|
||||
}
|
||||
}
|
||||
@@ -67,3 +67,9 @@
|
||||
| test.cpp:83:28:83:33 | call to getenv | test.cpp:88:7:88:27 | (bool)... | |
|
||||
| test.cpp:83:28:83:33 | call to getenv | test.cpp:88:14:88:17 | (const char *)... | |
|
||||
| test.cpp:83:28:83:33 | call to getenv | test.cpp:88:14:88:17 | copy | |
|
||||
| test.cpp:100:12:100:15 | call to gets | test.cpp:98:8:98:14 | pointer | |
|
||||
| test.cpp:100:12:100:15 | call to gets | test.cpp:100:2:100:8 | pointer | |
|
||||
| test.cpp:100:12:100:15 | call to gets | test.cpp:100:12:100:15 | call to gets | |
|
||||
| test.cpp:100:17:100:22 | buffer | test.cpp:93:18:93:18 | s | |
|
||||
| test.cpp:100:17:100:22 | buffer | test.cpp:97:7:97:12 | buffer | |
|
||||
| test.cpp:100:17:100:22 | buffer | test.cpp:100:17:100:22 | buffer | |
|
||||
|
||||
@@ -11,3 +11,6 @@
|
||||
| test.cpp:83:28:83:33 | call to getenv | test.cpp:11:20:11:21 | s1 | AST only |
|
||||
| test.cpp:83:28:83:33 | call to getenv | test.cpp:85:8:85:11 | copy | AST only |
|
||||
| test.cpp:83:28:83:33 | call to getenv | test.cpp:86:9:86:12 | copy | AST only |
|
||||
| test.cpp:100:12:100:15 | call to gets | test.cpp:100:2:100:8 | pointer | AST only |
|
||||
| test.cpp:100:17:100:22 | buffer | test.cpp:97:7:97:12 | buffer | AST only |
|
||||
| test.cpp:100:17:100:22 | buffer | test.cpp:100:17:100:22 | array to pointer conversion | IR only |
|
||||
|
||||
@@ -52,3 +52,8 @@
|
||||
| test.cpp:83:28:83:33 | call to getenv | test.cpp:88:7:88:27 | (bool)... | |
|
||||
| test.cpp:83:28:83:33 | call to getenv | test.cpp:88:14:88:17 | (const char *)... | |
|
||||
| test.cpp:83:28:83:33 | call to getenv | test.cpp:88:14:88:17 | copy | |
|
||||
| test.cpp:100:12:100:15 | call to gets | test.cpp:98:8:98:14 | pointer | |
|
||||
| test.cpp:100:12:100:15 | call to gets | test.cpp:100:12:100:15 | call to gets | |
|
||||
| test.cpp:100:17:100:22 | buffer | test.cpp:93:18:93:18 | s | |
|
||||
| test.cpp:100:17:100:22 | buffer | test.cpp:100:17:100:22 | array to pointer conversion | |
|
||||
| test.cpp:100:17:100:22 | buffer | test.cpp:100:17:100:22 | buffer | |
|
||||
|
||||
@@ -88,4 +88,14 @@ void mallocBuffer() {
|
||||
if (!strcmp(copy, "admin")) { // copy should be tainted
|
||||
isAdmin = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
char *gets(char *s);
|
||||
|
||||
void test_gets()
|
||||
{
|
||||
char buffer[1024];
|
||||
char *pointer;
|
||||
|
||||
pointer = gets(buffer);
|
||||
}
|
||||
|
||||
@@ -8303,6 +8303,107 @@ ir.cpp:
|
||||
# 1219| Type = [IntType] int
|
||||
# 1219| ValueCategory = prvalue(load)
|
||||
# 1220| 4: [ReturnStmt] return ...
|
||||
# 1222| [TopLevelFunction] int staticLocalInit(int)
|
||||
# 1222| params:
|
||||
# 1222| 0: [Parameter] x
|
||||
# 1222| Type = [IntType] int
|
||||
# 1222| body: [Block] { ... }
|
||||
# 1223| 0: [DeclStmt] declaration
|
||||
# 1223| 0: [VariableDeclarationEntry] definition of a
|
||||
# 1223| Type = [IntType] int
|
||||
# 1223| init: [Initializer] initializer for a
|
||||
# 1223| expr: [Literal] 0
|
||||
# 1223| Type = [IntType] int
|
||||
# 1223| Value = [Literal] 0
|
||||
# 1223| ValueCategory = prvalue
|
||||
# 1224| 1: [DeclStmt] declaration
|
||||
# 1224| 0: [VariableDeclarationEntry] definition of b
|
||||
# 1224| Type = [IntType] int
|
||||
# 1224| init: [Initializer] initializer for b
|
||||
# 1224| expr: [CStyleCast] (int)...
|
||||
# 1224| Conversion = [IntegralConversion] integral conversion
|
||||
# 1224| Type = [IntType] int
|
||||
# 1224| Value = [CStyleCast] 4
|
||||
# 1224| ValueCategory = prvalue
|
||||
# 1224| expr: [SizeofExprOperator] sizeof(<expr>)
|
||||
# 1224| Type = [LongType] unsigned long
|
||||
# 1224| Value = [SizeofExprOperator] 4
|
||||
# 1224| ValueCategory = prvalue
|
||||
# 1224| 0: [ParenthesisExpr] (...)
|
||||
# 1224| Type = [IntType] int
|
||||
# 1224| ValueCategory = lvalue
|
||||
# 1224| expr: [VariableAccess] x
|
||||
# 1224| Type = [IntType] int
|
||||
# 1224| ValueCategory = lvalue
|
||||
# 1225| 2: [DeclStmt] declaration
|
||||
# 1225| 0: [VariableDeclarationEntry] definition of c
|
||||
# 1225| Type = [IntType] int
|
||||
# 1225| init: [Initializer] initializer for c
|
||||
# 1225| expr: [VariableAccess] x
|
||||
# 1225| Type = [IntType] int
|
||||
# 1225| ValueCategory = prvalue(load)
|
||||
# 1226| 3: [DeclStmt] declaration
|
||||
# 1226| 0: [VariableDeclarationEntry] definition of d
|
||||
# 1226| Type = [IntType] int
|
||||
# 1228| 4: [ReturnStmt] return ...
|
||||
# 1228| 0: [AddExpr] ... + ...
|
||||
# 1228| Type = [IntType] int
|
||||
# 1228| ValueCategory = prvalue
|
||||
# 1228| 0: [AddExpr] ... + ...
|
||||
# 1228| Type = [IntType] int
|
||||
# 1228| ValueCategory = prvalue
|
||||
# 1228| 0: [AddExpr] ... + ...
|
||||
# 1228| Type = [IntType] int
|
||||
# 1228| ValueCategory = prvalue
|
||||
# 1228| 0: [VariableAccess] a
|
||||
# 1228| Type = [IntType] int
|
||||
# 1228| ValueCategory = prvalue(load)
|
||||
# 1228| 1: [VariableAccess] b
|
||||
# 1228| Type = [IntType] int
|
||||
# 1228| ValueCategory = prvalue(load)
|
||||
# 1228| 1: [VariableAccess] c
|
||||
# 1228| Type = [IntType] int
|
||||
# 1228| ValueCategory = prvalue(load)
|
||||
# 1228| 1: [VariableAccess] d
|
||||
# 1228| Type = [IntType] int
|
||||
# 1228| ValueCategory = prvalue(load)
|
||||
# 1231| [TopLevelFunction] void staticLocalWithConstructor(char const*)
|
||||
# 1231| params:
|
||||
# 1231| 0: [Parameter] dynamic
|
||||
# 1231| Type = [PointerType] const char *
|
||||
# 1231| body: [Block] { ... }
|
||||
# 1232| 0: [DeclStmt] declaration
|
||||
# 1232| 0: [VariableDeclarationEntry] definition of a
|
||||
# 1232| Type = [Struct] String
|
||||
#-----| init: [Initializer] initializer for a
|
||||
#-----| expr: [ConstructorCall] call to String
|
||||
#-----| Type = [VoidType] void
|
||||
#-----| ValueCategory = prvalue
|
||||
# 1233| 1: [DeclStmt] declaration
|
||||
# 1233| 0: [VariableDeclarationEntry] definition of b
|
||||
# 1233| Type = [Struct] String
|
||||
# 1233| init: [Initializer] initializer for b
|
||||
# 1233| expr: [ConstructorCall] call to String
|
||||
# 1233| Type = [VoidType] void
|
||||
# 1233| ValueCategory = prvalue
|
||||
# 1233| 0: [ArrayToPointerConversion] array to pointer conversion
|
||||
# 1233| Type = [PointerType] const char *
|
||||
# 1233| ValueCategory = prvalue
|
||||
# 1233| expr: static
|
||||
# 1233| Type = [ArrayType] const char[7]
|
||||
# 1233| Value = [StringLiteral] "static"
|
||||
# 1233| ValueCategory = lvalue
|
||||
# 1234| 2: [DeclStmt] declaration
|
||||
# 1234| 0: [VariableDeclarationEntry] definition of c
|
||||
# 1234| Type = [Struct] String
|
||||
# 1234| init: [Initializer] initializer for c
|
||||
# 1234| expr: [ConstructorCall] call to String
|
||||
# 1234| Type = [VoidType] void
|
||||
# 1234| ValueCategory = prvalue
|
||||
# 1234| 0: [VariableAccess] dynamic
|
||||
# 1234| Type = [PointerType] const char *
|
||||
# 1234| ValueCategory = prvalue(load)
|
||||
# 1235| 3: [ReturnStmt] return ...
|
||||
perf-regression.cpp:
|
||||
# 4| [CopyAssignmentOperator] Big& Big::operator=(Big const&)
|
||||
# 4| params:
|
||||
|
||||
@@ -1219,4 +1219,19 @@ void switch2Case_default(int x) {
|
||||
int z = y;
|
||||
}
|
||||
|
||||
int staticLocalInit(int x) {
|
||||
static int a = 0; // Constant initialization
|
||||
static int b = sizeof(x); // Constant initialization
|
||||
static int c = x; // Dynamic initialization
|
||||
static int d; // Zero initialization
|
||||
|
||||
return a + b + c + d;
|
||||
}
|
||||
|
||||
void staticLocalWithConstructor(const char* dynamic) {
|
||||
static String a;
|
||||
static String b("static");
|
||||
static String c(dynamic);
|
||||
}
|
||||
|
||||
// semmle-extractor-options: -std=c++17 --clang
|
||||
|
||||
@@ -6232,6 +6232,125 @@ ir.cpp:
|
||||
# 1205| v1205_9(void) = AliasedUse : ~mu1205_4
|
||||
# 1205| v1205_10(void) = ExitFunction :
|
||||
|
||||
# 1222| int staticLocalInit(int)
|
||||
# 1222| Block 0
|
||||
# 1222| v1222_1(void) = EnterFunction :
|
||||
# 1222| mu1222_2(unknown) = AliasedDefinition :
|
||||
# 1222| mu1222_3(unknown) = InitializeNonLocal :
|
||||
# 1222| mu1222_4(unknown) = UnmodeledDefinition :
|
||||
# 1222| r1222_5(glval<int>) = VariableAddress[x] :
|
||||
# 1222| mu1222_6(int) = InitializeParameter[x] : &:r1222_5
|
||||
# 1225| r1225_1(glval<bool>) = VariableAddress[c#init] :
|
||||
# 1225| r1225_2(bool) = Load : &:r1225_1, ~mu1222_4
|
||||
# 1225| v1225_3(void) = ConditionalBranch : r1225_2
|
||||
#-----| False -> Block 2
|
||||
#-----| True -> Block 1
|
||||
|
||||
# 1228| Block 1
|
||||
# 1228| r1228_1(glval<int>) = VariableAddress[#return] :
|
||||
# 1228| r1228_2(glval<int>) = VariableAddress[a] :
|
||||
# 1228| r1228_3(int) = Load : &:r1228_2, ~mu1222_4
|
||||
# 1228| r1228_4(glval<int>) = VariableAddress[b] :
|
||||
# 1228| r1228_5(int) = Load : &:r1228_4, ~mu1222_4
|
||||
# 1228| r1228_6(int) = Add : r1228_3, r1228_5
|
||||
# 1228| r1228_7(glval<int>) = VariableAddress[c] :
|
||||
# 1228| r1228_8(int) = Load : &:r1228_7, ~mu1222_4
|
||||
# 1228| r1228_9(int) = Add : r1228_6, r1228_8
|
||||
# 1228| r1228_10(glval<int>) = VariableAddress[d] :
|
||||
# 1228| r1228_11(int) = Load : &:r1228_10, ~mu1222_4
|
||||
# 1228| r1228_12(int) = Add : r1228_9, r1228_11
|
||||
# 1228| mu1228_13(int) = Store : &:r1228_1, r1228_12
|
||||
# 1222| r1222_7(glval<int>) = VariableAddress[#return] :
|
||||
# 1222| v1222_8(void) = ReturnValue : &:r1222_7, ~mu1222_4
|
||||
# 1222| v1222_9(void) = UnmodeledUse : mu*
|
||||
# 1222| v1222_10(void) = AliasedUse : ~mu1222_4
|
||||
# 1222| v1222_11(void) = ExitFunction :
|
||||
|
||||
# 1225| Block 2
|
||||
# 1225| r1225_4(glval<int>) = VariableAddress[c] :
|
||||
# 1225| r1225_5(glval<int>) = VariableAddress[x] :
|
||||
# 1225| r1225_6(int) = Load : &:r1225_5, ~mu1222_4
|
||||
# 1225| mu1225_7(int) = Store : &:r1225_4, r1225_6
|
||||
# 1225| r1225_8(bool) = Constant[1] :
|
||||
# 1225| mu1225_9(bool) = Store : &:r1225_1, r1225_8
|
||||
#-----| Goto -> Block 1
|
||||
|
||||
# 1231| void staticLocalWithConstructor(char const*)
|
||||
# 1231| Block 0
|
||||
# 1231| v1231_1(void) = EnterFunction :
|
||||
# 1231| mu1231_2(unknown) = AliasedDefinition :
|
||||
# 1231| mu1231_3(unknown) = InitializeNonLocal :
|
||||
# 1231| mu1231_4(unknown) = UnmodeledDefinition :
|
||||
# 1231| r1231_5(glval<char *>) = VariableAddress[dynamic] :
|
||||
# 1231| mu1231_6(char *) = InitializeParameter[dynamic] : &:r1231_5
|
||||
# 1231| r1231_7(char *) = Load : &:r1231_5, ~mu1231_6
|
||||
# 1231| mu1231_8(unknown) = InitializeIndirection[dynamic] : &:r1231_7
|
||||
# 1232| r1232_1(glval<bool>) = VariableAddress[a#init] :
|
||||
# 1232| r1232_2(bool) = Load : &:r1232_1, ~mu1231_4
|
||||
# 1232| v1232_3(void) = ConditionalBranch : r1232_2
|
||||
#-----| False -> Block 6
|
||||
#-----| True -> Block 1
|
||||
|
||||
# 1233| Block 1
|
||||
# 1233| r1233_1(glval<bool>) = VariableAddress[b#init] :
|
||||
# 1233| r1233_2(bool) = Load : &:r1233_1, ~mu1231_4
|
||||
# 1233| v1233_3(void) = ConditionalBranch : r1233_2
|
||||
#-----| False -> Block 2
|
||||
#-----| True -> Block 3
|
||||
|
||||
# 1233| Block 2
|
||||
# 1233| r1233_4(glval<String>) = VariableAddress[b] :
|
||||
# 1233| r1233_5(glval<unknown>) = FunctionAddress[String] :
|
||||
# 1233| r1233_6(glval<char[7]>) = StringConstant["static"] :
|
||||
# 1233| r1233_7(char *) = Convert : r1233_6
|
||||
# 1233| v1233_8(void) = Call : func:r1233_5, this:r1233_4, 0:r1233_7
|
||||
# 1233| mu1233_9(unknown) = ^CallSideEffect : ~mu1231_4
|
||||
# 1233| mu1233_10(String) = ^IndirectMayWriteSideEffect[-1] : &:r1233_4
|
||||
# 1233| v1233_11(void) = ^BufferReadSideEffect[0] : &:r1233_7, ~mu1231_4
|
||||
# 1233| mu1233_12(unknown) = ^BufferMayWriteSideEffect[0] : &:r1233_7
|
||||
# 1233| r1233_13(bool) = Constant[1] :
|
||||
# 1233| mu1233_14(bool) = Store : &:r1233_1, r1233_13
|
||||
#-----| Goto -> Block 3
|
||||
|
||||
# 1234| Block 3
|
||||
# 1234| r1234_1(glval<bool>) = VariableAddress[c#init] :
|
||||
# 1234| r1234_2(bool) = Load : &:r1234_1, ~mu1231_4
|
||||
# 1234| v1234_3(void) = ConditionalBranch : r1234_2
|
||||
#-----| False -> Block 4
|
||||
#-----| True -> Block 5
|
||||
|
||||
# 1234| Block 4
|
||||
# 1234| r1234_4(glval<String>) = VariableAddress[c] :
|
||||
# 1234| r1234_5(glval<unknown>) = FunctionAddress[String] :
|
||||
# 1234| r1234_6(glval<char *>) = VariableAddress[dynamic] :
|
||||
# 1234| r1234_7(char *) = Load : &:r1234_6, ~mu1231_4
|
||||
# 1234| v1234_8(void) = Call : func:r1234_5, this:r1234_4, 0:r1234_7
|
||||
# 1234| mu1234_9(unknown) = ^CallSideEffect : ~mu1231_4
|
||||
# 1234| mu1234_10(String) = ^IndirectMayWriteSideEffect[-1] : &:r1234_4
|
||||
# 1234| v1234_11(void) = ^BufferReadSideEffect[0] : &:r1234_7, ~mu1231_4
|
||||
# 1234| mu1234_12(unknown) = ^BufferMayWriteSideEffect[0] : &:r1234_7
|
||||
# 1234| r1234_13(bool) = Constant[1] :
|
||||
# 1234| mu1234_14(bool) = Store : &:r1234_1, r1234_13
|
||||
#-----| Goto -> Block 5
|
||||
|
||||
# 1235| Block 5
|
||||
# 1235| v1235_1(void) = NoOp :
|
||||
# 1231| v1231_9(void) = ReturnIndirection : &:r1231_7, ~mu1231_4
|
||||
# 1231| v1231_10(void) = ReturnVoid :
|
||||
# 1231| v1231_11(void) = UnmodeledUse : mu*
|
||||
# 1231| v1231_12(void) = AliasedUse : ~mu1231_4
|
||||
# 1231| v1231_13(void) = ExitFunction :
|
||||
|
||||
# 1232| Block 6
|
||||
# 1232| r1232_4(glval<String>) = VariableAddress[a] :
|
||||
#-----| r0_1(glval<unknown>) = FunctionAddress[String] :
|
||||
#-----| v0_2(void) = Call : func:r0_1, this:r1232_4
|
||||
#-----| mu0_3(unknown) = ^CallSideEffect : ~mu1231_4
|
||||
#-----| mu0_4(String) = ^IndirectMayWriteSideEffect[-1] : &:r1232_4
|
||||
# 1232| r1232_5(bool) = Constant[1] :
|
||||
# 1232| mu1232_6(bool) = Store : &:r1232_1, r1232_5
|
||||
#-----| Goto -> Block 1
|
||||
|
||||
perf-regression.cpp:
|
||||
# 6| void Big::Big()
|
||||
# 6| Block 0
|
||||
@@ -6305,8 +6424,6 @@ struct_init.cpp:
|
||||
# 20| mu20_2(unknown) = AliasedDefinition :
|
||||
# 20| mu20_3(unknown) = InitializeNonLocal :
|
||||
# 20| mu20_4(unknown) = UnmodeledDefinition :
|
||||
# 21| r21_1(glval<Info[2]>) = VariableAddress[static_infos] :
|
||||
# 21| mu21_2(Info[2]) = Uninitialized[static_infos] : &:r21_1
|
||||
# 25| r25_1(glval<unknown>) = FunctionAddress[let_info_escape] :
|
||||
# 25| r25_2(glval<Info[2]>) = VariableAddress[static_infos] :
|
||||
# 25| r25_3(Info *) = Convert : r25_2
|
||||
@@ -6362,45 +6479,56 @@ struct_init.cpp:
|
||||
|
||||
# 36| void declare_static_runtime_infos(char const*)
|
||||
# 36| Block 0
|
||||
# 36| v36_1(void) = EnterFunction :
|
||||
# 36| mu36_2(unknown) = AliasedDefinition :
|
||||
# 36| mu36_3(unknown) = InitializeNonLocal :
|
||||
# 36| mu36_4(unknown) = UnmodeledDefinition :
|
||||
# 36| r36_5(glval<char *>) = VariableAddress[name1] :
|
||||
# 36| mu36_6(char *) = InitializeParameter[name1] : &:r36_5
|
||||
# 36| r36_7(char *) = Load : &:r36_5, ~mu36_6
|
||||
# 36| mu36_8(unknown) = InitializeIndirection[name1] : &:r36_7
|
||||
# 37| r37_1(glval<Info[2]>) = VariableAddress[static_infos] :
|
||||
# 37| mu37_2(Info[2]) = Uninitialized[static_infos] : &:r37_1
|
||||
# 37| r37_3(int) = Constant[0] :
|
||||
# 37| r37_4(glval<Info>) = PointerAdd[16] : r37_1, r37_3
|
||||
# 38| r38_1(glval<char *>) = FieldAddress[name] : r37_4
|
||||
# 38| r38_2(glval<char *>) = VariableAddress[name1] :
|
||||
# 38| r38_3(char *) = Load : &:r38_2, ~mu36_4
|
||||
# 38| mu38_4(char *) = Store : &:r38_1, r38_3
|
||||
# 38| r38_5(glval<..(*)(..)>) = FieldAddress[handler] : r37_4
|
||||
# 38| r38_6(..(*)(..)) = FunctionAddress[handler1] :
|
||||
# 38| mu38_7(..(*)(..)) = Store : &:r38_5, r38_6
|
||||
# 37| r37_5(int) = Constant[1] :
|
||||
# 37| r37_6(glval<Info>) = PointerAdd[16] : r37_1, r37_5
|
||||
# 39| r39_1(glval<char *>) = FieldAddress[name] : r37_6
|
||||
# 39| r39_2(glval<char[2]>) = StringConstant["2"] :
|
||||
# 39| r39_3(char *) = Convert : r39_2
|
||||
# 39| mu39_4(char *) = Store : &:r39_1, r39_3
|
||||
# 39| r39_5(glval<..(*)(..)>) = FieldAddress[handler] : r37_6
|
||||
# 39| r39_6(glval<..()(..)>) = FunctionAddress[handler2] :
|
||||
# 39| r39_7(..(*)(..)) = CopyValue : r39_6
|
||||
# 39| mu39_8(..(*)(..)) = Store : &:r39_5, r39_7
|
||||
# 41| r41_1(glval<unknown>) = FunctionAddress[let_info_escape] :
|
||||
# 41| r41_2(glval<Info[2]>) = VariableAddress[static_infos] :
|
||||
# 41| r41_3(Info *) = Convert : r41_2
|
||||
# 41| v41_4(void) = Call : func:r41_1, 0:r41_3
|
||||
# 41| mu41_5(unknown) = ^CallSideEffect : ~mu36_4
|
||||
# 41| v41_6(void) = ^BufferReadSideEffect[0] : &:r41_3, ~mu36_4
|
||||
# 41| mu41_7(unknown) = ^BufferMayWriteSideEffect[0] : &:r41_3
|
||||
# 42| v42_1(void) = NoOp :
|
||||
# 36| v36_9(void) = ReturnIndirection : &:r36_7, ~mu36_4
|
||||
# 36| v36_10(void) = ReturnVoid :
|
||||
# 36| v36_11(void) = UnmodeledUse : mu*
|
||||
# 36| v36_12(void) = AliasedUse : ~mu36_4
|
||||
# 36| v36_13(void) = ExitFunction :
|
||||
# 36| v36_1(void) = EnterFunction :
|
||||
# 36| mu36_2(unknown) = AliasedDefinition :
|
||||
# 36| mu36_3(unknown) = InitializeNonLocal :
|
||||
# 36| mu36_4(unknown) = UnmodeledDefinition :
|
||||
# 36| r36_5(glval<char *>) = VariableAddress[name1] :
|
||||
# 36| mu36_6(char *) = InitializeParameter[name1] : &:r36_5
|
||||
# 36| r36_7(char *) = Load : &:r36_5, ~mu36_6
|
||||
# 36| mu36_8(unknown) = InitializeIndirection[name1] : &:r36_7
|
||||
# 37| r37_1(glval<bool>) = VariableAddress[static_infos#init] :
|
||||
# 37| r37_2(bool) = Load : &:r37_1, ~mu36_4
|
||||
# 37| v37_3(void) = ConditionalBranch : r37_2
|
||||
#-----| False -> Block 2
|
||||
#-----| True -> Block 1
|
||||
|
||||
# 41| Block 1
|
||||
# 41| r41_1(glval<unknown>) = FunctionAddress[let_info_escape] :
|
||||
# 41| r41_2(glval<Info[2]>) = VariableAddress[static_infos] :
|
||||
# 41| r41_3(Info *) = Convert : r41_2
|
||||
# 41| v41_4(void) = Call : func:r41_1, 0:r41_3
|
||||
# 41| mu41_5(unknown) = ^CallSideEffect : ~mu36_4
|
||||
# 41| v41_6(void) = ^BufferReadSideEffect[0] : &:r41_3, ~mu36_4
|
||||
# 41| mu41_7(unknown) = ^BufferMayWriteSideEffect[0] : &:r41_3
|
||||
# 42| v42_1(void) = NoOp :
|
||||
# 36| v36_9(void) = ReturnIndirection : &:r36_7, ~mu36_4
|
||||
# 36| v36_10(void) = ReturnVoid :
|
||||
# 36| v36_11(void) = UnmodeledUse : mu*
|
||||
# 36| v36_12(void) = AliasedUse : ~mu36_4
|
||||
# 36| v36_13(void) = ExitFunction :
|
||||
|
||||
# 37| Block 2
|
||||
# 37| r37_4(glval<Info[2]>) = VariableAddress[static_infos] :
|
||||
# 37| r37_5(int) = Constant[0] :
|
||||
# 37| r37_6(glval<Info>) = PointerAdd[16] : r37_4, r37_5
|
||||
# 38| r38_1(glval<char *>) = FieldAddress[name] : r37_6
|
||||
# 38| r38_2(glval<char *>) = VariableAddress[name1] :
|
||||
# 38| r38_3(char *) = Load : &:r38_2, ~mu36_4
|
||||
# 38| mu38_4(char *) = Store : &:r38_1, r38_3
|
||||
# 38| r38_5(glval<..(*)(..)>) = FieldAddress[handler] : r37_6
|
||||
# 38| r38_6(..(*)(..)) = FunctionAddress[handler1] :
|
||||
# 38| mu38_7(..(*)(..)) = Store : &:r38_5, r38_6
|
||||
# 37| r37_7(int) = Constant[1] :
|
||||
# 37| r37_8(glval<Info>) = PointerAdd[16] : r37_4, r37_7
|
||||
# 39| r39_1(glval<char *>) = FieldAddress[name] : r37_8
|
||||
# 39| r39_2(glval<char[2]>) = StringConstant["2"] :
|
||||
# 39| r39_3(char *) = Convert : r39_2
|
||||
# 39| mu39_4(char *) = Store : &:r39_1, r39_3
|
||||
# 39| r39_5(glval<..(*)(..)>) = FieldAddress[handler] : r37_8
|
||||
# 39| r39_6(glval<..()(..)>) = FunctionAddress[handler2] :
|
||||
# 39| r39_7(..(*)(..)) = CopyValue : r39_6
|
||||
# 39| mu39_8(..(*)(..)) = Store : &:r39_5, r39_7
|
||||
# 37| r37_9(bool) = Constant[1] :
|
||||
# 37| mu37_10(bool) = Store : &:r37_1, r37_9
|
||||
#-----| Goto -> Block 1
|
||||
|
||||
@@ -137,7 +137,6 @@
|
||||
| test.c:109:14:109:16 | Constant: 44 | positive strictlyPositive |
|
||||
| test.c:110:14:110:14 | Constant: 1 | positive strictlyPositive |
|
||||
| test.c:110:14:110:14 | Store: 1 | positive strictlyPositive |
|
||||
| test.c:118:20:118:20 | Uninitialized: definition of n | positive |
|
||||
| test.c:119:10:119:10 | Load: n | positive |
|
||||
| test.c:119:10:119:12 | Add: ... ++ | positive strictlyPositive |
|
||||
| test.c:119:10:119:12 | Constant: ... ++ | positive strictlyPositive |
|
||||
|
||||
@@ -52,7 +52,7 @@ instructionWithoutSuccessor
|
||||
| vla.c:11:6:11:16 | UnmodeledDefinition: vla_typedef |
|
||||
ambiguousSuccessors
|
||||
| allocators.cpp:14:5:14:8 | UnmodeledDefinition: main | Goto | 4 | allocators.cpp:16:8:16:10 | VariableAddress: definition of foo |
|
||||
| allocators.cpp:14:5:14:8 | UnmodeledDefinition: main | Goto | 4 | no_dynamic_init.cpp:10:16:10:16 | VariableAddress: definition of m |
|
||||
| allocators.cpp:14:5:14:8 | UnmodeledDefinition: main | Goto | 4 | no_dynamic_init.cpp:11:3:11:11 | VariableAddress: return ... |
|
||||
| allocators.cpp:14:5:14:8 | UnmodeledDefinition: main | Goto | 4 | parameterinitializer.cpp:19:5:19:5 | FunctionAddress: call to f |
|
||||
| allocators.cpp:14:5:14:8 | UnmodeledDefinition: main | Goto | 4 | stream_it.cpp:18:15:18:16 | VariableAddress: definition of xs |
|
||||
| array_delete.cpp:5:6:5:6 | UnmodeledDefinition: f | Goto | 14 | array_delete.cpp:6:12:6:24 | Constant: (Foo *)... |
|
||||
@@ -358,7 +358,7 @@ ambiguousSuccessors
|
||||
| newexpr.cpp:6:6:6:6 | UnmodeledDefinition: f | Goto | 14 | staticmembercallexpr.cpp:7:4:7:4 | VariableAddress: definition of c |
|
||||
| newexpr.cpp:6:6:6:6 | UnmodeledDefinition: f | Goto | 14 | staticmembercallexpr_args.cpp:8:6:8:6 | VariableAddress: definition of i |
|
||||
| no_dynamic_init.cpp:9:5:9:8 | UnmodeledDefinition: main | Goto | 4 | allocators.cpp:16:8:16:10 | VariableAddress: definition of foo |
|
||||
| no_dynamic_init.cpp:9:5:9:8 | UnmodeledDefinition: main | Goto | 4 | no_dynamic_init.cpp:10:16:10:16 | VariableAddress: definition of m |
|
||||
| no_dynamic_init.cpp:9:5:9:8 | UnmodeledDefinition: main | Goto | 4 | no_dynamic_init.cpp:11:3:11:11 | VariableAddress: return ... |
|
||||
| no_dynamic_init.cpp:9:5:9:8 | UnmodeledDefinition: main | Goto | 4 | parameterinitializer.cpp:19:5:19:5 | FunctionAddress: call to f |
|
||||
| no_dynamic_init.cpp:9:5:9:8 | UnmodeledDefinition: main | Goto | 4 | stream_it.cpp:18:15:18:16 | VariableAddress: definition of xs |
|
||||
| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | aggregateinitializer.c:2:6:2:6 | VariableAddress: definition of a |
|
||||
@@ -408,7 +408,7 @@ ambiguousSuccessors
|
||||
| nonmembercallexpr.c:1:6:1:6 | UnmodeledDefinition: g | Goto | 2 | nonmembercallexpr.c:1:12:1:12 | NoOp: return ... |
|
||||
| nonmembercallexpr.c:1:6:1:6 | UnmodeledDefinition: g | Goto | 2 | revsubscriptexpr.c:2:9:2:9 | VariableAddress: definition of x |
|
||||
| parameterinitializer.cpp:18:5:18:8 | UnmodeledDefinition: main | Goto | 4 | allocators.cpp:16:8:16:10 | VariableAddress: definition of foo |
|
||||
| parameterinitializer.cpp:18:5:18:8 | UnmodeledDefinition: main | Goto | 4 | no_dynamic_init.cpp:10:16:10:16 | VariableAddress: definition of m |
|
||||
| parameterinitializer.cpp:18:5:18:8 | UnmodeledDefinition: main | Goto | 4 | no_dynamic_init.cpp:11:3:11:11 | VariableAddress: return ... |
|
||||
| parameterinitializer.cpp:18:5:18:8 | UnmodeledDefinition: main | Goto | 4 | parameterinitializer.cpp:19:5:19:5 | FunctionAddress: call to f |
|
||||
| parameterinitializer.cpp:18:5:18:8 | UnmodeledDefinition: main | Goto | 4 | stream_it.cpp:18:15:18:16 | VariableAddress: definition of xs |
|
||||
| pmcallexpr.cpp:6:6:6:6 | UnmodeledDefinition: f | Goto | 14 | array_delete.cpp:6:12:6:24 | Constant: (Foo *)... |
|
||||
@@ -460,7 +460,7 @@ ambiguousSuccessors
|
||||
| staticmembercallexpr_args.cpp:7:6:7:6 | UnmodeledDefinition: f | Goto | 14 | staticmembercallexpr.cpp:7:4:7:4 | VariableAddress: definition of c |
|
||||
| staticmembercallexpr_args.cpp:7:6:7:6 | UnmodeledDefinition: f | Goto | 14 | staticmembercallexpr_args.cpp:8:6:8:6 | VariableAddress: definition of i |
|
||||
| stream_it.cpp:16:5:16:8 | UnmodeledDefinition: main | Goto | 4 | allocators.cpp:16:8:16:10 | VariableAddress: definition of foo |
|
||||
| stream_it.cpp:16:5:16:8 | UnmodeledDefinition: main | Goto | 4 | no_dynamic_init.cpp:10:16:10:16 | VariableAddress: definition of m |
|
||||
| stream_it.cpp:16:5:16:8 | UnmodeledDefinition: main | Goto | 4 | no_dynamic_init.cpp:11:3:11:11 | VariableAddress: return ... |
|
||||
| stream_it.cpp:16:5:16:8 | UnmodeledDefinition: main | Goto | 4 | parameterinitializer.cpp:19:5:19:5 | FunctionAddress: call to f |
|
||||
| stream_it.cpp:16:5:16:8 | UnmodeledDefinition: main | Goto | 4 | stream_it.cpp:18:15:18:16 | VariableAddress: definition of xs |
|
||||
| switchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | aggregateinitializer.c:2:6:2:6 | VariableAddress: definition of a |
|
||||
|
||||
@@ -107,7 +107,7 @@ instructionWithoutSuccessor
|
||||
| vla.c:14:92:14:94 | Store: (char *)... |
|
||||
ambiguousSuccessors
|
||||
| allocators.cpp:14:5:14:8 | UnmodeledDefinition: main | Goto | 4 | allocators.cpp:16:8:16:10 | VariableAddress: definition of foo |
|
||||
| allocators.cpp:14:5:14:8 | UnmodeledDefinition: main | Goto | 4 | no_dynamic_init.cpp:10:16:10:16 | VariableAddress: definition of m |
|
||||
| allocators.cpp:14:5:14:8 | UnmodeledDefinition: main | Goto | 4 | no_dynamic_init.cpp:11:3:11:11 | VariableAddress: return ... |
|
||||
| allocators.cpp:14:5:14:8 | UnmodeledDefinition: main | Goto | 4 | parameterinitializer.cpp:19:5:19:5 | FunctionAddress: call to f |
|
||||
| allocators.cpp:14:5:14:8 | UnmodeledDefinition: main | Goto | 4 | stream_it.cpp:18:15:18:16 | VariableAddress: definition of xs |
|
||||
| array_delete.cpp:5:6:5:6 | UnmodeledDefinition: f | Goto | 14 | array_delete.cpp:6:12:6:24 | Constant: (Foo *)... |
|
||||
@@ -413,7 +413,7 @@ ambiguousSuccessors
|
||||
| newexpr.cpp:6:6:6:6 | UnmodeledDefinition: f | Goto | 14 | staticmembercallexpr.cpp:7:4:7:4 | VariableAddress: definition of c |
|
||||
| newexpr.cpp:6:6:6:6 | UnmodeledDefinition: f | Goto | 14 | staticmembercallexpr_args.cpp:8:6:8:6 | VariableAddress: definition of i |
|
||||
| no_dynamic_init.cpp:9:5:9:8 | UnmodeledDefinition: main | Goto | 4 | allocators.cpp:16:8:16:10 | VariableAddress: definition of foo |
|
||||
| no_dynamic_init.cpp:9:5:9:8 | UnmodeledDefinition: main | Goto | 4 | no_dynamic_init.cpp:10:16:10:16 | VariableAddress: definition of m |
|
||||
| no_dynamic_init.cpp:9:5:9:8 | UnmodeledDefinition: main | Goto | 4 | no_dynamic_init.cpp:11:3:11:11 | VariableAddress: return ... |
|
||||
| no_dynamic_init.cpp:9:5:9:8 | UnmodeledDefinition: main | Goto | 4 | parameterinitializer.cpp:19:5:19:5 | FunctionAddress: call to f |
|
||||
| no_dynamic_init.cpp:9:5:9:8 | UnmodeledDefinition: main | Goto | 4 | stream_it.cpp:18:15:18:16 | VariableAddress: definition of xs |
|
||||
| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | aggregateinitializer.c:2:6:2:6 | VariableAddress: definition of a |
|
||||
@@ -463,7 +463,7 @@ ambiguousSuccessors
|
||||
| nonmembercallexpr.c:1:6:1:6 | UnmodeledDefinition: g | Goto | 2 | nonmembercallexpr.c:1:12:1:12 | NoOp: return ... |
|
||||
| nonmembercallexpr.c:1:6:1:6 | UnmodeledDefinition: g | Goto | 2 | revsubscriptexpr.c:2:9:2:9 | VariableAddress: definition of x |
|
||||
| parameterinitializer.cpp:18:5:18:8 | UnmodeledDefinition: main | Goto | 4 | allocators.cpp:16:8:16:10 | VariableAddress: definition of foo |
|
||||
| parameterinitializer.cpp:18:5:18:8 | UnmodeledDefinition: main | Goto | 4 | no_dynamic_init.cpp:10:16:10:16 | VariableAddress: definition of m |
|
||||
| parameterinitializer.cpp:18:5:18:8 | UnmodeledDefinition: main | Goto | 4 | no_dynamic_init.cpp:11:3:11:11 | VariableAddress: return ... |
|
||||
| parameterinitializer.cpp:18:5:18:8 | UnmodeledDefinition: main | Goto | 4 | parameterinitializer.cpp:19:5:19:5 | FunctionAddress: call to f |
|
||||
| parameterinitializer.cpp:18:5:18:8 | UnmodeledDefinition: main | Goto | 4 | stream_it.cpp:18:15:18:16 | VariableAddress: definition of xs |
|
||||
| pmcallexpr.cpp:6:6:6:6 | UnmodeledDefinition: f | Goto | 14 | array_delete.cpp:6:12:6:24 | Constant: (Foo *)... |
|
||||
@@ -515,7 +515,7 @@ ambiguousSuccessors
|
||||
| staticmembercallexpr_args.cpp:7:6:7:6 | UnmodeledDefinition: f | Goto | 14 | staticmembercallexpr.cpp:7:4:7:4 | VariableAddress: definition of c |
|
||||
| staticmembercallexpr_args.cpp:7:6:7:6 | UnmodeledDefinition: f | Goto | 14 | staticmembercallexpr_args.cpp:8:6:8:6 | VariableAddress: definition of i |
|
||||
| stream_it.cpp:16:5:16:8 | UnmodeledDefinition: main | Goto | 4 | allocators.cpp:16:8:16:10 | VariableAddress: definition of foo |
|
||||
| stream_it.cpp:16:5:16:8 | UnmodeledDefinition: main | Goto | 4 | no_dynamic_init.cpp:10:16:10:16 | VariableAddress: definition of m |
|
||||
| stream_it.cpp:16:5:16:8 | UnmodeledDefinition: main | Goto | 4 | no_dynamic_init.cpp:11:3:11:11 | VariableAddress: return ... |
|
||||
| stream_it.cpp:16:5:16:8 | UnmodeledDefinition: main | Goto | 4 | parameterinitializer.cpp:19:5:19:5 | FunctionAddress: call to f |
|
||||
| stream_it.cpp:16:5:16:8 | UnmodeledDefinition: main | Goto | 4 | stream_it.cpp:18:15:18:16 | VariableAddress: definition of xs |
|
||||
| switchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | aggregateinitializer.c:2:6:2:6 | VariableAddress: definition of a |
|
||||
|
||||
@@ -61,7 +61,7 @@ instructionWithoutSuccessor
|
||||
| vla.c:11:6:11:16 | UnmodeledDefinition: vla_typedef |
|
||||
ambiguousSuccessors
|
||||
| allocators.cpp:14:5:14:8 | UnmodeledDefinition: main | Goto | 4 | allocators.cpp:16:8:16:10 | VariableAddress: definition of foo |
|
||||
| allocators.cpp:14:5:14:8 | UnmodeledDefinition: main | Goto | 4 | no_dynamic_init.cpp:10:16:10:16 | VariableAddress: definition of m |
|
||||
| allocators.cpp:14:5:14:8 | UnmodeledDefinition: main | Goto | 4 | no_dynamic_init.cpp:11:3:11:11 | VariableAddress: return ... |
|
||||
| allocators.cpp:14:5:14:8 | UnmodeledDefinition: main | Goto | 4 | parameterinitializer.cpp:19:5:19:5 | FunctionAddress: call to f |
|
||||
| allocators.cpp:14:5:14:8 | UnmodeledDefinition: main | Goto | 4 | stream_it.cpp:18:15:18:16 | VariableAddress: definition of xs |
|
||||
| array_delete.cpp:5:6:5:6 | UnmodeledDefinition: f | Goto | 14 | array_delete.cpp:6:12:6:24 | Constant: (Foo *)... |
|
||||
@@ -367,7 +367,7 @@ ambiguousSuccessors
|
||||
| newexpr.cpp:6:6:6:6 | UnmodeledDefinition: f | Goto | 14 | staticmembercallexpr.cpp:7:4:7:4 | VariableAddress: definition of c |
|
||||
| newexpr.cpp:6:6:6:6 | UnmodeledDefinition: f | Goto | 14 | staticmembercallexpr_args.cpp:8:6:8:6 | VariableAddress: definition of i |
|
||||
| no_dynamic_init.cpp:9:5:9:8 | UnmodeledDefinition: main | Goto | 4 | allocators.cpp:16:8:16:10 | VariableAddress: definition of foo |
|
||||
| no_dynamic_init.cpp:9:5:9:8 | UnmodeledDefinition: main | Goto | 4 | no_dynamic_init.cpp:10:16:10:16 | VariableAddress: definition of m |
|
||||
| no_dynamic_init.cpp:9:5:9:8 | UnmodeledDefinition: main | Goto | 4 | no_dynamic_init.cpp:11:3:11:11 | VariableAddress: return ... |
|
||||
| no_dynamic_init.cpp:9:5:9:8 | UnmodeledDefinition: main | Goto | 4 | parameterinitializer.cpp:19:5:19:5 | FunctionAddress: call to f |
|
||||
| no_dynamic_init.cpp:9:5:9:8 | UnmodeledDefinition: main | Goto | 4 | stream_it.cpp:18:15:18:16 | VariableAddress: definition of xs |
|
||||
| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | aggregateinitializer.c:2:6:2:6 | VariableAddress: definition of a |
|
||||
@@ -417,7 +417,7 @@ ambiguousSuccessors
|
||||
| nonmembercallexpr.c:1:6:1:6 | UnmodeledDefinition: g | Goto | 2 | nonmembercallexpr.c:1:12:1:12 | NoOp: return ... |
|
||||
| nonmembercallexpr.c:1:6:1:6 | UnmodeledDefinition: g | Goto | 2 | revsubscriptexpr.c:2:9:2:9 | VariableAddress: definition of x |
|
||||
| parameterinitializer.cpp:18:5:18:8 | UnmodeledDefinition: main | Goto | 4 | allocators.cpp:16:8:16:10 | VariableAddress: definition of foo |
|
||||
| parameterinitializer.cpp:18:5:18:8 | UnmodeledDefinition: main | Goto | 4 | no_dynamic_init.cpp:10:16:10:16 | VariableAddress: definition of m |
|
||||
| parameterinitializer.cpp:18:5:18:8 | UnmodeledDefinition: main | Goto | 4 | no_dynamic_init.cpp:11:3:11:11 | VariableAddress: return ... |
|
||||
| parameterinitializer.cpp:18:5:18:8 | UnmodeledDefinition: main | Goto | 4 | parameterinitializer.cpp:19:5:19:5 | FunctionAddress: call to f |
|
||||
| parameterinitializer.cpp:18:5:18:8 | UnmodeledDefinition: main | Goto | 4 | stream_it.cpp:18:15:18:16 | VariableAddress: definition of xs |
|
||||
| pmcallexpr.cpp:6:6:6:6 | UnmodeledDefinition: f | Goto | 14 | array_delete.cpp:6:12:6:24 | Constant: (Foo *)... |
|
||||
@@ -469,7 +469,7 @@ ambiguousSuccessors
|
||||
| staticmembercallexpr_args.cpp:7:6:7:6 | UnmodeledDefinition: f | Goto | 14 | staticmembercallexpr.cpp:7:4:7:4 | VariableAddress: definition of c |
|
||||
| staticmembercallexpr_args.cpp:7:6:7:6 | UnmodeledDefinition: f | Goto | 14 | staticmembercallexpr_args.cpp:8:6:8:6 | VariableAddress: definition of i |
|
||||
| stream_it.cpp:16:5:16:8 | UnmodeledDefinition: main | Goto | 4 | allocators.cpp:16:8:16:10 | VariableAddress: definition of foo |
|
||||
| stream_it.cpp:16:5:16:8 | UnmodeledDefinition: main | Goto | 4 | no_dynamic_init.cpp:10:16:10:16 | VariableAddress: definition of m |
|
||||
| stream_it.cpp:16:5:16:8 | UnmodeledDefinition: main | Goto | 4 | no_dynamic_init.cpp:11:3:11:11 | VariableAddress: return ... |
|
||||
| stream_it.cpp:16:5:16:8 | UnmodeledDefinition: main | Goto | 4 | parameterinitializer.cpp:19:5:19:5 | FunctionAddress: call to f |
|
||||
| stream_it.cpp:16:5:16:8 | UnmodeledDefinition: main | Goto | 4 | stream_it.cpp:18:15:18:16 | VariableAddress: definition of xs |
|
||||
| switchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | aggregateinitializer.c:2:6:2:6 | VariableAddress: definition of a |
|
||||
|
||||
@@ -59,8 +59,7 @@
|
||||
| variables.cpp:37:6:37:8 | ap3 | file://:0:0:0:0 | int * | StaticStorageDurationVariable | | |
|
||||
| variables.cpp:41:7:41:11 | local | file://:0:0:0:0 | char[] | LocalVariable | | |
|
||||
| variables.cpp:41:7:41:11 | local | file://:0:0:0:0 | char[] | SemanticStackVariable | | |
|
||||
| variables.cpp:43:14:43:18 | local | file://:0:0:0:0 | int | LocalVariable | | static |
|
||||
| variables.cpp:43:14:43:18 | local | file://:0:0:0:0 | int | StaticStorageDurationVariable | | static |
|
||||
| variables.cpp:43:14:43:18 | local | file://:0:0:0:0 | int | StaticLocalVariable | | static |
|
||||
| variables.cpp:48:9:48:12 | name | file://:0:0:0:0 | char * | Field | | |
|
||||
| variables.cpp:49:12:49:17 | number | file://:0:0:0:0 | long | Field | | |
|
||||
| variables.cpp:50:9:50:14 | street | file://:0:0:0:0 | char * | Field | | |
|
||||
|
||||
@@ -112,4 +112,29 @@ void myFunction() {
|
||||
assert(CHECK_RANGE(ui, 0, 10)); // reasonable use
|
||||
assert(UI >= ZERO); // violation (not detected)
|
||||
assert(ui GE 0); // violation
|
||||
|
||||
if ((unsigned char)si >= 0) { // violation
|
||||
}
|
||||
if ((unsigned char)(signed int)si >= 0) { // violation
|
||||
}
|
||||
if ((signed int)(unsigned char)si >= 0) { // violation
|
||||
}
|
||||
if ((unsigned char)(signed char)si >= 0) { // violation
|
||||
}
|
||||
if ((signed char)(unsigned char)si >= 0) {
|
||||
}
|
||||
|
||||
if ((signed int)(unsigned char)(signed int)si >= 0) { // violation
|
||||
}
|
||||
if ((signed char)(unsigned char)(signed int)si >= 0) {
|
||||
}
|
||||
if ((signed int)(unsigned char)(signed char)si >= 0) { // violation
|
||||
}
|
||||
|
||||
if (ui <= 0) {
|
||||
}
|
||||
if (0 <= ui) { // violation
|
||||
}
|
||||
if (0 < ui) {
|
||||
}
|
||||
}
|
||||
|
||||
@@ -112,4 +112,29 @@ void myFunction() {
|
||||
assert(CHECK_RANGE(ui, 0, 10)); // reasonable use
|
||||
assert(UI >= ZERO); // violation (not detected)
|
||||
assert(ui GE 0); // violation
|
||||
|
||||
if ((unsigned char)si >= 0) { // violation
|
||||
}
|
||||
if ((unsigned char)(signed int)si >= 0) { // violation
|
||||
}
|
||||
if ((signed int)(unsigned char)si >= 0) { // violation
|
||||
}
|
||||
if ((unsigned char)(signed char)si >= 0) { // violation
|
||||
}
|
||||
if ((signed char)(unsigned char)si >= 0) {
|
||||
}
|
||||
|
||||
if ((signed int)(unsigned char)(signed int)si >= 0) { // violation
|
||||
}
|
||||
if ((signed char)(unsigned char)(signed int)si >= 0) {
|
||||
}
|
||||
if ((signed int)(unsigned char)(signed char)si >= 0) { // violation
|
||||
}
|
||||
|
||||
if (ui <= 0) {
|
||||
}
|
||||
if (0 <= ui) { // violation
|
||||
}
|
||||
if (0 < ui) {
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,6 +14,13 @@
|
||||
| UnsignedGEZero.c:101:9:101:15 | ... >= ... | Pointless comparison of unsigned value to zero. |
|
||||
| UnsignedGEZero.c:111:9:111:15 | ... >= ... | Pointless comparison of unsigned value to zero. |
|
||||
| UnsignedGEZero.c:114:9:114:15 | ... >= ... | Pointless comparison of unsigned value to zero. |
|
||||
| UnsignedGEZero.c:116:6:116:27 | ... >= ... | Pointless comparison of unsigned value to zero. |
|
||||
| UnsignedGEZero.c:118:6:118:39 | ... >= ... | Pointless comparison of unsigned value to zero. |
|
||||
| UnsignedGEZero.c:120:6:120:39 | ... >= ... | Pointless comparison of unsigned value to zero. |
|
||||
| UnsignedGEZero.c:122:6:122:40 | ... >= ... | Pointless comparison of unsigned value to zero. |
|
||||
| UnsignedGEZero.c:127:6:127:51 | ... >= ... | Pointless comparison of unsigned value to zero. |
|
||||
| UnsignedGEZero.c:131:6:131:52 | ... >= ... | Pointless comparison of unsigned value to zero. |
|
||||
| UnsignedGEZero.c:136:6:136:12 | ... <= ... | Pointless comparison of unsigned value to zero. |
|
||||
| UnsignedGEZero.cpp:40:6:40:12 | ... >= ... | Pointless comparison of unsigned value to zero. |
|
||||
| UnsignedGEZero.cpp:48:6:48:15 | ... >= ... | Pointless comparison of unsigned value to zero. |
|
||||
| UnsignedGEZero.cpp:54:6:54:12 | ... >= ... | Pointless comparison of unsigned value to zero. |
|
||||
@@ -29,3 +36,10 @@
|
||||
| UnsignedGEZero.cpp:101:9:101:15 | ... >= ... | Pointless comparison of unsigned value to zero. |
|
||||
| UnsignedGEZero.cpp:111:9:111:15 | ... >= ... | Pointless comparison of unsigned value to zero. |
|
||||
| UnsignedGEZero.cpp:114:9:114:15 | ... >= ... | Pointless comparison of unsigned value to zero. |
|
||||
| UnsignedGEZero.cpp:116:6:116:27 | ... >= ... | Pointless comparison of unsigned value to zero. |
|
||||
| UnsignedGEZero.cpp:118:6:118:39 | ... >= ... | Pointless comparison of unsigned value to zero. |
|
||||
| UnsignedGEZero.cpp:120:6:120:39 | ... >= ... | Pointless comparison of unsigned value to zero. |
|
||||
| UnsignedGEZero.cpp:122:6:122:40 | ... >= ... | Pointless comparison of unsigned value to zero. |
|
||||
| UnsignedGEZero.cpp:127:6:127:51 | ... >= ... | Pointless comparison of unsigned value to zero. |
|
||||
| UnsignedGEZero.cpp:131:6:131:52 | ... >= ... | Pointless comparison of unsigned value to zero. |
|
||||
| UnsignedGEZero.cpp:136:6:136:12 | ... <= ... | Pointless comparison of unsigned value to zero. |
|
||||
|
||||
@@ -1,10 +1,5 @@
|
||||
| tests.c:28:3:28:9 | call to sprintf | This 'call to sprintf' with input from $@ may overflow the destination. | tests.c:28:22:28:25 | argv | argv |
|
||||
| tests.c:29:3:29:9 | call to sprintf | This 'call to sprintf' with input from $@ may overflow the destination. | tests.c:29:28:29:31 | argv | argv |
|
||||
| tests.c:31:15:31:23 | buffer100 | This 'scanf string argument' with input from $@ may overflow the destination. | tests.c:28:22:28:25 | argv | argv |
|
||||
| tests.c:31:15:31:23 | buffer100 | This 'scanf string argument' with input from $@ may overflow the destination. | tests.c:29:28:29:31 | argv | argv |
|
||||
| tests.c:31:15:31:23 | buffer100 | This 'scanf string argument' with input from $@ may overflow the destination. | tests.c:31:15:31:23 | buffer100 | buffer100 |
|
||||
| tests.c:33:21:33:29 | buffer100 | This 'scanf string argument' with input from $@ may overflow the destination. | tests.c:28:22:28:25 | argv | argv |
|
||||
| tests.c:33:21:33:29 | buffer100 | This 'scanf string argument' with input from $@ may overflow the destination. | tests.c:29:28:29:31 | argv | argv |
|
||||
| tests.c:33:21:33:29 | buffer100 | This 'scanf string argument' with input from $@ may overflow the destination. | tests.c:31:15:31:23 | buffer100 | buffer100 |
|
||||
| tests.c:33:21:33:29 | buffer100 | This 'scanf string argument' with input from $@ may overflow the destination. | tests.c:33:21:33:29 | buffer100 | buffer100 |
|
||||
| tests.c:34:25:34:33 | buffer100 | This 'sscanf string argument' with input from $@ may overflow the destination. | tests.c:34:10:34:13 | argv | argv |
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
| funcsLocal.c:17:9:17:10 | i1 | The value of this argument may come from $@ and is being used as a formatting argument to printf(format) | funcsLocal.c:16:8:16:9 | i1 | fread |
|
||||
| funcsLocal.c:27:9:27:10 | i3 | The value of this argument may come from $@ and is being used as a formatting argument to printf(format) | funcsLocal.c:26:8:26:9 | i3 | fgets |
|
||||
| funcsLocal.c:32:9:32:10 | i4 | The value of this argument may come from $@ and is being used as a formatting argument to printf(format) | funcsLocal.c:31:13:31:17 | call to fgets | fgets |
|
||||
| funcsLocal.c:32:9:32:10 | i4 | The value of this argument may come from $@ and is being used as a formatting argument to printf(format) | funcsLocal.c:31:19:31:21 | i41 | fgets |
|
||||
| funcsLocal.c:37:9:37:10 | i5 | The value of this argument may come from $@ and is being used as a formatting argument to printf(format) | funcsLocal.c:36:7:36:8 | i5 | gets |
|
||||
| funcsLocal.c:42:9:42:10 | i6 | The value of this argument may come from $@ and is being used as a formatting argument to printf(format) | funcsLocal.c:41:13:41:16 | call to gets | gets |
|
||||
| funcsLocal.c:42:9:42:10 | i6 | The value of this argument may come from $@ and is being used as a formatting argument to printf(format) | funcsLocal.c:41:18:41:20 | i61 | gets |
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
| test.c:21:17:21:17 | r | $@ flows to here and is used in arithmetic, potentially causing an overflow. | test.c:18:13:18:16 | call to rand | Uncontrolled value |
|
||||
| test.c:35:5:35:5 | r | $@ flows to here and is used in arithmetic, potentially causing an overflow. | test.c:34:13:34:18 | call to rand | Uncontrolled value |
|
||||
| test.c:40:5:40:5 | r | $@ flows to here and is used in arithmetic, potentially causing an overflow. | test.c:39:13:39:21 | ... % ... | Uncontrolled value |
|
||||
| test.c:40:5:40:5 | r | $@ flows to here and is used in arithmetic, potentially causing an overflow. | test.c:39:13:39:22 | call to rand | Uncontrolled value |
|
||||
| test.c:45:5:45:5 | r | $@ flows to here and is used in arithmetic, potentially causing an overflow. | test.c:44:13:44:16 | call to rand | Uncontrolled value |
|
||||
| test.c:56:5:56:5 | r | $@ flows to here and is used in arithmetic, potentially causing an overflow. | test.c:54:13:54:16 | call to rand | Uncontrolled value |
|
||||
| test.c:67:5:67:5 | r | $@ flows to here and is used in arithmetic, potentially causing an overflow. | test.c:66:13:66:16 | call to rand | Uncontrolled value |
|
||||
|
||||
Reference in New Issue
Block a user