Compare commits

..

84 Commits

Author SHA1 Message Date
Mathias Vorreiter Pedersen
9ddacf55a5 C++/C#: Sync identical files. 2022-08-29 12:21:02 +01:00
Mathias Vorreiter Pedersen
ba1005f875 C#: Fix Code Scanning alert. 2022-08-29 12:21:01 +01:00
Mathias Vorreiter Pedersen
99b21b3d79 C++: Accept test changes. 2022-08-29 12:21:01 +01:00
Mathias Vorreiter Pedersen
5b51fcbd3d C++: Suppress Code Scanning warning. 2022-08-26 09:07:08 +01:00
Mathias Vorreiter Pedersen
e13ae70eeb C++: Autoformat. 2022-08-26 09:06:38 +01:00
Mathias Vorreiter Pedersen
9f17bd0d89 C++: Accept test changes. 2022-08-25 15:51:10 +01:00
Mathias Vorreiter Pedersen
86bb9c38ce C#: Sync identical files. 2022-08-25 15:47:21 +01:00
Mathias Vorreiter Pedersen
dc105b404b C++: Only GVN side-effect-free functions. This improves the performance dramatically. 2022-08-25 15:46:41 +01:00
Mathias Vorreiter Pedersen
fac28ccbe0 Merge branch 'main' into rdmarsh2/cpp/gvn-functions 2022-08-25 15:43:12 +01:00
Erik Krogh Kristensen
06afe9c0f4 Merge pull request #9816 from erik-krogh/msgConsis
Make alert messages consistent across languages
2022-08-25 15:20:01 +02:00
Ian Lynagh
2e2621adad Merge pull request #10154 from igfoo/igfoo/findSubType
Kotlin: Implement and use fun <T,reified S: T> Iterable<T>.findSubType
2022-08-25 12:57:46 +01:00
Erik Krogh Kristensen
ba1ad00d2a Merge pull request #10062 from erik-krogh/redosPrefix
JS: use the shared regular expression libraries in `js/case-sensitive-middleware-path`
2022-08-25 12:57:16 +02:00
erik-krogh
c7aa58252a change "does not seem to check" to "does not check" in unchecked-cast-in-equals queries 2022-08-25 12:31:58 +02:00
Ian Lynagh
12eab3d7f0 Kotlin: Specialise findSubType to IrDeclaration
We only use it on that type, and this makes the uses a bit quieter.
2022-08-25 10:11:19 +01:00
erik-krogh
014dcd1454 fixup a Python query, it didn't select something with a location 2022-08-24 16:23:20 +02:00
erik-krogh
5d9b25c75d Merge branch 'main' into msgConsis 2022-08-24 16:19:32 +02:00
erik-krogh
1c0f2251e2 Merge branch 'main' into msgConsis 2022-08-24 14:38:57 +02:00
Ian Lynagh
4cd90a15d0 Kotlin: Use findSubType in KotlinUsesExtractor too 2022-08-24 12:16:16 +01:00
Ian Lynagh
28d95f4d99 Kotlin: Implement and use fun <T,reified S: T> Iterable<T>.findSubType
We had a lot of uses of find which looked for a subtype, but then had to
cast (seemingly unsafely) the result to that subtype. This pulls all the
casts out into a utility function.
2022-08-24 12:10:53 +01:00
erik-krogh
f1799ae3d2 print the endpointExample in the alert-messsage, and only report one working example 2022-08-24 13:09:48 +02:00
erik-krogh
27fcc90a97 Merge branch 'main' into msgConsis 2022-08-24 09:21:43 +02:00
erik-krogh
a50234adb0 apply suggestion from review 2022-08-23 15:41:37 +02:00
erik-krogh
5e3cb08ed2 rename stateInPumpableRegexp to stateInRelevantRegexp 2022-08-23 12:40:45 +02:00
erik-krogh
1a7d3ee831 update expected output after changing queries 2022-08-23 12:35:32 +02:00
erik-krogh
afadcd9b45 use a more detailed alert message in bitwise-sign-check 2022-08-23 11:18:45 +02:00
erik-krogh
d96d6721ba change the alert message of unused-local-variable 2022-08-23 11:15:11 +02:00
erik-krogh
de8384d904 revert alert message change to java/unused-local-variable 2022-08-23 11:14:58 +02:00
erik-krogh
305a23b952 apply suggestion from review 2022-08-23 11:05:32 +02:00
erik-krogh
f7846a598e add change-notes 2022-08-23 07:54:01 +02:00
erik-krogh
7e0bd5bde4 update expected output of tests 2022-08-22 21:41:47 +02:00
erik-krogh
df9a9f4a56 update rb/stored-css to match javascript 2022-08-22 21:41:47 +02:00
erik-krogh
9b257bfa9e update rb/reflected-xss to match javascript 2022-08-22 21:41:47 +02:00
erik-krogh
ca299b9dc1 update py/unreachable-statement to match javascript/go 2022-08-22 21:41:47 +02:00
erik-krogh
31e15e27fc update py/unsafe-deserialization to match ruby/javascript/java 2022-08-22 21:41:47 +02:00
erik-krogh
778879908e update rb/code-injection to match python 2022-08-22 21:41:46 +02:00
erik-krogh
60908de089 update js/nested-loops-with-same-variable to match cpp 2022-08-22 21:41:46 +02:00
erik-krogh
20625ae60d update {js/go/py}/xpath-injection to match csharp/java 2022-08-22 21:41:46 +02:00
erik-krogh
b5458b2125 update js/insecure-randomness to match csharp 2022-08-22 21:41:46 +02:00
erik-krogh
9cdd8cc8f5 update js/tainted-format-string to match ruby/java 2022-08-22 21:41:46 +02:00
erik-krogh
9395f156de update {js/py}/command-line-injection to match csharp/java 2022-08-22 21:41:46 +02:00
erik-krogh
684a987abf update java/unused-import to match python 2022-08-22 21:41:46 +02:00
erik-krogh
54268f4424 update java/static-array to match csharp 2022-08-22 21:41:46 +02:00
erik-krogh
8899c1be04 update java/unassigned-field to match csharp 2022-08-22 21:41:46 +02:00
erik-krogh
280b101caa update java/useless-assignment-to-local to match go 2022-08-22 21:41:46 +02:00
erik-krogh
034d197e01 update {java/rb}/xxe to match python/javascript 2022-08-22 21:41:46 +02:00
erik-krogh
2d0a4c3d83 update {go/py}/stack-trace-exposure to match javascript 2022-08-22 21:41:46 +02:00
erik-krogh
5a0183f1e2 update java/password-in-configuration to match csharp 2022-08-22 21:41:46 +02:00
erik-krogh
151529d08f correct the query-id of the experimental go/pam-auth-bypass query 2022-08-22 21:41:46 +02:00
erik-krogh
b5f3cd7a55 update cs/useless-tostring-call to match java 2022-08-22 21:41:46 +02:00
erik-krogh
49a3e208d7 update cs/index-out-of-bounds to match javascript/go 2022-08-22 21:41:46 +02:00
erik-krogh
52171d6733 update cs/unchecked-cast-in-equals to match java 2022-08-22 21:41:46 +02:00
erik-krogh
ea11f744e1 update cs/confusing-override-name to match java 2022-08-22 21:41:46 +02:00
erik-krogh
064c9a6938 update {cs/java}/todo-comment to match javascript 2022-08-22 21:41:46 +02:00
erik-krogh
678e433013 update cpp/missing-case-in-switch to match java 2022-08-22 21:41:45 +02:00
erik-krogh
ea2777fa3e update {cs/cpp}/equality-on-floats to use the same alert-message/description 2022-08-22 21:41:45 +02:00
erik-krogh
55c8863e92 update java/sql-injection to match go/javascript/python/ruby 2022-08-22 21:41:45 +02:00
erik-krogh
3553f3d9b8 update {rb/py/js/go}/path-injection to match java/csharp 2022-08-22 21:41:45 +02:00
erik-krogh
39c1832995 update {cpp/js}/bitwise-sign-check to match java 2022-08-22 21:41:45 +02:00
erik-krogh
cc41a83a8d update {py/cpp}/commented-out-code to match csharp/java/javascript 2022-08-22 21:41:45 +02:00
erik-krogh
b471a401cc update {rb/js/java}/unused-parameter to match python 2022-08-22 21:41:45 +02:00
erik-krogh
698ccd8850 update {cpp/java}/unused-local to match python 2022-08-22 21:41:45 +02:00
erik-krogh
5a312cd0da update cpp/complex-block to match java/csharp 2022-08-22 21:41:45 +02:00
erik-krogh
b1c9843d15 update {cs/cpp}/empty-block so they have the same alert message 2022-08-22 21:41:45 +02:00
erik-krogh
594fbc678e update js/zip-slip to match java/go/csharp 2022-08-22 21:41:45 +02:00
erik-krogh
e52fa9a469 update {cs/java}/regex-injection to match javascript 2022-08-22 21:41:45 +02:00
erik-krogh
049af68bc2 restrict suffix-construction to relevant regexps 2022-08-21 20:35:39 +02:00
erik-krogh
0aebc90b61 don't lowercase the endpointExample, and correctly handle root states 2022-08-21 18:38:47 +02:00
erik-krogh
bcf4c57060 Merge branch 'main' into redosPrefix 2022-08-19 19:22:49 +02:00
erik-krogh
d052b1e3c9 also support regular expressions without repetitions 2022-08-19 19:21:44 +02:00
erik-krogh
26fcf6b25b apply suggestions from review 2022-08-18 15:00:57 +02:00
erik-krogh
de3e1c39e4 use the shared regular expression libraries in js/case-sensitive-middleware-path 2022-08-18 10:07:55 +02:00
erik-krogh
473bc92e2d move the PrefixConstruction module out of the ReDoSPruning module 2022-08-18 10:07:48 +02:00
Robert Marsh
af2c96f344 Merge branch 'main' into rdmarsh2/cpp/gvn-functions 2022-08-12 12:39:37 -04:00
Robert Marsh
7c4d3800b6 C++: change note for function call GVNs 2022-08-01 13:32:12 -04:00
Robert Marsh
5c11062d21 C++/C#: sync GVN files 2022-08-01 13:26:04 -04:00
Robert Marsh
83af49c72f C++: respond to PR comments 2022-08-01 12:59:23 -04:00
Robert Marsh
e0cfbb53dc C++: add missing SideEffectElimination.qll 2022-08-01 09:52:46 -04:00
Robert Marsh
844aabe3d6 C++/C#: fix join order in GVN 2022-07-29 14:51:09 -04:00
Robert Marsh
c09c38c9a8 C++/C#: sync for IR side effect removal 2022-07-29 12:08:52 -04:00
Robert Marsh
d324969d68 C++: remove some side-effect instructions
This leverages the existing alias analysis to identify functions which
have no reads or writes of the AllAliasedMemory virtual variable, and
therefore have no global side effects. A recursion over the call graph
identifies functions which have no indirect global side effects, and
calls to those functions have their global side effect instructions
removed.
2022-07-29 10:38:25 -04:00
Robert Marsh
4ae218729a C++/C#: Sync identical files 2022-07-25 15:21:39 -04:00
Robert Marsh
cc8e65f811 C++: include aliased memory in function call GVNs 2022-07-25 14:55:20 -04:00
Robert Marsh
76b292da6a C++: initial GVN for function calls 2022-07-25 14:26:54 -04:00
Robert Marsh
0b691dd46c C++: function tests for GVN 2022-07-25 14:24:41 -04:00
324 changed files with 3637 additions and 3839 deletions

View File

@@ -1,21 +1,3 @@
## 0.3.5
## 0.3.4
### Deprecated APIs
* Many classes/predicates/modules with upper-case acronyms in their name have been renamed to follow our style-guide.
The old name still exists as a deprecated alias.
### New Features
* Added support for getting the link targets of global and namespace variables.
* Added a `BlockAssignExpr` class, which models a `memcpy`-like operation used in compiler generated copy/move constructors and assignment operations.
### Minor Analysis Improvements
* All deprecated predicates/classes/modules that have been deprecated for over a year have been deleted.
## 0.3.3 ## 0.3.3
### New Features ### New Features

View File

@@ -0,0 +1,4 @@
---
category: minorAnalysis
---
* Multiple function calls made in the same function may now receive the same global value number when the analysis can show they produce the same results.

View File

@@ -0,0 +1,4 @@
---
category: feature
---
* Added a `BlockAssignExpr` class, which models a `memcpy`-like operation used in compiler generated copy/move constructors and assignment operations.

View File

@@ -0,0 +1,6 @@
---
category: minorAnalysis
---
* All deprecated predicates/classes/modules that have been deprecated for over a year have been
deleted.

View File

@@ -0,0 +1,4 @@
---
category: feature
---
* Added support for getting the link targets of global and namespace variables.

View File

@@ -0,0 +1,5 @@
---
category: deprecated
---
* Many classes/predicates/modules with upper-case acronyms in their name have been renamed to follow our style-guide.
The old name still exists as a deprecated alias.

View File

@@ -1,15 +0,0 @@
## 0.3.4
### Deprecated APIs
* Many classes/predicates/modules with upper-case acronyms in their name have been renamed to follow our style-guide.
The old name still exists as a deprecated alias.
### New Features
* Added support for getting the link targets of global and namespace variables.
* Added a `BlockAssignExpr` class, which models a `memcpy`-like operation used in compiler generated copy/move constructors and assignment operations.
### Minor Analysis Improvements
* All deprecated predicates/classes/modules that have been deprecated for over a year have been deleted.

View File

@@ -1 +0,0 @@
## 0.3.5

View File

@@ -1,2 +1,2 @@
--- ---
lastReleaseVersion: 0.3.5 lastReleaseVersion: 0.3.3

View File

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

View File

