This commit is contained in:
Dilan Bhalla
2023-08-27 23:53:31 -07:00
1277 changed files with 66418 additions and 44671 deletions

View File

@@ -7,15 +7,17 @@ on:
- .github/workflows/go-tests-other-os.yml - .github/workflows/go-tests-other-os.yml
- .github/actions/** - .github/actions/**
- codeql-workspace.yml - codeql-workspace.yml
env:
GO_VERSION: '~1.21.0'
jobs: jobs:
test-mac: test-mac:
name: Test MacOS name: Test MacOS
runs-on: macos-latest runs-on: macos-latest
steps: steps:
- name: Set up Go 1.20 - name: Set up Go ${{ env.GO_VERSION }}
uses: actions/setup-go@v4 uses: actions/setup-go@v4
with: with:
go-version: '1.20' go-version: ${{ env.GO_VERSION }}
id: go id: go
- name: Check out code - name: Check out code
@@ -47,10 +49,10 @@ jobs:
name: Test Windows name: Test Windows
runs-on: windows-latest-xl runs-on: windows-latest-xl
steps: steps:
- name: Set up Go 1.20 - name: Set up Go ${{ env.GO_VERSION }}
uses: actions/setup-go@v4 uses: actions/setup-go@v4
with: with:
go-version: '1.20' go-version: ${{ env.GO_VERSION }}
id: go id: go
- name: Check out code - name: Check out code

View File

@@ -15,15 +15,17 @@ on:
- .github/workflows/go-tests.yml - .github/workflows/go-tests.yml
- .github/actions/** - .github/actions/**
- codeql-workspace.yml - codeql-workspace.yml
env:
GO_VERSION: '~1.21.0'
jobs: jobs:
test-linux: test-linux:
name: Test Linux (Ubuntu) name: Test Linux (Ubuntu)
runs-on: ubuntu-latest-xl runs-on: ubuntu-latest-xl
steps: steps:
- name: Set up Go 1.20 - name: Set up Go ${{ env.GO_VERSION }}
uses: actions/setup-go@v4 uses: actions/setup-go@v4
with: with:
go-version: '1.20' go-version: ${{ env.GO_VERSION }}
id: go id: go
- name: Check out code - name: Check out code

View File

@@ -22,7 +22,6 @@
"csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl5.qll", "csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl5.qll",
"go/ql/lib/semmle/go/dataflow/internal/DataFlowImpl1.qll", "go/ql/lib/semmle/go/dataflow/internal/DataFlowImpl1.qll",
"go/ql/lib/semmle/go/dataflow/internal/DataFlowImpl2.qll", "go/ql/lib/semmle/go/dataflow/internal/DataFlowImpl2.qll",
"go/ql/lib/semmle/go/dataflow/internal/DataFlowImplForStringsNewReplacer.qll",
"python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl1.qll", "python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl1.qll",
"python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl2.qll", "python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl2.qll",
"python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl3.qll", "python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl3.qll",
@@ -33,16 +32,6 @@
"ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowImplForPathname.qll", "ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowImplForPathname.qll",
"swift/ql/lib/codeql/swift/dataflow/internal/DataFlowImpl1.qll" "swift/ql/lib/codeql/swift/dataflow/internal/DataFlowImpl1.qll"
], ],
"TaintTracking Java/C++/C#/Go/Python/Ruby/Swift": [
"cpp/ql/lib/semmle/code/cpp/dataflow/internal/tainttracking1/TaintTracking.qll",
"cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/tainttracking1/TaintTracking.qll",
"csharp/ql/lib/semmle/code/csharp/dataflow/internal/tainttracking1/TaintTracking.qll",
"go/ql/lib/semmle/go/dataflow/internal/tainttracking1/TaintTracking.qll",
"java/ql/lib/semmle/code/java/dataflow/internal/tainttracking1/TaintTracking.qll",
"python/ql/lib/semmle/python/dataflow/new/internal/tainttracking1/TaintTracking.qll",
"ruby/ql/lib/codeql/ruby/dataflow/internal/tainttracking1/TaintTracking.qll",
"swift/ql/lib/codeql/swift/dataflow/internal/tainttracking1/TaintTracking.qll"
],
"TaintTracking Legacy Configuration Java/C++/C#/Go/Python/Ruby/Swift": [ "TaintTracking Legacy Configuration Java/C++/C#/Go/Python/Ruby/Swift": [
"cpp/ql/lib/semmle/code/cpp/dataflow/internal/tainttracking1/TaintTrackingImpl.qll", "cpp/ql/lib/semmle/code/cpp/dataflow/internal/tainttracking1/TaintTrackingImpl.qll",
"cpp/ql/lib/semmle/code/cpp/dataflow/internal/tainttracking2/TaintTrackingImpl.qll", "cpp/ql/lib/semmle/code/cpp/dataflow/internal/tainttracking2/TaintTrackingImpl.qll",
@@ -484,10 +473,6 @@
"ruby/ql/lib/codeql/ruby/security/internal/SensitiveDataHeuristics.qll", "ruby/ql/lib/codeql/ruby/security/internal/SensitiveDataHeuristics.qll",
"swift/ql/lib/codeql/swift/security/internal/SensitiveDataHeuristics.qll" "swift/ql/lib/codeql/swift/security/internal/SensitiveDataHeuristics.qll"
], ],
"CFG": [
"csharp/ql/lib/semmle/code/csharp/controlflow/internal/ControlFlowGraphImplShared.qll",
"swift/ql/lib/codeql/swift/controlflow/internal/ControlFlowGraphImplShared.qll"
],
"TypeTracker": [ "TypeTracker": [
"python/ql/lib/semmle/python/dataflow/new/internal/TypeTracker.qll", "python/ql/lib/semmle/python/dataflow/new/internal/TypeTracker.qll",
"ruby/ql/lib/codeql/ruby/typetracking/TypeTracker.qll" "ruby/ql/lib/codeql/ruby/typetracking/TypeTracker.qll"

View File

@@ -327,7 +327,7 @@ namespace Semmle.Autobuild.Cpp.Tests
{ {
Actions.RunProcess[@"cmd.exe /C nuget restore C:\Project\test.sln -DisableParallelProcessing"] = 1; Actions.RunProcess[@"cmd.exe /C nuget restore C:\Project\test.sln -DisableParallelProcessing"] = 1;
Actions.RunProcess[@"cmd.exe /C C:\Project\.nuget\nuget.exe restore C:\Project\test.sln -DisableParallelProcessing"] = 0; Actions.RunProcess[@"cmd.exe /C C:\Project\.nuget\nuget.exe restore C:\Project\test.sln -DisableParallelProcessing"] = 0;
Actions.RunProcess[@"cmd.exe /C CALL ^""C:\Program Files ^(x86^)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat^"" && set Platform=&& type NUL && msbuild C:\Project\test.sln /t:rebuild /p:Platform=""x86"" /p:Configuration=""Release"""] = 0; Actions.RunProcess[@"cmd.exe /C CALL ^""C:\Program^ Files^ ^(x86^)\Microsoft^ Visual^ Studio^ 14.0\VC\vcvarsall.bat^"" && set Platform=&& type NUL && msbuild C:\Project\test.sln /t:rebuild /p:Platform=""x86"" /p:Configuration=""Release"""] = 0;
Actions.RunProcessOut[@"C:\Program Files (x86)\Microsoft Visual Studio\Installer\vswhere.exe -prerelease -legacy -property installationPath"] = ""; Actions.RunProcessOut[@"C:\Program Files (x86)\Microsoft Visual Studio\Installer\vswhere.exe -prerelease -legacy -property installationPath"] = "";
Actions.RunProcess[@"C:\Program Files (x86)\Microsoft Visual Studio\Installer\vswhere.exe -prerelease -legacy -property installationPath"] = 1; Actions.RunProcess[@"C:\Program Files (x86)\Microsoft Visual Studio\Installer\vswhere.exe -prerelease -legacy -property installationPath"] = 1;
Actions.RunProcess[@"C:\Program Files (x86)\Microsoft Visual Studio\Installer\vswhere.exe -prerelease -legacy -property installationVersion"] = 0; Actions.RunProcess[@"C:\Program Files (x86)\Microsoft Visual Studio\Installer\vswhere.exe -prerelease -legacy -property installationVersion"] = 0;

View File

@@ -0,0 +1,4 @@
---
category: minorAnalysis
---
* Only the 2 level indirection of `argv` (corresponding to `**argv`) is consided for `FlowSource`.

View File

@@ -1,5 +1,5 @@
name: codeql/cpp-all name: codeql/cpp-all
version: 0.9.0 version: 0.9.1-dev
groups: cpp groups: cpp
dbscheme: semmlecode.cpp.dbscheme dbscheme: semmlecode.cpp.dbscheme
extractor: cpp extractor: cpp

View File

@@ -25,6 +25,10 @@ import semmle.code.cpp.dataflow.DataFlow2
* global (inter-procedural) taint-tracking analyses. * global (inter-procedural) taint-tracking analyses.
*/ */
deprecated module TaintTracking { deprecated module TaintTracking {
import semmle.code.cpp.dataflow.internal.tainttracking1.TaintTracking import semmle.code.cpp.dataflow.internal.tainttracking1.TaintTrackingParameter::Public
private import semmle.code.cpp.dataflow.internal.DataFlowImplSpecific
private import semmle.code.cpp.dataflow.internal.TaintTrackingImplSpecific
private import codeql.dataflow.TaintTracking
import TaintFlowMake<CppOldDataFlow, CppOldTaintTracking>
import semmle.code.cpp.dataflow.internal.tainttracking1.TaintTrackingImpl import semmle.code.cpp.dataflow.internal.tainttracking1.TaintTrackingImpl
} }

View File

@@ -0,0 +1,10 @@
/**
* Provides C++-specific definitions for use in the taint tracking library.
*/
private import codeql.dataflow.TaintTracking
private import DataFlowImplSpecific
module CppOldTaintTracking implements InputSig<CppOldDataFlow> {
import TaintTrackingUtil
}

View File

@@ -39,7 +39,7 @@ predicate defaultAdditionalTaintStep(DataFlow::Node src, DataFlow::Node sink) {
* of `c` at sinks and inputs to additional taint steps. * of `c` at sinks and inputs to additional taint steps.
*/ */
bindingset[node] bindingset[node]
predicate defaultImplicitTaintRead(DataFlow::Node node, DataFlow::Content c) { none() } predicate defaultImplicitTaintRead(DataFlow::Node node, DataFlow::ContentSet c) { none() }
/** /**
* Holds if `node` should be a sanitizer in all global taint flow configurations * Holds if `node` should be a sanitizer in all global taint flow configurations

View File

@@ -1,75 +0,0 @@
/**
* Provides classes for performing local (intra-procedural) and
* global (inter-procedural) taint-tracking analyses.
*/
import TaintTrackingParameter::Public
private import TaintTrackingParameter::Private
private module AddTaintDefaults<DataFlowInternal::FullStateConfigSig Config> implements
DataFlowInternal::FullStateConfigSig
{
import Config
predicate isBarrier(DataFlow::Node node) {
Config::isBarrier(node) or defaultTaintSanitizer(node)
}
predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) {
Config::isAdditionalFlowStep(node1, node2) or
defaultAdditionalTaintStep(node1, node2)
}
predicate allowImplicitRead(DataFlow::Node node, DataFlow::ContentSet c) {
Config::allowImplicitRead(node, c)
or
(
Config::isSink(node) or
Config::isSink(node, _) or
Config::isAdditionalFlowStep(node, _) or
Config::isAdditionalFlowStep(node, _, _, _)
) and
defaultImplicitTaintRead(node, c)
}
}
/**
* Constructs a global taint tracking computation.
*/
module Global<DataFlow::ConfigSig Config> implements DataFlow::GlobalFlowSig {
private module Config0 implements DataFlowInternal::FullStateConfigSig {
import DataFlowInternal::DefaultState<Config>
import Config
}
private module C implements DataFlowInternal::FullStateConfigSig {
import AddTaintDefaults<Config0>
}
import DataFlowInternal::Impl<C>
}
/** DEPRECATED: Use `Global` instead. */
deprecated module Make<DataFlow::ConfigSig Config> implements DataFlow::GlobalFlowSig {
import Global<Config>
}
/**
* Constructs a global taint tracking computation using flow state.
*/
module GlobalWithState<DataFlow::StateConfigSig Config> implements DataFlow::GlobalFlowSig {
private module Config0 implements DataFlowInternal::FullStateConfigSig {
import Config
}
private module C implements DataFlowInternal::FullStateConfigSig {
import AddTaintDefaults<Config0>
}
import DataFlowInternal::Impl<C>
}
/** DEPRECATED: Use `GlobalWithState` instead. */
deprecated module MakeWithState<DataFlow::StateConfigSig Config> implements DataFlow::GlobalFlowSig {
import GlobalWithState<Config>
}

View File

@@ -23,6 +23,10 @@ import semmle.code.cpp.dataflow.new.DataFlow2
* global (inter-procedural) taint-tracking analyses. * global (inter-procedural) taint-tracking analyses.
*/ */
module TaintTracking { module TaintTracking {
import semmle.code.cpp.ir.dataflow.internal.tainttracking1.TaintTracking import semmle.code.cpp.ir.dataflow.internal.tainttracking1.TaintTrackingParameter::Public
private import semmle.code.cpp.ir.dataflow.internal.DataFlowImplSpecific
private import semmle.code.cpp.ir.dataflow.internal.TaintTrackingImplSpecific
private import codeql.dataflow.TaintTracking
import TaintFlowMake<CppDataFlow, CppTaintTracking>
import semmle.code.cpp.ir.dataflow.internal.tainttracking1.TaintTrackingImpl import semmle.code.cpp.ir.dataflow.internal.tainttracking1.TaintTrackingImpl
} }

View File

@@ -19,6 +19,10 @@ import semmle.code.cpp.ir.dataflow.DataFlow
import semmle.code.cpp.ir.dataflow.DataFlow2 import semmle.code.cpp.ir.dataflow.DataFlow2
module TaintTracking { module TaintTracking {
import semmle.code.cpp.ir.dataflow.internal.tainttracking1.TaintTracking import semmle.code.cpp.ir.dataflow.internal.tainttracking1.TaintTrackingParameter::Public
private import semmle.code.cpp.ir.dataflow.internal.DataFlowImplSpecific
private import semmle.code.cpp.ir.dataflow.internal.TaintTrackingImplSpecific
private import codeql.dataflow.TaintTracking
import TaintFlowMake<CppDataFlow, CppTaintTracking>
import semmle.code.cpp.ir.dataflow.internal.tainttracking1.TaintTrackingImpl import semmle.code.cpp.ir.dataflow.internal.tainttracking1.TaintTrackingImpl
} }

View File

@@ -1078,7 +1078,7 @@ private IRVariable getIRVariableForParameterNode(ParameterNode p) {
/** Holds if `v` is the source variable corresponding to the parameter represented by `p`. */ /** Holds if `v` is the source variable corresponding to the parameter represented by `p`. */
pragma[nomagic] pragma[nomagic]
private predicate parameterNodeHasSourceVariable(ParameterNode p, Ssa::SourceIRVariable v) { private predicate parameterNodeHasSourceVariable(ParameterNode p, Ssa::SourceVariable v) {
v.getIRVariable() = getIRVariableForParameterNode(p) and v.getIRVariable() = getIRVariableForParameterNode(p) and
exists(Position pos | p.isParameterOf(_, pos) | exists(Position pos | p.isParameterOf(_, pos) |
pos instanceof DirectPosition and pos instanceof DirectPosition and

View File

@@ -781,26 +781,12 @@ class IndirectArgumentOutNode extends Node, TIndirectArgumentOutNode, PartialDef
override Expr getDefinedExpr() { result = operand.getDef().getUnconvertedResultExpression() } override Expr getDefinedExpr() { result = operand.getDef().getUnconvertedResultExpression() }
} }
pragma[nomagic]
predicate indirectReturnOutNodeOperand0(CallInstruction call, Operand operand, int indirectionIndex) {
Ssa::hasRawIndirectInstruction(call, indirectionIndex) and
operandForFullyConvertedCall(operand, call)
}
pragma[nomagic]
predicate indirectReturnOutNodeInstruction0(
CallInstruction call, Instruction instr, int indirectionIndex
) {
Ssa::hasRawIndirectInstruction(call, indirectionIndex) and
instructionForFullyConvertedCall(instr, call)
}
/** /**
* Holds if `node` is an indirect operand with columns `(operand, indirectionIndex)`, and * Holds if `node` is an indirect operand with columns `(operand, indirectionIndex)`, and
* `operand` represents a use of the fully converted value of `call`. * `operand` represents a use of the fully converted value of `call`.
*/ */
private predicate hasOperand(Node node, CallInstruction call, int indirectionIndex, Operand operand) { private predicate hasOperand(Node node, CallInstruction call, int indirectionIndex, Operand operand) {
indirectReturnOutNodeOperand0(call, operand, indirectionIndex) and operandForFullyConvertedCall(operand, call) and
hasOperandAndIndex(node, operand, indirectionIndex) hasOperandAndIndex(node, operand, indirectionIndex)
} }
@@ -813,7 +799,7 @@ private predicate hasOperand(Node node, CallInstruction call, int indirectionInd
private predicate hasInstruction( private predicate hasInstruction(
Node node, CallInstruction call, int indirectionIndex, Instruction instr Node node, CallInstruction call, int indirectionIndex, Instruction instr
) { ) {
indirectReturnOutNodeInstruction0(call, instr, indirectionIndex) and instructionForFullyConvertedCall(instr, call) and
hasInstructionAndIndex(node, instr, indirectionIndex) hasInstructionAndIndex(node, instr, indirectionIndex)
} }
@@ -1534,6 +1520,25 @@ private module Cached {
) )
} }
/**
* Holds if `operand.getDef() = instr`, but there exists a `StoreInstruction` that
* writes to an address that is equivalent to the value computed by `instr` in
* between `instr` and `operand`, and therefore there should not be flow from `*instr`
* to `*operand`.
*/
pragma[nomagic]
private predicate isStoredToBetween(Instruction instr, Operand operand) {
simpleOperandLocalFlowStep(pragma[only_bind_into](instr), pragma[only_bind_into](operand)) and
exists(StoreInstruction store, IRBlock block, int storeIndex, int instrIndex, int operandIndex |
store.getDestinationAddress() = instr and
block.getInstruction(storeIndex) = store and
block.getInstruction(instrIndex) = instr and
block.getInstruction(operandIndex) = operand.getUse() and
instrIndex < storeIndex and
storeIndex < operandIndex
)
}
private predicate indirectionInstructionFlow( private predicate indirectionInstructionFlow(
RawIndirectInstruction nodeFrom, IndirectOperand nodeTo RawIndirectInstruction nodeFrom, IndirectOperand nodeTo
) { ) {
@@ -1543,7 +1548,8 @@ private module Cached {
simpleOperandLocalFlowStep(pragma[only_bind_into](instr), pragma[only_bind_into](operand)) simpleOperandLocalFlowStep(pragma[only_bind_into](instr), pragma[only_bind_into](operand))
| |
hasOperandAndIndex(nodeTo, operand, pragma[only_bind_into](indirectionIndex)) and hasOperandAndIndex(nodeTo, operand, pragma[only_bind_into](indirectionIndex)) and
hasInstructionAndIndex(nodeFrom, instr, pragma[only_bind_into](indirectionIndex)) hasInstructionAndIndex(nodeFrom, instr, pragma[only_bind_into](indirectionIndex)) and
not isStoredToBetween(instr, operand)
) )
} }

View File