@@ -1712,6 +1712,11 @@ class SideEffectInstruction extends Instruction {
*/ */
class CallSideEffectInstruction extends SideEffectInstruction { class CallSideEffectInstruction extends SideEffectInstruction {
CallSideEffectInstruction() { this.getOpcode() instanceof Opcode::CallSideEffect } CallSideEffectInstruction() { this.getOpcode() instanceof Opcode::CallSideEffect }
/** Gets the operand for the value that will be read by this instruction */
final SideEffectOperand getSideEffectOperand() { result = this.getAnOperand() }
final Instruction getSideEffect() { result = this.getAnOperand().getDef() }
} }
/** /**
@@ -1723,6 +1728,11 @@ class CallSideEffectInstruction extends SideEffectInstruction {
*/ */
class CallReadSideEffectInstruction extends SideEffectInstruction { class CallReadSideEffectInstruction extends SideEffectInstruction {
CallReadSideEffectInstruction() { this.getOpcode() instanceof Opcode::CallReadSideEffect } CallReadSideEffectInstruction() { this.getOpcode() instanceof Opcode::CallReadSideEffect }
/** Gets the operand for the value that will be read by this instruction */
final SideEffectOperand getSideEffectOperand() { result = this.getAnOperand() }
final Instruction getSideEffect() { result = this.getAnOperand().getDef() }
} }
/** /**

View File

@@ -1,3 +1,4 @@
import semmle.code.cpp.ir.implementation.aliased_ssa.IR import semmle.code.cpp.ir.implementation.aliased_ssa.IR
import semmle.code.cpp.ir.internal.Overlap import semmle.code.cpp.ir.internal.Overlap
import semmle.code.cpp.ir.internal.IRCppLanguage as Language import semmle.code.cpp.ir.internal.IRCppLanguage as Language
import semmle.code.cpp.models.interfaces.SideEffect as SideEffect

View File

@@ -41,8 +41,92 @@ newtype TValueNumber =
) { ) {
loadTotalOverlapValueNumber(_, irFunc, type, memOperand, operand) loadTotalOverlapValueNumber(_, irFunc, type, memOperand, operand)
} or } or
TCallValueNumber(TCallPartialValueNumber vn) { callValueNumber(_, _, vn) } or
TUniqueValueNumber(IRFunction irFunc, Instruction instr) { uniqueValueNumber(instr, irFunc) } TUniqueValueNumber(IRFunction irFunc, Instruction instr) { uniqueValueNumber(instr, irFunc) }
private class NumberableCallInstruction extends CallInstruction {
NumberableCallInstruction() {
not this.getResultIRType() instanceof IRVoidType and
exists(SideEffect::SideEffectFunction sideEffectFunc |
sideEffectFunc = this.getStaticCallTarget()
|
sideEffectFunc.hasOnlySpecificReadSideEffects() and
sideEffectFunc.hasOnlySpecificWriteSideEffects()
)
}
}
private newtype TCallPartialValueNumber =
TNilArgument() or
TArgument(TCallPartialValueNumber head, TValueNumber arg) {
exists(NumberableCallInstruction call, int index |
callArgValueNumber(call, index, arg) and
callPartialValueNumber(call, index, head)
)
}
private predicate callValueNumber(
NumberableCallInstruction call, int index, TCallPartialValueNumber vn
) {
index = max(int n | callArgRank(call, n, _) | n) and
exists(TCallPartialValueNumber head, TValueNumber arg |
callPartialValueNumber(call, index, pragma[only_bind_out](head)) and
callArgValueNumber(call, index, pragma[only_bind_into](arg)) and
vn = TArgument(head, arg)
)
or
not exists(int n | callArgRank(call, n, _)) and
index = -1 and
vn = TNilArgument()
}
private predicate callPartialValueNumber(
NumberableCallInstruction call, int index, TCallPartialValueNumber head
) {
exists(call) and
index = 1 and
head = TNilArgument()
or
exists(TCallPartialValueNumber prev, TValueNumber prevVN |
callPartialValueNumber(call, index - 1, pragma[only_bind_out](prev)) and
callArgValueNumber(call, index - 1, pragma[only_bind_into](prevVN)) and
head = TArgument(prev, prevVN)
)
}
/**
*/
private predicate callArgValueNumber(NumberableCallInstruction call, int index, TValueNumber arg) {
exists(Instruction instr |
callArgRank(call, index, instr) and
arg = tvalueNumber(instr)
)
}
/**
* Holds if `arg` is the `index`th element in `call`'s extended argument list, including the `this`
* argument and side-effect reads.
*/
private predicate callArgRank(NumberableCallInstruction call, int index, Instruction arg) {
arg =
rank[index](int argIndex, boolean isEffect, Instruction instr |
// There is no need to include the call's read and write side effects on
// all-aliased-memory as `NumberableCallInstruction`s do not read or write
// to all-aliased-memory.
instr = call.getArgument(argIndex) and
isEffect = false
or
exists(ReadSideEffectInstruction read |
read.getPrimaryInstruction() = call and
read.getSideEffectOperand().getAnyDef() = instr and
read.getIndex() = argIndex and
isEffect = true
)
|
instr order by argIndex, isEffect
)
}
/** /**
* A `CopyInstruction` whose source operand's value is congruent to the definition of that source * A `CopyInstruction` whose source operand's value is congruent to the definition of that source
* operand. * operand.
@@ -93,6 +177,8 @@ private predicate numberableInstruction(Instruction instr) {
instr instanceof CongruentCopyInstruction instr instanceof CongruentCopyInstruction
or or
instr instanceof LoadTotalOverlapInstruction instr instanceof LoadTotalOverlapInstruction
or
instr instanceof NumberableCallInstruction
} }
private predicate filteredNumberableInstruction(Instruction instr) { private predicate filteredNumberableInstruction(Instruction instr) {
@@ -309,6 +395,11 @@ private TValueNumber nonUniqueValueNumber(Instruction instr) {
or or
// The value number of a copy is just the value number of its source value. // The value number of a copy is just the value number of its source value.
result = tvalueNumber(instr.(CongruentCopyInstruction).getSourceValue()) result = tvalueNumber(instr.(CongruentCopyInstruction).getSourceValue())
or
exists(TCallPartialValueNumber pvn |
callValueNumber(instr, _, pvn) and
result = TCallValueNumber(pvn)
)
) )
) )
} }

View File

@@ -8,11 +8,6 @@ private import Imports::RawIR as RawIR
private import SsaInstructions private import SsaInstructions
private import SsaOperands private import SsaOperands
private import NewIR private import NewIR
private class OldBlock = Reachability::ReachableBlock;
private class OldInstruction = Reachability::ReachableInstruction;
import Cached import Cached
cached cached
@@ -58,7 +53,9 @@ private module Cached {
cached cached
predicate hasInstruction(TStageInstruction instr) { predicate hasInstruction(TStageInstruction instr) {
instr instanceof TRawInstruction and instr instanceof OldInstruction instr instanceof TRawInstruction and
instr instanceof OldInstruction and
not removedInstruction(instr)
or or
instr = phiInstruction(_, _) instr = phiInstruction(_, _)
or or
@@ -382,7 +379,14 @@ private module Cached {
( (
if Reachability::isInfeasibleInstructionSuccessor(oldInstruction, kind) if Reachability::isInfeasibleInstructionSuccessor(oldInstruction, kind)
then result = unreachedInstruction(instruction.getEnclosingIRFunction()) then result = unreachedInstruction(instruction.getEnclosingIRFunction())
else result = getNewInstruction(oldInstruction.getSuccessor(kind)) else
if removedInstruction(oldInstruction.getSuccessor(kind))
then
// the only removed nodes are side-effect writes, but those may have Chi nodes
// skip to the following instruction in the old IR, which won't be removed
// if we start skipping specific side effects, this may no longer hold
result = getNewInstruction(oldInstruction.getSuccessor(kind).getSuccessor(kind))
else result = getNewInstruction(oldInstruction.getSuccessor(kind))
) )
) )
or or

View File

@@ -13,3 +13,15 @@ import semmle.code.cpp.ir.implementation.internal.TOperand::AliasedSsaOperands a
/** DEPRECATED: Alias for SsaOperands */ /** DEPRECATED: Alias for SsaOperands */
deprecated module SSAOperands = SsaOperands; deprecated module SSAOperands = SsaOperands;
private import SideEffectElimination as Elim
predicate removedInstruction(Reachability::ReachableInstruction instr) {
Elim::removeableSideEffect(instr)
}
class OldBlock = Reachability::ReachableBlock;
class OldInstruction extends Reachability::ReachableInstruction {
OldInstruction() { not Elim::removeableSideEffect(this) }
}

View File

@@ -0,0 +1,42 @@
import cpp as CPP
import semmle.code.cpp.ir.implementation.unaliased_ssa.IR as Unaliased
import AliasAnalysis as Alias
import AliasConfiguration as Conf
import semmle.code.cpp.models.interfaces.SideEffect as SideEffect
private predicate noLocalSideEffectWrite(CPP::Function func) {
forall(Unaliased::AddressOperand addr | addr.getUse().getEnclosingFunction() = func |
not (
Alias::getAddressOperandAllocation(addr) instanceof Conf::VariableAllocation and
Alias::getAddressOperandAllocation(addr).(Conf::VariableAllocation).alwaysEscapes()
)
)
}
language[monotonicAggregates]
private predicate noTransitiveSideEffectWrite(CPP::Function func) {
exists(Unaliased::IRFunction irFunc | irFunc.getFunction() = func) and
noLocalSideEffectWrite(func) and
forall(Unaliased::CallInstruction call | call.getEnclosingFunction() = func |
exists(call.getStaticCallTarget())
) and
forall(Unaliased::CallInstruction call, CPP::Function callee |
call.getStaticCallTarget() = callee and
call.getEnclosingFunction() = func
|
noTransitiveSideEffectWrite(callee)
or
callee.(SideEffect::SideEffectFunction).hasOnlySpecificWriteSideEffects()
)
}
predicate removeableSideEffect(Unaliased::SideEffectInstruction instr) {
(
instr instanceof Unaliased::CallSideEffectInstruction or
instr instanceof Unaliased::CallReadSideEffectInstruction
) and
noTransitiveSideEffectWrite(instr
.getPrimaryInstruction()
.(Unaliased::CallInstruction)
.getStaticCallTarget())
}

View File

@@ -34,6 +34,7 @@ newtype TInstruction =
AliasedSsa::SSA::hasPhiInstruction(blockStartInstr, memoryLocation) AliasedSsa::SSA::hasPhiInstruction(blockStartInstr, memoryLocation)
} or } or
TAliasedSsaChiInstruction(TRawInstruction primaryInstruction) { TAliasedSsaChiInstruction(TRawInstruction primaryInstruction) {
not AliasedSsa::removedInstruction(primaryInstruction) and
AliasedSsa::SSA::hasChiInstruction(primaryInstruction) AliasedSsa::SSA::hasChiInstruction(primaryInstruction)
} or } or
TAliasedSsaUnreachedInstruction(IRFunctionBase irFunc) { TAliasedSsaUnreachedInstruction(IRFunctionBase irFunc) {

View File

@@ -5,3 +5,5 @@ import semmle.code.cpp.ir.implementation.aliased_ssa.internal.SSAConstruction as
/** DEPRECATED: Alias for AliasedSsa */ /** DEPRECATED: Alias for AliasedSsa */
deprecated module AliasedSSA = AliasedSsa; deprecated module AliasedSSA = AliasedSsa;
import semmle.code.cpp.ir.implementation.aliased_ssa.internal.SideEffectElimination as Elim

View File

@@ -1712,6 +1712,11 @@ class SideEffectInstruction extends Instruction {
*/ */
class CallSideEffectInstruction extends SideEffectInstruction { class CallSideEffectInstruction extends SideEffectInstruction {
CallSideEffectInstruction() { this.getOpcode() instanceof Opcode::CallSideEffect } CallSideEffectInstruction() { this.getOpcode() instanceof Opcode::CallSideEffect }
/** Gets the operand for the value that will be read by this instruction */
final SideEffectOperand getSideEffectOperand() { result = this.getAnOperand() }
final Instruction getSideEffect() { result = this.getAnOperand().getDef() }
} }
/** /**
@@ -1723,6 +1728,11 @@ class CallSideEffectInstruction extends SideEffectInstruction {
*/ */
class CallReadSideEffectInstruction extends SideEffectInstruction { class CallReadSideEffectInstruction extends SideEffectInstruction {
CallReadSideEffectInstruction() { this.getOpcode() instanceof Opcode::CallReadSideEffect } CallReadSideEffectInstruction() { this.getOpcode() instanceof Opcode::CallReadSideEffect }
/** Gets the operand for the value that will be read by this instruction */
final SideEffectOperand getSideEffectOperand() { result = this.getAnOperand() }
final Instruction getSideEffect() { result = this.getAnOperand().getDef() }
} }
/** /**

View File

@@ -1,3 +1,4 @@
import semmle.code.cpp.ir.implementation.aliased_ssa.IR import semmle.code.cpp.ir.implementation.aliased_ssa.IR
import semmle.code.cpp.ir.internal.Overlap import semmle.code.cpp.ir.internal.Overlap
import semmle.code.cpp.ir.internal.IRCppLanguage as Language import semmle.code.cpp.ir.internal.IRCppLanguage as Language
import semmle.code.cpp.models.interfaces.SideEffect as SideEffect

View File

@@ -41,8 +41,92 @@ newtype TValueNumber =
) { ) {
loadTotalOverlapValueNumber(_, irFunc, type, memOperand, operand) loadTotalOverlapValueNumber(_, irFunc, type, memOperand, operand)
} or } or
TCallValueNumber(TCallPartialValueNumber vn) { callValueNumber(_, _, vn) } or
TUniqueValueNumber(IRFunction irFunc, Instruction instr) { uniqueValueNumber(instr, irFunc) } TUniqueValueNumber(IRFunction irFunc, Instruction instr) { uniqueValueNumber(instr, irFunc) }
private class NumberableCallInstruction extends CallInstruction {
NumberableCallInstruction() {
not this.getResultIRType() instanceof IRVoidType and
exists(SideEffect::SideEffectFunction sideEffectFunc |
sideEffectFunc = this.getStaticCallTarget()
|
sideEffectFunc.hasOnlySpecificReadSideEffects() and
sideEffectFunc.hasOnlySpecificWriteSideEffects()
)
}
}
private newtype TCallPartialValueNumber =
TNilArgument() or
TArgument(TCallPartialValueNumber head, TValueNumber arg) {
exists(NumberableCallInstruction call, int index |
callArgValueNumber(call, index, arg) and
callPartialValueNumber(call, index, head)
)
}
private predicate callValueNumber(
NumberableCallInstruction call, int index, TCallPartialValueNumber vn
) {
index = max(int n | callArgRank(call, n, _) | n) and
exists(TCallPartialValueNumber head, TValueNumber arg |
callPartialValueNumber(call, index, pragma[only_bind_out](head)) and
callArgValueNumber(call, index, pragma[only_bind_into](arg)) and
vn = TArgument(head, arg)
)
or
not exists(int n | callArgRank(call, n, _)) and
index = -1 and
vn = TNilArgument()
}
private predicate callPartialValueNumber(
NumberableCallInstruction call, int index, TCallPartialValueNumber head
) {
exists(call) and
index = 1 and
head = TNilArgument()
or
exists(TCallPartialValueNumber prev, TValueNumber prevVN |
callPartialValueNumber(call, index - 1, pragma[only_bind_out](prev)) and
callArgValueNumber(call, index - 1, pragma[only_bind_into](prevVN)) and
head = TArgument(prev, prevVN)
)
}
/**
*/
private predicate callArgValueNumber(NumberableCallInstruction call, int index, TValueNumber arg) {
exists(Instruction instr |
callArgRank(call, index, instr) and
arg = tvalueNumber(instr)
)
}
/**
* Holds if `arg` is the `index`th element in `call`'s extended argument list, including the `this`
* argument and side-effect reads.
*/
private predicate callArgRank(NumberableCallInstruction call, int index, Instruction arg) {
arg =
rank[index](int argIndex, boolean isEffect, Instruction instr |
// There is no need to include the call's read and write side effects on
// all-aliased-memory as `NumberableCallInstruction`s do not read or write
// to all-aliased-memory.
instr = call.getArgument(argIndex) and
isEffect = false
or
exists(ReadSideEffectInstruction read |
read.getPrimaryInstruction() = call and
read.getSideEffectOperand().getAnyDef() = instr and
read.getIndex() = argIndex and
isEffect = true
)
|
instr order by argIndex, isEffect
)
}
/** /**
* A `CopyInstruction` whose source operand's value is congruent to the definition of that source * A `CopyInstruction` whose source operand's value is congruent to the definition of that source
* operand. * operand.
@@ -93,6 +177,8 @@ private predicate numberableInstruction(Instruction instr) {
instr instanceof CongruentCopyInstruction instr instanceof CongruentCopyInstruction
or or
instr instanceof LoadTotalOverlapInstruction instr instanceof LoadTotalOverlapInstruction
or
instr instanceof NumberableCallInstruction
} }
private predicate filteredNumberableInstruction(Instruction instr) { private predicate filteredNumberableInstruction(Instruction instr) {
@@ -309,6 +395,11 @@ private TValueNumber nonUniqueValueNumber(Instruction instr) {
or or
// The value number of a copy is just the value number of its source value. // The value number of a copy is just the value number of its source value.
result = tvalueNumber(instr.(CongruentCopyInstruction).getSourceValue()) result = tvalueNumber(instr.(CongruentCopyInstruction).getSourceValue())
or
exists(TCallPartialValueNumber pvn |
callValueNumber(instr, _, pvn) and
result = TCallValueNumber(pvn)
)
) )
) )
} }

View File

@@ -1712,6 +1712,11 @@ class SideEffectInstruction extends Instruction {
*/ */
class CallSideEffectInstruction extends SideEffectInstruction { class CallSideEffectInstruction extends SideEffectInstruction {
CallSideEffectInstruction() { this.getOpcode() instanceof Opcode::CallSideEffect } CallSideEffectInstruction() { this.getOpcode() instanceof Opcode::CallSideEffect }
/** Gets the operand for the value that will be read by this instruction */
final SideEffectOperand getSideEffectOperand() { result = this.getAnOperand() }
final Instruction getSideEffect() { result = this.getAnOperand().getDef() }
} }
/** /**
@@ -1723,6 +1728,11 @@ class CallSideEffectInstruction extends SideEffectInstruction {
*/ */
class CallReadSideEffectInstruction extends SideEffectInstruction { class CallReadSideEffectInstruction extends SideEffectInstruction {
CallReadSideEffectInstruction() { this.getOpcode() instanceof Opcode::CallReadSideEffect } CallReadSideEffectInstruction() { this.getOpcode() instanceof Opcode::CallReadSideEffect }
/** Gets the operand for the value that will be read by this instruction */
final SideEffectOperand getSideEffectOperand() { result = this.getAnOperand() }
final Instruction getSideEffect() { result = this.getAnOperand().getDef() }
} }
/** /**

View File

@@ -1,3 +1,4 @@
import semmle.code.cpp.ir.implementation.aliased_ssa.IR import semmle.code.cpp.ir.implementation.aliased_ssa.IR
import semmle.code.cpp.ir.internal.Overlap import semmle.code.cpp.ir.internal.Overlap
import semmle.code.cpp.ir.internal.IRCppLanguage as Language import semmle.code.cpp.ir.internal.IRCppLanguage as Language
import semmle.code.cpp.models.interfaces.SideEffect as SideEffect

View File

@@ -41,8 +41,92 @@ newtype TValueNumber =
) { ) {
loadTotalOverlapValueNumber(_, irFunc, type, memOperand, operand) loadTotalOverlapValueNumber(_, irFunc, type, memOperand, operand)
} or } or
TCallValueNumber(TCallPartialValueNumber vn) { callValueNumber(_, _, vn) } or
TUniqueValueNumber(IRFunction irFunc, Instruction instr) { uniqueValueNumber(instr, irFunc) } TUniqueValueNumber(IRFunction irFunc, Instruction instr) { uniqueValueNumber(instr, irFunc) }
private class NumberableCallInstruction extends CallInstruction {
NumberableCallInstruction() {
not this.getResultIRType() instanceof IRVoidType and
exists(SideEffect::SideEffectFunction sideEffectFunc |
sideEffectFunc = this.getStaticCallTarget()
|
sideEffectFunc.hasOnlySpecificReadSideEffects() and
sideEffectFunc.hasOnlySpecificWriteSideEffects()
)
}
}
private newtype TCallPartialValueNumber =
TNilArgument() or
TArgument(TCallPartialValueNumber head, TValueNumber arg) {
exists(NumberableCallInstruction call, int index |
callArgValueNumber(call, index, arg) and
callPartialValueNumber(call, index, head)
)
}
private predicate callValueNumber(
NumberableCallInstruction call, int index, TCallPartialValueNumber vn
) {
index = max(int n | callArgRank(call, n, _) | n) and
exists(TCallPartialValueNumber head, TValueNumber arg |
callPartialValueNumber(call, index, pragma[only_bind_out](head)) and
callArgValueNumber(call, index, pragma[only_bind_into](arg)) and
vn = TArgument(head, arg)
)
or
not exists(int n | callArgRank(call, n, _)) and
index = -1 and
vn = TNilArgument()
}
private predicate callPartialValueNumber(
NumberableCallInstruction call, int index, TCallPartialValueNumber head
) {
exists(call) and
index = 1 and
head = TNilArgument()
or
exists(TCallPartialValueNumber prev, TValueNumber prevVN |
callPartialValueNumber(call, index - 1, pragma[only_bind_out](prev)) and
callArgValueNumber(call, index - 1, pragma[only_bind_into](prevVN)) and
head = TArgument(prev, prevVN)
)
}
/**
*/
private predicate callArgValueNumber(NumberableCallInstruction call, int index, TValueNumber arg) {
exists(Instruction instr |
callArgRank(call, index, instr) and
arg = tvalueNumber(instr)
)
}
/**
* Holds if `arg` is the `index`th element in `call`'s extended argument list, including the `this`
* argument and side-effect reads.
*/
private predicate callArgRank(NumberableCallInstruction call, int index, Instruction arg) {
arg =
rank[index](int argIndex, boolean isEffect, Instruction instr |
// There is no need to include the call's read and write side effects on
// all-aliased-memory as `NumberableCallInstruction`s do not read or write
// to all-aliased-memory.
instr = call.getArgument(argIndex) and
isEffect = false
or
exists(ReadSideEffectInstruction read |
read.getPrimaryInstruction() = call and
read.getSideEffectOperand().getAnyDef() = instr and
read.getIndex() = argIndex and
isEffect = true
)
|
instr order by argIndex, isEffect
)
}
/** /**
* A `CopyInstruction` whose source operand's value is congruent to the definition of that source * A `CopyInstruction` whose source operand's value is congruent to the definition of that source
* operand. * operand.
@@ -93,6 +177,8 @@ private predicate numberableInstruction(Instruction instr) {
instr instanceof CongruentCopyInstruction instr instanceof CongruentCopyInstruction
or or
instr instanceof LoadTotalOverlapInstruction instr instanceof LoadTotalOverlapInstruction
or
instr instanceof NumberableCallInstruction
} }
private predicate filteredNumberableInstruction(Instruction instr) { private predicate filteredNumberableInstruction(Instruction instr) {
@@ -309,6 +395,11 @@ private TValueNumber nonUniqueValueNumber(Instruction instr) {
or or
// The value number of a copy is just the value number of its source value. // The value number of a copy is just the value number of its source value.
result = tvalueNumber(instr.(CongruentCopyInstruction).getSourceValue()) result = tvalueNumber(instr.(CongruentCopyInstruction).getSourceValue())
or
exists(TCallPartialValueNumber pvn |
callValueNumber(instr, _, pvn) and
result = TCallValueNumber(pvn)
)
) )
) )
} }

View File

@@ -8,11 +8,6 @@ private import Imports::RawIR as RawIR
private import SsaInstructions private import SsaInstructions
private import SsaOperands private import SsaOperands
private import NewIR private import NewIR
private class OldBlock = Reachability::ReachableBlock;
private class OldInstruction = Reachability::ReachableInstruction;
import Cached import Cached
cached cached
@@ -58,7 +53,9 @@ private module Cached {
cached cached
predicate hasInstruction(TStageInstruction instr) { predicate hasInstruction(TStageInstruction instr) {
instr instanceof TRawInstruction and instr instanceof OldInstruction instr instanceof TRawInstruction and
instr instanceof OldInstruction and
not removedInstruction(instr)
or or
instr = phiInstruction(_, _) instr = phiInstruction(_, _)
or or
@@ -382,7 +379,14 @@ private module Cached {
( (
if Reachability::isInfeasibleInstructionSuccessor(oldInstruction, kind) if Reachability::isInfeasibleInstructionSuccessor(oldInstruction, kind)
then result = unreachedInstruction(instruction.getEnclosingIRFunction()) then result = unreachedInstruction(instruction.getEnclosingIRFunction())
else result = getNewInstruction(oldInstruction.getSuccessor(kind)) else
if removedInstruction(oldInstruction.getSuccessor(kind))
then
// the only removed nodes are side-effect writes, but those may have Chi nodes
// skip to the following instruction in the old IR, which won't be removed
// if we start skipping specific side effects, this may no longer hold
result = getNewInstruction(oldInstruction.getSuccessor(kind).getSuccessor(kind))
else result = getNewInstruction(oldInstruction.getSuccessor(kind))
) )
) )
or or

View File

@@ -14,3 +14,9 @@ import semmle.code.cpp.ir.implementation.internal.TOperand::UnaliasedSsaOperands
/** DEPRECATED: Alias for SsaOperands */ /** DEPRECATED: Alias for SsaOperands */
deprecated module SSAOperands = SsaOperands; deprecated module SSAOperands = SsaOperands;
predicate removedInstruction(Reachability::ReachableInstruction instr) { none() }
class OldBlock = Reachability::ReachableBlock;
class OldInstruction = Reachability::ReachableInstruction;

View File

@@ -29,7 +29,4 @@ where
n = strictcount(ComplexStmt s | s = b.getAStmt()) and n = strictcount(ComplexStmt s | s = b.getAStmt()) and
n > 3 and n > 3 and
complexStmt = b.getAStmt() complexStmt = b.getAStmt()
select b, select b, "Block with too many statements (" + n.toString() + " complex statements in the block)."
"Block with too many statements (" + n.toString() +
" complex statements in the block). Complex statements at: $@", complexStmt,
complexStmt.toString()

View File

@@ -110,4 +110,4 @@ where
emptyBlock(s, eb) and emptyBlock(s, eb) and
not emptyBlockContainsNonchild(eb) and not emptyBlockContainsNonchild(eb) and
not lineComment(eb) not lineComment(eb)
select eb, "Empty block without comment" select eb, "Empty block without comment."

View File

@@ -1,11 +1,3 @@
## 0.3.4
## 0.3.3
### Minor Analysis Improvements
* The "Cleartext storage of sensitive information in buffer" (`cpp/cleartext-storage-buffer`) query has been improved to produce fewer false positives.
## 0.3.2 ## 0.3.2
### Minor Analysis Improvements ### Minor Analysis Improvements

View File

@@ -12,4 +12,4 @@
import CommentedOutCode import CommentedOutCode
from CommentedOutCode comment from CommentedOutCode comment
select comment, "This comment appears to contain commented-out code" select comment, "This comment appears to contain commented-out code."

View File

@@ -1,7 +1,6 @@
/** /**
* @name Sign check of bitwise operation * @name Sign check of bitwise operation
* @description Checking the sign of a bitwise operation often has surprising * @description Checking the sign of the result of a bitwise operation may yield unexpected results.
* edge cases.
* @kind problem * @kind problem
* @problem.severity warning * @problem.severity warning
* @precision high * @precision high
@@ -26,4 +25,4 @@ where
forall(int op | op = lhs.(BitwiseAndExpr).getAnOperand().getValue().toInt() | op < 0) and forall(int op | op = lhs.(BitwiseAndExpr).getAnOperand().getValue().toInt() | op < 0) and
// exception for cases involving macros // exception for cases involving macros
not e.isAffectedByMacro() not e.isAffectedByMacro()
select e, "Potential unsafe sign check of a bitwise operation." select e, "Potentially unsafe sign check of a bitwise operation."

View File

@@ -21,4 +21,4 @@ where
FloatingPointType and FloatingPointType and
not ro.getAnOperand().isConstant() and // comparisons to constants generate too many false positives not ro.getAnOperand().isConstant() and // comparisons to constants generate too many false positives
not left.(VariableAccess).getTarget() = right.(VariableAccess).getTarget() // skip self comparison not left.(VariableAccess).getTarget() = right.(VariableAccess).getTarget() // skip self comparison
select ro, "Equality test on floating point values may not behave as expected." select ro, "Equality checks on floating point values can yield unexpected results."

View File

@@ -13,10 +13,11 @@
import cpp import cpp
from EnumSwitch es, float missing, float total from EnumSwitch es, float missing, float total, EnumConstant case
where where
not es.hasDefaultCase() and not es.hasDefaultCase() and
missing = count(es.getAMissingCase()) and missing = count(es.getAMissingCase()) and
total = missing + count(es.getASwitchCase()) and total = missing + count(es.getASwitchCase()) and
missing / total < 0.3 missing / total < 0.3 and
select es, "Switch statement is missing case for " + es.getAMissingCase().getName() case = es.getAMissingCase()
select es, "Switch statement does not have a case for $@.", case, case.getName()

View File

@@ -163,46 +163,19 @@ TGlobalAddress globalAddress(Instruction instr) {
result = globalAddress(instr.(PointerOffsetInstruction).getLeft()) result = globalAddress(instr.(PointerOffsetInstruction).getLeft())
} }
/** /** Gets a `StoreInstruction` that may be executed after executing `store`. */
* Gets a first `StoreInstruction` that writes to address `globalAddress` reachable pragma[inline]
* from `block`. StoreInstruction getAStoreStrictlyAfter(StoreInstruction store) {
*/ exists(IRBlock block, int index1, int index2 |
StoreInstruction getFirstStore(IRBlock block, TGlobalAddress globalAddress) { block.getInstruction(index1) = store and
1 = getStoreRank(result, block, globalAddress) block.getInstruction(index2) = result and
or index2 > index1
not exists(getStoreRank(_, block, globalAddress)) and
result = getFirstStore(block.getASuccessor(), globalAddress)
}
/**
* Gets the rank of `store` in block `block` (i.e., a rank of `1` means that it is the
* first `store` to write to `globalAddress`, a rank of `2` means it's the second, etc.)
*/
int getStoreRank(StoreInstruction store, IRBlock block, TGlobalAddress globalAddress) {
blockStoresToAddress(block, _, store, globalAddress) and
store =
rank[result](StoreInstruction anotherStore, int i |
blockStoresToAddress(_, i, anotherStore, globalAddress)
|
anotherStore order by i
)
}
/**
* Gets a next subsequent `StoreInstruction` to write to `globalAddress`
* after `store` has done so.
*/
StoreInstruction getANextStoreTo(StoreInstruction store, TGlobalAddress globalAddress) {
exists(IRBlock block, int rnk |
rnk = getStoreRank(store, block, globalAddress) and
rnk + 1 = getStoreRank(result, block, globalAddress)
) )
or or
exists(IRBlock block, int rnk, IRBlock succ | exists(IRBlock block1, IRBlock block2 |
rnk = getStoreRank(store, block, globalAddress) and store.getBlock() = block1 and
not rnk + 1 = getStoreRank(_, block, globalAddress) and result.getBlock() = block2 and
succ = block.getASuccessor() and block1.getASuccessor+() = block2
result = getFirstStore(succ, globalAddress)
) )
} }
@@ -219,7 +192,7 @@ predicate stackAddressEscapes(
stackPointerFlowsToUse(store.getSourceValue(), vai) stackPointerFlowsToUse(store.getSourceValue(), vai)
) and ) and
// Ensure there's no subsequent store that overrides the global address. // Ensure there's no subsequent store that overrides the global address.
not exists(getANextStoreTo(store, globalAddress)) not globalAddress = globalAddress(getAStoreStrictlyAfter(store).getDestinationAddress())
} }
predicate blockStoresToAddress( predicate blockStoresToAddress(

View File

@@ -1,5 +1,4 @@
## 0.3.3 ---
category: minorAnalysis
### Minor Analysis Improvements ---
* The "Cleartext storage of sensitive information in buffer" (`cpp/cleartext-storage-buffer`) query has been improved to produce fewer false positives. * The "Cleartext storage of sensitive information in buffer" (`cpp/cleartext-storage-buffer`) query has been improved to produce fewer false positives.

View File

@@ -0,0 +1,4 @@
---
category: minorAnalysis
---
* The alert message of many queries have been changed to make the message consistent with other languages.

View File

@@ -1 +0,0 @@
## 0.3.4

View File

@@ -1,2 +1,2 @@
--- ---
lastReleaseVersion: 0.3.4 lastReleaseVersion: 0.3.2

View File

@@ -1,5 +1,5 @@
name: codeql/cpp-queries name: codeql/cpp-queries
version: 0.3.5-dev version: 0.3.3-dev
groups: groups:
- cpp - cpp
- queries - queries

File diff suppressed because it is too large Load Diff

View File

@@ -1050,46 +1050,36 @@ ssa.cpp:
# 240| r240_3(glval<unknown>) = FunctionAddress[Constructible] : # 240| r240_3(glval<unknown>) = FunctionAddress[Constructible] :
# 240| r240_4(int) = Constant[1] : # 240| r240_4(int) = Constant[1] :
# 240| v240_5(void) = Call[Constructible] : func:r240_3, this:r240_1, 0:r240_4 # 240| v240_5(void) = Call[Constructible] : func:r240_3, this:r240_1, 0:r240_4
# 240| m240_6(unknown) = ^CallSideEffect : ~m239_4 # 240| m240_6(Constructible) = ^IndirectMayWriteSideEffect[-1] : &:r240_1
# 240| m240_7(unknown) = Chi : total:m239_4, partial:m240_6 # 240| m240_7(Constructible) = Chi : total:m240_2, partial:m240_6
# 240| m240_8(Constructible) = ^IndirectMayWriteSideEffect[-1] : &:r240_1
# 240| m240_9(Constructible) = Chi : total:m240_2, partial:m240_8
# 241| r241_1(glval<Constructible>) = VariableAddress[c] : # 241| r241_1(glval<Constructible>) = VariableAddress[c] :
# 241| r241_2(glval<unknown>) = FunctionAddress[g] : # 241| r241_2(glval<unknown>) = FunctionAddress[g] :
# 241| v241_3(void) = Call[g] : func:r241_2, this:r241_1 # 241| v241_3(void) = Call[g] : func:r241_2, this:r241_1
# 241| m241_4(unknown) = ^CallSideEffect : ~m240_7 # 241| v241_4(void) = ^IndirectReadSideEffect[-1] : &:r241_1, m240_7
# 241| m241_5(unknown) = Chi : total:m240_7, partial:m241_4 # 241| m241_5(Constructible) = ^IndirectMayWriteSideEffect[-1] : &:r241_1
# 241| v241_6(void) = ^IndirectReadSideEffect[-1] : &:r241_1, m240_9 # 241| m241_6(Constructible) = Chi : total:m240_7, partial:m241_5
# 241| m241_7(Constructible) = ^IndirectMayWriteSideEffect[-1] : &:r241_1
# 241| m241_8(Constructible) = Chi : total:m240_9, partial:m241_7
# 242| r242_1(glval<Constructible>) = VariableAddress[c] : # 242| r242_1(glval<Constructible>) = VariableAddress[c] :
# 242| r242_2(glval<unknown>) = FunctionAddress[g] : # 242| r242_2(glval<unknown>) = FunctionAddress[g] :
# 242| v242_3(void) = Call[g] : func:r242_2, this:r242_1 # 242| v242_3(void) = Call[g] : func:r242_2, this:r242_1
# 242| m242_4(unknown) = ^CallSideEffect : ~m241_5 # 242| v242_4(void) = ^IndirectReadSideEffect[-1] : &:r242_1, m241_6
# 242| m242_5(unknown) = Chi : total:m241_5, partial:m242_4 # 242| m242_5(Constructible) = ^IndirectMayWriteSideEffect[-1] : &:r242_1
# 242| v242_6(void) = ^IndirectReadSideEffect[-1] : &:r242_1, m241_8 # 242| m242_6(Constructible) = Chi : total:m241_6, partial:m242_5
# 242| m242_7(Constructible) = ^IndirectMayWriteSideEffect[-1] : &:r242_1
# 242| m242_8(Constructible) = Chi : total:m241_8, partial:m242_7
# 243| r243_1(glval<Constructible>) = VariableAddress[c2] : # 243| r243_1(glval<Constructible>) = VariableAddress[c2] :
# 243| m243_2(Constructible) = Uninitialized[c2] : &:r243_1 # 243| m243_2(Constructible) = Uninitialized[c2] : &:r243_1
# 243| r243_3(glval<unknown>) = FunctionAddress[Constructible] : # 243| r243_3(glval<unknown>) = FunctionAddress[Constructible] :
# 243| r243_4(int) = Constant[2] : # 243| r243_4(int) = Constant[2] :
# 243| v243_5(void) = Call[Constructible] : func:r243_3, this:r243_1, 0:r243_4 # 243| v243_5(void) = Call[Constructible] : func:r243_3, this:r243_1, 0:r243_4
# 243| m243_6(unknown) = ^CallSideEffect : ~m242_5 # 243| m243_6(Constructible) = ^IndirectMayWriteSideEffect[-1] : &:r243_1
# 243| m243_7(unknown) = Chi : total:m242_5, partial:m243_6 # 243| m243_7(Constructible) = Chi : total:m243_2, partial:m243_6
# 243| m243_8(Constructible) = ^IndirectMayWriteSideEffect[-1] : &:r243_1
# 243| m243_9(Constructible) = Chi : total:m243_2, partial:m243_8
# 244| r244_1(glval<Constructible>) = VariableAddress[c2] : # 244| r244_1(glval<Constructible>) = VariableAddress[c2] :
# 244| r244_2(glval<unknown>) = FunctionAddress[g] : # 244| r244_2(glval<unknown>) = FunctionAddress[g] :
# 244| v244_3(void) = Call[g] : func:r244_2, this:r244_1 # 244| v244_3(void) = Call[g] : func:r244_2, this:r244_1
# 244| m244_4(unknown) = ^CallSideEffect : ~m243_7 # 244| v244_4(void) = ^IndirectReadSideEffect[-1] : &:r244_1, m243_7
# 244| m244_5(unknown) = Chi : total:m243_7, partial:m244_4 # 244| m244_5(Constructible) = ^IndirectMayWriteSideEffect[-1] : &:r244_1
# 244| v244_6(void) = ^IndirectReadSideEffect[-1] : &:r244_1, m243_9 # 244| m244_6(Constructible) = Chi : total:m243_7, partial:m244_5
# 244| m244_7(Constructible) = ^IndirectMayWriteSideEffect[-1] : &:r244_1
# 244| m244_8(Constructible) = Chi : total:m243_9, partial:m244_7
# 245| v245_1(void) = NoOp : # 245| v245_1(void) = NoOp :
# 239| v239_5(void) = ReturnVoid : # 239| v239_5(void) = ReturnVoid :
# 239| v239_6(void) = AliasedUse : ~m244_5 # 239| v239_6(void) = AliasedUse : m239_3
# 239| v239_7(void) = ExitFunction : # 239| v239_7(void) = ExitFunction :
# 247| char* VoidStarIndirectParameters(char*, int) # 247| char* VoidStarIndirectParameters(char*, int)
@@ -1391,43 +1381,37 @@ ssa.cpp:
# 294| r294_18(glval<int>) = VariableAddress[x] : # 294| r294_18(glval<int>) = VariableAddress[x] :
# 294| r294_19(int) = Load[x] : &:r294_18, m291_6 # 294| r294_19(int) = Load[x] : &:r294_18, m291_6
# 294| v294_20(void) = Call[A] : func:r294_17, this:r294_16, 0:r294_19 # 294| v294_20(void) = Call[A] : func:r294_17, this:r294_16, 0:r294_19
# 294| m294_21(unknown) = ^CallSideEffect : ~m294_14 # 294| m294_21(A) = ^IndirectMayWriteSideEffect[-1] : &:r294_16
# 294| m294_22(unknown) = Chi : total:m294_14, partial:m294_21 # 294| m294_22(unknown) = Chi : total:m294_15, partial:m294_21
# 294| m294_23(A) = ^IndirectMayWriteSideEffect[-1] : &:r294_16 # 294| v294_23(void) = Call[A] : func:r294_9, this:r294_8, 0:r294_16
# 294| m294_24(unknown) = Chi : total:m294_15, partial:m294_23 # 294| v294_24(void) = ^BufferReadSideEffect[0] : &:r294_16, ~m294_22
# 294| v294_25(void) = Call[A] : func:r294_9, this:r294_8, 0:r294_16 # 294| m294_25(A) = ^IndirectMayWriteSideEffect[-1] : &:r294_8
# 294| m294_26(unknown) = ^CallSideEffect : ~m294_22 # 294| m294_26(unknown) = Chi : total:m294_7, partial:m294_25
# 294| m294_27(unknown) = Chi : total:m294_22, partial:m294_26 # 294| m294_27(unknown) = ^BufferMayWriteSideEffect[0] : &:r294_16
# 294| v294_28(void) = ^BufferReadSideEffect[0] : &:r294_16, ~m294_24 # 294| m294_28(unknown) = Chi : total:m294_22, partial:m294_27
# 294| m294_29(A) = ^IndirectMayWriteSideEffect[-1] : &:r294_8 # 294| r294_29(glval<int>) = FieldAddress[i] : r294_8
# 294| m294_30(unknown) = Chi : total:m294_7, partial:m294_29 # 294| r294_30(int) = Load[?] : &:r294_29, ~m294_26
# 294| m294_31(unknown) = ^BufferMayWriteSideEffect[0] : &:r294_16 # 294| m294_31(int) = Store[j] : &:r294_1, r294_30
# 294| m294_32(unknown) = Chi : total:m294_24, partial:m294_31
# 294| r294_33(glval<int>) = FieldAddress[i] : r294_8
# 294| r294_34(int) = Load[?] : &:r294_33, ~m294_30
# 294| m294_35(int) = Store[j] : &:r294_1, r294_34
# 295| r295_1(glval<A *>) = VariableAddress[a] : # 295| r295_1(glval<A *>) = VariableAddress[a] :
# 295| r295_2(glval<unknown>) = FunctionAddress[operator new] : # 295| r295_2(glval<unknown>) = FunctionAddress[operator new] :
# 295| r295_3(unsigned long) = Constant[4] : # 295| r295_3(unsigned long) = Constant[4] :
# 295| r295_4(void *) = Call[operator new] : func:r295_2, 0:r295_3 # 295| r295_4(void *) = Call[operator new] : func:r295_2, 0:r295_3
# 295| m295_5(unknown) = ^CallSideEffect : ~m294_27 # 295| m295_5(unknown) = ^CallSideEffect : ~m294_14
# 295| m295_6(unknown) = Chi : total:m294_27, partial:m295_5 # 295| m295_6(unknown) = Chi : total:m294_14, partial:m295_5
# 295| m295_7(unknown) = ^InitializeDynamicAllocation : &:r295_4 # 295| m295_7(unknown) = ^InitializeDynamicAllocation : &:r295_4
# 295| r295_8(A *) = Convert : r295_4 # 295| r295_8(A *) = Convert : r295_4
# 295| r295_9(glval<unknown>) = FunctionAddress[A] : # 295| r295_9(glval<unknown>) = FunctionAddress[A] :
# 295| v295_10(void) = Call[A] : func:r295_9, this:r295_8 # 295| v295_10(void) = Call[A] : func:r295_9, this:r295_8
# 295| m295_11(unknown) = ^CallSideEffect : ~m295_6 # 295| m295_11(A) = ^IndirectMayWriteSideEffect[-1] : &:r295_8
# 295| m295_12(unknown) = Chi : total:m295_6, partial:m295_11 # 295| m295_12(unknown) = Chi : total:m295_7, partial:m295_11
# 295| m295_13(A) = ^IndirectMayWriteSideEffect[-1] : &:r295_8 # 295| m295_13(A *) = Store[a] : &:r295_1, r295_8
# 295| m295_14(unknown) = Chi : total:m295_7, partial:m295_13
# 295| m295_15(A *) = Store[a] : &:r295_1, r295_8
# 296| r296_1(glval<Point *>) = VariableAddress[#return] : # 296| r296_1(glval<Point *>) = VariableAddress[#return] :
# 296| r296_2(glval<Point *>) = VariableAddress[p] : # 296| r296_2(glval<Point *>) = VariableAddress[p] :
# 296| r296_3(Point *) = Load[p] : &:r296_2, m292_9 # 296| r296_3(Point *) = Load[p] : &:r296_2, m292_9
# 296| m296_4(Point *) = Store[#return] : &:r296_1, r296_3 # 296| m296_4(Point *) = Store[#return] : &:r296_1, r296_3
# 291| r291_7(glval<Point *>) = VariableAddress[#return] : # 291| r291_7(glval<Point *>) = VariableAddress[#return] :
# 291| v291_8(void) = ReturnValue : &:r291_7, m296_4 # 291| v291_8(void) = ReturnValue : &:r291_7, m296_4
# 291| v291_9(void) = AliasedUse : ~m295_12 # 291| v291_9(void) = AliasedUse : ~m295_6
# 291| v291_10(void) = ExitFunction : # 291| v291_10(void) = ExitFunction :
# 301| int main(int, char**) # 301| int main(int, char**)

View File

@@ -1045,46 +1045,36 @@ ssa.cpp:
# 240| r240_3(glval<unknown>) = FunctionAddress[Constructible] : # 240| r240_3(glval<unknown>) = FunctionAddress[Constructible] :
# 240| r240_4(int) = Constant[1] : # 240| r240_4(int) = Constant[1] :
# 240| v240_5(void) = Call[Constructible] : func:r240_3, this:r240_1, 0:r240_4 # 240| v240_5(void) = Call[Constructible] : func:r240_3, this:r240_1, 0:r240_4
# 240| m240_6(unknown) = ^CallSideEffect : ~m239_4 # 240| m240_6(Constructible) = ^IndirectMayWriteSideEffect[-1] : &:r240_1
# 240| m240_7(unknown) = Chi : total:m239_4, partial:m240_6 # 240| m240_7(Constructible) = Chi : total:m240_2, partial:m240_6
# 240| m240_8(Constructible) = ^IndirectMayWriteSideEffect[-1] : &:r240_1
# 240| m240_9(Constructible) = Chi : total:m240_2, partial:m240_8
# 241| r241_1(glval<Constructible>) = VariableAddress[c] : # 241| r241_1(glval<Constructible>) = VariableAddress[c] :
# 241| r241_2(glval<unknown>) = FunctionAddress[g] : # 241| r241_2(glval<unknown>) = FunctionAddress[g] :
# 241| v241_3(void) = Call[g] : func:r241_2, this:r241_1 # 241| v241_3(void) = Call[g] : func:r241_2, this:r241_1
# 241| m241_4(unknown) = ^CallSideEffect : ~m240_7 # 241| v241_4(void) = ^IndirectReadSideEffect[-1] : &:r241_1, m240_7
# 241| m241_5(unknown) = Chi : total:m240_7, partial:m241_4 # 241| m241_5(Constructible) = ^IndirectMayWriteSideEffect[-1] : &:r241_1
# 241| v241_6(void) = ^IndirectReadSideEffect[-1] : &:r241_1, m240_9 # 241| m241_6(Constructible) = Chi : total:m240_7, partial:m241_5
# 241| m241_7(Constructible) = ^IndirectMayWriteSideEffect[-1] : &:r241_1
# 241| m241_8(Constructible) = Chi : total:m240_9, partial:m241_7
# 242| r242_1(glval<Constructible>) = VariableAddress[c] : # 242| r242_1(glval<Constructible>) = VariableAddress[c] :
# 242| r242_2(glval<unknown>) = FunctionAddress[g] : # 242| r242_2(glval<unknown>) = FunctionAddress[g] :
# 242| v242_3(void) = Call[g] : func:r242_2, this:r242_1 # 242| v242_3(void) = Call[g] : func:r242_2, this:r242_1
# 242| m242_4(unknown) = ^CallSideEffect : ~m241_5 # 242| v242_4(void) = ^IndirectReadSideEffect[-1] : &:r242_1, m241_6
# 242| m242_5(unknown) = Chi : total:m241_5, partial:m242_4 # 242| m242_5(Constructible) = ^IndirectMayWriteSideEffect[-1] : &:r242_1
# 242| v242_6(void) = ^IndirectReadSideEffect[-1] : &:r242_1, m241_8 # 242| m242_6(Constructible) = Chi : total:m241_6, partial:m242_5
# 242| m242_7(Constructible) = ^IndirectMayWriteSideEffect[-1] : &:r242_1
# 242| m242_8(Constructible) = Chi : total:m241_8, partial:m242_7
# 243| r243_1(glval<Constructible>) = VariableAddress[c2] : # 243| r243_1(glval<Constructible>) = VariableAddress[c2] :
# 243| m243_2(Constructible) = Uninitialized[c2] : &:r243_1 # 243| m243_2(Constructible) = Uninitialized[c2] : &:r243_1
# 243| r243_3(glval<unknown>) = FunctionAddress[Constructible] : # 243| r243_3(glval<unknown>) = FunctionAddress[Constructible] :
# 243| r243_4(int) = Constant[2] : # 243| r243_4(int) = Constant[2] :
# 243| v243_5(void) = Call[Constructible] : func:r243_3, this:r243_1, 0:r243_4 # 243| v243_5(void) = Call[Constructible] : func:r243_3, this:r243_1, 0:r243_4
# 243| m243_6(unknown) = ^CallSideEffect : ~m242_5 # 243| m243_6(Constructible) = ^IndirectMayWriteSideEffect[-1] : &:r243_1
# 243| m243_7(unknown) = Chi : total:m242_5, partial:m243_6 # 243| m243_7(Constructible) = Chi : total:m243_2, partial:m243_6
# 243| m243_8(Constructible) = ^IndirectMayWriteSideEffect[-1] : &:r243_1
# 243| m243_9(Constructible) = Chi : total:m243_2, partial:m243_8
# 244| r244_1(glval<Constructible>) = VariableAddress[c2] : # 244| r244_1(glval<Constructible>) = VariableAddress[c2] :
# 244| r244_2(glval<unknown>) = FunctionAddress[g] : # 244| r244_2(glval<unknown>) = FunctionAddress[g] :
# 244| v244_3(void) = Call[g] : func:r244_2, this:r244_1 # 244| v244_3(void) = Call[g] : func:r244_2, this:r244_1
# 244| m244_4(unknown) = ^CallSideEffect : ~m243_7 # 244| v244_4(void) = ^IndirectReadSideEffect[-1] : &:r244_1, m243_7
# 244| m244_5(unknown) = Chi : total:m243_7, partial:m244_4 # 244| m244_5(Constructible) = ^IndirectMayWriteSideEffect[-1] : &:r244_1
# 244| v244_6(void) = ^IndirectReadSideEffect[-1] : &:r244_1, m243_9 # 244| m244_6(Constructible) = Chi : total:m243_7, partial:m244_5
# 244| m244_7(Constructible) = ^IndirectMayWriteSideEffect[-1] : &:r244_1
# 244| m244_8(Constructible) = Chi : total:m243_9, partial:m244_7
# 245| v245_1(void) = NoOp : # 245| v245_1(void) = NoOp :
# 239| v239_5(void) = ReturnVoid : # 239| v239_5(void) = ReturnVoid :
# 239| v239_6(void) = AliasedUse : ~m244_5 # 239| v239_6(void) = AliasedUse : m239_3
# 239| v239_7(void) = ExitFunction : # 239| v239_7(void) = ExitFunction :
# 247| char* VoidStarIndirectParameters(char*, int) # 247| char* VoidStarIndirectParameters(char*, int)
@@ -1385,43 +1375,37 @@ ssa.cpp:
# 294| r294_18(glval<int>) = VariableAddress[x] : # 294| r294_18(glval<int>) = VariableAddress[x] :
# 294| r294_19(int) = Load[x] : &:r294_18, m291_6 # 294| r294_19(int) = Load[x] : &:r294_18, m291_6
# 294| v294_20(void) = Call[A] : func:r294_17, this:r294_16, 0:r294_19 # 294| v294_20(void) = Call[A] : func:r294_17, this:r294_16, 0:r294_19
# 294| m294_21(unknown) = ^CallSideEffect : ~m294_14 # 294| m294_21(A) = ^IndirectMayWriteSideEffect[-1] : &:r294_16
# 294| m294_22(unknown) = Chi : total:m294_14, partial:m294_21 # 294| m294_22(unknown) = Chi : total:m294_15, partial:m294_21
# 294| m294_23(A) = ^IndirectMayWriteSideEffect[-1] : &:r294_16 # 294| v294_23(void) = Call[A] : func:r294_9, this:r294_8, 0:r294_16
# 294| m294_24(unknown) = Chi : total:m294_15, partial:m294_23 # 294| v294_24(void) = ^BufferReadSideEffect[0] : &:r294_16, ~m294_22
# 294| v294_25(void) = Call[A] : func:r294_9, this:r294_8, 0:r294_16 # 294| m294_25(A) = ^IndirectMayWriteSideEffect[-1] : &:r294_8
# 294| m294_26(unknown) = ^CallSideEffect : ~m294_22 # 294| m294_26(unknown) = Chi : total:m294_7, partial:m294_25
# 294| m294_27(unknown) = Chi : total:m294_22, partial:m294_26 # 294| m294_27(unknown) = ^BufferMayWriteSideEffect[0] : &:r294_16
# 294| v294_28(void) = ^BufferReadSideEffect[0] : &:r294_16, ~m294_24 # 294| m294_28(unknown) = Chi : total:m294_22, partial:m294_27
# 294| m294_29(A) = ^IndirectMayWriteSideEffect[-1] : &:r294_8 # 294| r294_29(glval<int>) = FieldAddress[i] : r294_8
# 294| m294_30(unknown) = Chi : total:m294_7, partial:m294_29 # 294| r294_30(int) = Load[?] : &:r294_29, ~m294_26
# 294| m294_31(unknown) = ^BufferMayWriteSideEffect[0] : &:r294_16 # 294| m294_31(int) = Store[j] : &:r294_1, r294_30
# 294| m294_32(unknown) = Chi : total:m294_24, partial:m294_31
# 294| r294_33(glval<int>) = FieldAddress[i] : r294_8
# 294| r294_34(int) = Load[?] : &:r294_33, ~m294_30
# 294| m294_35(int) = Store[j] : &:r294_1, r294_34
# 295| r295_1(glval<A *>) = VariableAddress[a] : # 295| r295_1(glval<A *>) = VariableAddress[a] :
# 295| r295_2(glval<unknown>) = FunctionAddress[operator new] : # 295| r295_2(glval<unknown>) = FunctionAddress[operator new] :
# 295| r295_3(unsigned long) = Constant[4] : # 295| r295_3(unsigned long) = Constant[4] :
# 295| r295_4(void *) = Call[operator new] : func:r295_2, 0:r295_3 # 295| r295_4(void *) = Call[operator new] : func:r295_2, 0:r295_3
# 295| m295_5(unknown) = ^CallSideEffect : ~m294_27 # 295| m295_5(unknown) = ^CallSideEffect : ~m294_14
# 295| m295_6(unknown) = Chi : total:m294_27, partial:m295_5 # 295| m295_6(unknown) = Chi : total:m294_14, partial:m295_5
# 295| m295_7(unknown) = ^InitializeDynamicAllocation : &:r295_4 # 295| m295_7(unknown) = ^InitializeDynamicAllocation : &:r295_4
# 295| r295_8(A *) = Convert : r295_4 # 295| r295_8(A *) = Convert : r295_4
# 295| r295_9(glval<unknown>) = FunctionAddress[A] : # 295| r295_9(glval<unknown>) = FunctionAddress[A] :
# 295| v295_10(void) = Call[A] : func:r295_9, this:r295_8 # 295| v295_10(void) = Call[A] : func:r295_9, this:r295_8
# 295| m295_11(unknown) = ^CallSideEffect : ~m295_6 # 295| m295_11(A) = ^IndirectMayWriteSideEffect[-1] : &:r295_8
# 295| m295_12(unknown) = Chi : total:m295_6, partial:m295_11 # 295| m295_12(unknown) = Chi : total:m295_7, partial:m295_11
# 295| m295_13(A) = ^IndirectMayWriteSideEffect[-1] : &:r295_8 # 295| m295_13(A *) = Store[a] : &:r295_1, r295_8
# 295| m295_14(unknown) = Chi : total:m295_7, partial:m295_13
# 295| m295_15(A *) = Store[a] : &:r295_1, r295_8
# 296| r296_1(glval<Point *>) = VariableAddress[#return] : # 296| r296_1(glval<Point *>) = VariableAddress[#return] :
# 296| r296_2(glval<Point *>) = VariableAddress[p] : # 296| r296_2(glval<Point *>) = VariableAddress[p] :
# 296| r296_3(Point *) = Load[p] : &:r296_2, m292_9 # 296| r296_3(Point *) = Load[p] : &:r296_2, m292_9
# 296| m296_4(Point *) = Store[#return] : &:r296_1, r296_3 # 296| m296_4(Point *) = Store[#return] : &:r296_1, r296_3
# 291| r291_7(glval<Point *>) = VariableAddress[#return] : # 291| r291_7(glval<Point *>) = VariableAddress[#return] :
# 291| v291_8(void) = ReturnValue : &:r291_7, m296_4 # 291| v291_8(void) = ReturnValue : &:r291_7, m296_4
# 291| v291_9(void) = AliasedUse : ~m295_12 # 291| v291_9(void) = AliasedUse : ~m295_6
# 291| v291_10(void) = ExitFunction : # 291| v291_10(void) = ExitFunction :
# 301| int main(int, char**) # 301| int main(int, char**)

View File

@@ -149,9 +149,6 @@ uniqueNodeLocation
| conditional_destructors.cpp:29:6:29:7 | EnterFunction | Node should have one location but has 2. | | conditional_destructors.cpp:29:6:29:7 | EnterFunction | Node should have one location but has 2. |
| conditional_destructors.cpp:29:6:29:7 | ExitFunction | Node should have one location but has 2. | | conditional_destructors.cpp:29:6:29:7 | ExitFunction | Node should have one location but has 2. |
| conditional_destructors.cpp:29:6:29:7 | InitializeNonLocal | Node should have one location but has 2. | | conditional_destructors.cpp:29:6:29:7 | InitializeNonLocal | Node should have one location but has 2. |
| conditional_destructors.cpp:29:6:29:7 | Phi | Node should have one location but has 2. |
| conditional_destructors.cpp:29:6:29:7 | Phi | Node should have one location but has 2. |
| conditional_destructors.cpp:29:6:29:7 | Phi | Node should have one location but has 2. |
| conditional_destructors.cpp:29:6:29:7 | ReturnVoid | Node should have one location but has 2. | | conditional_destructors.cpp:29:6:29:7 | ReturnVoid | Node should have one location but has 2. |
| conditional_destructors.cpp:29:6:29:7 | SideEffect | Node should have one location but has 2. | | conditional_destructors.cpp:29:6:29:7 | SideEffect | Node should have one location but has 2. |
| conditional_destructors.cpp:38:6:38:7 | AliasedDefinition | Node should have one location but has 2. | | conditional_destructors.cpp:38:6:38:7 | AliasedDefinition | Node should have one location but has 2. |
@@ -162,9 +159,6 @@ uniqueNodeLocation
| conditional_destructors.cpp:38:6:38:7 | EnterFunction | Node should have one location but has 2. | | conditional_destructors.cpp:38:6:38:7 | EnterFunction | Node should have one location but has 2. |
| conditional_destructors.cpp:38:6:38:7 | ExitFunction | Node should have one location but has 2. | | conditional_destructors.cpp:38:6:38:7 | ExitFunction | Node should have one location but has 2. |
| conditional_destructors.cpp:38:6:38:7 | InitializeNonLocal | Node should have one location but has 2. | | conditional_destructors.cpp:38:6:38:7 | InitializeNonLocal | Node should have one location but has 2. |
| conditional_destructors.cpp:38:6:38:7 | Phi | Node should have one location but has 2. |
| conditional_destructors.cpp:38:6:38:7 | Phi | Node should have one location but has 2. |
| conditional_destructors.cpp:38:6:38:7 | Phi | Node should have one location but has 2. |
| conditional_destructors.cpp:38:6:38:7 | ReturnVoid | Node should have one location but has 2. | | conditional_destructors.cpp:38:6:38:7 | ReturnVoid | Node should have one location but has 2. |
| conditional_destructors.cpp:38:6:38:7 | SideEffect | Node should have one location but has 2. | | conditional_destructors.cpp:38:6:38:7 | SideEffect | Node should have one location but has 2. |
| conditional_destructors.cpp:38:6:38:7 | Unreached | Node should have one location but has 2. | | conditional_destructors.cpp:38:6:38:7 | Unreached | Node should have one location but has 2. |
@@ -561,9 +555,6 @@ uniqueNodeLocation
| forstmt.cpp:1:6:1:7 | EnterFunction | Node should have one location but has 2. | | forstmt.cpp:1:6:1:7 | EnterFunction | Node should have one location but has 2. |
| forstmt.cpp:1:6:1:7 | ExitFunction | Node should have one location but has 2. | | forstmt.cpp:1:6:1:7 | ExitFunction | Node should have one location but has 2. |
| forstmt.cpp:1:6:1:7 | InitializeNonLocal | Node should have one location but has 2. | | forstmt.cpp:1:6:1:7 | InitializeNonLocal | Node should have one location but has 2. |
| forstmt.cpp:1:6:1:7 | Phi | Node should have one location but has 2. |
| forstmt.cpp:1:6:1:7 | Phi | Node should have one location but has 2. |
| forstmt.cpp:1:6:1:7 | Phi | Node should have one location but has 2. |
| forstmt.cpp:1:6:1:7 | ReturnVoid | Node should have one location but has 2. | | forstmt.cpp:1:6:1:7 | ReturnVoid | Node should have one location but has 2. |
| forstmt.cpp:1:6:1:7 | SideEffect | Node should have one location but has 2. | | forstmt.cpp:1:6:1:7 | SideEffect | Node should have one location but has 2. |
| forstmt.cpp:8:6:8:7 | AliasedDefinition | Node should have one location but has 2. | | forstmt.cpp:8:6:8:7 | AliasedDefinition | Node should have one location but has 2. |
@@ -574,9 +565,6 @@ uniqueNodeLocation
| forstmt.cpp:8:6:8:7 | EnterFunction | Node should have one location but has 2. | | forstmt.cpp:8:6:8:7 | EnterFunction | Node should have one location but has 2. |
| forstmt.cpp:8:6:8:7 | ExitFunction | Node should have one location but has 2. | | forstmt.cpp:8:6:8:7 | ExitFunction | Node should have one location but has 2. |
| forstmt.cpp:8:6:8:7 | InitializeNonLocal | Node should have one location but has 2. | | forstmt.cpp:8:6:8:7 | InitializeNonLocal | Node should have one location but has 2. |
| forstmt.cpp:8:6:8:7 | Phi | Node should have one location but has 2. |
| forstmt.cpp:8:6:8:7 | Phi | Node should have one location but has 2. |
| forstmt.cpp:8:6:8:7 | Phi | Node should have one location but has 2. |
| forstmt.cpp:8:6:8:7 | ReturnVoid | Node should have one location but has 2. | | forstmt.cpp:8:6:8:7 | ReturnVoid | Node should have one location but has 2. |
| forstmt.cpp:8:6:8:7 | SideEffect | Node should have one location but has 2. | | forstmt.cpp:8:6:8:7 | SideEffect | Node should have one location but has 2. |
| forstmt.cpp:8:6:8:7 | Unreached | Node should have one location but has 2. | | forstmt.cpp:8:6:8:7 | Unreached | Node should have one location but has 2. |

View File

@@ -2,6 +2,7 @@
| test.cpp:5:7:5:8 | p0 | 5:c7-c8 6:c7-c8 | | test.cpp:5:7:5:8 | p0 | 5:c7-c8 6:c7-c8 |
| test.cpp:5:7:5:13 | ... + ... | 5:c7-c13 6:c7-c13 7:c7-c7 | | test.cpp:5:7:5:13 | ... + ... | 5:c7-c13 6:c7-c13 7:c7-c7 |
| test.cpp:5:12:5:13 | p1 | 5:c12-c13 6:c12-c13 | | test.cpp:5:12:5:13 | p1 | 5:c12-c13 6:c12-c13 |
| test.cpp:10:16:10:16 | 1 | 10:c16-c16 176:c7-c7 178:c7-c7 |
| test.cpp:16:3:16:3 | x | 16:c3-c3 17:c3-c3 | | test.cpp:16:3:16:3 | x | 16:c3-c3 17:c3-c3 |
| test.cpp:16:7:16:8 | p0 | 16:c7-c8 17:c7-c8 | | test.cpp:16:7:16:8 | p0 | 16:c7-c8 17:c7-c8 |
| test.cpp:16:7:16:13 | ... + ... | 16:c7-c13 17:c7-c13 | | test.cpp:16:7:16:13 | ... + ... | 16:c7-c13 17:c7-c13 |
@@ -38,3 +39,9 @@
| test.cpp:145:15:145:15 | y | 145:c15-c15 147:c7-c7 | | test.cpp:145:15:145:15 | y | 145:c15-c15 147:c7-c7 |
| test.cpp:153:11:153:18 | global_a | 153:c11-c18 154:c11-c18 156:c3-c10 | | test.cpp:153:11:153:18 | global_a | 153:c11-c18 154:c11-c18 156:c3-c10 |
| test.cpp:153:21:153:21 | x | 153:c21-c21 154:c21-c21 | | test.cpp:153:21:153:21 | x | 153:c21-c21 154:c21-c21 |
| test.cpp:166:18:166:20 | (const char *)... | 166:c18-c20 167:c18-c20 173:c18-c20 |
| test.cpp:166:18:166:20 | dst | 166:c18-c20 167:c18-c20 171:c10-c12 173:c18-c20 |
| test.cpp:168:18:168:20 | (const char *)... | 168:c18-c20 169:c18-c20 171:c15-c17 174:c18-c20 |
| test.cpp:168:18:168:20 | src | 168:c18-c20 169:c18-c20 171:c15-c17 174:c18-c20 |
| test.cpp:176:10:176:10 | 2 | 176:c10-c10 178:c10-c10 21:c16-c16 |
| test.cpp:177:7:177:7 | 3 | 177:c7-c7 35:c16-c16 |

View File

@@ -44,3 +44,11 @@
| test.cpp:144:15:144:15 | GVN | 144:c15-c15 149:c15-c15 | | test.cpp:144:15:144:15 | GVN | 144:c15-c15 149:c15-c15 |
| test.cpp:153:11:153:18 | GVN | 153:c11-c18 154:c11-c18 156:c3-c10 | | test.cpp:153:11:153:18 | GVN | 153:c11-c18 154:c11-c18 156:c3-c10 |
| test.cpp:153:21:153:21 | GVN | 153:c21-c21 154:c21-c21 | | test.cpp:153:21:153:21 | GVN | 153:c21-c21 154:c21-c21 |
| test.cpp:166:11:166:16 | GVN | 166:c11-c16 167:c11-c16 |
| test.cpp:166:18:166:20 | GVN | 166:c18-c20 167:c18-c20 171:c10-c12 173:c18-c20 |
| test.cpp:166:18:166:20 | GVN | 166:c18-c20 167:c18-c20 173:c18-c20 |
| test.cpp:168:11:168:16 | GVN | 168:c11-c16 169:c11-c16 174:c11-c16 |
| test.cpp:168:18:168:20 | GVN | 168:c18-c20 169:c18-c20 171:c15-c17 174:c18-c20 |
| test.cpp:168:18:168:20 | GVN | 168:c18-c20 169:c18-c20 171:c15-c17 174:c18-c20 |
| test.cpp:176:7:176:7 | GVN | 176:c7-c7 178:c7-c7 |
| test.cpp:176:10:176:10 | GVN | 176:c10-c10 178:c10-c10 |

View File

@@ -1,15 +1,20 @@
| test.cpp:5:3:5:13 | ... = ... | test.cpp:5:3:5:13 | ... = ... | AST only | | test.cpp:5:3:5:13 | ... = ... | test.cpp:5:3:5:13 | ... = ... | AST only |
| test.cpp:6:3:6:13 | ... = ... | test.cpp:6:3:6:13 | ... = ... | AST only | | test.cpp:6:3:6:13 | ... = ... | test.cpp:6:3:6:13 | ... = ... | AST only |
| test.cpp:7:3:7:7 | ... = ... | test.cpp:7:3:7:7 | ... = ... | AST only | | test.cpp:7:3:7:7 | ... = ... | test.cpp:7:3:7:7 | ... = ... | AST only |
| test.cpp:10:16:10:16 | 1 | test.cpp:176:7:176:7 | 1 | AST only |
| test.cpp:10:16:10:16 | 1 | test.cpp:178:7:178:7 | 1 | AST only |
| test.cpp:16:3:16:24 | ... = ... | test.cpp:16:3:16:24 | ... = ... | AST only | | test.cpp:16:3:16:24 | ... = ... | test.cpp:16:3:16:24 | ... = ... | AST only |
| test.cpp:17:3:17:24 | ... = ... | test.cpp:17:3:17:24 | ... = ... | AST only | | test.cpp:17:3:17:24 | ... = ... | test.cpp:17:3:17:24 | ... = ... | AST only |
| test.cpp:18:3:18:7 | ... = ... | test.cpp:18:3:18:7 | ... = ... | AST only | | test.cpp:18:3:18:7 | ... = ... | test.cpp:18:3:18:7 | ... = ... | AST only |
| test.cpp:21:16:21:16 | 2 | test.cpp:176:10:176:10 | 2 | AST only |
| test.cpp:21:16:21:16 | 2 | test.cpp:178:10:178:10 | 2 | AST only |
| test.cpp:29:3:29:3 | x | test.cpp:31:3:31:3 | x | IR only | | test.cpp:29:3:29:3 | x | test.cpp:31:3:31:3 | x | IR only |
| test.cpp:29:3:29:24 | ... = ... | test.cpp:29:3:29:24 | ... = ... | AST only | | test.cpp:29:3:29:24 | ... = ... | test.cpp:29:3:29:24 | ... = ... | AST only |
| test.cpp:30:3:30:17 | call to change_global02 | test.cpp:30:3:30:17 | call to change_global02 | AST only | | test.cpp:30:3:30:17 | call to change_global02 | test.cpp:30:3:30:17 | call to change_global02 | AST only |
| test.cpp:31:3:31:3 | x | test.cpp:29:3:29:3 | x | IR only | | test.cpp:31:3:31:3 | x | test.cpp:29:3:29:3 | x | IR only |
| test.cpp:31:3:31:24 | ... = ... | test.cpp:31:3:31:24 | ... = ... | AST only | | test.cpp:31:3:31:24 | ... = ... | test.cpp:31:3:31:24 | ... = ... | AST only |
| test.cpp:32:3:32:7 | ... = ... | test.cpp:32:3:32:7 | ... = ... | AST only | | test.cpp:32:3:32:7 | ... = ... | test.cpp:32:3:32:7 | ... = ... | AST only |
| test.cpp:35:16:35:16 | 3 | test.cpp:177:7:177:7 | 3 | AST only |
| test.cpp:43:3:43:3 | x | test.cpp:45:3:45:3 | x | IR only | | test.cpp:43:3:43:3 | x | test.cpp:45:3:45:3 | x | IR only |
| test.cpp:43:3:43:24 | ... = ... | test.cpp:43:3:43:24 | ... = ... | AST only | | test.cpp:43:3:43:24 | ... = ... | test.cpp:43:3:43:24 | ... = ... | AST only |
| test.cpp:43:7:43:24 | ... + ... | test.cpp:45:7:45:24 | ... + ... | IR only | | test.cpp:43:7:43:24 | ... + ... | test.cpp:45:7:45:24 | ... + ... | IR only |
@@ -127,3 +132,41 @@
| test.cpp:147:7:147:7 | y | test.cpp:145:15:145:15 | y | AST only | | test.cpp:147:7:147:7 | y | test.cpp:145:15:145:15 | y | AST only |
| test.cpp:149:15:149:15 | x | test.cpp:144:15:144:15 | x | IR only | | test.cpp:149:15:149:15 | x | test.cpp:144:15:144:15 | x | IR only |
| test.cpp:156:3:156:17 | ... = ... | test.cpp:156:3:156:17 | ... = ... | AST only | | test.cpp:156:3:156:17 | ... = ... | test.cpp:156:3:156:17 | ... = ... | AST only |
| test.cpp:166:11:166:16 | call to strlen | test.cpp:167:11:167:16 | call to strlen | IR only |
| test.cpp:166:18:166:20 | (const char *)... | test.cpp:166:18:166:20 | (const char *)... | AST only |
| test.cpp:166:18:166:20 | (const char *)... | test.cpp:167:18:167:20 | (const char *)... | AST only |
| test.cpp:166:18:166:20 | (const char *)... | test.cpp:173:18:173:20 | (const char *)... | AST only |
| test.cpp:167:11:167:16 | call to strlen | test.cpp:166:11:166:16 | call to strlen | IR only |
| test.cpp:167:18:167:20 | (const char *)... | test.cpp:166:18:166:20 | (const char *)... | AST only |
| test.cpp:167:18:167:20 | (const char *)... | test.cpp:167:18:167:20 | (const char *)... | AST only |
| test.cpp:167:18:167:20 | (const char *)... | test.cpp:173:18:173:20 | (const char *)... | AST only |
| test.cpp:168:11:168:16 | call to strlen | test.cpp:169:11:169:16 | call to strlen | IR only |
| test.cpp:168:11:168:16 | call to strlen | test.cpp:174:11:174:16 | call to strlen | IR only |
| test.cpp:168:18:168:20 | (const char *)... | test.cpp:168:18:168:20 | (const char *)... | AST only |
| test.cpp:168:18:168:20 | (const char *)... | test.cpp:169:18:169:20 | (const char *)... | AST only |
| test.cpp:168:18:168:20 | (const char *)... | test.cpp:171:15:171:17 | (const char *)... | AST only |
| test.cpp:168:18:168:20 | (const char *)... | test.cpp:174:18:174:20 | (const char *)... | AST only |
| test.cpp:169:11:169:16 | call to strlen | test.cpp:168:11:168:16 | call to strlen | IR only |
| test.cpp:169:11:169:16 | call to strlen | test.cpp:174:11:174:16 | call to strlen | IR only |
| test.cpp:169:18:169:20 | (const char *)... | test.cpp:168:18:168:20 | (const char *)... | AST only |
| test.cpp:169:18:169:20 | (const char *)... | test.cpp:169:18:169:20 | (const char *)... | AST only |
| test.cpp:169:18:169:20 | (const char *)... | test.cpp:171:15:171:17 | (const char *)... | AST only |
| test.cpp:169:18:169:20 | (const char *)... | test.cpp:174:18:174:20 | (const char *)... | AST only |
| test.cpp:171:15:171:17 | (const char *)... | test.cpp:168:18:168:20 | (const char *)... | AST only |
| test.cpp:171:15:171:17 | (const char *)... | test.cpp:169:18:169:20 | (const char *)... | AST only |
| test.cpp:171:15:171:17 | (const char *)... | test.cpp:171:15:171:17 | (const char *)... | AST only |
| test.cpp:171:15:171:17 | (const char *)... | test.cpp:174:18:174:20 | (const char *)... | AST only |
| test.cpp:173:18:173:20 | (const char *)... | test.cpp:166:18:166:20 | (const char *)... | AST only |
| test.cpp:173:18:173:20 | (const char *)... | test.cpp:167:18:167:20 | (const char *)... | AST only |
| test.cpp:173:18:173:20 | (const char *)... | test.cpp:173:18:173:20 | (const char *)... | AST only |
| test.cpp:174:11:174:16 | call to strlen | test.cpp:168:11:168:16 | call to strlen | IR only |
| test.cpp:174:11:174:16 | call to strlen | test.cpp:169:11:169:16 | call to strlen | IR only |
| test.cpp:174:18:174:20 | (const char *)... | test.cpp:168:18:168:20 | (const char *)... | AST only |
| test.cpp:174:18:174:20 | (const char *)... | test.cpp:169:18:169:20 | (const char *)... | AST only |
| test.cpp:174:18:174:20 | (const char *)... | test.cpp:171:15:171:17 | (const char *)... | AST only |
| test.cpp:174:18:174:20 | (const char *)... | test.cpp:174:18:174:20 | (const char *)... | AST only |
| test.cpp:176:7:176:7 | 1 | test.cpp:10:16:10:16 | 1 | AST only |
| test.cpp:176:10:176:10 | 2 | test.cpp:21:16:21:16 | 2 | AST only |
| test.cpp:177:7:177:7 | 3 | test.cpp:35:16:35:16 | 3 | AST only |
| test.cpp:178:7:178:7 | 1 | test.cpp:10:16:10:16 | 1 | AST only |
| test.cpp:178:10:178:10 | 2 | test.cpp:21:16:21:16 | 2 | AST only |

View File

@@ -1145,3 +1145,206 @@ test.cpp:
# 152| v152_7(void) = ReturnVoid : # 152| v152_7(void) = ReturnVoid :
# 152| v152_8(void) = AliasedUse : ~m156_7 # 152| v152_8(void) = AliasedUse : ~m156_7
# 152| v152_9(void) = ExitFunction : # 152| v152_9(void) = ExitFunction :
# 163| int add(int, int)
# 163| Block 0
# 163| v163_1(void) = EnterFunction :
# 163| m163_2(unknown) = AliasedDefinition :
# 163| valnum = unique
# 163| m163_3(unknown) = InitializeNonLocal :
# 163| valnum = unique
# 163| m163_4(unknown) = Chi : total:m163_2, partial:m163_3
# 163| valnum = unique
# 163| r163_5(glval<int>) = VariableAddress[a] :
# 163| valnum = r163_10, r163_5
# 163| m163_6(int) = InitializeParameter[a] : &:r163_5
# 163| valnum = m163_6, r163_11
# 163| r163_7(glval<int>) = VariableAddress[b] :
# 163| valnum = r163_12, r163_7
# 163| m163_8(int) = InitializeParameter[b] : &:r163_7
# 163| valnum = m163_8, r163_13
# 163| r163_9(glval<int>) = VariableAddress[#return] :
# 163| valnum = r163_16, r163_9
# 163| r163_10(glval<int>) = VariableAddress[a] :
# 163| valnum = r163_10, r163_5
# 163| r163_11(int) = Load[a] : &:r163_10, m163_6
# 163| valnum = m163_6, r163_11
# 163| r163_12(glval<int>) = VariableAddress[b] :
# 163| valnum = r163_12, r163_7
# 163| r163_13(int) = Load[b] : &:r163_12, m163_8
# 163| valnum = m163_8, r163_13
# 163| r163_14(int) = Add : r163_11, r163_13
# 163| valnum = m163_15, r163_14
# 163| m163_15(int) = Store[#return] : &:r163_9, r163_14
# 163| valnum = m163_15, r163_14
# 163| r163_16(glval<int>) = VariableAddress[#return] :
# 163| valnum = r163_16, r163_9
# 163| v163_17(void) = ReturnValue : &:r163_16, m163_15
# 163| v163_18(void) = AliasedUse : m163_3
# 163| v163_19(void) = ExitFunction :
# 165| void test_func_value_numbering(char*, char*)
# 165| Block 0
# 165| v165_1(void) = EnterFunction :
# 165| m165_2(unknown) = AliasedDefinition :
# 165| valnum = unique
# 165| m165_3(unknown) = InitializeNonLocal :
# 165| valnum = unique
# 165| m165_4(unknown) = Chi : total:m165_2, partial:m165_3
# 165| valnum = unique
# 165| r165_5(glval<char *>) = VariableAddress[dst] :
# 165| valnum = r165_5, r166_3, r167_3, r171_2, r173_3
# 165| m165_6(char *) = InitializeParameter[dst] : &:r165_5
# 165| valnum = m165_6, r165_7, r166_4, r167_4, r171_3, r173_4
# 165| r165_7(char *) = Load[dst] : &:r165_5, m165_6
# 165| valnum = m165_6, r165_7, r166_4, r167_4, r171_3, r173_4
# 165| m165_8(unknown) = InitializeIndirection[dst] : &:r165_7
# 165| valnum = unique
# 165| r165_9(glval<char *>) = VariableAddress[src] :
# 165| valnum = r165_9, r168_3, r169_3, r171_4, r174_3
# 165| m165_10(char *) = InitializeParameter[src] : &:r165_9
# 165| valnum = m165_10, r165_11, r168_4, r169_4, r171_5, r174_4
# 165| r165_11(char *) = Load[src] : &:r165_9, m165_10
# 165| valnum = m165_10, r165_11, r168_4, r169_4, r171_5, r174_4
# 165| m165_12(unknown) = InitializeIndirection[src] : &:r165_11
# 165| valnum = unique
# 166| r166_1(glval<int>) = VariableAddress[a] :
# 166| valnum = unique
# 166| r166_2(glval<unknown>) = FunctionAddress[strlen] :
# 166| valnum = unique
# 166| r166_3(glval<char *>) = VariableAddress[dst] :
# 166| valnum = r165_5, r166_3, r167_3, r171_2, r173_3
# 166| r166_4(char *) = Load[dst] : &:r166_3, m165_6
# 166| valnum = m165_6, r165_7, r166_4, r167_4, r171_3, r173_4
# 166| r166_5(char *) = Convert : r166_4
# 166| valnum = r166_5, r167_5, r173_5
# 166| r166_6(int) = Call[strlen] : func:r166_2, 0:r166_5
# 166| valnum = m166_8, m167_8, r166_6, r167_6
# 166| v166_7(void) = ^BufferReadSideEffect[0] : &:r166_5, ~m165_8
# 166| m166_8(int) = Store[a] : &:r166_1, r166_6
# 166| valnum = m166_8, m167_8, r166_6, r167_6
# 167| r167_1(glval<int>) = VariableAddress[b] :
# 167| valnum = unique
# 167| r167_2(glval<unknown>) = FunctionAddress[strlen] :
# 167| valnum = unique
# 167| r167_3(glval<char *>) = VariableAddress[dst] :
# 167| valnum = r165_5, r166_3, r167_3, r171_2, r173_3
# 167| r167_4(char *) = Load[dst] : &:r167_3, m165_6
# 167| valnum = m165_6, r165_7, r166_4, r167_4, r171_3, r173_4
# 167| r167_5(char *) = Convert : r167_4
# 167| valnum = r166_5, r167_5, r173_5
# 167| r167_6(int) = Call[strlen] : func:r167_2, 0:r167_5
# 167| valnum = m166_8, m167_8, r166_6, r167_6
# 167| v167_7(void) = ^BufferReadSideEffect[0] : &:r167_5, ~m165_8
# 167| m167_8(int) = Store[b] : &:r167_1, r167_6
# 167| valnum = m166_8, m167_8, r166_6, r167_6
# 168| r168_1(glval<int>) = VariableAddress[c] :
# 168| valnum = unique
# 168| r168_2(glval<unknown>) = FunctionAddress[strlen] :
# 168| valnum = unique
# 168| r168_3(glval<char *>) = VariableAddress[src] :
# 168| valnum = r165_9, r168_3, r169_3, r171_4, r174_3
# 168| r168_4(char *) = Load[src] : &:r168_3, m165_10
# 168| valnum = m165_10, r165_11, r168_4, r169_4, r171_5, r174_4
# 168| r168_5(char *) = Convert : r168_4
# 168| valnum = r168_5, r169_5, r171_6, r174_5
# 168| r168_6(int) = Call[strlen] : func:r168_2, 0:r168_5
# 168| valnum = m168_8, m169_8, m174_8, r168_6, r169_6, r174_6
# 168| v168_7(void) = ^BufferReadSideEffect[0] : &:r168_5, ~m165_12
# 168| m168_8(int) = Store[c] : &:r168_1, r168_6
# 168| valnum = m168_8, m169_8, m174_8, r168_6, r169_6, r174_6
# 169| r169_1(glval<int>) = VariableAddress[d] :
# 169| valnum = unique
# 169| r169_2(glval<unknown>) = FunctionAddress[strlen] :
# 169| valnum = unique
# 169| r169_3(glval<char *>) = VariableAddress[src] :
# 169| valnum = r165_9, r168_3, r169_3, r171_4, r174_3
# 169| r169_4(char *) = Load[src] : &:r169_3, m165_10
# 169| valnum = m165_10, r165_11, r168_4, r169_4, r171_5, r174_4
# 169| r169_5(char *) = Convert : r169_4
# 169| valnum = r168_5, r169_5, r171_6, r174_5
# 169| r169_6(int) = Call[strlen] : func:r169_2, 0:r169_5
# 169| valnum = m168_8, m169_8, m174_8, r168_6, r169_6, r174_6
# 169| v169_7(void) = ^BufferReadSideEffect[0] : &:r169_5, ~m165_12
# 169| m169_8(int) = Store[d] : &:r169_1, r169_6
# 169| valnum = m168_8, m169_8, m174_8, r168_6, r169_6, r174_6
# 171| r171_1(glval<unknown>) = FunctionAddress[strcat] :
# 171| valnum = unique
# 171| r171_2(glval<char *>) = VariableAddress[dst] :
# 171| valnum = r165_5, r166_3, r167_3, r171_2, r173_3
# 171| r171_3(char *) = Load[dst] : &:r171_2, m165_6
# 171| valnum = m165_6, r165_7, r166_4, r167_4, r171_3, r173_4
# 171| r171_4(glval<char *>) = VariableAddress[src] :
# 171| valnum = r165_9, r168_3, r169_3, r171_4, r174_3
# 171| r171_5(char *) = Load[src] : &:r171_4, m165_10
# 171| valnum = m165_10, r165_11, r168_4, r169_4, r171_5, r174_4
# 171| r171_6(char *) = Convert : r171_5
# 171| valnum = r168_5, r169_5, r171_6, r174_5
# 171| r171_7(char *) = Call[strcat] : func:r171_1, 0:r171_3, 1:r171_6
# 171| valnum = unique
# 171| v171_8(void) = ^BufferReadSideEffect[0] : &:r171_3, ~m165_8
# 171| v171_9(void) = ^BufferReadSideEffect[1] : &:r171_6, ~m165_12
# 171| m171_10(unknown) = ^BufferMayWriteSideEffect[0] : &:r171_3
# 171| valnum = unique
# 171| m171_11(unknown) = Chi : total:m165_8, partial:m171_10
# 171| valnum = unique
# 173| r173_1(glval<int>) = VariableAddress[e] :
# 173| valnum = unique
# 173| r173_2(glval<unknown>) = FunctionAddress[strlen] :
# 173| valnum = unique
# 173| r173_3(glval<char *>) = VariableAddress[dst] :
# 173| valnum = r165_5, r166_3, r167_3, r171_2, r173_3
# 173| r173_4(char *) = Load[dst] : &:r173_3, m165_6
# 173| valnum = m165_6, r165_7, r166_4, r167_4, r171_3, r173_4
# 173| r173_5(char *) = Convert : r173_4
# 173| valnum = r166_5, r167_5, r173_5
# 173| r173_6(int) = Call[strlen] : func:r173_2, 0:r173_5
# 173| valnum = m173_8, r173_6
# 173| v173_7(void) = ^BufferReadSideEffect[0] : &:r173_5, ~m171_11
# 173| m173_8(int) = Store[e] : &:r173_1, r173_6
# 173| valnum = m173_8, r173_6
# 174| r174_1(glval<int>) = VariableAddress[f] :
# 174| valnum = unique
# 174| r174_2(glval<unknown>) = FunctionAddress[strlen] :
# 174| valnum = unique
# 174| r174_3(glval<char *>) = VariableAddress[src] :
# 174| valnum = r165_9, r168_3, r169_3, r171_4, r174_3
# 174| r174_4(char *) = Load[src] : &:r174_3, m165_10
# 174| valnum = m165_10, r165_11, r168_4, r169_4, r171_5, r174_4
# 174| r174_5(char *) = Convert : r174_4
# 174| valnum = r168_5, r169_5, r171_6, r174_5
# 174| r174_6(int) = Call[strlen] : func:r174_2, 0:r174_5
# 174| valnum = m168_8, m169_8, m174_8, r168_6, r169_6, r174_6
# 174| v174_7(void) = ^BufferReadSideEffect[0] : &:r174_5, ~m165_12
# 174| m174_8(int) = Store[f] : &:r174_1, r174_6
# 174| valnum = m168_8, m169_8, m174_8, r168_6, r169_6, r174_6
# 176| r176_1(glval<unknown>) = FunctionAddress[add] :
# 176| valnum = unique
# 176| r176_2(int) = Constant[1] :
# 176| valnum = r176_2, r178_2
# 176| r176_3(int) = Constant[2] :
# 176| valnum = r176_3, r178_3
# 176| r176_4(int) = Call[add] : func:r176_1, 0:r176_2, 1:r176_3
# 176| valnum = unique
# 177| r177_1(glval<unknown>) = FunctionAddress[add] :
# 177| valnum = unique
# 177| r177_2(int) = Constant[3] :
# 177| valnum = unique
# 177| r177_3(int) = Constant[4] :
# 177| valnum = unique
# 177| r177_4(int) = Call[add] : func:r177_1, 0:r177_2, 1:r177_3
# 177| valnum = unique
# 178| r178_1(glval<unknown>) = FunctionAddress[add] :
# 178| valnum = unique
# 178| r178_2(int) = Constant[1] :
# 178| valnum = r176_2, r178_2
# 178| r178_3(int) = Constant[2] :
# 178| valnum = r176_3, r178_3
# 178| r178_4(int) = Call[add] : func:r178_1, 0:r178_2, 1:r178_3
# 178| valnum = unique
# 179| v179_1(void) = NoOp :
# 165| v165_13(void) = ReturnIndirection[dst] : &:r165_7, m171_11
# 165| v165_14(void) = ReturnIndirection[src] : &:r165_11, m165_12
# 165| v165_15(void) = ReturnVoid :
# 165| v165_16(void) = AliasedUse : m165_3
# 165| v165_17(void) = ExitFunction :

View File

@@ -157,3 +157,23 @@ void test_read_global_different(int n) {
int d = global_a->x; int d = global_a->x;
} }
int strlen(const char *str);
char *strcat(char *dst, const char *src);
int add(int a, int b) { return a+b; }
void test_func_value_numbering(char *dst, char *src) {
int a = strlen(dst);
int b = strlen(dst); // same as previous line
int c = strlen(src);
int d = strlen(src); // same as previous line
strcat(dst, src);
int e = strlen(dst); // different from a and b
int f = strlen(src); // same as c and d
add(1, 2);
add(3, 4);
add(1, 2); // same as two lines earlier
}

View File

@@ -1,3 +1,3 @@
| empty_block.cpp:9:10:9:11 | { ... } | Empty block without comment | | empty_block.cpp:9:10:9:11 | { ... } | Empty block without comment. |
| empty_block.cpp:12:10:13:3 | { ... } | Empty block without comment | | empty_block.cpp:12:10:13:3 | { ... } | Empty block without comment. |
| empty_block.cpp:20:10:21:3 | { ... } | Empty block without comment | | empty_block.cpp:20:10:21:3 | { ... } | Empty block without comment. |

View File

@@ -1,20 +1,20 @@
| test2.cpp:37:1:37:39 | // int myFunction() { return myValue; } | This comment appears to contain commented-out code | | test2.cpp:37:1:37:39 | // int myFunction() { return myValue; } | This comment appears to contain commented-out code. |
| test2.cpp:39:1:39:45 | // int myFunction() const { return myValue; } | This comment appears to contain commented-out code | | test2.cpp:39:1:39:45 | // int myFunction() const { return myValue; } | This comment appears to contain commented-out code. |
| test2.cpp:41:1:41:54 | // int myFunction() const noexcept { return myValue; } | This comment appears to contain commented-out code | | test2.cpp:41:1:41:54 | // int myFunction() const noexcept { return myValue; } | This comment appears to contain commented-out code. |
| test2.cpp:43:1:43:18 | // #define MYMACRO | This comment appears to contain commented-out code | | test2.cpp:43:1:43:18 | // #define MYMACRO | This comment appears to contain commented-out code. |
| test2.cpp:45:1:45:23 | // #include "include.h" | This comment appears to contain commented-out code | | test2.cpp:45:1:45:23 | // #include "include.h" | This comment appears to contain commented-out code. |
| test2.cpp:47:1:51:2 | /*\n#ifdef\nvoid myFunction();\n#endif\n*/ | This comment appears to contain commented-out code | | test2.cpp:47:1:51:2 | /*\n#ifdef\nvoid myFunction();\n#endif\n*/ | This comment appears to contain commented-out code. |
| test2.cpp:59:1:59:24 | // #if(defined(MYMACRO)) | This comment appears to contain commented-out code | | test2.cpp:59:1:59:24 | // #if(defined(MYMACRO)) | This comment appears to contain commented-out code. |
| test2.cpp:63:1:63:15 | // #pragma once | This comment appears to contain commented-out code | | test2.cpp:63:1:63:15 | // #pragma once | This comment appears to contain commented-out code. |
| test2.cpp:65:1:65:17 | // # pragma once | This comment appears to contain commented-out code | | test2.cpp:65:1:65:17 | // # pragma once | This comment appears to contain commented-out code. |
| test2.cpp:67:1:67:19 | /*#error"myerror"*/ | This comment appears to contain commented-out code | | test2.cpp:67:1:67:19 | /*#error"myerror"*/ | This comment appears to contain commented-out code. |
| test2.cpp:91:1:95:2 | /*\n#ifdef MYMACRO\n\t// ...\n#endif // #ifdef MYMACRO\n*/ | This comment appears to contain commented-out code | | test2.cpp:91:1:95:2 | /*\n#ifdef MYMACRO\n\t// ...\n#endif // #ifdef MYMACRO\n*/ | This comment appears to contain commented-out code. |
| test2.cpp:107:21:107:43 | // #include "config2.h" | This comment appears to contain commented-out code | | test2.cpp:107:21:107:43 | // #include "config2.h" | This comment appears to contain commented-out code. |
| test2.cpp:115:16:115:35 | /* #ifdef MYMACRO */ | This comment appears to contain commented-out code | | test2.cpp:115:16:115:35 | /* #ifdef MYMACRO */ | This comment appears to contain commented-out code. |
| test2.cpp:117:1:117:24 | // commented_out_code(); | This comment appears to contain commented-out code | | test2.cpp:117:1:117:24 | // commented_out_code(); | This comment appears to contain commented-out code. |
| test2.cpp:120:2:120:25 | // commented_out_code(); | This comment appears to contain commented-out code | | test2.cpp:120:2:120:25 | // commented_out_code(); | This comment appears to contain commented-out code. |
| test.c:2:1:2:22 | // commented out code; | This comment appears to contain commented-out code | | test.c:2:1:2:22 | // commented out code; | This comment appears to contain commented-out code. |
| test.c:4:1:7:8 | // some; | This comment appears to contain commented-out code | | test.c:4:1:7:8 | // some; | This comment appears to contain commented-out code. |
| test.c:9:1:13:8 | // also; | This comment appears to contain commented-out code | | test.c:9:1:13:8 | // also; | This comment appears to contain commented-out code. |
| test.c:21:1:26:2 | /*\n some;\n commented;\n out;\n code;\n*/ | This comment appears to contain commented-out code | | test.c:21:1:26:2 | /*\n some;\n commented;\n out;\n code;\n*/ | This comment appears to contain commented-out code. |
| test.c:28:1:34:2 | /*\n also;\n this\n is;\n commented-out\n code;\n*/ | This comment appears to contain commented-out code | | test.c:28:1:34:2 | /*\n also;\n this\n is;\n commented-out\n code;\n*/ | This comment appears to contain commented-out code. |

View File

@@ -1,4 +1,4 @@
| bsc.cpp:2:10:2:32 | ... > ... | Potential unsafe sign check of a bitwise operation. | | bsc.cpp:2:10:2:32 | ... > ... | Potentially unsafe sign check of a bitwise operation. |
| bsc.cpp:6:10:6:32 | ... > ... | Potential unsafe sign check of a bitwise operation. | | bsc.cpp:6:10:6:32 | ... > ... | Potentially unsafe sign check of a bitwise operation. |
| bsc.cpp:18:10:18:28 | ... > ... | Potential unsafe sign check of a bitwise operation. | | bsc.cpp:18:10:18:28 | ... > ... | Potentially unsafe sign check of a bitwise operation. |
| bsc.cpp:22:10:22:28 | ... < ... | Potential unsafe sign check of a bitwise operation. | | bsc.cpp:22:10:22:28 | ... < ... | Potentially unsafe sign check of a bitwise operation. |

View File

@@ -1,4 +1,4 @@
| c.c:10:5:10:10 | ... == ... | Equality test on floating point values may not behave as expected. | | c.c:10:5:10:10 | ... == ... | Equality checks on floating point values can yield unexpected results. |
| c.c:14:5:14:14 | ... == ... | Equality test on floating point values may not behave as expected. | | c.c:14:5:14:14 | ... == ... | Equality checks on floating point values can yield unexpected results. |
| c.c:16:5:16:12 | ... == ... | Equality test on floating point values may not behave as expected. | | c.c:16:5:16:12 | ... == ... | Equality checks on floating point values can yield unexpected results. |
| c.c:17:5:17:12 | ... == ... | Equality test on floating point values may not behave as expected. | | c.c:17:5:17:12 | ... == ... | Equality checks on floating point values can yield unexpected results. |

View File

@@ -64,10 +64,6 @@ edges
| test.cpp:201:5:201:17 | EnterFunction: maybe_deref_p | test.cpp:201:5:201:17 | VariableAddress: maybe_deref_p | | test.cpp:201:5:201:17 | EnterFunction: maybe_deref_p | test.cpp:201:5:201:17 | VariableAddress: maybe_deref_p |
| test.cpp:210:3:210:9 | Call: call to escape1 | test.cpp:201:5:201:17 | EnterFunction: maybe_deref_p | | test.cpp:210:3:210:9 | Call: call to escape1 | test.cpp:201:5:201:17 | EnterFunction: maybe_deref_p |
| test.cpp:210:3:210:9 | Call: call to escape1 | test.cpp:201:5:201:17 | VariableAddress: maybe_deref_p | | test.cpp:210:3:210:9 | Call: call to escape1 | test.cpp:201:5:201:17 | VariableAddress: maybe_deref_p |
| test.cpp:234:3:234:13 | Store: ... = ... | test.cpp:238:3:238:9 | Call: call to escape2 |
| test.cpp:238:3:238:9 | Call: call to escape2 | test.cpp:239:17:239:17 | Load: p |
| test.cpp:263:3:263:13 | Store: ... = ... | test.cpp:267:3:267:9 | Call: call to escape3 |
| test.cpp:267:3:267:9 | Call: call to escape3 | test.cpp:268:17:268:17 | Load: p |
#select #select
| test.cpp:15:16:15:16 | Load: p | test.cpp:10:3:10:13 | Store: ... = ... | test.cpp:15:16:15:16 | Load: p | Stack variable $@ escapes $@ and is used after it has expired. | test.cpp:9:7:9:7 | x | x | test.cpp:10:3:10:13 | Store: ... = ... | here | | test.cpp:15:16:15:16 | Load: p | test.cpp:10:3:10:13 | Store: ... = ... | test.cpp:15:16:15:16 | Load: p | Stack variable $@ escapes $@ and is used after it has expired. | test.cpp:9:7:9:7 | x | x | test.cpp:10:3:10:13 | Store: ... = ... | here |
| test.cpp:24:16:24:16 | Load: p | test.cpp:10:3:10:13 | Store: ... = ... | test.cpp:24:16:24:16 | Load: p | Stack variable $@ escapes $@ and is used after it has expired. | test.cpp:9:7:9:7 | x | x | test.cpp:10:3:10:13 | Store: ... = ... | here | | test.cpp:24:16:24:16 | Load: p | test.cpp:10:3:10:13 | Store: ... = ... | test.cpp:24:16:24:16 | Load: p | Stack variable $@ escapes $@ and is used after it has expired. | test.cpp:9:7:9:7 | x | x | test.cpp:10:3:10:13 | Store: ... = ... | here |
@@ -94,5 +90,3 @@ edges
| test.cpp:180:14:180:19 | Load: * ... | test.cpp:154:3:154:22 | Store: ... = ... | test.cpp:180:14:180:19 | Load: * ... | Stack variable $@ escapes $@ and is used after it has expired. | test.cpp:133:7:133:8 | b2 | b2 | test.cpp:154:3:154:22 | Store: ... = ... | here | | test.cpp:180:14:180:19 | Load: * ... | test.cpp:154:3:154:22 | Store: ... = ... | test.cpp:180:14:180:19 | Load: * ... | Stack variable $@ escapes $@ and is used after it has expired. | test.cpp:133:7:133:8 | b2 | b2 | test.cpp:154:3:154:22 | Store: ... = ... | here |
| test.cpp:181:13:181:20 | Load: access to array | test.cpp:155:3:155:21 | Store: ... = ... | test.cpp:181:13:181:20 | Load: access to array | Stack variable $@ escapes $@ and is used after it has expired. | test.cpp:134:7:134:8 | b3 | b3 | test.cpp:155:3:155:21 | Store: ... = ... | here | | test.cpp:181:13:181:20 | Load: access to array | test.cpp:155:3:155:21 | Store: ... = ... | test.cpp:181:13:181:20 | Load: access to array | Stack variable $@ escapes $@ and is used after it has expired. | test.cpp:134:7:134:8 | b3 | b3 | test.cpp:155:3:155:21 | Store: ... = ... | here |
| test.cpp:182:14:182:19 | Load: * ... | test.cpp:156:3:156:25 | Store: ... = ... | test.cpp:182:14:182:19 | Load: * ... | Stack variable $@ escapes $@ and is used after it has expired. | test.cpp:134:7:134:8 | b3 | b3 | test.cpp:156:3:156:25 | Store: ... = ... | here | | test.cpp:182:14:182:19 | Load: * ... | test.cpp:156:3:156:25 | Store: ... = ... | test.cpp:182:14:182:19 | Load: * ... | Stack variable $@ escapes $@ and is used after it has expired. | test.cpp:134:7:134:8 | b3 | b3 | test.cpp:156:3:156:25 | Store: ... = ... | here |
| test.cpp:239:17:239:17 | Load: p | test.cpp:234:3:234:13 | Store: ... = ... | test.cpp:239:17:239:17 | Load: p | Stack variable $@ escapes $@ and is used after it has expired. | test.cpp:232:7:232:7 | x | x | test.cpp:234:3:234:13 | Store: ... = ... | here |
| test.cpp:268:17:268:17 | Load: p | test.cpp:263:3:263:13 | Store: ... = ... | test.cpp:268:17:268:17 | Load: p | Stack variable $@ escapes $@ and is used after it has expired. | test.cpp:260:7:260:7 | x | x | test.cpp:263:3:263:13 | Store: ... = ... | here |

View File

@@ -210,60 +210,3 @@ int field_indirect_maybe_bad(bool b) {
escape1(); escape1();
return maybe_deref_p(b); return maybe_deref_p(b);
} }
// These next tests cover subsequent stores to the same address in the same basic block.
static struct S100 s102;
void not_escape1() {
int x;
s102.p = &x;
s102.p = nullptr;
}
void calls_not_escape1() {
not_escape1();
int x = *s102.p; // GOOD
}
static struct S100 s103;
void escape2() {
int x;
s103.p = nullptr;
s103.p = &x;
}
void calls_escape2() {
escape2();
int x = *s103.p; // BAD
}
bool unknown();
static struct S100 s104;
void not_escape2() {
int x;
s104.p = &x;
if(unknown()) { }
s104.p = nullptr;
}
void calls_not_escape2() {
not_escape2();
int x = *s104.p; // GOOD
}
static struct S100 s105;
void escape3() {
int x;
s105.p = nullptr;
if(unknown()) { }
s105.p = &x;
}
void calls_escape3() {
escape3();
int x = *s105.p; // BAD
}

View File

@@ -1,7 +1,3 @@
## 1.2.5
## 1.2.4
## 1.2.3 ## 1.2.3
## 1.2.2 ## 1.2.2

View File

@@ -1,2 +1,2 @@
--- ---
lastReleaseVersion: 1.2.5 lastReleaseVersion: 1.2.3

View File

@@ -1,5 +1,5 @@
name: codeql/csharp-solorigate-all name: codeql/csharp-solorigate-all
version: 1.2.6-dev version: 1.2.4-dev
groups: groups:
- csharp - csharp
- solorigate - solorigate

View File

@@ -1,7 +1,3 @@
## 1.2.5
## 1.2.4
## 1.2.3 ## 1.2.3
## 1.2.2 ## 1.2.2

View File

@@ -1,2 +1,2 @@
--- ---
lastReleaseVersion: 1.2.5 lastReleaseVersion: 1.2.3

View File

@@ -1,5 +1,5 @@
name: codeql/csharp-solorigate-queries name: codeql/csharp-solorigate-queries
version: 1.2.6-dev version: 1.2.4-dev
groups: groups:
- csharp - csharp
- solorigate - solorigate

View File

@@ -1,16 +1,3 @@
## 0.3.5
## 0.3.4
### Deprecated APIs
* Many classes/predicates/modules with upper-case acronyms in their name have been renamed to follow our style-guide.
The old name still exists as a deprecated alias.
### Minor Analysis Improvements
* All deprecated predicates/classes/modules that have been deprecated for over a year have been deleted.
## 0.3.3 ## 0.3.3
## 0.3.2 ## 0.3.2