@@ -10,32 +10,35 @@ private import ssa0.SsaInternals as SsaInternals0
import SsaInternalsCommon import SsaInternalsCommon
private module SourceVariables { private module SourceVariables {
int getMaxIndirectionForIRVariable(IRVariable var) {
exists(Type type, boolean isGLValue |
var.getLanguageType().hasType(type, isGLValue) and
if isGLValue = true
then result = 1 + getMaxIndirectionsForType(type)
else result = getMaxIndirectionsForType(type)
)
}
cached cached
private newtype TSourceVariable = private newtype TSourceVariable =
TSourceIRVariable(BaseIRVariable baseVar, int ind) { TMkSourceVariable(SsaInternals0::SourceVariable base, int ind) {
ind = [0 .. getMaxIndirectionForIRVariable(baseVar.getIRVariable())] ind = [0 .. countIndirectionsForCppType(base.getLanguageType()) + 1]
} or
TCallVariable(AllocationInstruction call, int ind) {
ind = [0 .. countIndirectionsForCppType(getResultLanguageType(call))]
} }
abstract class SourceVariable extends TSourceVariable { class SourceVariable extends TSourceVariable {
SsaInternals0::SourceVariable base;
int ind; int ind;
bindingset[ind] SourceVariable() { this = TMkSourceVariable(base, ind) }
SourceVariable() { any() }
/** Gets the IR variable associated with this `SourceVariable`, if any. */
IRVariable getIRVariable() { result = base.(BaseIRVariable).getIRVariable() }
/**
* Gets the base source variable (i.e., the variable without any
* indirections) of this source variable.
*/
SsaInternals0::SourceVariable getBaseVariable() { result = base }
/** Gets a textual representation of this element. */ /** Gets a textual representation of this element. */
abstract string toString(); string toString() {
ind = 0 and
result = this.getBaseVariable().toString()
or
ind > 0 and
result = this.getBaseVariable().toString() + " indirection"
}
/** /**
* Gets the number of loads performed on the base source variable * Gets the number of loads performed on the base source variable
@@ -43,65 +46,19 @@ private module SourceVariables {
*/ */
int getIndirection() { result = ind } int getIndirection() { result = ind }
/**
* Gets the base source variable (i.e., the variable without any
* indirections) of this source variable.
*/
abstract BaseSourceVariable getBaseVariable();
/** Holds if this variable is a glvalue. */ /** Holds if this variable is a glvalue. */
predicate isGLValue() { none() } predicate isGLValue() { ind = 0 }
/** /**
* Gets the type of this source variable. If `isGLValue()` holds, then * Gets the type of this source variable. If `isGLValue()` holds, then
* the type of this source variable should be thought of as "pointer * the type of this source variable should be thought of as "pointer
* to `getType()`". * to `getType()`".
*/ */
abstract DataFlowType getType(); DataFlowType getType() {
if this.isGLValue()
then result = base.getType()
else result = getTypeImpl(base.getType(), ind - 1)
} }
class SourceIRVariable extends SourceVariable, TSourceIRVariable {
BaseIRVariable var;
SourceIRVariable() { this = TSourceIRVariable(var, ind) }
IRVariable getIRVariable() { result = var.getIRVariable() }
override BaseIRVariable getBaseVariable() { result.getIRVariable() = this.getIRVariable() }
override string toString() {
ind = 0 and
result = this.getIRVariable().toString()
or
ind > 0 and
result = this.getIRVariable().toString() + " indirection"
}
override predicate isGLValue() { ind = 0 }
override DataFlowType getType() {
if ind = 0 then result = var.getType() else result = getTypeImpl(var.getType(), ind - 1)
}
}
class CallVariable extends SourceVariable, TCallVariable {
AllocationInstruction call;
CallVariable() { this = TCallVariable(call, ind) }
AllocationInstruction getCall() { result = call }
override BaseCallVariable getBaseVariable() { result.getCallInstruction() = call }
override string toString() {
ind = 0 and
result = "Call"
or
ind > 0 and
result = "Call indirection"
}
override DataFlowType getType() { result = getTypeImpl(call.getResultType(), ind) }
} }
} }
@@ -137,8 +94,9 @@ predicate hasRawIndirectInstruction(Instruction instr, int indirectionIndex) {
cached cached
private newtype TDefOrUseImpl = private newtype TDefOrUseImpl =
TDefImpl(Operand address, int indirectionIndex) { TDefImpl(BaseSourceVariableInstruction base, Operand address, int indirectionIndex) {
exists(Instruction base | isDef(_, _, address, base, _, indirectionIndex) | isDef(_, _, address, base, _, indirectionIndex) and
(
// We only include the definition if the SSA pruning stage // We only include the definition if the SSA pruning stage
// concluded that the definition is live after the write. // concluded that the definition is live after the write.
any(SsaInternals0::Def def).getAddressOperand() = address any(SsaInternals0::Def def).getAddressOperand() = address
@@ -148,8 +106,8 @@ private newtype TDefOrUseImpl =
base.(VariableAddressInstruction).getAstVariable() instanceof GlobalLikeVariable base.(VariableAddressInstruction).getAstVariable() instanceof GlobalLikeVariable
) )
} or } or
TUseImpl(Operand operand, int indirectionIndex) { TUseImpl(BaseSourceVariableInstruction base, Operand operand, int indirectionIndex) {
isUse(_, operand, _, _, indirectionIndex) and isUse(_, operand, base, _, indirectionIndex) and
not isDef(_, _, operand, _, _, _) not isDef(_, _, operand, _, _, _)
} or } or
TGlobalUse(GlobalLikeVariable v, IRFunction f, int indirectionIndex) { TGlobalUse(GlobalLikeVariable v, IRFunction f, int indirectionIndex) {
@@ -236,7 +194,7 @@ abstract private class DefOrUseImpl extends TDefOrUseImpl {
/** /**
* Gets the instruction that computes the base of this definition or use. * Gets the instruction that computes the base of this definition or use.
* This is always a `VariableAddressInstruction` or an `AllocationInstruction`. * This is always a `VariableAddressInstruction` or an `CallInstruction`.
*/ */
abstract BaseSourceVariableInstruction getBase(); abstract BaseSourceVariableInstruction getBase();
@@ -308,15 +266,17 @@ abstract class DefImpl extends DefOrUseImpl {
} }
private class DirectDef extends DefImpl, TDefImpl { private class DirectDef extends DefImpl, TDefImpl {
DirectDef() { this = TDefImpl(address, ind) } BaseSourceVariableInstruction base;
override BaseSourceVariableInstruction getBase() { isDef(_, _, address, result, _, _) } DirectDef() { this = TDefImpl(base, address, ind) }
override int getIndirection() { isDef(_, _, address, _, result, ind) } override BaseSourceVariableInstruction getBase() { result = base }
override Node0Impl getValue() { isDef(_, result, address, _, _, _) } override int getIndirection() { isDef(_, _, address, base, result, ind) }
override predicate isCertain() { isDef(true, _, address, _, _, ind) } override Node0Impl getValue() { isDef(_, result, address, base, _, _) }
override predicate isCertain() { isDef(true, _, address, base, _, ind) }
} }
private class IteratorDef extends DefImpl, TIteratorDef { private class IteratorDef extends DefImpl, TIteratorDef {
@@ -359,6 +319,7 @@ abstract class UseImpl extends DefOrUseImpl {
abstract private class OperandBasedUse extends UseImpl { abstract private class OperandBasedUse extends UseImpl {
Operand operand; Operand operand;
BaseSourceVariableInstruction base;
bindingset[ind] bindingset[ind]
OperandBasedUse() { any() } OperandBasedUse() { any() }
@@ -366,7 +327,6 @@ abstract private class OperandBasedUse extends UseImpl {
final override predicate hasIndexInBlock(IRBlock block, int index) { final override predicate hasIndexInBlock(IRBlock block, int index) {
// See the comment in `ssa0`'s `OperandBasedUse` for an explanation of this // See the comment in `ssa0`'s `OperandBasedUse` for an explanation of this
// predicate's implementation. // predicate's implementation.
exists(BaseSourceVariableInstruction base | base = this.getBase() |
if base.getAst() = any(Cpp::PostfixCrementOperation c).getOperand() if base.getAst() = any(Cpp::PostfixCrementOperation c).getOperand()
then then
exists(Operand op, int indirectionIndex, int indirection | exists(Operand op, int indirectionIndex, int indirection |
@@ -382,34 +342,29 @@ abstract private class OperandBasedUse extends UseImpl {
block.getInstruction(index) = op.getUse() block.getInstruction(index) = op.getUse()
) )
else operand.getUse() = block.getInstruction(index) else operand.getUse() = block.getInstruction(index)
)
} }
final override BaseSourceVariableInstruction getBase() { result = base }
final Operand getOperand() { result = operand } final Operand getOperand() { result = operand }
final override Cpp::Location getLocation() { result = operand.getLocation() } final override Cpp::Location getLocation() { result = operand.getLocation() }
} }
private class DirectUse extends OperandBasedUse, TUseImpl { private class DirectUse extends OperandBasedUse, TUseImpl {
DirectUse() { this = TUseImpl(operand, ind) } DirectUse() { this = TUseImpl(base, operand, ind) }
override int getIndirection() { isUse(_, operand, _, result, ind) } override int getIndirection() { isUse(_, operand, base, result, ind) }
override BaseSourceVariableInstruction getBase() { isUse(_, operand, result, _, ind) } override predicate isCertain() { isUse(true, operand, base, _, ind) }
override predicate isCertain() { isUse(true, operand, _, _, ind) }
override Node getNode() { nodeHasOperand(result, operand, ind) } override Node getNode() { nodeHasOperand(result, operand, ind) }
} }
private class IteratorUse extends OperandBasedUse, TIteratorUse { private class IteratorUse extends OperandBasedUse, TIteratorUse {
BaseSourceVariableInstruction container; IteratorUse() { this = TIteratorUse(operand, base, ind) }
IteratorUse() { this = TIteratorUse(operand, container, ind) } override int getIndirection() { isIteratorUse(base, operand, result, ind) }
override int getIndirection() { isIteratorUse(container, operand, result, ind) }
override BaseSourceVariableInstruction getBase() { result = container }
override predicate isCertain() { none() } override predicate isCertain() { none() }

View File

@@ -6,6 +6,7 @@ private import DataFlowImplCommon as DataFlowImplCommon
private import DataFlowUtil private import DataFlowUtil
private import semmle.code.cpp.models.interfaces.PointerWrapper private import semmle.code.cpp.models.interfaces.PointerWrapper
private import DataFlowPrivate private import DataFlowPrivate
private import semmle.code.cpp.ir.ValueNumbering
/** /**
* Holds if `operand` is an operand that is not used by the dataflow library. * Holds if `operand` is an operand that is not used by the dataflow library.
@@ -146,14 +147,6 @@ int countIndirectionsForCppType(LanguageType langType) {
) )
} }
/**
* A `CallInstruction` that calls an allocation function such
* as `malloc` or `operator new`.
*/
class AllocationInstruction extends CallInstruction {
AllocationInstruction() { this.getStaticCallTarget() instanceof Cpp::AllocationFunction }
}
private predicate isIndirectionType(Type t) { t instanceof Indirection } private predicate isIndirectionType(Type t) { t instanceof Indirection }
private predicate hasUnspecifiedBaseType(Indirection t, Type base) { private predicate hasUnspecifiedBaseType(Indirection t, Type base) {
@@ -368,17 +361,22 @@ newtype TBaseSourceVariable =
// Each IR variable gets its own source variable // Each IR variable gets its own source variable
TBaseIRVariable(IRVariable var) or TBaseIRVariable(IRVariable var) or
// Each allocation gets its own source variable // Each allocation gets its own source variable
TBaseCallVariable(AllocationInstruction call) TBaseCallVariable(CallInstruction call) { not call.getResultIRType() instanceof IRVoidType }
abstract class BaseSourceVariable extends TBaseSourceVariable { abstract private class AbstractBaseSourceVariable extends TBaseSourceVariable {
/** Gets a textual representation of this element. */ /** Gets a textual representation of this element. */
abstract string toString(); abstract string toString();
/** Gets the type of this base source variable. */ /** Gets the type of this base source variable. */
abstract DataFlowType getType(); final DataFlowType getType() { this.getLanguageType().hasUnspecifiedType(result, _) }
/** Gets the `CppType` of this base source variable. */
abstract CppType getLanguageType();
} }
class BaseIRVariable extends BaseSourceVariable, TBaseIRVariable { final class BaseSourceVariable = AbstractBaseSourceVariable;
class BaseIRVariable extends AbstractBaseSourceVariable, TBaseIRVariable {
IRVariable var; IRVariable var;
IRVariable getIRVariable() { result = var } IRVariable getIRVariable() { result = var }
@@ -387,19 +385,19 @@ class BaseIRVariable extends BaseSourceVariable, TBaseIRVariable {
override string toString() { result = var.toString() } override string toString() { result = var.toString() }
override DataFlowType getType() { result = var.getType() } override CppType getLanguageType() { result = var.getLanguageType() }
} }
class BaseCallVariable extends BaseSourceVariable, TBaseCallVariable { class BaseCallVariable extends AbstractBaseSourceVariable, TBaseCallVariable {
AllocationInstruction call; CallInstruction call;
BaseCallVariable() { this = TBaseCallVariable(call) } BaseCallVariable() { this = TBaseCallVariable(call) }
AllocationInstruction getCallInstruction() { result = call } CallInstruction getCallInstruction() { result = call }
override string toString() { result = call.toString() } override string toString() { result = call.toString() }
override DataFlowType getType() { result = call.getResultType() } override CppType getLanguageType() { result = getResultLanguageType(call) }
} }
/** /**
@@ -499,8 +497,7 @@ private class BaseIRVariableInstruction extends BaseSourceVariableInstruction,
override BaseIRVariable getBaseSourceVariable() { result.getIRVariable() = this.getIRVariable() } override BaseIRVariable getBaseSourceVariable() { result.getIRVariable() = this.getIRVariable() }
} }
private class BaseAllocationInstruction extends BaseSourceVariableInstruction, AllocationInstruction private class BaseCallInstruction extends BaseSourceVariableInstruction, CallInstruction {
{
override BaseCallVariable getBaseSourceVariable() { result.getCallInstruction() = this } override BaseCallVariable getBaseSourceVariable() { result.getCallInstruction() = this }
} }
@@ -868,7 +865,7 @@ private module Cached {
* to a specific address. * to a specific address.
*/ */
private predicate isCertainAddress(Operand operand) { private predicate isCertainAddress(Operand operand) {
operand.getDef() instanceof VariableAddressInstruction valueNumberOfOperand(operand).getAnInstruction() instanceof VariableAddressInstruction
or or
operand.getType() instanceof Cpp::ReferenceType operand.getType() instanceof Cpp::ReferenceType
} }

View File

@@ -0,0 +1,10 @@
/**
* Provides C++-specific definitions for use in the taint tracking library.
*/
private import codeql.dataflow.TaintTracking
private import DataFlowImplSpecific
module CppTaintTracking implements InputSig<CppDataFlow> {
import TaintTrackingUtil
}

View File

@@ -112,7 +112,7 @@ predicate defaultAdditionalTaintStep(DataFlow::Node src, DataFlow::Node sink) {
* of `c` at sinks and inputs to additional taint steps. * of `c` at sinks and inputs to additional taint steps.
*/ */
bindingset[node] bindingset[node]
predicate defaultImplicitTaintRead(DataFlow::Node node, DataFlow::Content c) { none() } predicate defaultImplicitTaintRead(DataFlow::Node node, DataFlow::ContentSet c) { none() }
/** /**
* Holds if `node` should be a sanitizer in all global taint flow configurations * Holds if `node` should be a sanitizer in all global taint flow configurations

View File

@@ -15,15 +15,12 @@ private import semmle.code.cpp.ir.dataflow.internal.DataFlowUtil
private import semmle.code.cpp.ir.dataflow.internal.SsaInternalsCommon private import semmle.code.cpp.ir.dataflow.internal.SsaInternalsCommon
private module SourceVariables { private module SourceVariables {
class SourceVariable instanceof BaseSourceVariable { class SourceVariable extends BaseSourceVariable {
string toString() { result = BaseSourceVariable.super.toString() } /**
* Gets the base source variable of this `SourceVariable`.
*/
BaseSourceVariable getBaseVariable() { result = this } BaseSourceVariable getBaseVariable() { result = this }
} }
class SourceIRVariable = BaseIRVariable;
class CallVariable = BaseCallVariable;
} }
import SourceVariables import SourceVariables

View File

@@ -1,75 +0,0 @@
/**
* Provides classes for performing local (intra-procedural) and
* global (inter-procedural) taint-tracking analyses.
*/
import TaintTrackingParameter::Public
private import TaintTrackingParameter::Private
private module AddTaintDefaults<DataFlowInternal::FullStateConfigSig Config> implements
DataFlowInternal::FullStateConfigSig
{
import Config
predicate isBarrier(DataFlow::Node node) {
Config::isBarrier(node) or defaultTaintSanitizer(node)
}
predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) {
Config::isAdditionalFlowStep(node1, node2) or
defaultAdditionalTaintStep(node1, node2)
}
predicate allowImplicitRead(DataFlow::Node node, DataFlow::ContentSet c) {
Config::allowImplicitRead(node, c)
or
(
Config::isSink(node) or
Config::isSink(node, _) or
Config::isAdditionalFlowStep(node, _) or
Config::isAdditionalFlowStep(node, _, _, _)
) and
defaultImplicitTaintRead(node, c)
}
}
/**
* Constructs a global taint tracking computation.
*/
module Global<DataFlow::ConfigSig Config> implements DataFlow::GlobalFlowSig {
private module Config0 implements DataFlowInternal::FullStateConfigSig {
import DataFlowInternal::DefaultState<Config>
import Config
}
private module C implements DataFlowInternal::FullStateConfigSig {
import AddTaintDefaults<Config0>
}
import DataFlowInternal::Impl<C>
}
/** DEPRECATED: Use `Global` instead. */
deprecated module Make<DataFlow::ConfigSig Config> implements DataFlow::GlobalFlowSig {
import Global<Config>
}
/**
* Constructs a global taint tracking computation using flow state.
*/
module GlobalWithState<DataFlow::StateConfigSig Config> implements DataFlow::GlobalFlowSig {
private module Config0 implements DataFlowInternal::FullStateConfigSig {
import Config
}
private module C implements DataFlowInternal::FullStateConfigSig {
import AddTaintDefaults<Config0>
}
import DataFlowInternal::Impl<C>
}
/** DEPRECATED: Use `GlobalWithState` instead. */
deprecated module MakeWithState<DataFlow::StateConfigSig Config> implements DataFlow::GlobalFlowSig {
import GlobalWithState<Config>
}

View File

@@ -574,16 +574,6 @@ module RangeStage<
) )
} }
/** Holds if `e >= 1` as determined by sign analysis. */
private predicate strictlyPositiveIntegralExpr(SemExpr e) {
semStrictlyPositive(e) and getTrackedType(e) instanceof SemIntegerType
}
/** Holds if `e <= -1` as determined by sign analysis. */
private predicate strictlyNegativeIntegralExpr(SemExpr e) {
semStrictlyNegative(e) and getTrackedType(e) instanceof SemIntegerType
}
/** /**
* Holds if `e1 + delta` is a valid bound for `e2`. * Holds if `e1 + delta` is a valid bound for `e2`.
* - `upper = true` : `e2 <= e1 + delta` * - `upper = true` : `e2 <= e1 + delta`
@@ -597,27 +587,6 @@ module RangeStage<
delta = D::fromInt(0) and delta = D::fromInt(0) and
(upper = true or upper = false) (upper = true or upper = false)
or or
exists(SemExpr x, SemSubExpr sub |
e2 = sub and
sub.getLeftOperand() = e1 and
sub.getRightOperand() = x
|
// `x instanceof ConstantIntegerExpr` is covered by valueFlowStep
not x instanceof SemConstantIntegerExpr and
if strictlyPositiveIntegralExpr(x)
then upper = true and delta = D::fromInt(-1)
else
if semPositive(x)
then upper = true and delta = D::fromInt(0)
else
if strictlyNegativeIntegralExpr(x)
then upper = false and delta = D::fromInt(1)
else
if semNegative(x)
then upper = false and delta = D::fromInt(0)
else none()
)
or
e2.(SemRemExpr).getRightOperand() = e1 and e2.(SemRemExpr).getRightOperand() = e1 and
semPositive(e1) and semPositive(e1) and
delta = D::fromInt(-1) and delta = D::fromInt(-1) and
@@ -1137,6 +1106,23 @@ module RangeStage<
b = bRight and origdelta = odRight and reason = rRight and bLeft instanceof SemZeroBound b = bRight and origdelta = odRight and reason = rRight and bLeft instanceof SemZeroBound
) )
or or
exists(D::Delta dLeft, D::Delta dRight, boolean fbeLeft, boolean fbeRight |
boundedSubOperandLeft(e, upper, b, dLeft, fbeLeft, origdelta, reason) and
boundedSubOperandRight(e, upper, dRight, fbeRight) and
// when `upper` is `true` we have:
// left <= b + dLeft
// right >= 0 + dRight
// left - right <= b + dLeft - (0 + dRight)
// = b + (dLeft - dRight)
// and when `upper` is `false` we have:
// left >= b + dLeft
// right <= 0 + dRight
// left - right >= b + dLeft - (0 + dRight)
// = b + (dLeft - dRight)
delta = D::fromFloat(D::toFloat(dLeft) - D::toFloat(dRight)) and
fromBackEdge = fbeLeft.booleanOr(fbeRight)
)
or
exists( exists(
SemRemExpr rem, D::Delta d_max, D::Delta d1, D::Delta d2, boolean fbe1, boolean fbe2, SemRemExpr rem, D::Delta d_max, D::Delta d1, D::Delta d2, boolean fbe1, boolean fbe2,
D::Delta od1, D::Delta od2, SemReason r1, SemReason r2 D::Delta od1, D::Delta od2, SemReason r1, SemReason r2
@@ -1201,6 +1187,37 @@ module RangeStage<
) )
} }
/**
* Holds if `sub = left - right` and `left <= b + delta` if `upper` is `true`
* and `left >= b + delta` is `upper` is `false`.
*/
pragma[nomagic]
private predicate boundedSubOperandLeft(
SemSubExpr sub, boolean upper, SemBound b, D::Delta delta, boolean fromBackEdge,
D::Delta origdelta, SemReason reason
) {
// `semValueFlowStep` already handles the case where one of the operands is a constant.
not semValueFlowStep(sub, _, _) and
bounded(sub.getLeftOperand(), b, delta, upper, fromBackEdge, origdelta, reason)
}
/**
* Holds if `sub = left - right` and `right <= 0 + delta` if `upper` is `false`
* and `right >= 0 + delta` is `upper` is `true`.
*
* Note that the boolean value of `upper` is flipped compared to many other predicates in
* this file. This ensures a clean join at the call-site.
*/
pragma[nomagic]
private predicate boundedSubOperandRight(
SemSubExpr sub, boolean upper, D::Delta delta, boolean fromBackEdge
) {
// `semValueFlowStep` already handles the case where one of the operands is a constant.
not semValueFlowStep(sub, _, _) and
bounded(sub.getRightOperand(), any(SemZeroBound zb), delta, upper.booleanNot(), fromBackEdge, _,
_)
}
pragma[nomagic] pragma[nomagic]
private predicate boundedRemExpr( private predicate boundedRemExpr(
SemRemExpr rem, boolean upper, D::Delta delta, boolean fromBackEdge, D::Delta origdelta, SemRemExpr rem, boolean upper, D::Delta delta, boolean fromBackEdge, D::Delta origdelta,

View File

@@ -53,7 +53,7 @@ private class ArgvSource extends LocalFlowSource {
exists(Function main, Parameter argv | exists(Function main, Parameter argv |
main.hasGlobalName("main") and main.hasGlobalName("main") and
main.getParameter(1) = argv and main.getParameter(1) = argv and
this.asParameter(_) = argv this.asParameter(2) = argv
) )
} }

View File

@@ -96,7 +96,7 @@ predicate hasSize(HeuristicAllocationExpr alloc, DataFlow::Node n, int state) {
* but because there's a strict comparison that compares `n` against the size of the allocation this * but because there's a strict comparison that compares `n` against the size of the allocation this
* snippet is fine. * snippet is fine.
*/ */
module SizeBarrier { private module SizeBarrier {
private module SizeBarrierConfig implements DataFlow::ConfigSig { private module SizeBarrierConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) { predicate isSource(DataFlow::Node source) {
// The sources is the same as in the sources for the second // The sources is the same as in the sources for the second
@@ -104,35 +104,60 @@ module SizeBarrier {
hasSize(_, source, _) hasSize(_, source, _)
} }
/**
* Holds if `small <= large + k` holds if `g` evaluates to `testIsTrue`.
*/
additional predicate isSink( additional predicate isSink(
DataFlow::Node left, DataFlow::Node right, IRGuardCondition g, int k, boolean testIsTrue DataFlow::Node small, DataFlow::Node large, IRGuardCondition g, int k, boolean testIsTrue
) { ) {
// The sink is any "large" side of a relational comparison. i.e., the `right` expression // The sink is any "large" side of a relational comparison. i.e., the `large` expression
// in a guard such as `left < right + k`. // in a guard such as `small <= large + k`.
g.comparesLt(left.asOperand(), right.asOperand(), k, true, testIsTrue) g.comparesLt(small.asOperand(), large.asOperand(), k + 1, true, testIsTrue)
} }
predicate isSink(DataFlow::Node sink) { isSink(_, sink, _, _, _) } predicate isSink(DataFlow::Node sink) { isSink(_, sink, _, _, _) }
} }
private import DataFlow::Global<SizeBarrierConfig> module SizeBarrierFlow = DataFlow::Global<SizeBarrierConfig>;
private int getAFlowStateForNode(DataFlow::Node node) { private int getASizeAddend(DataFlow::Node node) {
exists(DataFlow::Node source | exists(DataFlow::Node source |
flow(source, node) and SizeBarrierFlow::flow(source, node) and
hasSize(_, source, result) hasSize(_, source, result)
) )
} }
/**
* Holds if `small <= large + k` holds if `g` evaluates to `edge`.
*/
private predicate operandGuardChecks( private predicate operandGuardChecks(
IRGuardCondition g, Operand left, Operand right, int state, boolean edge IRGuardCondition g, Operand small, DataFlow::Node large, int k, boolean edge
) { ) {
exists(DataFlow::Node nLeft, DataFlow::Node nRight, int k | SizeBarrierFlow::flowTo(large) and
nRight.asOperand() = right and SizeBarrierConfig::isSink(DataFlow::operandNode(small), large, g, k, edge)
nLeft.asOperand() = left and }
SizeBarrierConfig::isSink(nLeft, nRight, g, k, edge) and
state = getAFlowStateForNode(nRight) and /**
k <= state * Gets an instruction `instr` that is guarded by a check such as `instr <= small + delta` where
* `small <= _ + k` and `small` is the "small side" of of a relational comparison that checks
* whether `small <= size` where `size` is the size of an allocation.
*/
Instruction getABarrierInstruction0(int delta, int k) {
exists(
IRGuardCondition g, ValueNumber value, Operand small, boolean edge, DataFlow::Node large
|
// We know:
// 1. result <= value + delta (by `bounded`)
// 2. value <= large + k (by `operandGuardChecks`).
// So:
// result <= value + delta (by 1.)
// <= large + k + delta (by 2.)
small = value.getAUse() and
operandGuardChecks(pragma[only_bind_into](g), pragma[only_bind_into](small), large,
pragma[only_bind_into](k), pragma[only_bind_into](edge)) and
bounded(result, value.getAnInstruction(), delta) and
g.controls(result.getBlock(), edge) and
k < getASizeAddend(large)
) )
} }
@@ -140,13 +165,14 @@ module SizeBarrier {
* Gets an instruction that is guarded by a guard condition which ensures that * Gets an instruction that is guarded by a guard condition which ensures that
* the value of the instruction is upper-bounded by size of some allocation. * the value of the instruction is upper-bounded by size of some allocation.
*/ */
bindingset[state]
pragma[inline_late]
Instruction getABarrierInstruction(int state) { Instruction getABarrierInstruction(int state) {
exists(IRGuardCondition g, ValueNumber value, Operand use, boolean edge | exists(int delta, int k |
use = value.getAUse() and state > k + delta and
operandGuardChecks(pragma[only_bind_into](g), pragma[only_bind_into](use), _, // result <= "size of allocation" + delta + k
pragma[only_bind_into](state), pragma[only_bind_into](edge)) and // < "size of allocation" + state
result = value.getAnInstruction() and result = getABarrierInstruction0(delta, k)
g.controls(result.getBlock(), edge)
) )
} }
@@ -155,14 +181,16 @@ module SizeBarrier {
* the value of the node is upper-bounded by size of some allocation. * the value of the node is upper-bounded by size of some allocation.
*/ */
DataFlow::Node getABarrierNode(int state) { DataFlow::Node getABarrierNode(int state) {
result.asOperand() = getABarrierInstruction(state).getAUse() exists(DataFlow::Node source, int delta, int k |
SizeBarrierFlow::flow(source, result) and
hasSize(_, source, state) and
result.asInstruction() = SizeBarrier::getABarrierInstruction0(delta, k) and
state > k + delta
// so now we have:
// result <= "size of allocation" + delta + k
// < "size of allocation" + state
)
} }
/**
* Gets the block of a node that is guarded (see `getABarrierInstruction` or
* `getABarrierNode` for the definition of what it means to be guarded).
*/
IRBlock getABarrierBlock(int state) { result.getAnInstruction() = getABarrierInstruction(state) }
} }
private module InterestingPointerAddInstruction { private module InterestingPointerAddInstruction {

View File

@@ -66,11 +66,14 @@
* module. Since the node we are tracking is not necessarily _equal_ to the pointer-arithmetic instruction, but rather satisfies * module. Since the node we are tracking is not necessarily _equal_ to the pointer-arithmetic instruction, but rather satisfies
* `node.asInstruction() <= pai + deltaDerefSourceAndPai`, we need to account for the delta when checking if a guard is sufficiently * `node.asInstruction() <= pai + deltaDerefSourceAndPai`, we need to account for the delta when checking if a guard is sufficiently
* strong to infer that a future dereference is safe. To do this, we check that the guard guarantees that a node `n` satisfies * strong to infer that a future dereference is safe. To do this, we check that the guard guarantees that a node `n` satisfies
* `n < node + k` where `node` is a node we know is equal to the value of the dereference source (i.e., it satisfies * `n < node + k` where `node` is a node such that `node <= pai`. Thus, we know that any node `m` such that `m <= n + delta` where
* `node.asInstruction() <= pai + deltaDerefSourceAndPai`) and `k <= deltaDerefSourceAndPai`. Combining this we have * `delta + k <= 0` will be safe because:
* `n < node + k <= node + deltaDerefSourceAndPai <= pai + 2*deltaDerefSourceAndPai` (TODO: Oops. This math doesn't quite work out. * ```
* I think this is because we need to redefine the `BarrierConfig` to start flow at the pointer-arithmetic instruction instead of * m <= n + delta
* at the dereference source. When combined with TODO above it's easy to show that this guard ensures that the dereference is safe). * < node + k + delta
* <= pai + k + delta
* <= pai
* ```
*/ */
private import cpp private import cpp
@@ -82,16 +85,19 @@ private import RangeAnalysisUtil
private module InvalidPointerToDerefBarrier { private module InvalidPointerToDerefBarrier {
private module BarrierConfig implements DataFlow::ConfigSig { private module BarrierConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) { additional predicate isSource(DataFlow::Node source, PointerArithmeticInstruction pai) {
// The sources is the same as in the sources for `InvalidPointerToDerefConfig`. invalidPointerToDerefSource(_, pai, _, _) and
invalidPointerToDerefSource(_, _, source, _) // source <= pai
bounded2(source.asInstruction(), pai, any(int d | d <= 0))
} }
predicate isSource(DataFlow::Node source) { isSource(source, _) }
additional predicate isSink( additional predicate isSink(
DataFlow::Node left, DataFlow::Node right, IRGuardCondition g, int k, boolean testIsTrue DataFlow::Node small, DataFlow::Node large, IRGuardCondition g, int k, boolean testIsTrue
) { ) {
// The sink is any "large" side of a relational comparison. // The sink is any "large" side of a relational comparison.
g.comparesLt(left.asOperand(), right.asOperand(), k, true, testIsTrue) g.comparesLt(small.asOperand(), large.asOperand(), k, true, testIsTrue)
} }
predicate isSink(DataFlow::Node sink) { isSink(_, sink, _, _, _) } predicate isSink(DataFlow::Node sink) { isSink(_, sink, _, _, _) }
@@ -99,59 +105,82 @@ private module InvalidPointerToDerefBarrier {
private module BarrierFlow = DataFlow::Global<BarrierConfig>; private module BarrierFlow = DataFlow::Global<BarrierConfig>;
private int getInvalidPointerToDerefSourceDelta(DataFlow::Node node) { /**
exists(DataFlow::Node source | * Holds if `g` ensures that `small < large + k` if `g` evaluates to `edge`.
BarrierFlow::flow(source, node) and *
invalidPointerToDerefSource(_, _, source, result) * Additionally, it also holds that `large <= pai`. Thus, when `g` evaluates to `edge`
) * it holds that `small < pai + k`.
} */
private predicate operandGuardChecks( private predicate operandGuardChecks(
IRGuardCondition g, Operand left, Operand right, int state, boolean edge PointerArithmeticInstruction pai, IRGuardCondition g, Operand small, int k, boolean edge
) { ) {
exists(DataFlow::Node nLeft, DataFlow::Node nRight, int k | exists(DataFlow::Node source, DataFlow::Node nSmall, DataFlow::Node nLarge |
nRight.asOperand() = right and nSmall.asOperand() = small and
nLeft.asOperand() = left and BarrierConfig::isSource(source, pai) and
BarrierConfig::isSink(nLeft, nRight, g, k, edge) and BarrierFlow::flow(source, nLarge) and
state = getInvalidPointerToDerefSourceDelta(nRight) and BarrierConfig::isSink(nSmall, nLarge, g, k, edge)
k <= state
) )
} }
Instruction getABarrierInstruction(int state) { /**
exists(IRGuardCondition g, ValueNumber value, Operand use, boolean edge | * Gets an instruction `instr` such that `instr < pai`.
*/
Instruction getABarrierInstruction(PointerArithmeticInstruction pai) {
exists(IRGuardCondition g, ValueNumber value, Operand use, boolean edge, int delta, int k |
use = value.getAUse() and use = value.getAUse() and
operandGuardChecks(pragma[only_bind_into](g), pragma[only_bind_into](use), _, state, // value < pai + k
pragma[only_bind_into](edge)) and operandGuardChecks(pai, pragma[only_bind_into](g), pragma[only_bind_into](use),
result = value.getAnInstruction() and pragma[only_bind_into](k), pragma[only_bind_into](edge)) and
g.controls(result.getBlock(), edge) // result <= value + delta
bounded(result, value.getAnInstruction(), delta) and
g.controls(result.getBlock(), edge) and
delta + k <= 0
// combining the above we have: result < pai + k + delta <= pai
) )
} }
DataFlow::Node getABarrierNode() { result.asOperand() = getABarrierInstruction(_).getAUse() } DataFlow::Node getABarrierNode(PointerArithmeticInstruction pai) {
result.asOperand() = getABarrierInstruction(pai).getAUse()
}
pragma[nomagic] /**
IRBlock getABarrierBlock(int state) { result.getAnInstruction() = getABarrierInstruction(state) } * Gets an address operand whose definition `instr` satisfies `instr < pai`.
*/
AddressOperand getABarrierAddressOperand(PointerArithmeticInstruction pai) {
result.getDef() = getABarrierInstruction(pai)
}
} }
/** /**
* A configuration to track flow from a pointer-arithmetic operation found * A configuration to track flow from a pointer-arithmetic operation found
* by `AllocToInvalidPointerConfig` to a dereference of the pointer. * by `AllocToInvalidPointerConfig` to a dereference of the pointer.
*/ */
private module InvalidPointerToDerefConfig implements DataFlow::ConfigSig { private module InvalidPointerToDerefConfig implements DataFlow::StateConfigSig {
predicate isSource(DataFlow::Node source) { invalidPointerToDerefSource(_, _, source, _) } class FlowState extends PointerArithmeticInstruction {
FlowState() { invalidPointerToDerefSource(_, this, _, _) }
}
predicate isSource(DataFlow::Node source, FlowState pai) {
invalidPointerToDerefSource(_, pai, source, _)
}
pragma[inline] pragma[inline]
predicate isSink(DataFlow::Node sink) { isInvalidPointerDerefSink(sink, _, _, _) } predicate isSink(DataFlow::Node sink) { isInvalidPointerDerefSink(sink, _, _, _, _) }
predicate isSink(DataFlow::Node sink, FlowState pai) { none() }
predicate isBarrier(DataFlow::Node node) { predicate isBarrier(DataFlow::Node node) {
node = any(DataFlow::SsaPhiNode phi | not phi.isPhiRead()).getAnInput(true) node = any(DataFlow::SsaPhiNode phi | not phi.isPhiRead()).getAnInput(true)
or }
node = InvalidPointerToDerefBarrier::getABarrierNode()
predicate isBarrier(DataFlow::Node node, FlowState pai) {
// `node = getABarrierNode(pai)` ensures that node < pai, so this node is safe to dereference.
// Note that this is the only place where the `FlowState` is used in this configuration.
node = InvalidPointerToDerefBarrier::getABarrierNode(pai)
} }
} }
private import DataFlow::Global<InvalidPointerToDerefConfig> private import DataFlow::GlobalWithState<InvalidPointerToDerefConfig>
/** /**
* Holds if `allocSource` is dataflow node that represents an allocation that flows to the * Holds if `allocSource` is dataflow node that represents an allocation that flows to the
@@ -165,19 +194,14 @@ private predicate invalidPointerToDerefSource(
DataFlow::Node allocSource, PointerArithmeticInstruction pai, DataFlow::Node derefSource, DataFlow::Node allocSource, PointerArithmeticInstruction pai, DataFlow::Node derefSource,
int deltaDerefSourceAndPai int deltaDerefSourceAndPai
) { ) {
exists(int rhsSizeDelta |
// Note that `deltaDerefSourceAndPai` is not necessarily equal to `rhsSizeDelta`: // Note that `deltaDerefSourceAndPai` is not necessarily equal to `rhsSizeDelta`:
// `rhsSizeDelta` is the constant offset added to the size of the allocation, and // `rhsSizeDelta` is the constant offset added to the size of the allocation, and
// `deltaDerefSourceAndPai` is the constant difference between the pointer-arithmetic instruction // `deltaDerefSourceAndPai` is the constant difference between the pointer-arithmetic instruction
// and the instruction computing the address for which we will search for a dereference. // and the instruction computing the address for which we will search for a dereference.
AllocToInvalidPointer::pointerAddInstructionHasBounds(allocSource, pai, _, rhsSizeDelta) and AllocToInvalidPointer::pointerAddInstructionHasBounds(allocSource, pai, _, _) and
// derefSource <= pai + deltaDerefSourceAndPai
bounded2(derefSource.asInstruction(), pai, deltaDerefSourceAndPai) and bounded2(derefSource.asInstruction(), pai, deltaDerefSourceAndPai) and
deltaDerefSourceAndPai >= 0 and deltaDerefSourceAndPai >= 0
// TODO: This condition will go away once #13725 is merged, and then we can make `SizeBarrier`
// private to `AllocationToInvalidPointer.qll`.
not derefSource.getBasicBlock() =
AllocToInvalidPointer::SizeBarrier::getABarrierBlock(rhsSizeDelta)
)
} }
/** /**
@@ -187,15 +211,14 @@ private predicate invalidPointerToDerefSource(
*/ */
pragma[inline] pragma[inline]
private predicate isInvalidPointerDerefSink( private predicate isInvalidPointerDerefSink(
DataFlow::Node sink, Instruction i, string operation, int deltaDerefSinkAndDerefAddress DataFlow::Node sink, AddressOperand addr, Instruction i, string operation,
int deltaDerefSinkAndDerefAddress
) { ) {
exists(AddressOperand addr, Instruction s, IRBlock b | exists(Instruction s |
s = sink.asInstruction() and s = sink.asInstruction() and
bounded(addr.getDef(), s, deltaDerefSinkAndDerefAddress) and bounded(addr.getDef(), s, deltaDerefSinkAndDerefAddress) and
deltaDerefSinkAndDerefAddress >= 0 and deltaDerefSinkAndDerefAddress >= 0 and
i.getAnOperand() = addr and i.getAnOperand() = addr
b = i.getBlock() and
not b = InvalidPointerToDerefBarrier::getABarrierBlock(deltaDerefSinkAndDerefAddress)
| |
i instanceof StoreInstruction and i instanceof StoreInstruction and
operation = "write" operation = "write"
@@ -221,9 +244,11 @@ private Instruction getASuccessor(Instruction instr) {
instr.getBlock().getASuccessor+() = result.getBlock() instr.getBlock().getASuccessor+() = result.getBlock()
} }
private predicate paiForDereferenceSink(PointerArithmeticInstruction pai, DataFlow::Node derefSink) { private predicate paiForDereferenceSink(
PointerArithmeticInstruction pai, DataFlow::Node derefSink, int deltaDerefSourceAndPai
) {
exists(DataFlow::Node derefSource | exists(DataFlow::Node derefSource |
invalidPointerToDerefSource(_, pai, derefSource, _) and invalidPointerToDerefSource(_, pai, derefSource, deltaDerefSourceAndPai) and
flow(derefSource, derefSink) flow(derefSource, derefSink)
) )
} }
@@ -235,13 +260,15 @@ private predicate paiForDereferenceSink(PointerArithmeticInstruction pai, DataFl
*/ */
private predicate derefSinkToOperation( private predicate derefSinkToOperation(
DataFlow::Node derefSink, PointerArithmeticInstruction pai, DataFlow::Node operation, DataFlow::Node derefSink, PointerArithmeticInstruction pai, DataFlow::Node operation,
string description, int deltaDerefSinkAndDerefAddress string description, int deltaDerefSourceAndPai, int deltaDerefSinkAndDerefAddress
) { ) {
exists(Instruction operationInstr | exists(Instruction operationInstr, AddressOperand addr |
paiForDereferenceSink(pai, pragma[only_bind_into](derefSink)) and paiForDereferenceSink(pai, pragma[only_bind_into](derefSink), deltaDerefSourceAndPai) and
isInvalidPointerDerefSink(derefSink, operationInstr, description, deltaDerefSinkAndDerefAddress) and isInvalidPointerDerefSink(derefSink, addr, operationInstr, description,
deltaDerefSinkAndDerefAddress) and
operationInstr = getASuccessor(derefSink.asInstruction()) and operationInstr = getASuccessor(derefSink.asInstruction()) and
operation.asInstruction() = operationInstr operation.asInstruction() = operationInstr and
not addr = InvalidPointerToDerefBarrier::getABarrierAddressOperand(pai)
) )
} }
@@ -260,7 +287,8 @@ predicate operationIsOffBy(
exists(int deltaDerefSourceAndPai, int deltaDerefSinkAndDerefAddress | exists(int deltaDerefSourceAndPai, int deltaDerefSinkAndDerefAddress |
invalidPointerToDerefSource(allocation, pai, derefSource, deltaDerefSourceAndPai) and invalidPointerToDerefSource(allocation, pai, derefSource, deltaDerefSourceAndPai) and
flow(derefSource, derefSink) and flow(derefSource, derefSink) and
derefSinkToOperation(derefSink, pai, operation, description, deltaDerefSinkAndDerefAddress) and derefSinkToOperation(derefSink, pai, operation, description, deltaDerefSourceAndPai,
deltaDerefSinkAndDerefAddress) and
delta = deltaDerefSourceAndPai + deltaDerefSinkAndDerefAddress delta = deltaDerefSourceAndPai + deltaDerefSinkAndDerefAddress
) )
} }

View File

@@ -18,7 +18,7 @@ private Instruction getABoundIn(SemBound b, IRFunction func) {
* Holds if `i <= b + delta`. * Holds if `i <= b + delta`.
*/ */
pragma[inline] pragma[inline]
private predicate boundedImpl(Instruction i, Instruction b, int delta) { private predicate boundedImplCand(Instruction i, Instruction b, int delta) {
exists(SemBound bound, IRFunction func | exists(SemBound bound, IRFunction func |
semBounded(getSemanticExpr(i), bound, delta, true, _) and semBounded(getSemanticExpr(i), bound, delta, true, _) and
b = getABoundIn(bound, func) and b = getABoundIn(bound, func) and
@@ -26,6 +26,15 @@ private predicate boundedImpl(Instruction i, Instruction b, int delta) {
) )
} }
/**
* Holds if `i <= b + delta` and `delta` is the smallest integer that satisfies
* this condition.
*/
pragma[inline]
private predicate boundedImpl(Instruction i, Instruction b, int delta) {
delta = min(int cand | boundedImplCand(i, b, cand))
}
/** /**
* Holds if `i <= b + delta`. * Holds if `i <= b + delta`.
* *

View File

@@ -105,8 +105,6 @@ predicate isNonConst(DataFlow::Node node, boolean isIndirect) {
or or
e instanceof NewArrayExpr e instanceof NewArrayExpr
or or
e instanceof AssignExpr
or
exists(Variable v | v = e.(VariableAccess).getTarget() | exists(Variable v | v = e.(VariableAccess).getTarget() |
v.getType().(ArrayType).getBaseType() instanceof CharType and v.getType().(ArrayType).getBaseType() instanceof CharType and
exists(AssignExpr ae | exists(AssignExpr ae |

View File

@@ -14,9 +14,11 @@
import cpp import cpp
import semmle.code.cpp.security.Security import semmle.code.cpp.security.Security
import semmle.code.cpp.security.FlowSources
import semmle.code.cpp.security.FunctionWithWrappers import semmle.code.cpp.security.FunctionWithWrappers
import semmle.code.cpp.ir.dataflow.internal.DefaultTaintTrackingImpl import semmle.code.cpp.ir.IR
import TaintedWithPath import semmle.code.cpp.ir.dataflow.TaintTracking
import SqlTainted::PathGraph
class SqlLikeFunction extends FunctionWithWrappers { class SqlLikeFunction extends FunctionWithWrappers {
SqlLikeFunction() { sqlArgument(this.getName(), _) } SqlLikeFunction() { sqlArgument(this.getName(), _) }
@@ -24,31 +26,43 @@ class SqlLikeFunction extends FunctionWithWrappers {
override predicate interestingArg(int arg) { sqlArgument(this.getName(), arg) } override predicate interestingArg(int arg) { sqlArgument(this.getName(), arg) }
} }
class Configuration extends TaintTrackingConfiguration { Expr asSinkExpr(DataFlow::Node node) {
override predicate isSink(Element tainted) { result = node.asIndirectArgument()
exists(SqlLikeFunction runSql | runSql.outermostWrapperFunctionCall(tainted, _)) or
// We want the conversion so we only get one node for the expression
result = node.asConvertedExpr()
} }
override predicate isBarrier(Expr e) { module SqlTaintedConfig implements DataFlow::ConfigSig {
super.isBarrier(e) predicate isSource(DataFlow::Node node) { node instanceof FlowSource }
or
e.getUnspecifiedType() instanceof IntegralType predicate isSink(DataFlow::Node node) {
or exists(SqlLikeFunction runSql | runSql.outermostWrapperFunctionCall(asSinkExpr(node), _))
}
predicate isBarrier(DataFlow::Node node) {
node.asExpr().getUnspecifiedType() instanceof IntegralType
}
predicate isBarrierIn(DataFlow::Node node) {
exists(SqlBarrierFunction sql, int arg, FunctionInput input | exists(SqlBarrierFunction sql, int arg, FunctionInput input |
e = sql.getACallToThisFunction().getArgument(arg) and node.asIndirectArgument() = sql.getACallToThisFunction().getArgument(arg) and
input.isParameterDeref(arg) and input.isParameterDeref(arg) and
sql.barrierSqlArgument(input, _) sql.barrierSqlArgument(input, _)
) )
} }
} }
module SqlTainted = TaintTracking::Global<SqlTaintedConfig>;
from from
SqlLikeFunction runSql, Expr taintedArg, Expr taintSource, PathNode sourceNode, PathNode sinkNode, SqlLikeFunction runSql, Expr taintedArg, FlowSource taintSource, SqlTainted::PathNode sourceNode,
string taintCause, string callChain SqlTainted::PathNode sinkNode, string callChain
where where
runSql.outermostWrapperFunctionCall(taintedArg, callChain) and runSql.outermostWrapperFunctionCall(taintedArg, callChain) and
taintedWithPath(taintSource, taintedArg, sourceNode, sinkNode) and SqlTainted::flowPath(sourceNode, sinkNode) and
isUserInput(taintSource, taintCause) taintedArg = asSinkExpr(sinkNode.getNode()) and
taintSource = sourceNode.getNode()
select taintedArg, sourceNode, sinkNode, select taintedArg, sourceNode, sinkNode,
"This argument to a SQL query function is derived from $@ and then passed to " + callChain + ".", "This argument to a SQL query function is derived from $@ and then passed to " + callChain + ".",
taintSource, "user input (" + taintCause + ")" taintSource, "user input (" + taintSource.getSourceType() + ")"

View File

@@ -0,0 +1,4 @@
---
category: minorAnalysis
---
* Some queries that had repeated results corresponding to different levels of indirection for `argv` now only have a single result.

View File

@@ -0,0 +1,4 @@
---
category: minorAnalysis
---
* The `cpp/non-constant-format` query no longer considers an assignment on the right-hand side of another assignment to be a source of non-constant format strings. As a result, the query may now produce fewer results.

View File

@@ -40,7 +40,7 @@ module WordexpTaintConfig implements DataFlow::ConfigSig {
predicate isSink(DataFlow::Node sink) { predicate isSink(DataFlow::Node sink) {
exists(FunctionCall fc | fc.getTarget() instanceof WordexpFunction | exists(FunctionCall fc | fc.getTarget() instanceof WordexpFunction |
fc.getArgument(0) = sink.asExpr() and fc.getArgument(0) = sink.asIndirectArgument(1) and
not isCommandSubstitutionDisabled(fc) not isCommandSubstitutionDisabled(fc)
) )
} }

View File

@@ -1,5 +1,5 @@
name: codeql/cpp-queries name: codeql/cpp-queries
version: 0.7.2 version: 0.7.3-dev
groups: groups:
- cpp - cpp
- queries - queries

View File

@@ -1,16 +1,8 @@
edges edges
| test.cpp:22:27:22:30 | argv | test.cpp:29:13:29:20 | filePath | | test.cpp:22:27:22:30 | argv indirection | test.cpp:29:13:29:20 | filePath indirection |
| test.cpp:22:27:22:30 | argv | test.cpp:29:13:29:20 | filePath |
| test.cpp:22:27:22:30 | argv indirection | test.cpp:29:13:29:20 | filePath |
| test.cpp:22:27:22:30 | argv indirection | test.cpp:29:13:29:20 | filePath |
nodes nodes
| test.cpp:22:27:22:30 | argv | semmle.label | argv |
| test.cpp:22:27:22:30 | argv indirection | semmle.label | argv indirection | | test.cpp:22:27:22:30 | argv indirection | semmle.label | argv indirection |
| test.cpp:29:13:29:20 | filePath | semmle.label | filePath | | test.cpp:29:13:29:20 | filePath indirection | semmle.label | filePath indirection |
| test.cpp:29:13:29:20 | filePath | semmle.label | filePath |
subpaths subpaths
#select #select
| test.cpp:29:13:29:20 | filePath | test.cpp:22:27:22:30 | argv | test.cpp:29:13:29:20 | filePath | Using user-supplied data in a `wordexp` command, without disabling command substitution, can make code vulnerable to command injection. | | test.cpp:29:13:29:20 | filePath indirection | test.cpp:22:27:22:30 | argv indirection | test.cpp:29:13:29:20 | filePath indirection | Using user-supplied data in a `wordexp` command, without disabling command substitution, can make code vulnerable to command injection. |
| test.cpp:29:13:29:20 | filePath | test.cpp:22:27:22:30 | argv | test.cpp:29:13:29:20 | filePath | Using user-supplied data in a `wordexp` command, without disabling command substitution, can make code vulnerable to command injection. |
| test.cpp:29:13:29:20 | filePath | test.cpp:22:27:22:30 | argv indirection | test.cpp:29:13:29:20 | filePath | Using user-supplied data in a `wordexp` command, without disabling command substitution, can make code vulnerable to command injection. |
| test.cpp:29:13:29:20 | filePath | test.cpp:22:27:22:30 | argv indirection | test.cpp:29:13:29:20 | filePath | Using user-supplied data in a `wordexp` command, without disabling command substitution, can make code vulnerable to command injection. |

View File

@@ -69,12 +69,6 @@ edges
| test.cpp:322:19:322:27 | ... + ... | test.cpp:325:24:325:26 | end | | test.cpp:322:19:322:27 | ... + ... | test.cpp:325:24:325:26 | end |
| test.cpp:324:23:324:26 | temp | test.cpp:324:23:324:32 | ... + ... | | test.cpp:324:23:324:26 | temp | test.cpp:324:23:324:32 | ... + ... |
| test.cpp:324:23:324:32 | ... + ... | test.cpp:325:15:325:19 | temp2 | | test.cpp:324:23:324:32 | ... + ... | test.cpp:325:15:325:19 | temp2 |
| test.cpp:351:9:351:11 | arr | test.cpp:351:9:351:14 | access to array |
| test.cpp:351:9:351:11 | arr | test.cpp:351:18:351:25 | access to array |
| test.cpp:351:18:351:20 | arr | test.cpp:351:9:351:14 | access to array |
| test.cpp:351:18:351:20 | arr | test.cpp:351:18:351:25 | access to array |
| test.cpp:351:29:351:31 | arr | test.cpp:351:9:351:14 | access to array |
| test.cpp:351:29:351:31 | arr | test.cpp:351:18:351:25 | access to array |
nodes nodes
| test.cpp:34:5:34:24 | access to array | semmle.label | access to array | | test.cpp:34:5:34:24 | access to array | semmle.label | access to array |
| test.cpp:34:10:34:12 | buf | semmle.label | buf | | test.cpp:34:10:34:12 | buf | semmle.label | buf |
@@ -167,11 +161,6 @@ nodes
| test.cpp:325:15:325:19 | temp2 | semmle.label | temp2 | | test.cpp:325:15:325:19 | temp2 | semmle.label | temp2 |
| test.cpp:325:24:325:26 | end | semmle.label | end | | test.cpp:325:24:325:26 | end | semmle.label | end |
| test.cpp:325:24:325:26 | end | semmle.label | end | | test.cpp:325:24:325:26 | end | semmle.label | end |
| test.cpp:351:9:351:11 | arr | semmle.label | arr |
| test.cpp:351:9:351:14 | access to array | semmle.label | access to array |
| test.cpp:351:18:351:20 | arr | semmle.label | arr |
| test.cpp:351:18:351:25 | access to array | semmle.label | access to array |
| test.cpp:351:29:351:31 | arr | semmle.label | arr |
subpaths subpaths
#select #select
| test.cpp:35:5:35:22 | PointerAdd: access to array | test.cpp:35:10:35:12 | buf | test.cpp:35:5:35:22 | access to array | This pointer arithmetic may have an off-by-1 error allowing it to overrun $@ at this $@. | test.cpp:15:9:15:11 | buf | buf | test.cpp:35:5:35:26 | Store: ... = ... | write | | test.cpp:35:5:35:22 | PointerAdd: access to array | test.cpp:35:10:35:12 | buf | test.cpp:35:5:35:22 | access to array | This pointer arithmetic may have an off-by-1 error allowing it to overrun $@ at this $@. | test.cpp:15:9:15:11 | buf | buf | test.cpp:35:5:35:26 | Store: ... = ... | write |
@@ -194,6 +183,3 @@ subpaths
| test.cpp:322:19:322:27 | PointerAdd: ... + ... | test.cpp:322:19:322:22 | temp | test.cpp:325:24:325:26 | end | This pointer arithmetic may have an off-by-1 error allowing it to overrun $@ at this $@. | test.cpp:314:10:314:13 | temp | temp | test.cpp:330:13:330:24 | Store: ... = ... | write | | test.cpp:322:19:322:27 | PointerAdd: ... + ... | test.cpp:322:19:322:22 | temp | test.cpp:325:24:325:26 | end | This pointer arithmetic may have an off-by-1 error allowing it to overrun $@ at this $@. | test.cpp:314:10:314:13 | temp | temp | test.cpp:330:13:330:24 | Store: ... = ... | write |
| test.cpp:322:19:322:27 | PointerAdd: ... + ... | test.cpp:322:19:322:22 | temp | test.cpp:325:24:325:26 | end | This pointer arithmetic may have an off-by-1 error allowing it to overrun $@ at this $@. | test.cpp:314:10:314:13 | temp | temp | test.cpp:331:13:331:24 | Store: ... = ... | write | | test.cpp:322:19:322:27 | PointerAdd: ... + ... | test.cpp:322:19:322:22 | temp | test.cpp:325:24:325:26 | end | This pointer arithmetic may have an off-by-1 error allowing it to overrun $@ at this $@. | test.cpp:314:10:314:13 | temp | temp | test.cpp:331:13:331:24 | Store: ... = ... | write |
| test.cpp:322:19:322:27 | PointerAdd: ... + ... | test.cpp:322:19:322:22 | temp | test.cpp:325:24:325:26 | end | This pointer arithmetic may have an off-by-1 error allowing it to overrun $@ at this $@. | test.cpp:314:10:314:13 | temp | temp | test.cpp:333:13:333:24 | Store: ... = ... | write | | test.cpp:322:19:322:27 | PointerAdd: ... + ... | test.cpp:322:19:322:22 | temp | test.cpp:325:24:325:26 | end | This pointer arithmetic may have an off-by-1 error allowing it to overrun $@ at this $@. | test.cpp:314:10:314:13 | temp | temp | test.cpp:333:13:333:24 | Store: ... = ... | write |
| test.cpp:351:18:351:25 | PointerAdd: access to array | test.cpp:351:9:351:11 | arr | test.cpp:351:18:351:25 | access to array | This pointer arithmetic may have an off-by-1 error allowing it to overrun $@ at this $@. | test.cpp:348:9:348:11 | arr | arr | test.cpp:351:18:351:25 | Load: access to array | read |
| test.cpp:351:18:351:25 | PointerAdd: access to array | test.cpp:351:18:351:20 | arr | test.cpp:351:18:351:25 | access to array | This pointer arithmetic may have an off-by-1 error allowing it to overrun $@ at this $@. | test.cpp:348:9:348:11 | arr | arr | test.cpp:351:18:351:25 | Load: access to array | read |
| test.cpp:351:18:351:25 | PointerAdd: access to array | test.cpp:351:29:351:31 | arr | test.cpp:351:18:351:25 | access to array | This pointer arithmetic may have an off-by-1 error allowing it to overrun $@ at this $@. | test.cpp:348:9:348:11 | arr | arr | test.cpp:351:18:351:25 | Load: access to array | read |

View File

@@ -348,7 +348,7 @@ int positiveRange(int x) {
int arr[128]; int arr[128];
for(int i=127-offset; i>= 0; i--) { for(int i=127-offset; i>= 0; i--) {
arr[i] = arr[i+1] + arr[i+offset]; // GOOD [FALSE POSITIVE] arr[i] = arr[i+1] + arr[i+offset]; // GOOD
} }
return arr[0]; return arr[0];
} }

View File

@@ -129,7 +129,6 @@ edges
| test.cpp:271:14:271:21 | ... + ... | test.cpp:271:14:271:21 | ... + ... | | test.cpp:271:14:271:21 | ... + ... | test.cpp:271:14:271:21 | ... + ... |
| test.cpp:271:14:271:21 | ... + ... | test.cpp:274:5:274:10 | ... = ... | | test.cpp:271:14:271:21 | ... + ... | test.cpp:274:5:274:10 | ... = ... |
| test.cpp:271:14:271:21 | ... + ... | test.cpp:274:5:274:10 | ... = ... | | test.cpp:271:14:271:21 | ... + ... | test.cpp:274:5:274:10 | ... = ... |
| test.cpp:304:15:304:26 | new[] | test.cpp:308:5:308:29 | ... = ... |
| test.cpp:355:14:355:27 | new[] | test.cpp:356:15:356:23 | ... + ... | | test.cpp:355:14:355:27 | new[] | test.cpp:356:15:356:23 | ... + ... |
| test.cpp:355:14:355:27 | new[] | test.cpp:356:15:356:23 | ... + ... | | test.cpp:355:14:355:27 | new[] | test.cpp:356:15:356:23 | ... + ... |
| test.cpp:355:14:355:27 | new[] | test.cpp:357:24:357:30 | ... + ... | | test.cpp:355:14:355:27 | new[] | test.cpp:357:24:357:30 | ... + ... |
@@ -214,20 +213,26 @@ edges
| test.cpp:543:14:543:27 | new[] | test.cpp:548:5:548:19 | ... = ... | | test.cpp:543:14:543:27 | new[] | test.cpp:548:5:548:19 | ... = ... |
| test.cpp:554:14:554:27 | new[] | test.cpp:559:5:559:19 | ... = ... | | test.cpp:554:14:554:27 | new[] | test.cpp:559:5:559:19 | ... = ... |
| test.cpp:642:14:642:31 | new[] | test.cpp:647:5:647:19 | ... = ... | | test.cpp:642:14:642:31 | new[] | test.cpp:647:5:647:19 | ... = ... |
| test.cpp:652:14:652:27 | new[] | test.cpp:656:3:656:6 | ... ++ |
| test.cpp:652:14:652:27 | new[] | test.cpp:656:3:656:6 | ... ++ |
| test.cpp:652:14:652:27 | new[] | test.cpp:662:3:662:11 | ... = ... |
| test.cpp:656:3:656:6 | ... ++ | test.cpp:656:3:656:6 | ... ++ |
| test.cpp:656:3:656:6 | ... ++ | test.cpp:662:3:662:11 | ... = ... |
| test.cpp:656:3:656:6 | ... ++ | test.cpp:662:3:662:11 | ... = ... |
| test.cpp:667:14:667:31 | new[] | test.cpp:675:7:675:23 | ... = ... |
| test.cpp:695:13:695:26 | new[] | test.cpp:698:5:698:10 | ... += ... | | test.cpp:695:13:695:26 | new[] | test.cpp:698:5:698:10 | ... += ... |
| test.cpp:695:13:695:26 | new[] | test.cpp:698:5:698:10 | ... += ... |
| test.cpp:698:5:698:10 | ... += ... | test.cpp:698:5:698:10 | ... += ... |
| test.cpp:698:5:698:10 | ... += ... | test.cpp:701:15:701:16 | * ... | | test.cpp:698:5:698:10 | ... += ... | test.cpp:701:15:701:16 | * ... |
| test.cpp:705:18:705:18 | q | test.cpp:705:18:705:18 | q | | test.cpp:705:18:705:18 | q | test.cpp:705:18:705:18 | q |
| test.cpp:705:18:705:18 | q | test.cpp:706:12:706:13 | * ... | | test.cpp:705:18:705:18 | q | test.cpp:706:12:706:13 | * ... |
| test.cpp:705:18:705:18 | q | test.cpp:706:12:706:13 | * ... | | test.cpp:705:18:705:18 | q | test.cpp:706:12:706:13 | * ... |
| test.cpp:711:13:711:26 | new[] | test.cpp:714:11:714:11 | q | | test.cpp:711:13:711:26 | new[] | test.cpp:714:11:714:11 | q |
| test.cpp:714:11:714:11 | q | test.cpp:705:18:705:18 | q | | test.cpp:714:11:714:11 | q | test.cpp:705:18:705:18 | q |
| test.cpp:730:12:730:28 | new[] | test.cpp:732:16:732:26 | ... + ... |
| test.cpp:730:12:730:28 | new[] | test.cpp:732:16:732:26 | ... + ... |
| test.cpp:730:12:730:28 | new[] | test.cpp:733:5:733:12 | ... = ... |
| test.cpp:732:16:732:26 | ... + ... | test.cpp:732:16:732:26 | ... + ... |
| test.cpp:732:16:732:26 | ... + ... | test.cpp:733:5:733:12 | ... = ... |
| test.cpp:732:16:732:26 | ... + ... | test.cpp:733:5:733:12 | ... = ... |
| test.cpp:754:18:754:31 | new[] | test.cpp:767:16:767:29 | access to array |
| test.cpp:754:18:754:31 | new[] | test.cpp:767:16:767:29 | access to array |
| test.cpp:754:18:754:31 | new[] | test.cpp:772:16:772:29 | access to array |
| test.cpp:754:18:754:31 | new[] | test.cpp:772:16:772:29 | access to array |
| test.cpp:781:14:781:27 | new[] | test.cpp:786:18:786:27 | access to array |
nodes nodes
| test.cpp:4:15:4:20 | call to malloc | semmle.label | call to malloc | | test.cpp:4:15:4:20 | call to malloc | semmle.label | call to malloc |
| test.cpp:5:15:5:22 | ... + ... | semmle.label | ... + ... | | test.cpp:5:15:5:22 | ... + ... | semmle.label | ... + ... |
@@ -320,8 +325,6 @@ nodes
| test.cpp:271:14:271:21 | ... + ... | semmle.label | ... + ... | | test.cpp:271:14:271:21 | ... + ... | semmle.label | ... + ... |
| test.cpp:271:14:271:21 | ... + ... | semmle.label | ... + ... | | test.cpp:271:14:271:21 | ... + ... | semmle.label | ... + ... |
| test.cpp:274:5:274:10 | ... = ... | semmle.label | ... = ... | | test.cpp:274:5:274:10 | ... = ... | semmle.label | ... = ... |
| test.cpp:304:15:304:26 | new[] | semmle.label | new[] |
| test.cpp:308:5:308:29 | ... = ... | semmle.label | ... = ... |
| test.cpp:355:14:355:27 | new[] | semmle.label | new[] | | test.cpp:355:14:355:27 | new[] | semmle.label | new[] |
| test.cpp:356:15:356:23 | ... + ... | semmle.label | ... + ... | | test.cpp:356:15:356:23 | ... + ... | semmle.label | ... + ... |
| test.cpp:356:15:356:23 | ... + ... | semmle.label | ... + ... | | test.cpp:356:15:356:23 | ... + ... | semmle.label | ... + ... |
@@ -371,20 +374,26 @@ nodes
| test.cpp:559:5:559:19 | ... = ... | semmle.label | ... = ... | | test.cpp:559:5:559:19 | ... = ... | semmle.label | ... = ... |
| test.cpp:642:14:642:31 | new[] | semmle.label | new[] | | test.cpp:642:14:642:31 | new[] | semmle.label | new[] |
| test.cpp:647:5:647:19 | ... = ... | semmle.label | ... = ... | | test.cpp:647:5:647:19 | ... = ... | semmle.label | ... = ... |
| test.cpp:652:14:652:27 | new[] | semmle.label | new[] |
| test.cpp:656:3:656:6 | ... ++ | semmle.label | ... ++ |
| test.cpp:656:3:656:6 | ... ++ | semmle.label | ... ++ |
| test.cpp:662:3:662:11 | ... = ... | semmle.label | ... = ... |
| test.cpp:667:14:667:31 | new[] | semmle.label | new[] |
| test.cpp:675:7:675:23 | ... = ... | semmle.label | ... = ... |
| test.cpp:695:13:695:26 | new[] | semmle.label | new[] | | test.cpp:695:13:695:26 | new[] | semmle.label | new[] |
| test.cpp:698:5:698:10 | ... += ... | semmle.label | ... += ... | | test.cpp:698:5:698:10 | ... += ... | semmle.label | ... += ... |
| test.cpp:698:5:698:10 | ... += ... | semmle.label | ... += ... |
| test.cpp:701:15:701:16 | * ... | semmle.label | * ... | | test.cpp:701:15:701:16 | * ... | semmle.label | * ... |
| test.cpp:705:18:705:18 | q | semmle.label | q | | test.cpp:705:18:705:18 | q | semmle.label | q |
| test.cpp:705:18:705:18 | q | semmle.label | q | | test.cpp:705:18:705:18 | q | semmle.label | q |
| test.cpp:706:12:706:13 | * ... | semmle.label | * ... | | test.cpp:706:12:706:13 | * ... | semmle.label | * ... |
| test.cpp:711:13:711:26 | new[] | semmle.label | new[] | | test.cpp:711:13:711:26 | new[] | semmle.label | new[] |
| test.cpp:714:11:714:11 | q | semmle.label | q | | test.cpp:714:11:714:11 | q | semmle.label | q |
| test.cpp:730:12:730:28 | new[] | semmle.label | new[] |
| test.cpp:732:16:732:26 | ... + ... | semmle.label | ... + ... |
| test.cpp:732:16:732:26 | ... + ... | semmle.label | ... + ... |
| test.cpp:733:5:733:12 | ... = ... | semmle.label | ... = ... |
| test.cpp:754:18:754:31 | new[] | semmle.label | new[] |
| test.cpp:767:16:767:29 | access to array | semmle.label | access to array |
| test.cpp:767:16:767:29 | access to array | semmle.label | access to array |
| test.cpp:772:16:772:29 | access to array | semmle.label | access to array |
| test.cpp:772:16:772:29 | access to array | semmle.label | access to array |
| test.cpp:781:14:781:27 | new[] | semmle.label | new[] |
| test.cpp:786:18:786:27 | access to array | semmle.label | access to array |
subpaths subpaths
#select #select
| test.cpp:6:14:6:15 | * ... | test.cpp:4:15:4:20 | call to malloc | test.cpp:6:14:6:15 | * ... | This read might be out of bounds, as the pointer might be equal to $@ + $@. | test.cpp:4:15:4:20 | call to malloc | call to malloc | test.cpp:5:19:5:22 | size | size | | test.cpp:6:14:6:15 | * ... | test.cpp:4:15:4:20 | call to malloc | test.cpp:6:14:6:15 | * ... | This read might be out of bounds, as the pointer might be equal to $@ + $@. | test.cpp:4:15:4:20 | call to malloc | call to malloc | test.cpp:5:19:5:22 | size | size |
@@ -406,7 +415,6 @@ subpaths
| test.cpp:254:9:254:16 | ... = ... | test.cpp:248:24:248:30 | call to realloc | test.cpp:254:9:254:16 | ... = ... | This write might be out of bounds, as the pointer might be equal to $@ + $@. | test.cpp:248:24:248:30 | call to realloc | call to realloc | test.cpp:254:11:254:11 | i | i | | test.cpp:254:9:254:16 | ... = ... | test.cpp:248:24:248:30 | call to realloc | test.cpp:254:9:254:16 | ... = ... | This write might be out of bounds, as the pointer might be equal to $@ + $@. | test.cpp:248:24:248:30 | call to realloc | call to realloc | test.cpp:254:11:254:11 | i | i |
| test.cpp:264:13:264:14 | * ... | test.cpp:260:13:260:24 | new[] | test.cpp:264:13:264:14 | * ... | This read might be out of bounds, as the pointer might be equal to $@ + $@. | test.cpp:260:13:260:24 | new[] | new[] | test.cpp:261:19:261:21 | len | len | | test.cpp:264:13:264:14 | * ... | test.cpp:260:13:260:24 | new[] | test.cpp:264:13:264:14 | * ... | This read might be out of bounds, as the pointer might be equal to $@ + $@. | test.cpp:260:13:260:24 | new[] | new[] | test.cpp:261:19:261:21 | len | len |
| test.cpp:274:5:274:10 | ... = ... | test.cpp:270:13:270:24 | new[] | test.cpp:274:5:274:10 | ... = ... | This write might be out of bounds, as the pointer might be equal to $@ + $@. | test.cpp:270:13:270:24 | new[] | new[] | test.cpp:271:19:271:21 | len | len | | test.cpp:274:5:274:10 | ... = ... | test.cpp:270:13:270:24 | new[] | test.cpp:274:5:274:10 | ... = ... | This write might be out of bounds, as the pointer might be equal to $@ + $@. | test.cpp:270:13:270:24 | new[] | new[] | test.cpp:271:19:271:21 | len | len |
| test.cpp:308:5:308:29 | ... = ... | test.cpp:304:15:304:26 | new[] | test.cpp:308:5:308:29 | ... = ... | This write might be out of bounds, as the pointer might be equal to $@ + $@. | test.cpp:304:15:304:26 | new[] | new[] | test.cpp:308:8:308:10 | ... + ... | ... + ... |
| test.cpp:358:14:358:26 | * ... | test.cpp:355:14:355:27 | new[] | test.cpp:358:14:358:26 | * ... | This read might be out of bounds, as the pointer might be equal to $@ + $@ + 1. | test.cpp:355:14:355:27 | new[] | new[] | test.cpp:356:20:356:23 | size | size | | test.cpp:358:14:358:26 | * ... | test.cpp:355:14:355:27 | new[] | test.cpp:358:14:358:26 | * ... | This read might be out of bounds, as the pointer might be equal to $@ + $@ + 1. | test.cpp:355:14:355:27 | new[] | new[] | test.cpp:356:20:356:23 | size | size |
| test.cpp:359:14:359:32 | * ... | test.cpp:355:14:355:27 | new[] | test.cpp:359:14:359:32 | * ... | This read might be out of bounds, as the pointer might be equal to $@ + $@ + 2. | test.cpp:355:14:355:27 | new[] | new[] | test.cpp:356:20:356:23 | size | size | | test.cpp:359:14:359:32 | * ... | test.cpp:355:14:355:27 | new[] | test.cpp:359:14:359:32 | * ... | This read might be out of bounds, as the pointer might be equal to $@ + $@ + 2. | test.cpp:355:14:355:27 | new[] | new[] | test.cpp:356:20:356:23 | size | size |
| test.cpp:384:13:384:16 | * ... | test.cpp:377:14:377:27 | new[] | test.cpp:384:13:384:16 | * ... | This read might be out of bounds, as the pointer might be equal to $@ + $@. | test.cpp:377:14:377:27 | new[] | new[] | test.cpp:378:20:378:23 | size | size | | test.cpp:384:13:384:16 | * ... | test.cpp:377:14:377:27 | new[] | test.cpp:384:13:384:16 | * ... | This read might be out of bounds, as the pointer might be equal to $@ + $@. | test.cpp:377:14:377:27 | new[] | new[] | test.cpp:378:20:378:23 | size | size |
@@ -418,7 +426,11 @@ subpaths
| test.cpp:548:5:548:19 | ... = ... | test.cpp:543:14:543:27 | new[] | test.cpp:548:5:548:19 | ... = ... | This write might be out of bounds, as the pointer might be equal to $@ + $@. | test.cpp:543:14:543:27 | new[] | new[] | test.cpp:548:8:548:14 | src_pos | src_pos | | test.cpp:548:5:548:19 | ... = ... | test.cpp:543:14:543:27 | new[] | test.cpp:548:5:548:19 | ... = ... | This write might be out of bounds, as the pointer might be equal to $@ + $@. | test.cpp:543:14:543:27 | new[] | new[] | test.cpp:548:8:548:14 | src_pos | src_pos |
| test.cpp:559:5:559:19 | ... = ... | test.cpp:554:14:554:27 | new[] | test.cpp:559:5:559:19 | ... = ... | This write might be out of bounds, as the pointer might be equal to $@ + $@. | test.cpp:554:14:554:27 | new[] | new[] | test.cpp:559:8:559:14 | src_pos | src_pos | | test.cpp:559:5:559:19 | ... = ... | test.cpp:554:14:554:27 | new[] | test.cpp:559:5:559:19 | ... = ... | This write might be out of bounds, as the pointer might be equal to $@ + $@. | test.cpp:554:14:554:27 | new[] | new[] | test.cpp:559:8:559:14 | src_pos | src_pos |
| test.cpp:647:5:647:19 | ... = ... | test.cpp:642:14:642:31 | new[] | test.cpp:647:5:647:19 | ... = ... | This write might be out of bounds, as the pointer might be equal to $@ + $@. | test.cpp:642:14:642:31 | new[] | new[] | test.cpp:647:8:647:14 | src_pos | src_pos | | test.cpp:647:5:647:19 | ... = ... | test.cpp:642:14:642:31 | new[] | test.cpp:647:5:647:19 | ... = ... | This write might be out of bounds, as the pointer might be equal to $@ + $@. | test.cpp:642:14:642:31 | new[] | new[] | test.cpp:647:8:647:14 | src_pos | src_pos |
| test.cpp:662:3:662:11 | ... = ... | test.cpp:652:14:652:27 | new[] | test.cpp:662:3:662:11 | ... = ... | This write might be out of bounds, as the pointer might be equal to $@ + $@ + 1. | test.cpp:652:14:652:27 | new[] | new[] | test.cpp:653:19:653:22 | size | size |
| test.cpp:675:7:675:23 | ... = ... | test.cpp:667:14:667:31 | new[] | test.cpp:675:7:675:23 | ... = ... | This write might be out of bounds, as the pointer might be equal to $@ + $@. | test.cpp:667:14:667:31 | new[] | new[] | test.cpp:675:10:675:18 | ... ++ | ... ++ |
| test.cpp:701:15:701:16 | * ... | test.cpp:695:13:695:26 | new[] | test.cpp:701:15:701:16 | * ... | This read might be out of bounds, as the pointer might be equal to $@ + $@. | test.cpp:695:13:695:26 | new[] | new[] | test.cpp:696:19:696:22 | size | size | | test.cpp:701:15:701:16 | * ... | test.cpp:695:13:695:26 | new[] | test.cpp:701:15:701:16 | * ... | This read might be out of bounds, as the pointer might be equal to $@ + $@. | test.cpp:695:13:695:26 | new[] | new[] | test.cpp:696:19:696:22 | size | size |
| test.cpp:706:12:706:13 | * ... | test.cpp:711:13:711:26 | new[] | test.cpp:706:12:706:13 | * ... | This read might be out of bounds, as the pointer might be equal to $@ + $@. | test.cpp:711:13:711:26 | new[] | new[] | test.cpp:712:19:712:22 | size | size | | test.cpp:706:12:706:13 | * ... | test.cpp:711:13:711:26 | new[] | test.cpp:706:12:706:13 | * ... | This read might be out of bounds, as the pointer might be equal to $@ + $@. | test.cpp:711:13:711:26 | new[] | new[] | test.cpp:712:19:712:22 | size | size |
| test.cpp:733:5:733:12 | ... = ... | test.cpp:730:12:730:28 | new[] | test.cpp:733:5:733:12 | ... = ... | This write might be out of bounds, as the pointer might be equal to $@ + $@. | test.cpp:730:12:730:28 | new[] | new[] | test.cpp:732:21:732:25 | ... + ... | ... + ... |
| test.cpp:767:16:767:29 | access to array | test.cpp:754:18:754:31 | new[] | test.cpp:767:16:767:29 | access to array | This read might be out of bounds, as the pointer might be equal to $@ + $@. | test.cpp:754:18:754:31 | new[] | new[] | test.cpp:767:22:767:28 | ... + ... | ... + ... |
| test.cpp:767:16:767:29 | access to array | test.cpp:754:18:754:31 | new[] | test.cpp:767:16:767:29 | access to array | This read might be out of bounds, as the pointer might be equal to $@ + $@. | test.cpp:754:18:754:31 | new[] | new[] | test.cpp:772:22:772:28 | ... + ... | ... + ... |
| test.cpp:772:16:772:29 | access to array | test.cpp:754:18:754:31 | new[] | test.cpp:772:16:772:29 | access to array | This read might be out of bounds, as the pointer might be equal to $@ + $@. | test.cpp:754:18:754:31 | new[] | new[] | test.cpp:767:22:767:28 | ... + ... | ... + ... |
| test.cpp:772:16:772:29 | access to array | test.cpp:754:18:754:31 | new[] | test.cpp:772:16:772:29 | access to array | This read might be out of bounds, as the pointer might be equal to $@ + $@. | test.cpp:754:18:754:31 | new[] | new[] | test.cpp:772:22:772:28 | ... + ... | ... + ... |
| test.cpp:786:18:786:27 | access to array | test.cpp:781:14:781:27 | new[] | test.cpp:786:18:786:27 | access to array | This read might be out of bounds, as the pointer might be equal to $@ + $@. | test.cpp:781:14:781:27 | new[] | new[] | test.cpp:786:20:786:26 | ... + ... | ... + ... |

View File

@@ -305,7 +305,7 @@ void test21() {
for (int i = 0; i < n; i += 2) { for (int i = 0; i < n; i += 2) {
xs[i] = test21_get(i); // GOOD xs[i] = test21_get(i); // GOOD
xs[i+1] = test21_get(i+1); // $ alloc=L304 alloc=L304-1 deref=L308 // GOOD [FALSE POSITIVE] xs[i+1] = test21_get(i+1); // GOOD
} }
} }
@@ -659,7 +659,7 @@ void test32(unsigned size) {
xs++; xs++;
if (xs >= end) if (xs >= end)
return; return;
xs[0] = 0; // $ deref=L656->L662+1 deref=L657->L662+1 GOOD [FALSE POSITIVE] xs[0] = 0; // GOOD
} }
void test33(unsigned size, unsigned src_pos) void test33(unsigned size, unsigned src_pos)
@@ -672,7 +672,7 @@ void test33(unsigned size, unsigned src_pos)
while (dst_pos < size - 1) { while (dst_pos < size - 1) {
dst_pos++; dst_pos++;
if (true) if (true)
xs[dst_pos++] = 0; // $ alloc=L667+1 deref=L675 // GOOD [FALSE POSITIVE] xs[dst_pos++] = 0; // GOOD
} }
} }
@@ -714,3 +714,77 @@ void test35(unsigned long size, char* q)
deref(q); deref(q);
} }
} }
void test21_simple(bool b) {
int n = 0;
if (b) n = 2;
int* xs = new int[n];
for (int i = 0; i < n; i += 2) {
xs[i+1] = 0; // GOOD
}
}
void test36(unsigned size, unsigned n) {
int* p = new int[size + 2];
if(n < size + 1) {
int* end = p + (n + 2); // $ alloc=L730+2
*end = 0; // $ deref=L733 // BAD
}
}
void test37(unsigned long n)
{
int *p = new int[n];
for (unsigned long i = n; i != 0u; i--)
{
p[n - i] = 0; // GOOD
}
}
unsigned get(char);
void exit(int);
void error(const char * msg) {
exit(1);
}
void test38(unsigned size) {
char * alloc = new char[size];
unsigned pos = 0;
while (pos < size) {
char kind = alloc[pos];
unsigned n = get(alloc[pos]);
if (pos + n >= size) {
error("");
}
switch (kind) {
case '0':
if (n != 1)
error("");
char x = alloc[pos + 1]; // $ alloc=L754 deref=L767 // GOOD [FALSE POSITIVE]
break;
case '1':
if (n != 2)
error("");
char a = alloc[pos + 1]; // $ alloc=L754 deref=L772 // GOOD [FALSE POSITIVE]
char b = alloc[pos + 2];
break;
}
pos += 1 + n;
}
}
void test38_simple(unsigned size, unsigned pos, unsigned numParams) {
char * p = new char[size];
if (pos < size) {
if (pos + numParams < size) {
if (numParams == 1) {
char x = p[pos + 1]; // $ alloc=L781 deref=L786 // GOOD [FALSE POSITIVE]
}
}
}
}

View File

@@ -732,7 +732,7 @@ void test_does_not_write_source_to_dereference()
{ {
int x; int x;
does_not_write_source_to_dereference(&x); does_not_write_source_to_dereference(&x);
sink(x); // $ ast,ir=733:7 SPURIOUS: ast,ir=726:11 sink(x); // $ ast=733:7 ir SPURIOUS: ast=726:11
} }
void sometimes_calls_sink_eq(int x, int n) { void sometimes_calls_sink_eq(int x, int n) {

View File

@@ -134,7 +134,7 @@ void pointer_test() {
sink(*p3); // $ ast,ir sink(*p3); // $ ast,ir
*p3 = 0; *p3 = 0;
sink(*p3); // $ SPURIOUS: ast,ir sink(*p3); // $ SPURIOUS: ast
} }
// --- return values --- // --- return values ---

View File

@@ -1,3 +0,0 @@
| file://:0:0:0:0 | There was an error during this compilation |
| float128.cpp:1:39:1:39 | 128-bit floating-point types are not supported in this configuration |
| float128.cpp:2:30:2:30 | 128-bit floating-point types are not supported in this configuration |

View File

@@ -1,4 +0,0 @@
import cpp
from Diagnostic d
select d

View File

@@ -1,5 +1,5 @@
typedef _Complex float __attribute__((mode(TC))) _Complex128; // [COMPILER ERROR AND ERROR-TYPE DUE TO __float128 BEING DISABLED] typedef _Complex float __attribute__((mode(TC))) _Complex128;
typedef float __attribute__((mode(TF))) _Float128; // [COMPILER ERROR AND ERROR-TYPE DUE TO __float128 BEING DISABLED] typedef float __attribute__((mode(TF))) _Float128;
int main() { int main() {
__float128 f = 1.0f; __float128 f = 1.0f;
@@ -25,4 +25,3 @@ __float128 id(__float128 q)
{ {
return q; return q;
} }
// semmle-extractor-options: --expect_errors

View File

@@ -1,5 +1,5 @@
| float128.cpp:1:50:1:60 | _Complex128 | file://:0:0:0:0 | <error-type> | | float128.cpp:1:50:1:60 | _Complex128 | file://:0:0:0:0 | float __complex__ |
| float128.cpp:2:41:2:49 | _Float128 | file://:0:0:0:0 | <error-type> | | float128.cpp:2:41:2:49 | _Float128 | file://:0:0:0:0 | __float128 |
| float128.cpp:13:29:13:54 | __is_floating_point_helper<T> | float128.cpp:10:8:10:17 | false_type | | float128.cpp:13:29:13:54 | __is_floating_point_helper<T> | float128.cpp:10:8:10:17 | false_type |
| float128.cpp:14:19:14:51 | __is_floating_point_helper<float> | float128.cpp:11:8:11:16 | true_type | | float128.cpp:14:19:14:51 | __is_floating_point_helper<float> | float128.cpp:11:8:11:16 | true_type |
| float128.cpp:15:19:15:52 | __is_floating_point_helper<double> | float128.cpp:11:8:11:16 | true_type | | float128.cpp:15:19:15:52 | __is_floating_point_helper<double> | float128.cpp:11:8:11:16 | true_type |

View File

@@ -1798,6 +1798,23 @@ ir.c:
# 10| Type = [CTypedefType] MyCoords # 10| Type = [CTypedefType] MyCoords
# 10| ValueCategory = lvalue # 10| ValueCategory = lvalue
# 11| getStmt(3): [ReturnStmt] return ... # 11| getStmt(3): [ReturnStmt] return ...
# 13| [TopLevelFunction] void CStyleCast(void*)
# 13| <params>:
# 13| getParameter(0): [Parameter] src
# 13| Type = [VoidPointerType] void *
# 14| getEntryPoint(): [BlockStmt] { ... }
# 15| getStmt(0): [DeclStmt] declaration
# 15| getDeclarationEntry(0): [VariableDeclarationEntry] definition of dst
# 15| Type = [CharPointerType] char *
# 15| getVariable().getInitializer(): [Initializer] initializer for dst
# 15| getExpr(): [VariableAccess] src
# 15| Type = [VoidPointerType] void *
# 15| ValueCategory = prvalue(load)
# 15| getExpr().getFullyConverted(): [CStyleCast] (char *)...
# 15| Conversion = [PointerConversion] pointer conversion
# 15| Type = [CharPointerType] char *
# 15| ValueCategory = prvalue
# 16| getStmt(1): [ReturnStmt] return ...
ir.cpp: ir.cpp:
# 1| [TopLevelFunction] void Constants() # 1| [TopLevelFunction] void Constants()
# 1| <params>: # 1| <params>:

View File

@@ -9,3 +9,10 @@ void MyCoordsTest(int pos) {
coords.x = coords.y = pos + 1; coords.x = coords.y = pos + 1;
coords.x = getX(&coords); coords.x = getX(&coords);
} }
void CStyleCast(void *src)
{
char *dst = (char*)src;
}
// semmle-extractor-options: --microsoft

View File

@@ -978,6 +978,20 @@
| ir.c:10:19:10:25 | ChiTotal | total:m9_13 | | ir.c:10:19:10:25 | ChiTotal | total:m9_13 |
| ir.c:10:19:10:25 | SideEffect | ~m9_13 | | ir.c:10:19:10:25 | SideEffect | ~m9_13 |
| ir.c:10:20:10:25 | Unary | r10_2 | | ir.c:10:20:10:25 | Unary | r10_2 |
| ir.c:13:6:13:15 | ChiPartial | partial:m13_3 |
| ir.c:13:6:13:15 | ChiTotal | total:m13_2 |
| ir.c:13:6:13:15 | SideEffect | m13_3 |
| ir.c:13:23:13:25 | Address | &:r13_5 |
| ir.c:13:23:13:25 | Address | &:r13_5 |
| ir.c:13:23:13:25 | Address | &:r13_7 |
| ir.c:13:23:13:25 | Address | &:r13_7 |
| ir.c:13:23:13:25 | Load | m13_6 |
| ir.c:13:23:13:25 | SideEffect | m13_8 |
| ir.c:15:11:15:13 | Address | &:r15_1 |
| ir.c:15:17:15:26 | StoreValue | r15_4 |
| ir.c:15:24:15:26 | Address | &:r15_2 |
| ir.c:15:24:15:26 | Load | m13_6 |
| ir.c:15:24:15:26 | Unary | r15_3 |
| ir.cpp:1:6:1:14 | ChiPartial | partial:m1_3 | | ir.cpp:1:6:1:14 | ChiPartial | partial:m1_3 |
| ir.cpp:1:6:1:14 | ChiTotal | total:m1_2 | | ir.cpp:1:6:1:14 | ChiTotal | total:m1_2 |
| ir.cpp:1:6:1:14 | SideEffect | m1_3 | | ir.cpp:1:6:1:14 | SideEffect | m1_3 |

View File

@@ -766,6 +766,26 @@ ir.c:
# 7| v7_7(void) = AliasedUse : ~m? # 7| v7_7(void) = AliasedUse : ~m?
# 7| v7_8(void) = ExitFunction : # 7| v7_8(void) = ExitFunction :
# 13| void CStyleCast(void*)
# 13| Block 0
# 13| v13_1(void) = EnterFunction :
# 13| mu13_2(unknown) = AliasedDefinition :
# 13| mu13_3(unknown) = InitializeNonLocal :
# 13| r13_4(glval<void *>) = VariableAddress[src] :
# 13| mu13_5(void *) = InitializeParameter[src] : &:r13_4
# 13| r13_6(void *) = Load[src] : &:r13_4, ~m?
# 13| mu13_7(unknown) = InitializeIndirection[src] : &:r13_6
# 15| r15_1(glval<char *>) = VariableAddress[dst] :
# 15| r15_2(glval<void *>) = VariableAddress[src] :
# 15| r15_3(void *) = Load[src] : &:r15_2, ~m?
# 15| r15_4(char *) = Convert : r15_3
# 15| mu15_5(char *) = Store[dst] : &:r15_1, r15_4
# 16| v16_1(void) = NoOp :
# 13| v13_8(void) = ReturnIndirection[src] : &:r13_6, ~m?
# 13| v13_9(void) = ReturnVoid :
# 13| v13_10(void) = AliasedUse : ~m?
# 13| v13_11(void) = ExitFunction :
ir.cpp: ir.cpp:
# 1| void Constants() # 1| void Constants()
# 1| Block 0 # 1| Block 0

View File

@@ -95,3 +95,25 @@ void gotoLoop(bool b1, bool b2)
} }
} }
} }
void test_sub(int x, int y, int n) {
if(x > 0 && x < 500) {
if(y > 0 && y < 10) {
range(x - y); // $ range=<=498 range=>=-8
}
if(n > 0 && n < 100) {
for (int i = 0; i < n; i++)
{
range(n - i); // $ range=">=Phi: i-97" range=<=99 range=>=-97
range(i - n); // $ range="<=Phi: i-1" range=">=Phi: i-99" range=<=97 range=>=-99
}
for (int i = n; i != 0; i--)
{
range(n - i); // $ SPURIOUS: overflow=+
range(i - n); // $ range=">=Phi: i-99"
}
}
}
}

View File

@@ -156,3 +156,10 @@ void fmt_via_strcpy(char *data) {
strcpy(data, "some string"); strcpy(data, "some string");
printf(data); // BAD printf(data); // BAD
} }
void fmt_with_assignment() {
const char *x, *y;
x = y = "a";
printf(y); // GOOD
}

View File

@@ -1,16 +1,10 @@
edges edges
| test.c:8:27:8:30 | argv | test.c:17:11:17:18 | fileName indirection |
| test.c:8:27:8:30 | argv indirection | test.c:17:11:17:18 | fileName indirection |
| test.c:8:27:8:30 | argv indirection | test.c:17:11:17:18 | fileName indirection | | test.c:8:27:8:30 | argv indirection | test.c:17:11:17:18 | fileName indirection |
| test.c:8:27:8:30 | argv indirection | test.c:32:11:32:18 | fileName indirection | | test.c:8:27:8:30 | argv indirection | test.c:32:11:32:18 | fileName indirection |
| test.c:8:27:8:30 | argv indirection | test.c:32:11:32:18 | fileName indirection |
| test.c:8:27:8:30 | argv indirection | test.c:57:10:57:16 | access to array indirection |
| test.c:8:27:8:30 | argv indirection | test.c:57:10:57:16 | access to array indirection | | test.c:8:27:8:30 | argv indirection | test.c:57:10:57:16 | access to array indirection |
| test.c:37:17:37:24 | scanf output argument | test.c:38:11:38:18 | fileName indirection | | test.c:37:17:37:24 | scanf output argument | test.c:38:11:38:18 | fileName indirection |
| test.c:43:17:43:24 | scanf output argument | test.c:44:11:44:18 | fileName indirection | | test.c:43:17:43:24 | scanf output argument | test.c:44:11:44:18 | fileName indirection |
nodes nodes
| test.c:8:27:8:30 | argv | semmle.label | argv |
| test.c:8:27:8:30 | argv indirection | semmle.label | argv indirection |
| test.c:8:27:8:30 | argv indirection | semmle.label | argv indirection | | test.c:8:27:8:30 | argv indirection | semmle.label | argv indirection |
| test.c:17:11:17:18 | fileName indirection | semmle.label | fileName indirection | | test.c:17:11:17:18 | fileName indirection | semmle.label | fileName indirection |
| test.c:32:11:32:18 | fileName indirection | semmle.label | fileName indirection | | test.c:32:11:32:18 | fileName indirection | semmle.label | fileName indirection |
@@ -21,12 +15,8 @@ nodes
| test.c:57:10:57:16 | access to array indirection | semmle.label | access to array indirection | | test.c:57:10:57:16 | access to array indirection | semmle.label | access to array indirection |
subpaths subpaths
#select #select
| test.c:17:11:17:18 | fileName | test.c:8:27:8:30 | argv | test.c:17:11:17:18 | fileName indirection | This argument to a file access function is derived from $@ and then passed to fopen(filename). | test.c:8:27:8:30 | argv | user input (a command-line argument) |
| test.c:17:11:17:18 | fileName | test.c:8:27:8:30 | argv indirection | test.c:17:11:17:18 | fileName indirection | This argument to a file access function is derived from $@ and then passed to fopen(filename). | test.c:8:27:8:30 | argv indirection | user input (a command-line argument) | | test.c:17:11:17:18 | fileName | test.c:8:27:8:30 | argv indirection | test.c:17:11:17:18 | fileName indirection | This argument to a file access function is derived from $@ and then passed to fopen(filename). | test.c:8:27:8:30 | argv indirection | user input (a command-line argument) |
| test.c:17:11:17:18 | fileName | test.c:8:27:8:30 | argv indirection | test.c:17:11:17:18 | fileName indirection | This argument to a file access function is derived from $@ and then passed to fopen(filename). | test.c:8:27:8:30 | argv indirection | user input (a command-line argument) |
| test.c:32:11:32:18 | fileName | test.c:8:27:8:30 | argv indirection | test.c:32:11:32:18 | fileName indirection | This argument to a file access function is derived from $@ and then passed to fopen(filename). | test.c:8:27:8:30 | argv indirection | user input (a command-line argument) |
| test.c:32:11:32:18 | fileName | test.c:8:27:8:30 | argv indirection | test.c:32:11:32:18 | fileName indirection | This argument to a file access function is derived from $@ and then passed to fopen(filename). | test.c:8:27:8:30 | argv indirection | user input (a command-line argument) | | test.c:32:11:32:18 | fileName | test.c:8:27:8:30 | argv indirection | test.c:32:11:32:18 | fileName indirection | This argument to a file access function is derived from $@ and then passed to fopen(filename). | test.c:8:27:8:30 | argv indirection | user input (a command-line argument) |
| test.c:38:11:38:18 | fileName | test.c:37:17:37:24 | scanf output argument | test.c:38:11:38:18 | fileName indirection | This argument to a file access function is derived from $@ and then passed to fopen(filename). | test.c:37:17:37:24 | scanf output argument | user input (value read by scanf) | | test.c:38:11:38:18 | fileName | test.c:37:17:37:24 | scanf output argument | test.c:38:11:38:18 | fileName indirection | This argument to a file access function is derived from $@ and then passed to fopen(filename). | test.c:37:17:37:24 | scanf output argument | user input (value read by scanf) |
| test.c:44:11:44:18 | fileName | test.c:43:17:43:24 | scanf output argument | test.c:44:11:44:18 | fileName indirection | This argument to a file access function is derived from $@ and then passed to fopen(filename). | test.c:43:17:43:24 | scanf output argument | user input (value read by scanf) | | test.c:44:11:44:18 | fileName | test.c:43:17:43:24 | scanf output argument | test.c:44:11:44:18 | fileName indirection | This argument to a file access function is derived from $@ and then passed to fopen(filename). | test.c:43:17:43:24 | scanf output argument | user input (value read by scanf) |
| test.c:57:10:57:16 | access to array | test.c:8:27:8:30 | argv indirection | test.c:57:10:57:16 | access to array indirection | This argument to a file access function is derived from $@ and then passed to read(fileName), which calls fopen(filename). | test.c:8:27:8:30 | argv indirection | user input (a command-line argument) | | test.c:57:10:57:16 | access to array | test.c:8:27:8:30 | argv indirection | test.c:57:10:57:16 | access to array indirection | This argument to a file access function is derived from $@ and then passed to read(fileName), which calls fopen(filename). | test.c:8:27:8:30 | argv indirection | user input (a command-line argument) |
| test.c:57:10:57:16 | access to array | test.c:8:27:8:30 | argv indirection | test.c:57:10:57:16 | access to array indirection | This argument to a file access function is derived from $@ and then passed to read(fileName), which calls fopen(filename). | test.c:8:27:8:30 | argv indirection | user input (a command-line argument) |

View File

@@ -1,6 +1,5 @@
edges edges
| test.cpp:15:27:15:30 | argv indirection | test.cpp:22:45:22:52 | userName indirection | | test.cpp:15:27:15:30 | argv indirection | test.cpp:22:45:22:52 | userName indirection |
| test.cpp:15:27:15:30 | argv indirection | test.cpp:22:45:22:52 | userName indirection |
| test.cpp:22:13:22:20 | sprintf output argument | test.cpp:23:12:23:19 | command1 indirection | | test.cpp:22:13:22:20 | sprintf output argument | test.cpp:23:12:23:19 | command1 indirection |
| test.cpp:22:45:22:52 | userName indirection | test.cpp:22:13:22:20 | sprintf output argument | | test.cpp:22:45:22:52 | userName indirection | test.cpp:22:13:22:20 | sprintf output argument |
| test.cpp:47:21:47:26 | call to getenv indirection | test.cpp:50:35:50:43 | envCflags indirection | | test.cpp:47:21:47:26 | call to getenv indirection | test.cpp:50:35:50:43 | envCflags indirection |
@@ -71,7 +70,6 @@ edges
| test.cpp:220:19:220:26 | filename indirection | test.cpp:220:19:220:26 | filename indirection | | test.cpp:220:19:220:26 | filename indirection | test.cpp:220:19:220:26 | filename indirection |
nodes nodes
| test.cpp:15:27:15:30 | argv indirection | semmle.label | argv indirection | | test.cpp:15:27:15:30 | argv indirection | semmle.label | argv indirection |
| test.cpp:15:27:15:30 | argv indirection | semmle.label | argv indirection |
| test.cpp:22:13:22:20 | sprintf output argument | semmle.label | sprintf output argument | | test.cpp:22:13:22:20 | sprintf output argument | semmle.label | sprintf output argument |
| test.cpp:22:45:22:52 | userName indirection | semmle.label | userName indirection | | test.cpp:22:45:22:52 | userName indirection | semmle.label | userName indirection |
| test.cpp:23:12:23:19 | command1 indirection | semmle.label | command1 indirection | | test.cpp:23:12:23:19 | command1 indirection | semmle.label | command1 indirection |
@@ -154,7 +152,6 @@ subpaths
| test.cpp:196:26:196:33 | filename indirection | test.cpp:186:47:186:54 | filename indirection | test.cpp:188:11:188:17 | strncat output argument | test.cpp:196:10:196:16 | concat output argument | | test.cpp:196:26:196:33 | filename indirection | test.cpp:186:47:186:54 | filename indirection | test.cpp:188:11:188:17 | strncat output argument | test.cpp:196:10:196:16 | concat output argument |
#select #select
| test.cpp:23:12:23:19 | command1 | test.cpp:15:27:15:30 | argv indirection | test.cpp:23:12:23:19 | command1 indirection | This argument to an OS command is derived from $@, dangerously concatenated into $@, and then passed to system(string). | test.cpp:15:27:15:30 | argv indirection | user input (a command-line argument) | test.cpp:22:13:22:20 | sprintf output argument | sprintf output argument | | test.cpp:23:12:23:19 | command1 | test.cpp:15:27:15:30 | argv indirection | test.cpp:23:12:23:19 | command1 indirection | This argument to an OS command is derived from $@, dangerously concatenated into $@, and then passed to system(string). | test.cpp:15:27:15:30 | argv indirection | user input (a command-line argument) | test.cpp:22:13:22:20 | sprintf output argument | sprintf output argument |
| test.cpp:23:12:23:19 | command1 | test.cpp:15:27:15:30 | argv indirection | test.cpp:23:12:23:19 | command1 indirection | This argument to an OS command is derived from $@, dangerously concatenated into $@, and then passed to system(string). | test.cpp:15:27:15:30 | argv indirection | user input (a command-line argument) | test.cpp:22:13:22:20 | sprintf output argument | sprintf output argument |
| test.cpp:51:10:51:16 | command | test.cpp:47:21:47:26 | call to getenv indirection | test.cpp:51:10:51:16 | command indirection | This argument to an OS command is derived from $@, dangerously concatenated into $@, and then passed to system(string). | test.cpp:47:21:47:26 | call to getenv indirection | user input (an environment variable) | test.cpp:50:11:50:17 | sprintf output argument | sprintf output argument | | test.cpp:51:10:51:16 | command | test.cpp:47:21:47:26 | call to getenv indirection | test.cpp:51:10:51:16 | command indirection | This argument to an OS command is derived from $@, dangerously concatenated into $@, and then passed to system(string). | test.cpp:47:21:47:26 | call to getenv indirection | user input (an environment variable) | test.cpp:50:11:50:17 | sprintf output argument | sprintf output argument |
| test.cpp:65:10:65:16 | command | test.cpp:62:9:62:16 | fread output argument | test.cpp:65:10:65:16 | command indirection | This argument to an OS command is derived from $@, dangerously concatenated into $@, and then passed to system(string). | test.cpp:62:9:62:16 | fread output argument | user input (string read by fread) | test.cpp:64:11:64:17 | strncat output argument | strncat output argument | | test.cpp:65:10:65:16 | command | test.cpp:62:9:62:16 | fread output argument | test.cpp:65:10:65:16 | command indirection | This argument to an OS command is derived from $@, dangerously concatenated into $@, and then passed to system(string). | test.cpp:62:9:62:16 | fread output argument | user input (string read by fread) | test.cpp:64:11:64:17 | strncat output argument | strncat output argument |
| test.cpp:85:32:85:38 | command | test.cpp:82:9:82:16 | fread output argument | test.cpp:85:32:85:38 | command indirection | This argument to an OS command is derived from $@, dangerously concatenated into $@, and then passed to execl. | test.cpp:82:9:82:16 | fread output argument | user input (string read by fread) | test.cpp:84:11:84:17 | strncat output argument | strncat output argument | | test.cpp:85:32:85:38 | command | test.cpp:82:9:82:16 | fread output argument | test.cpp:85:32:85:38 | command indirection | This argument to an OS command is derived from $@, dangerously concatenated into $@, and then passed to execl. | test.cpp:82:9:82:16 | fread output argument | user input (string read by fread) | test.cpp:84:11:84:17 | strncat output argument | strncat output argument |

View File

@@ -1,25 +1,12 @@
edges edges
| test.c:15:20:15:23 | argv | test.c:21:18:21:23 | query1 | | test.c:14:27:14:30 | argv indirection | test.c:21:18:21:23 | query1 indirection |
| test.c:15:20:15:23 | argv | test.c:21:18:21:23 | query1 | | test.cpp:39:27:39:30 | argv indirection | test.cpp:43:27:43:33 | access to array indirection |
| test.c:15:20:15:23 | argv | test.c:21:18:21:23 | query1 |
| test.c:15:20:15:23 | argv | test.c:21:18:21:23 | query1 |
| test.cpp:43:27:43:30 | argv | test.cpp:43:27:43:33 | access to array |
| test.cpp:43:27:43:30 | argv | test.cpp:43:27:43:33 | access to array |
| test.cpp:43:27:43:30 | argv | test.cpp:43:27:43:33 | access to array |
| test.cpp:43:27:43:30 | argv | test.cpp:43:27:43:33 | access to array |
| test.cpp:43:27:43:30 | argv | test.cpp:43:27:43:33 | access to array |
| test.cpp:43:27:43:30 | argv | test.cpp:43:27:43:33 | access to array |
subpaths
nodes nodes
| test.c:15:20:15:23 | argv | semmle.label | argv | | test.c:14:27:14:30 | argv indirection | semmle.label | argv indirection |
| test.c:15:20:15:23 | argv | semmle.label | argv | | test.c:21:18:21:23 | query1 indirection | semmle.label | query1 indirection |
| test.c:21:18:21:23 | query1 | semmle.label | query1 | | test.cpp:39:27:39:30 | argv indirection | semmle.label | argv indirection |
| test.c:21:18:21:23 | query1 | semmle.label | query1 | | test.cpp:43:27:43:33 | access to array indirection | semmle.label | access to array indirection |
| test.cpp:43:27:43:30 | argv | semmle.label | argv | subpaths
| test.cpp:43:27:43:30 | argv | semmle.label | argv |
| test.cpp:43:27:43:33 | access to array | semmle.label | access to array |
| test.cpp:43:27:43:33 | access to array | semmle.label | access to array |
| test.cpp:43:27:43:33 | access to array | semmle.label | access to array |
#select #select
| test.c:21:18:21:23 | query1 | test.c:15:20:15:23 | argv | test.c:21:18:21:23 | query1 | This argument to a SQL query function is derived from $@ and then passed to mysql_query(sqlArg). | test.c:15:20:15:23 | argv | user input (argv) | | test.c:21:18:21:23 | query1 | test.c:14:27:14:30 | argv indirection | test.c:21:18:21:23 | query1 indirection | This argument to a SQL query function is derived from $@ and then passed to mysql_query(sqlArg). | test.c:14:27:14:30 | argv indirection | user input (a command-line argument) |
| test.cpp:43:27:43:33 | access to array | test.cpp:43:27:43:30 | argv | test.cpp:43:27:43:33 | access to array | This argument to a SQL query function is derived from $@ and then passed to pqxx::work::exec1((unnamed parameter 0)). | test.cpp:43:27:43:30 | argv | user input (argv) | | test.cpp:43:27:43:33 | access to array | test.cpp:39:27:39:30 | argv indirection | test.cpp:43:27:43:33 | access to array indirection | This argument to a SQL query function is derived from $@ and then passed to pqxx::work::exec1((unnamed parameter 0)). | test.cpp:39:27:39:30 | argv indirection | user input (a command-line argument) |

View File

@@ -1,10 +1,6 @@
edges edges
| main.cpp:6:27:6:30 | argv indirection | main.cpp:7:33:7:36 | argv indirection | | main.cpp:6:27:6:30 | argv indirection | main.cpp:7:33:7:36 | argv indirection |
| main.cpp:6:27:6:30 | argv indirection | main.cpp:7:33:7:36 | argv indirection |
| main.cpp:7:33:7:36 | argv indirection | overflowdestination.cpp:23:45:23:48 | argv indirection | | main.cpp:7:33:7:36 | argv indirection | overflowdestination.cpp:23:45:23:48 | argv indirection |
| main.cpp:7:33:7:36 | argv indirection | overflowdestination.cpp:23:45:23:48 | argv indirection |
| overflowdestination.cpp:23:45:23:48 | argv indirection | overflowdestination.cpp:30:17:30:20 | arg1 indirection |
| overflowdestination.cpp:23:45:23:48 | argv indirection | overflowdestination.cpp:30:17:30:20 | arg1 indirection |
| overflowdestination.cpp:23:45:23:48 | argv indirection | overflowdestination.cpp:30:17:30:20 | arg1 indirection | | overflowdestination.cpp:23:45:23:48 | argv indirection | overflowdestination.cpp:30:17:30:20 | arg1 indirection |
| overflowdestination.cpp:23:45:23:48 | argv indirection | overflowdestination.cpp:30:17:30:20 | arg1 indirection | | overflowdestination.cpp:23:45:23:48 | argv indirection | overflowdestination.cpp:30:17:30:20 | arg1 indirection |
| overflowdestination.cpp:43:8:43:10 | fgets output argument | overflowdestination.cpp:46:15:46:17 | src indirection | | overflowdestination.cpp:43:8:43:10 | fgets output argument | overflowdestination.cpp:46:15:46:17 | src indirection |
@@ -24,10 +20,7 @@ edges
| overflowdestination.cpp:76:30:76:32 | src indirection | overflowdestination.cpp:57:52:57:54 | src indirection | | overflowdestination.cpp:76:30:76:32 | src indirection | overflowdestination.cpp:57:52:57:54 | src indirection |
nodes nodes
| main.cpp:6:27:6:30 | argv indirection | semmle.label | argv indirection | | main.cpp:6:27:6:30 | argv indirection | semmle.label | argv indirection |
| main.cpp:6:27:6:30 | argv indirection | semmle.label | argv indirection |
| main.cpp:7:33:7:36 | argv indirection | semmle.label | argv indirection | | main.cpp:7:33:7:36 | argv indirection | semmle.label | argv indirection |
| main.cpp:7:33:7:36 | argv indirection | semmle.label | argv indirection |
| overflowdestination.cpp:23:45:23:48 | argv indirection | semmle.label | argv indirection |
| overflowdestination.cpp:23:45:23:48 | argv indirection | semmle.label | argv indirection | | overflowdestination.cpp:23:45:23:48 | argv indirection | semmle.label | argv indirection |
| overflowdestination.cpp:30:17:30:20 | arg1 indirection | semmle.label | arg1 indirection | | overflowdestination.cpp:30:17:30:20 | arg1 indirection | semmle.label | arg1 indirection |
| overflowdestination.cpp:30:17:30:20 | arg1 indirection | semmle.label | arg1 indirection | | overflowdestination.cpp:30:17:30:20 | arg1 indirection | semmle.label | arg1 indirection |
@@ -51,8 +44,6 @@ subpaths
#select #select
| overflowdestination.cpp:30:2:30:8 | call to strncpy | main.cpp:6:27:6:30 | argv indirection | overflowdestination.cpp:30:17:30:20 | arg1 indirection | To avoid overflow, this operation should be bounded by destination-buffer size, not source-buffer size. | | overflowdestination.cpp:30:2:30:8 | call to strncpy | main.cpp:6:27:6:30 | argv indirection | overflowdestination.cpp:30:17:30:20 | arg1 indirection | To avoid overflow, this operation should be bounded by destination-buffer size, not source-buffer size. |
| overflowdestination.cpp:30:2:30:8 | call to strncpy | main.cpp:6:27:6:30 | argv indirection | overflowdestination.cpp:30:17:30:20 | arg1 indirection | To avoid overflow, this operation should be bounded by destination-buffer size, not source-buffer size. | | overflowdestination.cpp:30:2:30:8 | call to strncpy | main.cpp:6:27:6:30 | argv indirection | overflowdestination.cpp:30:17:30:20 | arg1 indirection | To avoid overflow, this operation should be bounded by destination-buffer size, not source-buffer size. |
| overflowdestination.cpp:30:2:30:8 | call to strncpy | main.cpp:6:27:6:30 | argv indirection | overflowdestination.cpp:30:17:30:20 | arg1 indirection | To avoid overflow, this operation should be bounded by destination-buffer size, not source-buffer size. |
| overflowdestination.cpp:30:2:30:8 | call to strncpy | main.cpp:6:27:6:30 | argv indirection | overflowdestination.cpp:30:17:30:20 | arg1 indirection | To avoid overflow, this operation should be bounded by destination-buffer size, not source-buffer size. |
| overflowdestination.cpp:46:2:46:7 | call to memcpy | overflowdestination.cpp:43:8:43:10 | fgets output argument | overflowdestination.cpp:46:15:46:17 | src indirection | To avoid overflow, this operation should be bounded by destination-buffer size, not source-buffer size. | | overflowdestination.cpp:46:2:46:7 | call to memcpy | overflowdestination.cpp:43:8:43:10 | fgets output argument | overflowdestination.cpp:46:15:46:17 | src indirection | To avoid overflow, this operation should be bounded by destination-buffer size, not source-buffer size. |
| overflowdestination.cpp:53:2:53:7 | call to memcpy | overflowdestination.cpp:73:8:73:10 | fgets output argument | overflowdestination.cpp:53:15:53:17 | src indirection | To avoid overflow, this operation should be bounded by destination-buffer size, not source-buffer size. | | overflowdestination.cpp:53:2:53:7 | call to memcpy | overflowdestination.cpp:73:8:73:10 | fgets output argument | overflowdestination.cpp:53:15:53:17 | src indirection | To avoid overflow, this operation should be bounded by destination-buffer size, not source-buffer size. |
| overflowdestination.cpp:53:2:53:7 | call to memcpy | overflowdestination.cpp:73:8:73:10 | fgets output argument | overflowdestination.cpp:53:15:53:17 | src indirection | To avoid overflow, this operation should be bounded by destination-buffer size, not source-buffer size. | | overflowdestination.cpp:53:2:53:7 | call to memcpy | overflowdestination.cpp:73:8:73:10 | fgets output argument | overflowdestination.cpp:53:15:53:17 | src indirection | To avoid overflow, this operation should be bounded by destination-buffer size, not source-buffer size. |

View File

@@ -1,2 +1,6 @@
| tests2.cpp:59:3:59:10 | call to snprintf | This 'call to snprintf' operation is limited to 13 bytes but the destination is only 0 bytes. |
| tests2.cpp:59:3:59:10 | call to snprintf | This 'call to snprintf' operation is limited to 13 bytes but the destination is only 2 bytes. |
| tests2.cpp:63:3:63:10 | call to snprintf | This 'call to snprintf' operation is limited to 13 bytes but the destination is only 0 bytes. |
| tests2.cpp:63:3:63:10 | call to snprintf | This 'call to snprintf' operation is limited to 13 bytes but the destination is only 3 bytes. |
| tests.c:43:3:43:10 | call to snprintf | This 'call to snprintf' operation is limited to 111 bytes but the destination is only 110 bytes. | | tests.c:43:3:43:10 | call to snprintf | This 'call to snprintf' operation is limited to 111 bytes but the destination is only 110 bytes. |
| tests.c:46:3:46:10 | call to snprintf | This 'call to snprintf' operation is limited to 111 bytes but the destination is only 110 bytes. | | tests.c:46:3:46:10 | call to snprintf | This 'call to snprintf' operation is limited to 111 bytes but the destination is only 110 bytes. |

View File

@@ -1,10 +1,10 @@
| tests2.cpp:17:3:17:8 | call to wcscpy | This 'call to wcscpy' operation requires 12 bytes but the destination is only 8 bytes. | | tests2.cpp:18:3:18:8 | call to wcscpy | This 'call to wcscpy' operation requires 12 bytes but the destination is only 8 bytes. |
| tests2.cpp:22:3:22:8 | call to wcscpy | This 'call to wcscpy' operation requires 16 bytes but the destination is only 12 bytes. | | tests2.cpp:23:3:23:8 | call to wcscpy | This 'call to wcscpy' operation requires 16 bytes but the destination is only 12 bytes. |
| tests2.cpp:27:3:27:8 | call to wcscpy | This 'call to wcscpy' operation requires 20 bytes but the destination is only 16 bytes. | | tests2.cpp:28:3:28:8 | call to wcscpy | This 'call to wcscpy' operation requires 20 bytes but the destination is only 16 bytes. |
| tests2.cpp:31:3:31:8 | call to wcscpy | This 'call to wcscpy' operation requires 24 bytes but the destination is only 20 bytes. | | tests2.cpp:32:3:32:8 | call to wcscpy | This 'call to wcscpy' operation requires 24 bytes but the destination is only 20 bytes. |
| tests2.cpp:36:3:36:8 | call to wcscpy | This 'call to wcscpy' operation requires 28 bytes but the destination is only 24 bytes. | | tests2.cpp:37:3:37:8 | call to wcscpy | This 'call to wcscpy' operation requires 28 bytes but the destination is only 24 bytes. |
| tests2.cpp:41:3:41:8 | call to wcscpy | This 'call to wcscpy' operation requires 32 bytes but the destination is only 28 bytes. | | tests2.cpp:42:3:42:8 | call to wcscpy | This 'call to wcscpy' operation requires 32 bytes but the destination is only 28 bytes. |
| tests2.cpp:46:3:46:8 | call to wcscpy | This 'call to wcscpy' operation requires 36 bytes but the destination is only 32 bytes. | | tests2.cpp:47:3:47:8 | call to wcscpy | This 'call to wcscpy' operation requires 36 bytes but the destination is only 32 bytes. |
| tests.c:54:3:54:9 | call to sprintf | This 'call to sprintf' operation requires 11 bytes but the destination is only 10 bytes. | | tests.c:54:3:54:9 | call to sprintf | This 'call to sprintf' operation requires 11 bytes but the destination is only 10 bytes. |
| tests.c:58:3:58:9 | call to sprintf | This 'call to sprintf' operation requires 11 bytes but the destination is only 10 bytes. | | tests.c:58:3:58:9 | call to sprintf | This 'call to sprintf' operation requires 11 bytes but the destination is only 10 bytes. |
| tests.c:62:17:62:24 | buffer10 | This 'scanf string argument' operation requires 11 bytes but the destination is only 10 bytes. | | tests.c:62:17:62:24 | buffer10 | This 'scanf string argument' operation requires 11 bytes but the destination is only 10 bytes. |

View File

@@ -6,6 +6,7 @@ void *realloc(void *ptr, size_t size);
void *calloc(size_t nmemb, size_t size); void *calloc(size_t nmemb, size_t size);
void free(void *ptr); void free(void *ptr);
wchar_t *wcscpy(wchar_t *s1, const wchar_t *s2); wchar_t *wcscpy(wchar_t *s1, const wchar_t *s2);
int snprintf(char *s, size_t n, const char *format, ...);
// --- Semmle tests --- // --- Semmle tests ---
@@ -46,3 +47,18 @@ void tests2() {
wcscpy(buffer, L"12345678"); // BAD: buffer overflow wcscpy(buffer, L"12345678"); // BAD: buffer overflow
delete [] buffer; delete [] buffer;
} }
char* dest1 = "a";
char* dest2 = "abcdefghijklmnopqrstuvwxyz";
void test3() {
const char src[] = "abcdefghijkl";
dest1 = (char*)malloc(sizeof(src));
if (!dest1)
return;
snprintf(dest1, sizeof(src), "%s", src); // GOOD [FALSE POSITIVE]
dest2 = (char*)malloc(3);
if (!dest2)
return;
snprintf(dest2, sizeof(src), "%s", src); // BAD (but with duplicate alerts)
}

View File

@@ -1,12 +1,6 @@
edges edges
| test1.c:7:26:7:29 | argv | test1.c:9:9:9:9 | i |
| test1.c:7:26:7:29 | argv | test1.c:11:9:11:9 | i |
| test1.c:7:26:7:29 | argv | test1.c:13:9:13:9 | i |
| test1.c:7:26:7:29 | argv indirection | test1.c:9:9:9:9 | i |
| test1.c:7:26:7:29 | argv indirection | test1.c:9:9:9:9 | i | | test1.c:7:26:7:29 | argv indirection | test1.c:9:9:9:9 | i |
| test1.c:7:26:7:29 | argv indirection | test1.c:11:9:11:9 | i | | test1.c:7:26:7:29 | argv indirection | test1.c:11:9:11:9 | i |
| test1.c:7:26:7:29 | argv indirection | test1.c:11:9:11:9 | i |
| test1.c:7:26:7:29 | argv indirection | test1.c:13:9:13:9 | i |
| test1.c:7:26:7:29 | argv indirection | test1.c:13:9:13:9 | i | | test1.c:7:26:7:29 | argv indirection | test1.c:13:9:13:9 | i |
| test1.c:9:9:9:9 | i | test1.c:16:16:16:16 | i | | test1.c:9:9:9:9 | i | test1.c:16:16:16:16 | i |
| test1.c:11:9:11:9 | i | test1.c:32:16:32:16 | i | | test1.c:11:9:11:9 | i | test1.c:32:16:32:16 | i |
@@ -15,8 +9,6 @@ edges
| test1.c:32:16:32:16 | i | test1.c:33:11:33:11 | i | | test1.c:32:16:32:16 | i | test1.c:33:11:33:11 | i |
| test1.c:48:16:48:16 | i | test1.c:53:15:53:15 | j | | test1.c:48:16:48:16 | i | test1.c:53:15:53:15 | j |
nodes nodes
| test1.c:7:26:7:29 | argv | semmle.label | argv |
| test1.c:7:26:7:29 | argv indirection | semmle.label | argv indirection |
| test1.c:7:26:7:29 | argv indirection | semmle.label | argv indirection | | test1.c:7:26:7:29 | argv indirection | semmle.label | argv indirection |
| test1.c:9:9:9:9 | i | semmle.label | i | | test1.c:9:9:9:9 | i | semmle.label | i |
| test1.c:11:9:11:9 | i | semmle.label | i | | test1.c:11:9:11:9 | i | semmle.label | i |
@@ -29,12 +21,6 @@ nodes
| test1.c:53:15:53:15 | j | semmle.label | j | | test1.c:53:15:53:15 | j | semmle.label | j |
subpaths subpaths
#select #select
| test1.c:18:16:18:16 | i | test1.c:7:26:7:29 | argv | test1.c:18:16:18:16 | i | An array indexing expression depends on $@ that might be outside the bounds of the array. | test1.c:7:26:7:29 | argv | a command-line argument |
| test1.c:18:16:18:16 | i | test1.c:7:26:7:29 | argv indirection | test1.c:18:16:18:16 | i | An array indexing expression depends on $@ that might be outside the bounds of the array. | test1.c:7:26:7:29 | argv indirection | a command-line argument | | test1.c:18:16:18:16 | i | test1.c:7:26:7:29 | argv indirection | test1.c:18:16:18:16 | i | An array indexing expression depends on $@ that might be outside the bounds of the array. | test1.c:7:26:7:29 | argv indirection | a command-line argument |
| test1.c:18:16:18:16 | i | test1.c:7:26:7:29 | argv indirection | test1.c:18:16:18:16 | i | An array indexing expression depends on $@ that might be outside the bounds of the array. | test1.c:7:26:7:29 | argv indirection | a command-line argument |
| test1.c:33:11:33:11 | i | test1.c:7:26:7:29 | argv | test1.c:33:11:33:11 | i | An array indexing expression depends on $@ that might be outside the bounds of the array. | test1.c:7:26:7:29 | argv | a command-line argument |
| test1.c:33:11:33:11 | i | test1.c:7:26:7:29 | argv indirection | test1.c:33:11:33:11 | i | An array indexing expression depends on $@ that might be outside the bounds of the array. | test1.c:7:26:7:29 | argv indirection | a command-line argument | | test1.c:33:11:33:11 | i | test1.c:7:26:7:29 | argv indirection | test1.c:33:11:33:11 | i | An array indexing expression depends on $@ that might be outside the bounds of the array. | test1.c:7:26:7:29 | argv indirection | a command-line argument |
| test1.c:33:11:33:11 | i | test1.c:7:26:7:29 | argv indirection | test1.c:33:11:33:11 | i | An array indexing expression depends on $@ that might be outside the bounds of the array. | test1.c:7:26:7:29 | argv indirection | a command-line argument |
| test1.c:53:15:53:15 | j | test1.c:7:26:7:29 | argv | test1.c:53:15:53:15 | j | An array indexing expression depends on $@ that might be outside the bounds of the array. | test1.c:7:26:7:29 | argv | a command-line argument |
| test1.c:53:15:53:15 | j | test1.c:7:26:7:29 | argv indirection | test1.c:53:15:53:15 | j | An array indexing expression depends on $@ that might be outside the bounds of the array. | test1.c:7:26:7:29 | argv indirection | a command-line argument |
| test1.c:53:15:53:15 | j | test1.c:7:26:7:29 | argv indirection | test1.c:53:15:53:15 | j | An array indexing expression depends on $@ that might be outside the bounds of the array. | test1.c:7:26:7:29 | argv indirection | a command-line argument | | test1.c:53:15:53:15 | j | test1.c:7:26:7:29 | argv indirection | test1.c:53:15:53:15 | j | An array indexing expression depends on $@ that might be outside the bounds of the array. | test1.c:7:26:7:29 | argv indirection | a command-line argument |

View File

@@ -1,21 +1,9 @@
edges edges
| test.cpp:39:27:39:30 | argv | test.cpp:43:38:43:44 | tainted |
| test.cpp:39:27:39:30 | argv | test.cpp:44:38:44:63 | ... * ... |
| test.cpp:39:27:39:30 | argv | test.cpp:46:38:46:63 | ... + ... |
| test.cpp:39:27:39:30 | argv | test.cpp:49:32:49:35 | size |
| test.cpp:39:27:39:30 | argv | test.cpp:50:26:50:29 | size |
| test.cpp:39:27:39:30 | argv | test.cpp:53:35:53:60 | ... * ... |
| test.cpp:39:27:39:30 | argv indirection | test.cpp:43:38:43:44 | tainted |
| test.cpp:39:27:39:30 | argv indirection | test.cpp:43:38:43:44 | tainted | | test.cpp:39:27:39:30 | argv indirection | test.cpp:43:38:43:44 | tainted |
| test.cpp:39:27:39:30 | argv indirection | test.cpp:44:38:44:63 | ... * ... | | test.cpp:39:27:39:30 | argv indirection | test.cpp:44:38:44:63 | ... * ... |
| test.cpp:39:27:39:30 | argv indirection | test.cpp:44:38:44:63 | ... * ... |
| test.cpp:39:27:39:30 | argv indirection | test.cpp:46:38:46:63 | ... + ... |
| test.cpp:39:27:39:30 | argv indirection | test.cpp:46:38:46:63 | ... + ... | | test.cpp:39:27:39:30 | argv indirection | test.cpp:46:38:46:63 | ... + ... |
| test.cpp:39:27:39:30 | argv indirection | test.cpp:49:32:49:35 | size | | test.cpp:39:27:39:30 | argv indirection | test.cpp:49:32:49:35 | size |
| test.cpp:39:27:39:30 | argv indirection | test.cpp:49:32:49:35 | size |
| test.cpp:39:27:39:30 | argv indirection | test.cpp:50:26:50:29 | size | | test.cpp:39:27:39:30 | argv indirection | test.cpp:50:26:50:29 | size |
| test.cpp:39:27:39:30 | argv indirection | test.cpp:50:26:50:29 | size |
| test.cpp:39:27:39:30 | argv indirection | test.cpp:53:35:53:60 | ... * ... |
| test.cpp:39:27:39:30 | argv indirection | test.cpp:53:35:53:60 | ... * ... | | test.cpp:39:27:39:30 | argv indirection | test.cpp:53:35:53:60 | ... * ... |
| test.cpp:124:18:124:23 | call to getenv | test.cpp:128:24:128:41 | ... * ... | | test.cpp:124:18:124:23 | call to getenv | test.cpp:128:24:128:41 | ... * ... |
| test.cpp:124:18:124:31 | call to getenv indirection | test.cpp:128:24:128:41 | ... * ... | | test.cpp:124:18:124:31 | call to getenv indirection | test.cpp:128:24:128:41 | ... * ... |
@@ -47,8 +35,6 @@ edges
| test.cpp:353:18:353:31 | call to getenv indirection | test.cpp:355:35:355:38 | size | | test.cpp:353:18:353:31 | call to getenv indirection | test.cpp:355:35:355:38 | size |
| test.cpp:353:18:353:31 | call to getenv indirection | test.cpp:356:35:356:38 | size | | test.cpp:353:18:353:31 | call to getenv indirection | test.cpp:356:35:356:38 | size |
nodes nodes
| test.cpp:39:27:39:30 | argv | semmle.label | argv |
| test.cpp:39:27:39:30 | argv indirection | semmle.label | argv indirection |
| test.cpp:39:27:39:30 | argv indirection | semmle.label | argv indirection | | test.cpp:39:27:39:30 | argv indirection | semmle.label | argv indirection |
| test.cpp:43:38:43:44 | tainted | semmle.label | tainted | | test.cpp:43:38:43:44 | tainted | semmle.label | tainted |
| test.cpp:44:38:44:63 | ... * ... | semmle.label | ... * ... | | test.cpp:44:38:44:63 | ... * ... | semmle.label | ... * ... |
@@ -92,23 +78,11 @@ nodes
| test.cpp:356:35:356:38 | size | semmle.label | size | | test.cpp:356:35:356:38 | size | semmle.label | size |
subpaths subpaths
#select #select
| test.cpp:43:31:43:36 | call to malloc | test.cpp:39:27:39:30 | argv | test.cpp:43:38:43:44 | tainted | This allocation size is derived from $@ and might overflow. | test.cpp:39:27:39:30 | argv | user input (a command-line argument) |
| test.cpp:43:31:43:36 | call to malloc | test.cpp:39:27:39:30 | argv indirection | test.cpp:43:38:43:44 | tainted | This allocation size is derived from $@ and might overflow. | test.cpp:39:27:39:30 | argv indirection | user input (a command-line argument) | | test.cpp:43:31:43:36 | call to malloc | test.cpp:39:27:39:30 | argv indirection | test.cpp:43:38:43:44 | tainted | This allocation size is derived from $@ and might overflow. | test.cpp:39:27:39:30 | argv indirection | user input (a command-line argument) |
| test.cpp:43:31:43:36 | call to malloc | test.cpp:39:27:39:30 | argv indirection | test.cpp:43:38:43:44 | tainted | This allocation size is derived from $@ and might overflow. | test.cpp:39:27:39:30 | argv indirection | user input (a command-line argument) |
| test.cpp:44:31:44:36 | call to malloc | test.cpp:39:27:39:30 | argv | test.cpp:44:38:44:63 | ... * ... | This allocation size is derived from $@ and might overflow. | test.cpp:39:27:39:30 | argv | user input (a command-line argument) |
| test.cpp:44:31:44:36 | call to malloc | test.cpp:39:27:39:30 | argv indirection | test.cpp:44:38:44:63 | ... * ... | This allocation size is derived from $@ and might overflow. | test.cpp:39:27:39:30 | argv indirection | user input (a command-line argument) | | test.cpp:44:31:44:36 | call to malloc | test.cpp:39:27:39:30 | argv indirection | test.cpp:44:38:44:63 | ... * ... | This allocation size is derived from $@ and might overflow. | test.cpp:39:27:39:30 | argv indirection | user input (a command-line argument) |
| test.cpp:44:31:44:36 | call to malloc | test.cpp:39:27:39:30 | argv indirection | test.cpp:44:38:44:63 | ... * ... | This allocation size is derived from $@ and might overflow. | test.cpp:39:27:39:30 | argv indirection | user input (a command-line argument) |
| test.cpp:46:31:46:36 | call to malloc | test.cpp:39:27:39:30 | argv | test.cpp:46:38:46:63 | ... + ... | This allocation size is derived from $@ and might overflow. | test.cpp:39:27:39:30 | argv | user input (a command-line argument) |
| test.cpp:46:31:46:36 | call to malloc | test.cpp:39:27:39:30 | argv indirection | test.cpp:46:38:46:63 | ... + ... | This allocation size is derived from $@ and might overflow. | test.cpp:39:27:39:30 | argv indirection | user input (a command-line argument) | | test.cpp:46:31:46:36 | call to malloc | test.cpp:39:27:39:30 | argv indirection | test.cpp:46:38:46:63 | ... + ... | This allocation size is derived from $@ and might overflow. | test.cpp:39:27:39:30 | argv indirection | user input (a command-line argument) |
| test.cpp:46:31:46:36 | call to malloc | test.cpp:39:27:39:30 | argv indirection | test.cpp:46:38:46:63 | ... + ... | This allocation size is derived from $@ and might overflow. | test.cpp:39:27:39:30 | argv indirection | user input (a command-line argument) |
| test.cpp:49:25:49:30 | call to malloc | test.cpp:39:27:39:30 | argv | test.cpp:49:32:49:35 | size | This allocation size is derived from $@ and might overflow. | test.cpp:39:27:39:30 | argv | user input (a command-line argument) |
| test.cpp:49:25:49:30 | call to malloc | test.cpp:39:27:39:30 | argv indirection | test.cpp:49:32:49:35 | size | This allocation size is derived from $@ and might overflow. | test.cpp:39:27:39:30 | argv indirection | user input (a command-line argument) | | test.cpp:49:25:49:30 | call to malloc | test.cpp:39:27:39:30 | argv indirection | test.cpp:49:32:49:35 | size | This allocation size is derived from $@ and might overflow. | test.cpp:39:27:39:30 | argv indirection | user input (a command-line argument) |
| test.cpp:49:25:49:30 | call to malloc | test.cpp:39:27:39:30 | argv indirection | test.cpp:49:32:49:35 | size | This allocation size is derived from $@ and might overflow. | test.cpp:39:27:39:30 | argv indirection | user input (a command-line argument) |
| test.cpp:50:17:50:30 | new[] | test.cpp:39:27:39:30 | argv | test.cpp:50:26:50:29 | size | This allocation size is derived from $@ and might overflow. | test.cpp:39:27:39:30 | argv | user input (a command-line argument) |
| test.cpp:50:17:50:30 | new[] | test.cpp:39:27:39:30 | argv indirection | test.cpp:50:26:50:29 | size | This allocation size is derived from $@ and might overflow. | test.cpp:39:27:39:30 | argv indirection | user input (a command-line argument) | | test.cpp:50:17:50:30 | new[] | test.cpp:39:27:39:30 | argv indirection | test.cpp:50:26:50:29 | size | This allocation size is derived from $@ and might overflow. | test.cpp:39:27:39:30 | argv indirection | user input (a command-line argument) |
| test.cpp:50:17:50:30 | new[] | test.cpp:39:27:39:30 | argv indirection | test.cpp:50:26:50:29 | size | This allocation size is derived from $@ and might overflow. | test.cpp:39:27:39:30 | argv indirection | user input (a command-line argument) |
| test.cpp:53:21:53:27 | call to realloc | test.cpp:39:27:39:30 | argv | test.cpp:53:35:53:60 | ... * ... | This allocation size is derived from $@ and might overflow. | test.cpp:39:27:39:30 | argv | user input (a command-line argument) |
| test.cpp:53:21:53:27 | call to realloc | test.cpp:39:27:39:30 | argv indirection | test.cpp:53:35:53:60 | ... * ... | This allocation size is derived from $@ and might overflow. | test.cpp:39:27:39:30 | argv indirection | user input (a command-line argument) |
| test.cpp:53:21:53:27 | call to realloc | test.cpp:39:27:39:30 | argv indirection | test.cpp:53:35:53:60 | ... * ... | This allocation size is derived from $@ and might overflow. | test.cpp:39:27:39:30 | argv indirection | user input (a command-line argument) | | test.cpp:53:21:53:27 | call to realloc | test.cpp:39:27:39:30 | argv indirection | test.cpp:53:35:53:60 | ... * ... | This allocation size is derived from $@ and might overflow. | test.cpp:39:27:39:30 | argv indirection | user input (a command-line argument) |
| test.cpp:128:17:128:22 | call to malloc | test.cpp:124:18:124:23 | call to getenv | test.cpp:128:24:128:41 | ... * ... | This allocation size is derived from $@ and might overflow. | test.cpp:124:18:124:23 | call to getenv | user input (an environment variable) | | test.cpp:128:17:128:22 | call to malloc | test.cpp:124:18:124:23 | call to getenv | test.cpp:128:24:128:41 | ... * ... | This allocation size is derived from $@ and might overflow. | test.cpp:124:18:124:23 | call to getenv | user input (an environment variable) |
| test.cpp:128:17:128:22 | call to malloc | test.cpp:124:18:124:31 | call to getenv indirection | test.cpp:128:24:128:41 | ... * ... | This allocation size is derived from $@ and might overflow. | test.cpp:124:18:124:31 | call to getenv indirection | user input (an environment variable) | | test.cpp:128:17:128:22 | call to malloc | test.cpp:124:18:124:31 | call to getenv indirection | test.cpp:128:24:128:41 | ... * ... | This allocation size is derived from $@ and might overflow. | test.cpp:124:18:124:31 | call to getenv indirection | user input (an environment variable) |

View File

@@ -1,12 +1,9 @@
edges edges
| test.cpp:53:27:53:30 | argv indirection | test.cpp:58:25:58:29 | input indirection | | test.cpp:53:27:53:30 | argv indirection | test.cpp:58:25:58:29 | input indirection |
| test.cpp:53:27:53:30 | argv indirection | test.cpp:58:25:58:29 | input indirection | | test.cpp:53:27:53:30 | argv indirection | test.cpp:58:25:58:29 | input indirection |
| test.cpp:53:27:53:30 | argv indirection | test.cpp:58:25:58:29 | input indirection |
| test.cpp:53:27:53:30 | argv indirection | test.cpp:58:25:58:29 | input indirection |
nodes nodes
| test2.cpp:110:3:110:6 | call to gets indirection | semmle.label | call to gets indirection | | test2.cpp:110:3:110:6 | call to gets indirection | semmle.label | call to gets indirection |
| test.cpp:53:27:53:30 | argv indirection | semmle.label | argv indirection | | test.cpp:53:27:53:30 | argv indirection | semmle.label | argv indirection |
| test.cpp:53:27:53:30 | argv indirection | semmle.label | argv indirection |
| test.cpp:58:25:58:29 | input indirection | semmle.label | input indirection | | test.cpp:58:25:58:29 | input indirection | semmle.label | input indirection |
| test.cpp:58:25:58:29 | input indirection | semmle.label | input indirection | | test.cpp:58:25:58:29 | input indirection | semmle.label | input indirection |
subpaths subpaths
@@ -14,5 +11,3 @@ subpaths
| test2.cpp:110:3:110:6 | call to gets | test2.cpp:110:3:110:6 | call to gets indirection | test2.cpp:110:3:110:6 | call to gets indirection | This write into buffer 'password' may contain unencrypted data from $@. | test2.cpp:110:3:110:6 | call to gets indirection | user input (string read by gets) | | test2.cpp:110:3:110:6 | call to gets | test2.cpp:110:3:110:6 | call to gets indirection | test2.cpp:110:3:110:6 | call to gets indirection | This write into buffer 'password' may contain unencrypted data from $@. | test2.cpp:110:3:110:6 | call to gets indirection | user input (string read by gets) |
| test.cpp:58:3:58:9 | call to sprintf | test.cpp:53:27:53:30 | argv indirection | test.cpp:58:25:58:29 | input indirection | This write into buffer 'passwd' may contain unencrypted data from $@. | test.cpp:53:27:53:30 | argv indirection | user input (a command-line argument) | | test.cpp:58:3:58:9 | call to sprintf | test.cpp:53:27:53:30 | argv indirection | test.cpp:58:25:58:29 | input indirection | This write into buffer 'passwd' may contain unencrypted data from $@. | test.cpp:53:27:53:30 | argv indirection | user input (a command-line argument) |
| test.cpp:58:3:58:9 | call to sprintf | test.cpp:53:27:53:30 | argv indirection | test.cpp:58:25:58:29 | input indirection | This write into buffer 'passwd' may contain unencrypted data from $@. | test.cpp:53:27:53:30 | argv indirection | user input (a command-line argument) | | test.cpp:58:3:58:9 | call to sprintf | test.cpp:53:27:53:30 | argv indirection | test.cpp:58:25:58:29 | input indirection | This write into buffer 'passwd' may contain unencrypted data from $@. | test.cpp:53:27:53:30 | argv indirection | user input (a command-line argument) |
| test.cpp:58:3:58:9 | call to sprintf | test.cpp:53:27:53:30 | argv indirection | test.cpp:58:25:58:29 | input indirection | This write into buffer 'passwd' may contain unencrypted data from $@. | test.cpp:53:27:53:30 | argv indirection | user input (a command-line argument) |
| test.cpp:58:3:58:9 | call to sprintf | test.cpp:53:27:53:30 | argv indirection | test.cpp:58:25:58:29 | input indirection | This write into buffer 'passwd' may contain unencrypted data from $@. | test.cpp:53:27:53:30 | argv indirection | user input (a command-line argument) |

View File

@@ -1,9 +1,11 @@
{ {
"recommendations": [ "recommendations": [
"github.vscode-codeql",
"ms-dotnettools.csharp",
"formulahendry.dotnet-test-explorer", "formulahendry.dotnet-test-explorer",
"hbenl.vscode-test-explorer" "gaoshan0621.csharp-format-usings",
"github.vscode-codeql",
"hbenl.vscode-test-explorer",
"ms-dotnettools.csharp",
"ms-dotnettools.csdevkit"
], ],
"unwantedRecommendations": [] "unwantedRecommendations": []
} }

View File

@@ -7,5 +7,8 @@
"editor.defaultFormatter": "ms-dotnettools.csharp" "editor.defaultFormatter": "ms-dotnettools.csharp"
}, },
"omnisharp.enableEditorConfigSupport": true, "omnisharp.enableEditorConfigSupport": true,
"omnisharp.enableRoslynAnalyzers": true "omnisharp.enableRoslynAnalyzers": true,
"csharpFormatUsings.splitGroups": false,
"csharpFormatUsings.sortOrder": "Xunit System Microsoft Semmle.Util Semmle",
"dotnet.defaultSolution": "CSharp.sln"
} }

View File

@@ -1,53 +0,0 @@
{
"version": "2.0.0",
"tasks": [
{
"label": "dotnet build",
"command": "dotnet",
"type": "shell",
"args": [
"build",
// Ask dotnet build to generate full paths for file names.
"/property:GenerateFullPaths=true",
// Do not generate summary otherwise it leads to duplicate errors in Problems panel
"/consoleloggerparameters:NoSummary"
],
"group": "build",
"presentation": {
"reveal": "always"
},
"problemMatcher": "$msCompile"
},
{
"label": "dotnet rebuild",
"command": "dotnet",
"type": "shell",
"args": [
"build",
"--no-incremental",
"/property:GenerateFullPaths=true",
"/consoleloggerparameters:NoSummary"
],
"group": "build",
"presentation": {
"reveal": "always"
},
"problemMatcher": "$msCompile"
},
{
"label": "dotnet test",
"command": "dotnet",
"type": "shell",
"args": [
"test",
"/property:GenerateFullPaths=true",
"/consoleloggerparameters:NoSummary"
],
"group": "test",
"presentation": {
"reveal": "always"
},
"problemMatcher": "$msCompile"
}
]
}

View File

@@ -11,6 +11,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Semmle.Extraction.CSharp",
EndProject EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Semmle.Extraction.CIL", "extractor\Semmle.Extraction.CIL\Semmle.Extraction.CIL.csproj", "{399A1579-68F0-40F4-9A23-F241BA697F9C}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Semmle.Extraction.CIL", "extractor\Semmle.Extraction.CIL\Semmle.Extraction.CIL.csproj", "{399A1579-68F0-40F4-9A23-F241BA697F9C}"
EndProject EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Semmle.Extraction.CSharp.DependencyFetching", "extractor\Semmle.Extraction.CSharp.DependencyFetching\Semmle.Extraction.CSharp.DependencyFetching.csproj", "{541D1AC5-E42C-4AB2-A1A4-C2355CE2A2EF}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Semmle.Extraction.CSharp.Standalone", "extractor\Semmle.Extraction.CSharp.Standalone\Semmle.Extraction.CSharp.Standalone.csproj", "{D00E7D25-0FA0-48EC-B048-CD60CE1B30D8}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Semmle.Extraction.CSharp.Standalone", "extractor\Semmle.Extraction.CSharp.Standalone\Semmle.Extraction.CSharp.Standalone.csproj", "{D00E7D25-0FA0-48EC-B048-CD60CE1B30D8}"
EndProject EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Semmle.Extraction.CIL.Driver", "extractor\Semmle.Extraction.CIL.Driver\Semmle.Extraction.CIL.Driver.csproj", "{EFA400B3-C1CE-446F-A4E2-8B44E61EF47C}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Semmle.Extraction.CIL.Driver", "extractor\Semmle.Extraction.CIL.Driver\Semmle.Extraction.CIL.Driver.csproj", "{EFA400B3-C1CE-446F-A4E2-8B44E61EF47C}"
@@ -49,6 +51,10 @@ Global
{399A1579-68F0-40F4-9A23-F241BA697F9C}.Debug|Any CPU.Build.0 = Debug|Any CPU {399A1579-68F0-40F4-9A23-F241BA697F9C}.Debug|Any CPU.Build.0 = Debug|Any CPU
{399A1579-68F0-40F4-9A23-F241BA697F9C}.Release|Any CPU.ActiveCfg = Release|Any CPU {399A1579-68F0-40F4-9A23-F241BA697F9C}.Release|Any CPU.ActiveCfg = Release|Any CPU
{399A1579-68F0-40F4-9A23-F241BA697F9C}.Release|Any CPU.Build.0 = Release|Any CPU {399A1579-68F0-40F4-9A23-F241BA697F9C}.Release|Any CPU.Build.0 = Release|Any CPU
{541D1AC5-E42C-4AB2-A1A4-C2355CE2A2EF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{541D1AC5-E42C-4AB2-A1A4-C2355CE2A2EF}.Debug|Any CPU.Build.0 = Debug|Any CPU
{541D1AC5-E42C-4AB2-A1A4-C2355CE2A2EF}.Release|Any CPU.ActiveCfg = Release|Any CPU
{541D1AC5-E42C-4AB2-A1A4-C2355CE2A2EF}.Release|Any CPU.Build.0 = Release|Any CPU
{D00E7D25-0FA0-48EC-B048-CD60CE1B30D8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {D00E7D25-0FA0-48EC-B048-CD60CE1B30D8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{D00E7D25-0FA0-48EC-B048-CD60CE1B30D8}.Debug|Any CPU.Build.0 = Debug|Any CPU {D00E7D25-0FA0-48EC-B048-CD60CE1B30D8}.Debug|Any CPU.Build.0 = Debug|Any CPU
{D00E7D25-0FA0-48EC-B048-CD60CE1B30D8}.Release|Any CPU.ActiveCfg = Release|Any CPU {D00E7D25-0FA0-48EC-B048-CD60CE1B30D8}.Release|Any CPU.ActiveCfg = Release|Any CPU

View File

@@ -725,7 +725,7 @@ namespace Semmle.Autobuild.CSharp.Tests
[Fact] [Fact]
public void TestWindowsCmdIgnoreErrors() public void TestWindowsCmdIgnoreErrors()
{ {
actions.RunProcess["cmd.exe /C ^\"build.cmd --skip-tests^\""] = 3; actions.RunProcess["cmd.exe /C ^\"build.cmd^ --skip-tests^\""] = 3;
actions.RunProcess[@"cmd.exe /C C:\codeql\tools\java\bin\java -jar C:\codeql\csharp\tools\extractor-asp.jar ."] = 0; actions.RunProcess[@"cmd.exe /C C:\codeql\tools\java\bin\java -jar C:\codeql\csharp\tools\extractor-asp.jar ."] = 0;
actions.RunProcess[@"cmd.exe /C C:\codeql\tools\codeql index --xml --extensions config"] = 0; actions.RunProcess[@"cmd.exe /C C:\codeql\tools\codeql index --xml --extensions config"] = 0;
actions.FileExists["csharp.log"] = true; actions.FileExists["csharp.log"] = true;
@@ -744,9 +744,9 @@ namespace Semmle.Autobuild.CSharp.Tests
public void TestWindowCSharpMsBuild() public void TestWindowCSharpMsBuild()
{ {
actions.RunProcess[@"cmd.exe /C C:\Project\.nuget\nuget.exe restore C:\Project\test1.sln -DisableParallelProcessing"] = 0; actions.RunProcess[@"cmd.exe /C C:\Project\.nuget\nuget.exe restore C:\Project\test1.sln -DisableParallelProcessing"] = 0;
actions.RunProcess["cmd.exe /C CALL ^\"C:\\Program Files ^(x86^)\\Microsoft Visual Studio 12.0\\VC\\vcvarsall.bat^\" && set Platform=&& type NUL && msbuild C:\\Project\\test1.sln /t:Windows /p:Platform=\"x86\" /p:Configuration=\"Debug\" /P:Fu=Bar"] = 0; actions.RunProcess["cmd.exe /C CALL ^\"C:\\Program^ Files^ ^(x86^)\\Microsoft^ Visual^ Studio^ 12.0\\VC\\vcvarsall.bat^\" && set Platform=&& type NUL && msbuild C:\\Project\\test1.sln /t:Windows /p:Platform=\"x86\" /p:Configuration=\"Debug\" /P:Fu=Bar"] = 0;
actions.RunProcess[@"cmd.exe /C C:\Project\.nuget\nuget.exe restore C:\Project\test2.sln -DisableParallelProcessing"] = 0; actions.RunProcess[@"cmd.exe /C C:\Project\.nuget\nuget.exe restore C:\Project\test2.sln -DisableParallelProcessing"] = 0;
actions.RunProcess["cmd.exe /C CALL ^\"C:\\Program Files ^(x86^)\\Microsoft Visual Studio 12.0\\VC\\vcvarsall.bat^\" && set Platform=&& type NUL && msbuild C:\\Project\\test2.sln /t:Windows /p:Platform=\"x86\" /p:Configuration=\"Debug\" /P:Fu=Bar"] = 0; actions.RunProcess["cmd.exe /C CALL ^\"C:\\Program^ Files^ ^(x86^)\\Microsoft^ Visual^ Studio^ 12.0\\VC\\vcvarsall.bat^\" && set Platform=&& type NUL && msbuild C:\\Project\\test2.sln /t:Windows /p:Platform=\"x86\" /p:Configuration=\"Debug\" /P:Fu=Bar"] = 0;
actions.FileExists["csharp.log"] = true; actions.FileExists["csharp.log"] = true;
actions.FileExists[@"C:\Program Files (x86)\Microsoft Visual Studio\Installer\vswhere.exe"] = false; actions.FileExists[@"C:\Program Files (x86)\Microsoft Visual Studio\Installer\vswhere.exe"] = false;
actions.FileExists[@"C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat"] = false; actions.FileExists[@"C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat"] = false;
@@ -775,9 +775,9 @@ namespace Semmle.Autobuild.CSharp.Tests
public void TestWindowCSharpMsBuildMultipleSolutions() public void TestWindowCSharpMsBuildMultipleSolutions()
{ {
actions.RunProcess[@"cmd.exe /C nuget restore C:\Project\test1.csproj -DisableParallelProcessing"] = 0; actions.RunProcess[@"cmd.exe /C nuget restore C:\Project\test1.csproj -DisableParallelProcessing"] = 0;
actions.RunProcess["cmd.exe /C CALL ^\"C:\\Program Files ^(x86^)\\Microsoft Visual Studio 12.0\\VC\\vcvarsall.bat^\" && set Platform=&& type NUL && msbuild C:\\Project\\test1.csproj /t:Windows /p:Platform=\"x86\" /p:Configuration=\"Debug\" /P:Fu=Bar"] = 0; actions.RunProcess["cmd.exe /C CALL ^\"C:\\Program^ Files^ ^(x86^)\\Microsoft^ Visual^ Studio^ 12.0\\VC\\vcvarsall.bat^\" && set Platform=&& type NUL && msbuild C:\\Project\\test1.csproj /t:Windows /p:Platform=\"x86\" /p:Configuration=\"Debug\" /P:Fu=Bar"] = 0;
actions.RunProcess[@"cmd.exe /C nuget restore C:\Project\test2.csproj -DisableParallelProcessing"] = 0; actions.RunProcess[@"cmd.exe /C nuget restore C:\Project\test2.csproj -DisableParallelProcessing"] = 0;
actions.RunProcess["cmd.exe /C CALL ^\"C:\\Program Files ^(x86^)\\Microsoft Visual Studio 12.0\\VC\\vcvarsall.bat^\" && set Platform=&& type NUL && msbuild C:\\Project\\test2.csproj /t:Windows /p:Platform=\"x86\" /p:Configuration=\"Debug\" /P:Fu=Bar"] = 0; actions.RunProcess["cmd.exe /C CALL ^\"C:\\Program^ Files^ ^(x86^)\\Microsoft^ Visual^ Studio^ 12.0\\VC\\vcvarsall.bat^\" && set Platform=&& type NUL && msbuild C:\\Project\\test2.csproj /t:Windows /p:Platform=\"x86\" /p:Configuration=\"Debug\" /P:Fu=Bar"] = 0;
actions.FileExists["csharp.log"] = true; actions.FileExists["csharp.log"] = true;
actions.FileExists[@"C:\Project\test1.csproj"] = true; actions.FileExists[@"C:\Project\test1.csproj"] = true;
actions.FileExists[@"C:\Project\test2.csproj"] = true; actions.FileExists[@"C:\Project\test2.csproj"] = true;
@@ -820,7 +820,7 @@ namespace Semmle.Autobuild.CSharp.Tests
public void TestWindowCSharpMsBuildFailed() public void TestWindowCSharpMsBuildFailed()
{ {
actions.RunProcess[@"cmd.exe /C nuget restore C:\Project\test1.sln -DisableParallelProcessing"] = 0; actions.RunProcess[@"cmd.exe /C nuget restore C:\Project\test1.sln -DisableParallelProcessing"] = 0;
actions.RunProcess["cmd.exe /C CALL ^\"C:\\Program Files ^(x86^)\\Microsoft Visual Studio 12.0\\VC\\vcvarsall.bat^\" && set Platform=&& type NUL && msbuild C:\\Project\\test1.sln /t:Windows /p:Platform=\"x86\" /p:Configuration=\"Debug\" /P:Fu=Bar"] = 1; actions.RunProcess["cmd.exe /C CALL ^\"C:\\Program^ Files^ ^(x86^)\\Microsoft^ Visual^ Studio^ 12.0\\VC\\vcvarsall.bat^\" && set Platform=&& type NUL && msbuild C:\\Project\\test1.sln /t:Windows /p:Platform=\"x86\" /p:Configuration=\"Debug\" /P:Fu=Bar"] = 1;
actions.FileExists["csharp.log"] = true; actions.FileExists["csharp.log"] = true;
actions.FileExists[@"C:\Program Files (x86)\Microsoft Visual Studio\Installer\vswhere.exe"] = false; actions.FileExists[@"C:\Program Files (x86)\Microsoft Visual Studio\Installer\vswhere.exe"] = false;
actions.FileExists[@"C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat"] = false; actions.FileExists[@"C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat"] = false;
@@ -846,8 +846,8 @@ namespace Semmle.Autobuild.CSharp.Tests
[Fact] [Fact]
public void TestSkipNugetMsBuild() public void TestSkipNugetMsBuild()
{ {
actions.RunProcess["cmd.exe /C CALL ^\"C:\\Program Files ^(x86^)\\Microsoft Visual Studio 12.0\\VC\\vcvarsall.bat^\" && set Platform=&& type NUL && msbuild C:\\Project\\test1.sln /t:Windows /p:Platform=\"x86\" /p:Configuration=\"Debug\" /P:Fu=Bar"] = 0; actions.RunProcess["cmd.exe /C CALL ^\"C:\\Program^ Files^ ^(x86^)\\Microsoft^ Visual^ Studio^ 12.0\\VC\\vcvarsall.bat^\" && set Platform=&& type NUL && msbuild C:\\Project\\test1.sln /t:Windows /p:Platform=\"x86\" /p:Configuration=\"Debug\" /P:Fu=Bar"] = 0;
actions.RunProcess["cmd.exe /C CALL ^\"C:\\Program Files ^(x86^)\\Microsoft Visual Studio 12.0\\VC\\vcvarsall.bat^\" && set Platform=&& type NUL && msbuild C:\\Project\\test2.sln /t:Windows /p:Platform=\"x86\" /p:Configuration=\"Debug\" /P:Fu=Bar"] = 0; actions.RunProcess["cmd.exe /C CALL ^\"C:\\Program^ Files^ ^(x86^)\\Microsoft^ Visual^ Studio^ 12.0\\VC\\vcvarsall.bat^\" && set Platform=&& type NUL && msbuild C:\\Project\\test2.sln /t:Windows /p:Platform=\"x86\" /p:Configuration=\"Debug\" /P:Fu=Bar"] = 0;
actions.FileExists["csharp.log"] = true; actions.FileExists["csharp.log"] = true;
actions.FileExists[@"C:\Program Files (x86)\Microsoft Visual Studio\Installer\vswhere.exe"] = false; actions.FileExists[@"C:\Program Files (x86)\Microsoft Visual Studio\Installer\vswhere.exe"] = false;
actions.FileExists[@"C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat"] = false; actions.FileExists[@"C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat"] = false;
@@ -1037,7 +1037,7 @@ namespace Semmle.Autobuild.CSharp.Tests
{ {
actions.RunProcess[@"cmd.exe /C nuget restore C:\Project\dirs.proj -DisableParallelProcessing"] = 1; actions.RunProcess[@"cmd.exe /C nuget restore C:\Project\dirs.proj -DisableParallelProcessing"] = 1;
actions.RunProcess[@"cmd.exe /C C:\Project\.nuget\nuget.exe restore C:\Project\dirs.proj -DisableParallelProcessing"] = 0; actions.RunProcess[@"cmd.exe /C C:\Project\.nuget\nuget.exe restore C:\Project\dirs.proj -DisableParallelProcessing"] = 0;
actions.RunProcess["cmd.exe /C CALL ^\"C:\\Program Files ^(x86^)\\Microsoft Visual Studio 12.0\\VC\\vcvarsall.bat^\" && set Platform=&& type NUL && msbuild C:\\Project\\dirs.proj /t:Windows /p:Platform=\"x86\" /p:Configuration=\"Debug\" /P:Fu=Bar"] = 0; actions.RunProcess["cmd.exe /C CALL ^\"C:\\Program^ Files^ ^(x86^)\\Microsoft^ Visual^ Studio^ 12.0\\VC\\vcvarsall.bat^\" && set Platform=&& type NUL && msbuild C:\\Project\\dirs.proj /t:Windows /p:Platform=\"x86\" /p:Configuration=\"Debug\" /P:Fu=Bar"] = 0;
actions.FileExists["csharp.log"] = true; actions.FileExists["csharp.log"] = true;
actions.FileExists[@"C:\Project\a\test.csproj"] = true; actions.FileExists[@"C:\Project\a\test.csproj"] = true;
actions.FileExists[@"C:\Project\dirs.proj"] = true; actions.FileExists[@"C:\Project\dirs.proj"] = true;

View File

@@ -55,7 +55,7 @@ namespace Semmle.Autobuild.Shared
} }
private static readonly char[] specialChars = { ' ', '\t', '\n', '\v', '\"' }; private static readonly char[] specialChars = { ' ', '\t', '\n', '\v', '\"' };
private static readonly char[] cmdMetacharacter = { '(', ')', '%', '!', '^', '\"', '<', '>', '&', '|' }; private static readonly char[] cmdMetacharacter = { '(', ')', '%', '!', '^', '\"', '<', '>', '&', '|', ' ' };
/// <summary> /// <summary>
/// Appends the given argument to the command line. /// Appends the given argument to the command line.

View File

@@ -1,4 +1,6 @@
name: "csharp" name: "csharp"
aliases:
- "c#"
display_name: "C#" display_name: "C#"
version: 1.22.1 version: 1.22.1
column_kind: "utf16" column_kind: "utf16"

View File

@@ -1,13 +1,12 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq;
using System.IO;
using System.Reflection.PortableExecutable;
using System.Reflection.Metadata;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Globalization; using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Reflection.Metadata;
using System.Reflection.PortableExecutable;
using System.Runtime.InteropServices;
using Semmle.Util; using Semmle.Util;
using Semmle.Util.Logging;
namespace Semmle.Extraction.CIL.Driver namespace Semmle.Extraction.CIL.Driver
{ {

View File

@@ -1,8 +1,8 @@
using System; using System;
using System.Diagnostics;
using System.Linq; using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using Semmle.Util.Logging; using Semmle.Util.Logging;
using System.Diagnostics;
namespace Semmle.Extraction.CIL.Driver namespace Semmle.Extraction.CIL.Driver
{ {

View File

@@ -1,6 +1,6 @@
using Semmle.Util.Logging;
using System; using System;
using Semmle.Util; using Semmle.Util;
using Semmle.Util.Logging;
using Semmle.Extraction.CIL.Entities; using Semmle.Extraction.CIL.Entities;
namespace Semmle.Extraction.CIL namespace Semmle.Extraction.CIL

View File

@@ -1,8 +1,7 @@
using Semmle.Extraction.CIL.Entities; using System;
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO;
using System.Reflection.Metadata; using System.Reflection.Metadata;
using Semmle.Extraction.CIL.Entities;
namespace Semmle.Extraction.CIL namespace Semmle.Extraction.CIL
{ {

View File

@@ -1,8 +1,7 @@
using System.Reflection; using System.Collections.Generic;
using System.Globalization; using System.Globalization;
using System.Collections.Generic; using System.Reflection;
using Semmle.Extraction.Entities; using Semmle.Extraction.Entities;
using System.IO;
namespace Semmle.Extraction.CIL.Entities namespace Semmle.Extraction.CIL.Entities
{ {

View File

@@ -1,5 +1,4 @@
using System; using System.Collections.Generic;
using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Reflection.Metadata; using System.Reflection.Metadata;

View File

@@ -1,6 +1,5 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO;
namespace Semmle.Extraction.CIL namespace Semmle.Extraction.CIL
{ {

View File

@@ -1,7 +1,7 @@
using System; using System;
using System.Linq;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.Linq;
using Semmle.Util; using Semmle.Util;
namespace Semmle.Extraction.CIL.Entities namespace Semmle.Extraction.CIL.Entities

View File

@@ -1,7 +1,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Reflection.Metadata;
using System.Reflection; using System.Reflection;
using System.Reflection.Metadata;
using System.Reflection.Metadata.Ecma335; using System.Reflection.Metadata.Ecma335;
namespace Semmle.Extraction.CIL.Entities namespace Semmle.Extraction.CIL.Entities

View File

@@ -1,7 +1,7 @@
using System.Reflection.Metadata;
using System.Collections.Generic; using System.Collections.Generic;
using System.Reflection;
using System.Linq; using System.Linq;
using System.Reflection;
using System.Reflection.Metadata;
using System.Reflection.Metadata.Ecma335; using System.Reflection.Metadata.Ecma335;
namespace Semmle.Extraction.CIL.Entities namespace Semmle.Extraction.CIL.Entities

View File

@@ -1,5 +1,4 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.IO;
using System.Reflection.Metadata; using System.Reflection.Metadata;
namespace Semmle.Extraction.CIL.Entities namespace Semmle.Extraction.CIL.Entities

View File

@@ -1,5 +1,4 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.IO;
namespace Semmle.Extraction.CIL.Entities namespace Semmle.Extraction.CIL.Entities
{ {

View File

@@ -1,5 +1,4 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.IO;
namespace Semmle.Extraction.CIL.Entities namespace Semmle.Extraction.CIL.Entities
{ {

View File

@@ -1,5 +1,3 @@
using System.IO;
namespace Semmle.Extraction.CIL.Entities namespace Semmle.Extraction.CIL.Entities
{ {
internal interface ITypeSignature internal interface ITypeSignature

View File

@@ -1,5 +1,4 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.IO;
namespace Semmle.Extraction.CIL.Entities namespace Semmle.Extraction.CIL.Entities
{ {

View File

@@ -1,6 +1,6 @@
using System.Reflection.Metadata;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Reflection.Metadata;
namespace Semmle.Extraction.CIL.Entities namespace Semmle.Extraction.CIL.Entities
{ {

View File

@@ -1,8 +1,7 @@
using System; using System;
using System.Reflection.Metadata;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.IO; using System.Reflection.Metadata;
namespace Semmle.Extraction.CIL.Entities namespace Semmle.Extraction.CIL.Entities
{ {

View File

@@ -1,9 +1,8 @@
using System; using System;
using System.Collections.Immutable;
using System.Reflection.Metadata;
using System.Collections.Generic; using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq; using System.Linq;
using System.IO; using System.Reflection.Metadata;
using Semmle.Util; using Semmle.Util;
namespace Semmle.Extraction.CIL.Entities namespace Semmle.Extraction.CIL.Entities

View File

@@ -1,6 +1,5 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO;
namespace Semmle.Extraction.CIL.Entities namespace Semmle.Extraction.CIL.Entities
{ {

View File

@@ -1,5 +1,4 @@
using System.Linq; using System.Linq;
using System.IO;
namespace Semmle.Extraction.CIL.Entities namespace Semmle.Extraction.CIL.Entities
{ {

View File

@@ -1,6 +1,5 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO;
namespace Semmle.Extraction.CIL.Entities namespace Semmle.Extraction.CIL.Entities
{ {

View File

@@ -1,4 +1,3 @@
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using Semmle.Util; using Semmle.Util;

View File

@@ -1,5 +1,4 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.IO;
namespace Semmle.Extraction.CIL.Entities namespace Semmle.Extraction.CIL.Entities
{ {

View File

@@ -1,7 +1,7 @@
using System; using System;
using System.Reflection.Metadata;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.Reflection.Metadata;
namespace Semmle.Extraction.CIL.Entities namespace Semmle.Extraction.CIL.Entities
{ {

View File

@@ -1,7 +1,6 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Reflection.Metadata; using System.Reflection.Metadata;
using System.Reflection.Metadata.Ecma335; using System.Reflection.Metadata.Ecma335;
using System.IO;
namespace Semmle.Extraction.CIL.Entities namespace Semmle.Extraction.CIL.Entities
{ {

View File

@@ -1,6 +1,5 @@
using System.Reflection.Metadata;
using System.Collections.Immutable; using System.Collections.Immutable;
using System.IO; using System.Reflection.Metadata;
namespace Semmle.Extraction.CIL.Entities namespace Semmle.Extraction.CIL.Entities
{ {

View File

@@ -1,5 +1,4 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.IO;
using Semmle.Extraction.PDB; using Semmle.Extraction.PDB;
namespace Semmle.Extraction.CIL.Entities namespace Semmle.Extraction.CIL.Entities

View File

@@ -1,8 +1,8 @@
using System.Reflection.Metadata; using System.Collections.Generic;
using System.Collections.Generic;
using System.IO;
using System.Diagnostics.CodeAnalysis; using System.Diagnostics.CodeAnalysis;
using System.IO;
using System.Linq; using System.Linq;
using System.Reflection.Metadata;
namespace Semmle.Extraction.CIL.Entities namespace Semmle.Extraction.CIL.Entities
{ {

View File

@@ -1,5 +1,4 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.IO;
namespace Semmle.Extraction.CIL.Entities namespace Semmle.Extraction.CIL.Entities
{ {

View File

@@ -1,10 +1,10 @@
using System; using System;
using System.Linq;
using System.Collections.Generic; using System.Collections.Generic;
using System.Reflection;
using System.IO; using System.IO;
using System.Reflection.Metadata.Ecma335; using System.Linq;
using System.Reflection;
using System.Reflection.Metadata; using System.Reflection.Metadata;
using System.Reflection.Metadata.Ecma335;
namespace Semmle.Extraction.CIL.Entities namespace Semmle.Extraction.CIL.Entities
{ {

View File

@@ -1,9 +1,9 @@
using System; using System;
using System.Reflection.Metadata;
using System.Linq;
using System.Collections.Generic; using System.Collections.Generic;
using System.Reflection;
using System.IO; using System.IO;
using System.Linq;
using System.Reflection;
using System.Reflection.Metadata;
namespace Semmle.Extraction.CIL.Entities namespace Semmle.Extraction.CIL.Entities
{ {

View File

@@ -1,8 +1,8 @@
using System; using System;
using System.Reflection.Metadata;
using System.Linq;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.Linq;
using System.Reflection.Metadata;
namespace Semmle.Extraction.CIL.Entities namespace Semmle.Extraction.CIL.Entities
{ {

View File

@@ -1,7 +1,7 @@
using System; using System;
using System.Reflection.Metadata;
using System.Collections.Immutable; using System.Collections.Immutable;
using System.Linq; using System.Linq;
using System.Reflection.Metadata;
namespace Semmle.Extraction.CIL.Entities namespace Semmle.Extraction.CIL.Entities
{ {

View File

@@ -1,6 +1,5 @@
using System.Linq;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.Linq;
namespace Semmle.Extraction.CIL.Entities namespace Semmle.Extraction.CIL.Entities
{ {

View File

@@ -1,6 +1,6 @@
using System; using System;
using Microsoft.DiaSymReader;
using System.Reflection; using System.Reflection;
using Microsoft.DiaSymReader;
#pragma warning disable IDE0060, CA1822 #pragma warning disable IDE0060, CA1822

Some files were not shown because too many files have changed in this diff Show More