View File

@@ -0,0 +1,6 @@
---
category: minorAnalysis
---
* All deprecated predicates/classes/modules that have been deprecated for over a year have been
deleted.

View File

@@ -0,0 +1,5 @@
---
category: deprecated
---
* Many classes/predicates/modules with upper-case acronyms in their name have been renamed to follow our style-guide.
The old name still exists as a deprecated alias.

View File

@@ -1,10 +0,0 @@
## 0.3.4
### Deprecated APIs
* Many classes/predicates/modules with upper-case acronyms in their name have been renamed to follow our style-guide.
The old name still exists as a deprecated alias.
### Minor Analysis Improvements
* All deprecated predicates/classes/modules that have been deprecated for over a year have been deleted.

View File

@@ -1 +0,0 @@
## 0.3.5

View File

@@ -1,2 +1,2 @@
--- ---
lastReleaseVersion: 0.3.5 lastReleaseVersion: 0.3.3

View File

@@ -1,5 +1,5 @@
name: codeql/csharp-all name: codeql/csharp-all
version: 0.3.6-dev version: 0.3.4-dev
groups: csharp groups: csharp
dbscheme: semmlecode.csharp.dbscheme dbscheme: semmlecode.csharp.dbscheme
extractor: csharp extractor: csharp

View File

@@ -14,4 +14,4 @@ import csharp
from CommentLine c from CommentLine c
where c.getText().regexpMatch("(?s).*FIXME.*|.*TODO.*|.*(?<!=)\\s*XXX.*") where c.getText().regexpMatch("(?s).*FIXME.*|.*TODO.*|.*(?<!=)\\s*XXX.*")
select c, "TODO comment." select c, "TODO comments should be addressed."

View File

@@ -72,5 +72,5 @@ where
) and ) and
m1.fromSource() m1.fromSource()
select m1, select m1,
"confusing to have methods " + m1.getName() + " in " + m1.getDeclaringType().getName() + " and " + "It is confusing to have methods " + m1.getName() + " in " + m1.getDeclaringType().getName() +
m2.getName() + " in " + m2.getDeclaringType().getName() + "." " and " + m2.getName() + " in " + m2.getDeclaringType().getName() + "."

View File

@@ -1,14 +1,3 @@
## 0.3.4
## 0.3.3
### Minor Analysis Improvements
* Parameters of delegates passed to routing endpoint calls like `MapGet` in ASP.NET Core are now considered remote flow sources.
* The query `cs/unsafe-deserialization-untrusted-input` is not reporting on all calls of `JsonConvert.DeserializeObject` any longer, it only covers cases that explicitly use unsafe serialization settings.
* Added better support for the SQLite framework in the SQL injection query.
* File streams are now considered stored flow sources. For example, reading query elements from a file can lead to a Second Order SQL injection alert.
## 0.3.2 ## 0.3.2
## 0.3.1 ## 0.3.1

View File

@@ -64,6 +64,5 @@ where
validGuard.controls(array, index) and validGuard.controls(array, index) and
validGuard.guards(indexAccess, _) validGuard.guards(indexAccess, _)
) )
select incorrectGuard, select incorrectGuard, "Off-by-one index comparison against length may lead to out-of-bounds $@.",
"Off-by-one index comparison against length leads to possible out of bounds $@.", ea, ea, ea.toString()
ea.toString()

View File

@@ -1,6 +1,8 @@
/** /**
* @name Equality check on floating point values * @name Equality check on floating point values
* @description Equality checks on floating point values can yield unexpected results. * @description Comparing results of floating-point computations with '==' or
* '!=' is likely to yield surprising results since floating-point
* computation does not follow the standard rules of algebra.
* @kind problem * @kind problem
* @problem.severity warning * @problem.severity warning
* @precision medium * @precision medium

View File

@@ -42,4 +42,4 @@ where
(loopStmtWithEmptyBlock(s) or conditionalWithEmptyBlock(s)) and (loopStmtWithEmptyBlock(s) or conditionalWithEmptyBlock(s)) and
not exists(CommentBlock c | c.getParent() = s) and not exists(CommentBlock c | c.getParent() = s) and
not exists(ForStmt fs | fs.getBody() = s and exists(fs.getAnUpdate())) not exists(ForStmt fs | fs.getBody() = s and exists(fs.getAnUpdate()))
select s, "Empty block." select s, "Empty block without comment."

View File

@@ -35,4 +35,4 @@ where
access = cast.getAChild() and access = cast.getAChild() and
access.getTarget().getDeclaringElement() = access.getEnclosingCallable() and access.getTarget().getDeclaringElement() = access.getEnclosingCallable() and
nodeBeforeParameterAccess(access.getAControlFlowNode()) nodeBeforeParameterAccess(access.getAControlFlowNode())
select cast, "Missing type-check before casting parameter to 'Equals'." select cast, "Equals() method does not check argument type."

View File

@@ -23,5 +23,5 @@ where
c.hasFlowPath(source, sink) and c.hasFlowPath(source, sink) and
// No global timeout set // No global timeout set
not exists(RegexGlobalTimeout r) not exists(RegexGlobalTimeout r)
select sink.getNode(), source, sink, "$@ flows to the construction of a regular expression.", select sink.getNode(), source, sink, "This regular expression is constructed from a $@.",
source.getNode(), "User-provided value" source.getNode(), "user-provided value"

View File

@@ -18,4 +18,4 @@ from MethodCall mc
where where
mc instanceof ImplicitToStringExpr and mc instanceof ImplicitToStringExpr and
mc.getTarget() instanceof ToStringMethod mc.getTarget() instanceof ToStringMethod
select mc, "Redundant call to 'ToString'." select mc, "Redundant call to 'ToString' on a String object."

View File

@@ -0,0 +1,5 @@
---
category: minorAnalysis
---
* Added better support for the SQLite framework in the SQL injection query.
* File streams are now considered stored flow sources. Eg. reading query elements from a file can lead to a Second Order SQL injection alert.

View File

@@ -0,0 +1,4 @@
---
category: minorAnalysis
---
* The query `cs/unsafe-deserialization-untrusted-input` is not reporting on all calls of `JsonConvert.DeserializeObject` any longer, it only covers cases that explicitly use unsafe serialization settings.

View File

@@ -0,0 +1,4 @@
---
category: minorAnalysis
---
* Parameters of delegates passed to routing endpoint calls like `MapGet` in ASP.NET Core are now considered remote flow sources.

View File

@@ -0,0 +1,4 @@
---
category: minorAnalysis
---
* The alert message of many queries have been changed to make the message consistent with other languages.

View File

@@ -1,8 +0,0 @@
## 0.3.3
### Minor Analysis Improvements
* Parameters of delegates passed to routing endpoint calls like `MapGet` in ASP.NET Core are now considered remote flow sources.
* The query `cs/unsafe-deserialization-untrusted-input` is not reporting on all calls of `JsonConvert.DeserializeObject` any longer, it only covers cases that explicitly use unsafe serialization settings.
* Added better support for the SQLite framework in the SQL injection query.
* File streams are now considered stored flow sources. For example, reading query elements from a file can lead to a Second Order SQL injection alert.

View File

@@ -1 +0,0 @@
## 0.3.4

View File

@@ -1,2 +1,2 @@
--- ---
lastReleaseVersion: 0.3.4 lastReleaseVersion: 0.3.2

View File

@@ -17,3 +17,5 @@ module SSA {
predicate hasUnreachedInstruction(IRFunctionBase irFunc) { none() } predicate hasUnreachedInstruction(IRFunctionBase irFunc) { none() }
} }
predicate removedInstruction(TRawInstruction instr) { none() }

View File

@@ -34,6 +34,7 @@ newtype TInstruction =
AliasedSsa::SSA::hasPhiInstruction(blockStartInstr, memoryLocation) AliasedSsa::SSA::hasPhiInstruction(blockStartInstr, memoryLocation)
} or } or
TAliasedSsaChiInstruction(TRawInstruction primaryInstruction) { TAliasedSsaChiInstruction(TRawInstruction primaryInstruction) {
not AliasedSsa::removedInstruction(primaryInstruction) and
AliasedSsa::SSA::hasChiInstruction(primaryInstruction) AliasedSsa::SSA::hasChiInstruction(primaryInstruction)
} or } or
TAliasedSsaUnreachedInstruction(IRFunctionBase irFunc) { TAliasedSsaUnreachedInstruction(IRFunctionBase irFunc) {

View File

@@ -1712,6 +1712,11 @@ class SideEffectInstruction extends Instruction {
*/ */
class CallSideEffectInstruction extends SideEffectInstruction { class CallSideEffectInstruction extends SideEffectInstruction {
CallSideEffectInstruction() { this.getOpcode() instanceof Opcode::CallSideEffect } CallSideEffectInstruction() { this.getOpcode() instanceof Opcode::CallSideEffect }
/** Gets the operand for the value that will be read by this instruction */
final SideEffectOperand getSideEffectOperand() { result = this.getAnOperand() }
final Instruction getSideEffect() { result = this.getAnOperand().getDef() }
} }
/** /**
@@ -1723,6 +1728,11 @@ class CallSideEffectInstruction extends SideEffectInstruction {
*/ */
class CallReadSideEffectInstruction extends SideEffectInstruction { class CallReadSideEffectInstruction extends SideEffectInstruction {
CallReadSideEffectInstruction() { this.getOpcode() instanceof Opcode::CallReadSideEffect } CallReadSideEffectInstruction() { this.getOpcode() instanceof Opcode::CallReadSideEffect }
/** Gets the operand for the value that will be read by this instruction */
final SideEffectOperand getSideEffectOperand() { result = this.getAnOperand() }
final Instruction getSideEffect() { result = this.getAnOperand().getDef() }
} }
/** /**

View File

@@ -1,3 +1,4 @@
import experimental.ir.internal.Overlap import experimental.ir.internal.Overlap
import experimental.ir.internal.IRCSharpLanguage as Language import experimental.ir.internal.IRCSharpLanguage as Language
import experimental.ir.implementation.unaliased_ssa.IR import experimental.ir.implementation.unaliased_ssa.IR
import experimental.ir.interfaces.SideEffect as SideEffect

View File

@@ -41,8 +41,92 @@ newtype TValueNumber =
) { ) {
loadTotalOverlapValueNumber(_, irFunc, type, memOperand, operand) loadTotalOverlapValueNumber(_, irFunc, type, memOperand, operand)
} or } or
TCallValueNumber(TCallPartialValueNumber vn) { callValueNumber(_, _, vn) } or
TUniqueValueNumber(IRFunction irFunc, Instruction instr) { uniqueValueNumber(instr, irFunc) } TUniqueValueNumber(IRFunction irFunc, Instruction instr) { uniqueValueNumber(instr, irFunc) }
private class NumberableCallInstruction extends CallInstruction {
NumberableCallInstruction() {
not this.getResultIRType() instanceof IRVoidType and
exists(SideEffect::SideEffectFunction sideEffectFunc |
sideEffectFunc = this.getStaticCallTarget()
|
sideEffectFunc.hasOnlySpecificReadSideEffects() and
sideEffectFunc.hasOnlySpecificWriteSideEffects()
)
}
}
private newtype TCallPartialValueNumber =
TNilArgument() or
TArgument(TCallPartialValueNumber head, TValueNumber arg) {
exists(NumberableCallInstruction call, int index |
callArgValueNumber(call, index, arg) and
callPartialValueNumber(call, index, head)
)
}
private predicate callValueNumber(
NumberableCallInstruction call, int index, TCallPartialValueNumber vn
) {
index = max(int n | callArgRank(call, n, _) | n) and
exists(TCallPartialValueNumber head, TValueNumber arg |
callPartialValueNumber(call, index, pragma[only_bind_out](head)) and
callArgValueNumber(call, index, pragma[only_bind_into](arg)) and
vn = TArgument(head, arg)
)
or
not exists(int n | callArgRank(call, n, _)) and
index = -1 and
vn = TNilArgument()
}
private predicate callPartialValueNumber(
NumberableCallInstruction call, int index, TCallPartialValueNumber head
) {
exists(call) and
index = 1 and
head = TNilArgument()
or
exists(TCallPartialValueNumber prev, TValueNumber prevVN |
callPartialValueNumber(call, index - 1, pragma[only_bind_out](prev)) and
callArgValueNumber(call, index - 1, pragma[only_bind_into](prevVN)) and
head = TArgument(prev, prevVN)
)
}
/**
*/
private predicate callArgValueNumber(NumberableCallInstruction call, int index, TValueNumber arg) {
exists(Instruction instr |
callArgRank(call, index, instr) and
arg = tvalueNumber(instr)
)
}
/**
* Holds if `arg` is the `index`th element in `call`'s extended argument list, including the `this`
* argument and side-effect reads.
*/
private predicate callArgRank(NumberableCallInstruction call, int index, Instruction arg) {
arg =
rank[index](int argIndex, boolean isEffect, Instruction instr |
// There is no need to include the call's read and write side effects on
// all-aliased-memory as `NumberableCallInstruction`s do not read or write
// to all-aliased-memory.
instr = call.getArgument(argIndex) and
isEffect = false
or
exists(ReadSideEffectInstruction read |
read.getPrimaryInstruction() = call and
read.getSideEffectOperand().getAnyDef() = instr and
read.getIndex() = argIndex and
isEffect = true
)
|
instr order by argIndex, isEffect
)
}
/** /**
* A `CopyInstruction` whose source operand's value is congruent to the definition of that source * A `CopyInstruction` whose source operand's value is congruent to the definition of that source
* operand. * operand.
@@ -93,6 +177,8 @@ private predicate numberableInstruction(Instruction instr) {
instr instanceof CongruentCopyInstruction instr instanceof CongruentCopyInstruction
or or
instr instanceof LoadTotalOverlapInstruction instr instanceof LoadTotalOverlapInstruction
or
instr instanceof NumberableCallInstruction
} }
private predicate filteredNumberableInstruction(Instruction instr) { private predicate filteredNumberableInstruction(Instruction instr) {
@@ -309,6 +395,11 @@ private TValueNumber nonUniqueValueNumber(Instruction instr) {
or or
// The value number of a copy is just the value number of its source value. // The value number of a copy is just the value number of its source value.
result = tvalueNumber(instr.(CongruentCopyInstruction).getSourceValue()) result = tvalueNumber(instr.(CongruentCopyInstruction).getSourceValue())
or
exists(TCallPartialValueNumber pvn |
callValueNumber(instr, _, pvn) and
result = TCallValueNumber(pvn)
)
) )
) )
} }

View File

@@ -1712,6 +1712,11 @@ class SideEffectInstruction extends Instruction {
*/ */
class CallSideEffectInstruction extends SideEffectInstruction { class CallSideEffectInstruction extends SideEffectInstruction {
CallSideEffectInstruction() { this.getOpcode() instanceof Opcode::CallSideEffect } CallSideEffectInstruction() { this.getOpcode() instanceof Opcode::CallSideEffect }
/** Gets the operand for the value that will be read by this instruction */
final SideEffectOperand getSideEffectOperand() { result = this.getAnOperand() }
final Instruction getSideEffect() { result = this.getAnOperand().getDef() }
} }
/** /**
@@ -1723,6 +1728,11 @@ class CallSideEffectInstruction extends SideEffectInstruction {
*/ */
class CallReadSideEffectInstruction extends SideEffectInstruction { class CallReadSideEffectInstruction extends SideEffectInstruction {
CallReadSideEffectInstruction() { this.getOpcode() instanceof Opcode::CallReadSideEffect } CallReadSideEffectInstruction() { this.getOpcode() instanceof Opcode::CallReadSideEffect }
/** Gets the operand for the value that will be read by this instruction */
final SideEffectOperand getSideEffectOperand() { result = this.getAnOperand() }
final Instruction getSideEffect() { result = this.getAnOperand().getDef() }
} }
/** /**

View File

@@ -1,3 +1,4 @@
import experimental.ir.internal.Overlap import experimental.ir.internal.Overlap
import experimental.ir.internal.IRCSharpLanguage as Language import experimental.ir.internal.IRCSharpLanguage as Language
import experimental.ir.implementation.unaliased_ssa.IR import experimental.ir.implementation.unaliased_ssa.IR
import experimental.ir.interfaces.SideEffect as SideEffect

View File

@@ -41,8 +41,92 @@ newtype TValueNumber =
) { ) {
loadTotalOverlapValueNumber(_, irFunc, type, memOperand, operand) loadTotalOverlapValueNumber(_, irFunc, type, memOperand, operand)
} or } or
TCallValueNumber(TCallPartialValueNumber vn) { callValueNumber(_, _, vn) } or
TUniqueValueNumber(IRFunction irFunc, Instruction instr) { uniqueValueNumber(instr, irFunc) } TUniqueValueNumber(IRFunction irFunc, Instruction instr) { uniqueValueNumber(instr, irFunc) }
private class NumberableCallInstruction extends CallInstruction {
NumberableCallInstruction() {
not this.getResultIRType() instanceof IRVoidType and
exists(SideEffect::SideEffectFunction sideEffectFunc |
sideEffectFunc = this.getStaticCallTarget()
|
sideEffectFunc.hasOnlySpecificReadSideEffects() and
sideEffectFunc.hasOnlySpecificWriteSideEffects()
)
}
}
private newtype TCallPartialValueNumber =
TNilArgument() or
TArgument(TCallPartialValueNumber head, TValueNumber arg) {
exists(NumberableCallInstruction call, int index |
callArgValueNumber(call, index, arg) and
callPartialValueNumber(call, index, head)
)
}
private predicate callValueNumber(
NumberableCallInstruction call, int index, TCallPartialValueNumber vn
) {
index = max(int n | callArgRank(call, n, _) | n) and
exists(TCallPartialValueNumber head, TValueNumber arg |
callPartialValueNumber(call, index, pragma[only_bind_out](head)) and
callArgValueNumber(call, index, pragma[only_bind_into](arg)) and
vn = TArgument(head, arg)
)
or
not exists(int n | callArgRank(call, n, _)) and
index = -1 and
vn = TNilArgument()
}
private predicate callPartialValueNumber(
NumberableCallInstruction call, int index, TCallPartialValueNumber head
) {
exists(call) and
index = 1 and
head = TNilArgument()
or
exists(TCallPartialValueNumber prev, TValueNumber prevVN |
callPartialValueNumber(call, index - 1, pragma[only_bind_out](prev)) and
callArgValueNumber(call, index - 1, pragma[only_bind_into](prevVN)) and
head = TArgument(prev, prevVN)
)
}
/**
*/
private predicate callArgValueNumber(NumberableCallInstruction call, int index, TValueNumber arg) {
exists(Instruction instr |
callArgRank(call, index, instr) and
arg = tvalueNumber(instr)
)
}
/**
* Holds if `arg` is the `index`th element in `call`'s extended argument list, including the `this`
* argument and side-effect reads.
*/
private predicate callArgRank(NumberableCallInstruction call, int index, Instruction arg) {
arg =
rank[index](int argIndex, boolean isEffect, Instruction instr |
// There is no need to include the call's read and write side effects on
// all-aliased-memory as `NumberableCallInstruction`s do not read or write
// to all-aliased-memory.
instr = call.getArgument(argIndex) and
isEffect = false
or
exists(ReadSideEffectInstruction read |
read.getPrimaryInstruction() = call and
read.getSideEffectOperand().getAnyDef() = instr and
read.getIndex() = argIndex and
isEffect = true
)
|
instr order by argIndex, isEffect
)
}
/** /**
* A `CopyInstruction` whose source operand's value is congruent to the definition of that source * A `CopyInstruction` whose source operand's value is congruent to the definition of that source
* operand. * operand.
@@ -93,6 +177,8 @@ private predicate numberableInstruction(Instruction instr) {
instr instanceof CongruentCopyInstruction instr instanceof CongruentCopyInstruction
or or
instr instanceof LoadTotalOverlapInstruction instr instanceof LoadTotalOverlapInstruction
or
instr instanceof NumberableCallInstruction
} }
private predicate filteredNumberableInstruction(Instruction instr) { private predicate filteredNumberableInstruction(Instruction instr) {
@@ -309,6 +395,11 @@ private TValueNumber nonUniqueValueNumber(Instruction instr) {
or or
// The value number of a copy is just the value number of its source value. // The value number of a copy is just the value number of its source value.
result = tvalueNumber(instr.(CongruentCopyInstruction).getSourceValue()) result = tvalueNumber(instr.(CongruentCopyInstruction).getSourceValue())
or
exists(TCallPartialValueNumber pvn |
callValueNumber(instr, _, pvn) and
result = TCallValueNumber(pvn)
)
) )
) )
} }

View File

@@ -8,11 +8,6 @@ private import Imports::RawIR as RawIR
private import SsaInstructions private import SsaInstructions
private import SsaOperands private import SsaOperands
private import NewIR private import NewIR
private class OldBlock = Reachability::ReachableBlock;
private class OldInstruction = Reachability::ReachableInstruction;
import Cached import Cached
cached cached
@@ -58,7 +53,9 @@ private module Cached {
cached cached
predicate hasInstruction(TStageInstruction instr) { predicate hasInstruction(TStageInstruction instr) {
instr instanceof TRawInstruction and instr instanceof OldInstruction instr instanceof TRawInstruction and
instr instanceof OldInstruction and
not removedInstruction(instr)
or or
instr = phiInstruction(_, _) instr = phiInstruction(_, _)
or or
@@ -382,7 +379,14 @@ private module Cached {
( (
if Reachability::isInfeasibleInstructionSuccessor(oldInstruction, kind) if Reachability::isInfeasibleInstructionSuccessor(oldInstruction, kind)
then result = unreachedInstruction(instruction.getEnclosingIRFunction()) then result = unreachedInstruction(instruction.getEnclosingIRFunction())
else result = getNewInstruction(oldInstruction.getSuccessor(kind)) else
if removedInstruction(oldInstruction.getSuccessor(kind))
then
// the only removed nodes are side-effect writes, but those may have Chi nodes
// skip to the following instruction in the old IR, which won't be removed
// if we start skipping specific side effects, this may no longer hold
result = getNewInstruction(oldInstruction.getSuccessor(kind).getSuccessor(kind))
else result = getNewInstruction(oldInstruction.getSuccessor(kind))
) )
) )
or or

View File

@@ -14,3 +14,9 @@ import experimental.ir.implementation.internal.TOperand::UnaliasedSsaOperands as
/** DEPRECATED: Alias for SsaOperands */ /** DEPRECATED: Alias for SsaOperands */
deprecated module SSAOperands = SsaOperands; deprecated module SSAOperands = SsaOperands;
predicate removedInstruction(Reachability::ReachableInstruction instr) { none() }
class OldBlock = Reachability::ReachableBlock;
class OldInstruction = Reachability::ReachableInstruction;

View File

@@ -0,0 +1,24 @@
private import csharp as CSharp
/**
* A class that models the side effects of a library function.
*/
abstract class SideEffectFunction extends CSharp::Callable {
/**
* Holds if the function never reads from memory that was defined before entry to the function.
* This memory could be from global variables, or from other memory that was reachable from a
* pointer that was passed into the function. Input side-effects, and reads from memory that
* cannot be visible to the caller (for example a buffer inside an I/O library) are not modeled
* here.
*/
abstract predicate hasOnlySpecificReadSideEffects();
/**
* Holds if the function never writes to memory that remains allocated after the function
* returns. This memory could be from global variables, or from other memory that was reachable
* from a pointer that was passed into the function. Output side-effects, and writes to memory
* that cannot be visible to the caller (for example a buffer inside an I/O library) are not
* modeled here.
*/
abstract predicate hasOnlySpecificWriteSideEffects();
}

View File

@@ -1,5 +1,5 @@
name: codeql/csharp-queries name: codeql/csharp-queries
version: 0.3.5-dev version: 0.3.3-dev
groups: groups:
- csharp - csharp
- queries - queries

View File

@@ -1,3 +1,3 @@
| TodoComments.cs:4:5:4:26 | // ... | TODO comment. | | TodoComments.cs:4:5:4:26 | // ... | TODO comments should be addressed. |
| TodoComments.cs:5:5:5:27 | // ... | TODO comment. | | TodoComments.cs:5:5:5:27 | // ... | TODO comments should be addressed. |
| TodoCommentsBad.cs:7:9:7:41 | // ... | TODO comment. | | TodoCommentsBad.cs:7:9:7:41 | // ... | TODO comments should be addressed. |

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