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
153 changed files with 2649 additions and 1793 deletions

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

@@ -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,6 +379,13 @@ private module Cached {
( (
if Reachability::isInfeasibleInstructionSuccessor(oldInstruction, kind) if Reachability::isInfeasibleInstructionSuccessor(oldInstruction, kind)
then result = unreachedInstruction(instruction.getEnclosingIRFunction()) then result = unreachedInstruction(instruction.getEnclosingIRFunction())
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)) else result = getNewInstruction(oldInstruction.getSuccessor(kind))
) )
) )

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,6 +379,13 @@ private module Cached {
( (
if Reachability::isInfeasibleInstructionSuccessor(oldInstruction, kind) if Reachability::isInfeasibleInstructionSuccessor(oldInstruction, kind)
then result = unreachedInstruction(instruction.getEnclosingIRFunction()) then result = unreachedInstruction(instruction.getEnclosingIRFunction())
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)) else result = getNewInstruction(oldInstruction.getSuccessor(kind))
) )
) )

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

@@ -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

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

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

@@ -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

@@ -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,4 @@
---
category: minorAnalysis
---
* The alert message of many queries have been changed to make the message consistent with other languages.

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,6 +379,13 @@ private module Cached {
( (
if Reachability::isInfeasibleInstructionSuccessor(oldInstruction, kind) if Reachability::isInfeasibleInstructionSuccessor(oldInstruction, kind)
then result = unreachedInstruction(instruction.getEnclosingIRFunction()) then result = unreachedInstruction(instruction.getEnclosingIRFunction())
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)) else result = getNewInstruction(oldInstruction.getSuccessor(kind))
) )
) )

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,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. |

View File

@@ -1,3 +1,3 @@
| EmptyBlock.cs:9:9:10:9 | {...} | Empty block. | | EmptyBlock.cs:9:9:10:9 | {...} | Empty block without comment. |
| EmptyBlock.cs:26:9:27:9 | {...} | Empty block. | | EmptyBlock.cs:26:9:27:9 | {...} | Empty block without comment. |
| EmptyBlock.cs:48:9:49:9 | {...} | Empty block. | | EmptyBlock.cs:48:9:49:9 | {...} | Empty block without comment. |

View File

@@ -1,4 +1,4 @@
| ContainerLengthCmpOffByOne.cs:8:25:8:40 | ... <= ... | Off-by-one index comparison against length leads to possible out of bounds $@. | ContainerLengthCmpOffByOne.cs:10:31:10:37 | access to array element | access to array element | | ContainerLengthCmpOffByOne.cs:8:25:8:40 | ... <= ... | Off-by-one index comparison against length may lead to out-of-bounds $@. | ContainerLengthCmpOffByOne.cs:10:31:10:37 | access to array element | access to array element |
| ContainerLengthCmpOffByOne.cs:14:25:14:40 | ... >= ... | Off-by-one index comparison against length leads to possible out of bounds $@. | ContainerLengthCmpOffByOne.cs:16:31:16:37 | access to array element | access to array element | | ContainerLengthCmpOffByOne.cs:14:25:14:40 | ... >= ... | Off-by-one index comparison against length may lead to out-of-bounds $@. | ContainerLengthCmpOffByOne.cs:16:31:16:37 | access to array element | access to array element |
| ContainerLengthCmpOffByOne.cs:27:13:27:28 | ... <= ... | Off-by-one index comparison against length leads to possible out of bounds $@. | ContainerLengthCmpOffByOne.cs:29:31:29:37 | access to array element | access to array element | | ContainerLengthCmpOffByOne.cs:27:13:27:28 | ... <= ... | Off-by-one index comparison against length may lead to out-of-bounds $@. | ContainerLengthCmpOffByOne.cs:29:31:29:37 | access to array element | access to array element |
| ContainerLengthCmpOffByOne.cs:33:13:33:28 | ... >= ... | Off-by-one index comparison against length leads to possible out of bounds $@. | ContainerLengthCmpOffByOne.cs:35:31:35:37 | access to array element | access to array element | | ContainerLengthCmpOffByOne.cs:33:13:33:28 | ... >= ... | Off-by-one index comparison against length may lead to out-of-bounds $@. | ContainerLengthCmpOffByOne.cs:35:31:35:37 | access to array element | access to array element |

View File

@@ -1 +1 @@
| UncheckedCastInEquals.cs:7:17:7:27 | (...) ... | Missing type-check before casting parameter to 'Equals'. | | UncheckedCastInEquals.cs:7:17:7:27 | (...) ... | Equals() method does not check argument type. |

View File

@@ -8,4 +8,4 @@ nodes
| RegexInjection.cs:14:19:14:23 | access to local variable regex | semmle.label | access to local variable regex | | RegexInjection.cs:14:19:14:23 | access to local variable regex | semmle.label | access to local variable regex |
subpaths subpaths
#select #select
| RegexInjection.cs:14:19:14:23 | access to local variable regex | RegexInjection.cs:10:24:10:46 | access to property QueryString : NameValueCollection | RegexInjection.cs:14:19:14:23 | access to local variable regex | $@ flows to the construction of a regular expression. | RegexInjection.cs:10:24:10:46 | access to property QueryString | User-provided value | | RegexInjection.cs:14:19:14:23 | access to local variable regex | RegexInjection.cs:10:24:10:46 | access to property QueryString : NameValueCollection | RegexInjection.cs:14:19:14:23 | access to local variable regex | This regular expression is constructed from a $@. | RegexInjection.cs:10:24:10:46 | access to property QueryString | user-provided value |

View File

@@ -1,3 +1,3 @@
| RedundantToStringCall.cs:7:27:7:38 | call to method ToString | Redundant call to 'ToString'. | | RedundantToStringCall.cs:7:27:7:38 | call to method ToString | Redundant call to 'ToString' on a String object. |
| RedundantToStringCall.cs:10:37:10:48 | call to method ToString | Redundant call to 'ToString'. | | RedundantToStringCall.cs:10:37:10:48 | call to method ToString | Redundant call to 'ToString' on a String object. |
| RedundantToStringCallBad.cs:7:45:7:56 | call to method ToString | Redundant call to 'ToString'. | | RedundantToStringCallBad.cs:7:45:7:56 | call to method ToString | Redundant call to 'ToString' on a String object. |

View File

@@ -21,5 +21,5 @@ import DataFlow::PathGraph
from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink
where cfg.hasFlowPath(source, sink) where cfg.hasFlowPath(source, sink)
select sink.getNode(), source, sink, "This path depends on $@.", source.getNode(), select sink.getNode(), source, sink, "$@ flows to here and is used in a path.", source.getNode(),
"a user-provided value" "User-provided value"

View File

@@ -76,5 +76,6 @@ class StackTraceExposureConfig extends TaintTracking::Configuration {
from StackTraceExposureConfig cfg, DataFlow::PathNode source, DataFlow::PathNode sink from StackTraceExposureConfig cfg, DataFlow::PathNode source, DataFlow::PathNode sink
where cfg.hasFlowPath(source, sink) where cfg.hasFlowPath(source, sink)
select source.getNode(), source, sink, "This stack trace is exposed to a remote user $@.", select sink.getNode(), source, sink,
sink.getNode(), "here" "Stack trace information from $@ may be exposed to an external user here.", source.getNode(),
"here"

View File

@@ -24,5 +24,5 @@ predicate isStringOrByte(DataFlow::PathNode node) {
from Configuration config, DataFlow::PathNode source, DataFlow::PathNode sink from Configuration config, DataFlow::PathNode source, DataFlow::PathNode sink
where config.hasFlowPath(source, sink) and isStringOrByte(sink) where config.hasFlowPath(source, sink) and isStringOrByte(sink)
select sink.getNode(), source, sink, "$@ flows here and is used in an XPath expression.", select sink.getNode(), source, sink, "$@ flows to here and is used in an XPath expression.",
source.getNode(), "A user-provided value" source.getNode(), "User-provided value"

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

@@ -3,7 +3,7 @@
* @description Not using `pam.AcctMgmt` after `pam.Authenticate` to check the validity of a login can lead to authorization bypass. * @description Not using `pam.AcctMgmt` after `pam.Authenticate` to check the validity of a login can lead to authorization bypass.
* @kind problem * @kind problem
* @problem.severity warning * @problem.severity warning
* @id go/unreachable-statement * @id go/pam-auth-bypass
* @tags maintainability * @tags maintainability
* correctness * correctness
* external/cwe/cwe-561 * external/cwe/cwe-561

View File

@@ -9,6 +9,6 @@ nodes
| test.go:211:35:211:43 | untrusted | semmle.label | untrusted | | test.go:211:35:211:43 | untrusted | semmle.label | untrusted |
subpaths subpaths
#select #select
| test.go:209:18:209:26 | untrusted | test.go:208:15:208:26 | call to Data : map type | test.go:209:18:209:26 | untrusted | This path depends on $@. | test.go:208:15:208:26 | call to Data | a user-provided value | | test.go:209:18:209:26 | untrusted | test.go:208:15:208:26 | call to Data : map type | test.go:209:18:209:26 | untrusted | $@ flows to here and is used in a path. | test.go:208:15:208:26 | call to Data | User-provided value |
| test.go:210:10:210:18 | untrusted | test.go:208:15:208:26 | call to Data : map type | test.go:210:10:210:18 | untrusted | This path depends on $@. | test.go:208:15:208:26 | call to Data | a user-provided value | | test.go:210:10:210:18 | untrusted | test.go:208:15:208:26 | call to Data : map type | test.go:210:10:210:18 | untrusted | $@ flows to here and is used in a path. | test.go:208:15:208:26 | call to Data | User-provided value |
| test.go:211:35:211:43 | untrusted | test.go:208:15:208:26 | call to Data : map type | test.go:211:35:211:43 | untrusted | This path depends on $@. | test.go:208:15:208:26 | call to Data | a user-provided value | | test.go:211:35:211:43 | untrusted | test.go:208:15:208:26 | call to Data : map type | test.go:211:35:211:43 | untrusted | $@ flows to here and is used in a path. | test.go:208:15:208:26 | call to Data | User-provided value |

View File

@@ -20,5 +20,5 @@ nodes
| EndToEnd.go:64:26:64:55 | call to Get | semmle.label | call to Get | | EndToEnd.go:64:26:64:55 | call to Get | semmle.label | call to Get |
subpaths subpaths
#select #select
| EndToEnd.go:58:18:58:47 | call to Get | EndToEnd.go:58:18:58:25 | selection of Params : pointer type | EndToEnd.go:58:18:58:47 | call to Get | This path depends on $@. | EndToEnd.go:58:18:58:25 | selection of Params | a user-provided value | | EndToEnd.go:58:18:58:47 | call to Get | EndToEnd.go:58:18:58:25 | selection of Params : pointer type | EndToEnd.go:58:18:58:47 | call to Get | $@ flows to here and is used in a path. | EndToEnd.go:58:18:58:25 | selection of Params | User-provided value |
| EndToEnd.go:64:26:64:55 | call to Get | EndToEnd.go:64:26:64:33 | selection of Params : pointer type | EndToEnd.go:64:26:64:55 | call to Get | This path depends on $@. | EndToEnd.go:64:26:64:33 | selection of Params | a user-provided value | | EndToEnd.go:64:26:64:55 | call to Get | EndToEnd.go:64:26:64:33 | selection of Params : pointer type | EndToEnd.go:64:26:64:55 | call to Get | $@ flows to here and is used in a path. | EndToEnd.go:64:26:64:33 | selection of Params | User-provided value |

View File

@@ -14,6 +14,6 @@ nodes
| tst.go:17:41:17:56 | selection of Filename | semmle.label | selection of Filename | | tst.go:17:41:17:56 | selection of Filename | semmle.label | selection of Filename |
subpaths subpaths
#select #select
| TaintedPath.go:16:29:16:40 | tainted_path | TaintedPath.go:13:18:13:22 | selection of URL : pointer type | TaintedPath.go:16:29:16:40 | tainted_path | This path depends on $@. | TaintedPath.go:13:18:13:22 | selection of URL | a user-provided value | | TaintedPath.go:16:29:16:40 | tainted_path | TaintedPath.go:13:18:13:22 | selection of URL : pointer type | TaintedPath.go:16:29:16:40 | tainted_path | $@ flows to here and is used in a path. | TaintedPath.go:13:18:13:22 | selection of URL | User-provided value |
| TaintedPath.go:20:28:20:69 | call to Join | TaintedPath.go:13:18:13:22 | selection of URL : pointer type | TaintedPath.go:20:28:20:69 | call to Join | This path depends on $@. | TaintedPath.go:13:18:13:22 | selection of URL | a user-provided value | | TaintedPath.go:20:28:20:69 | call to Join | TaintedPath.go:13:18:13:22 | selection of URL : pointer type | TaintedPath.go:20:28:20:69 | call to Join | $@ flows to here and is used in a path. | TaintedPath.go:13:18:13:22 | selection of URL | User-provided value |
| tst.go:17:41:17:56 | selection of Filename | tst.go:14:2:14:39 | ... := ...[1] : pointer type | tst.go:17:41:17:56 | selection of Filename | This path depends on $@. | tst.go:14:2:14:39 | ... := ...[1] | a user-provided value | | tst.go:17:41:17:56 | selection of Filename | tst.go:14:2:14:39 | ... := ...[1] : pointer type | tst.go:17:41:17:56 | selection of Filename | $@ flows to here and is used in a path. | tst.go:14:2:14:39 | ... := ...[1] | User-provided value |

View File

@@ -5,4 +5,4 @@ nodes
| test.go:17:10:17:12 | buf | semmle.label | buf | | test.go:17:10:17:12 | buf | semmle.label | buf |
subpaths subpaths
#select #select
| test.go:14:2:14:4 | definition of buf | test.go:14:2:14:4 | definition of buf : slice type | test.go:17:10:17:12 | buf | This stack trace is exposed to a remote user $@. | test.go:17:10:17:12 | buf | here | | test.go:17:10:17:12 | buf | test.go:14:2:14:4 | definition of buf : slice type | test.go:17:10:17:12 | buf | Stack trace information from $@ may be exposed to an external user here. | test.go:14:2:14:4 | definition of buf | here |

View File

@@ -85,43 +85,43 @@ nodes
| tst.go:180:27:180:122 | ...+... | semmle.label | ...+... | | tst.go:180:27:180:122 | ...+... | semmle.label | ...+... |
subpaths subpaths
#select #select
| XPathInjection.go:16:29:16:91 | ...+... | XPathInjection.go:13:14:13:19 | selection of Form : Values | XPathInjection.go:16:29:16:91 | ...+... | $@ flows here and is used in an XPath expression. | XPathInjection.go:13:14:13:19 | selection of Form | A user-provided value | | XPathInjection.go:16:29:16:91 | ...+... | XPathInjection.go:13:14:13:19 | selection of Form : Values | XPathInjection.go:16:29:16:91 | ...+... | $@ flows to here and is used in an XPath expression. | XPathInjection.go:13:14:13:19 | selection of Form | User-provided value |
| tst.go:35:23:35:85 | ...+... | tst.go:32:14:32:19 | selection of Form : Values | tst.go:35:23:35:85 | ...+... | $@ flows here and is used in an XPath expression. | tst.go:32:14:32:19 | selection of Form | A user-provided value | | tst.go:35:23:35:85 | ...+... | tst.go:32:14:32:19 | selection of Form : Values | tst.go:35:23:35:85 | ...+... | $@ flows to here and is used in an XPath expression. | tst.go:32:14:32:19 | selection of Form | User-provided value |
| tst.go:38:24:38:86 | ...+... | tst.go:32:14:32:19 | selection of Form : Values | tst.go:38:24:38:86 | ...+... | $@ flows here and is used in an XPath expression. | tst.go:32:14:32:19 | selection of Form | A user-provided value | | tst.go:38:24:38:86 | ...+... | tst.go:32:14:32:19 | selection of Form : Values | tst.go:38:24:38:86 | ...+... | $@ flows to here and is used in an XPath expression. | tst.go:32:14:32:19 | selection of Form | User-provided value |
| tst.go:41:24:41:82 | ...+... | tst.go:32:14:32:19 | selection of Form : Values | tst.go:41:24:41:82 | ...+... | $@ flows here and is used in an XPath expression. | tst.go:32:14:32:19 | selection of Form | A user-provided value | | tst.go:41:24:41:82 | ...+... | tst.go:32:14:32:19 | selection of Form : Values | tst.go:41:24:41:82 | ...+... | $@ flows to here and is used in an XPath expression. | tst.go:32:14:32:19 | selection of Form | User-provided value |
| tst.go:49:26:49:84 | ...+... | tst.go:46:14:46:19 | selection of Form : Values | tst.go:49:26:49:84 | ...+... | $@ flows here and is used in an XPath expression. | tst.go:46:14:46:19 | selection of Form | A user-provided value | | tst.go:49:26:49:84 | ...+... | tst.go:46:14:46:19 | selection of Form : Values | tst.go:49:26:49:84 | ...+... | $@ flows to here and is used in an XPath expression. | tst.go:46:14:46:19 | selection of Form | User-provided value |
| tst.go:52:29:52:87 | ...+... | tst.go:46:14:46:19 | selection of Form : Values | tst.go:52:29:52:87 | ...+... | $@ flows here and is used in an XPath expression. | tst.go:46:14:46:19 | selection of Form | A user-provided value | | tst.go:52:29:52:87 | ...+... | tst.go:46:14:46:19 | selection of Form : Values | tst.go:52:29:52:87 | ...+... | $@ flows to here and is used in an XPath expression. | tst.go:46:14:46:19 | selection of Form | User-provided value |
| tst.go:55:33:55:91 | ...+... | tst.go:46:14:46:19 | selection of Form : Values | tst.go:55:33:55:91 | ...+... | $@ flows here and is used in an XPath expression. | tst.go:46:14:46:19 | selection of Form | A user-provided value | | tst.go:55:33:55:91 | ...+... | tst.go:46:14:46:19 | selection of Form : Values | tst.go:55:33:55:91 | ...+... | $@ flows to here and is used in an XPath expression. | tst.go:46:14:46:19 | selection of Form | User-provided value |
| tst.go:58:30:58:88 | ...+... | tst.go:46:14:46:19 | selection of Form : Values | tst.go:58:30:58:88 | ...+... | $@ flows here and is used in an XPath expression. | tst.go:46:14:46:19 | selection of Form | A user-provided value | | tst.go:58:30:58:88 | ...+... | tst.go:46:14:46:19 | selection of Form : Values | tst.go:58:30:58:88 | ...+... | $@ flows to here and is used in an XPath expression. | tst.go:46:14:46:19 | selection of Form | User-provided value |
| tst.go:66:25:66:83 | ...+... | tst.go:63:14:63:19 | selection of Form : Values | tst.go:66:25:66:83 | ...+... | $@ flows here and is used in an XPath expression. | tst.go:63:14:63:19 | selection of Form | A user-provided value | | tst.go:66:25:66:83 | ...+... | tst.go:63:14:63:19 | selection of Form : Values | tst.go:66:25:66:83 | ...+... | $@ flows to here and is used in an XPath expression. | tst.go:63:14:63:19 | selection of Form | User-provided value |
| tst.go:69:28:69:86 | ...+... | tst.go:63:14:63:19 | selection of Form : Values | tst.go:69:28:69:86 | ...+... | $@ flows here and is used in an XPath expression. | tst.go:63:14:63:19 | selection of Form | A user-provided value | | tst.go:69:28:69:86 | ...+... | tst.go:63:14:63:19 | selection of Form : Values | tst.go:69:28:69:86 | ...+... | $@ flows to here and is used in an XPath expression. | tst.go:63:14:63:19 | selection of Form | User-provided value |
| tst.go:72:25:72:83 | ...+... | tst.go:63:14:63:19 | selection of Form : Values | tst.go:72:25:72:83 | ...+... | $@ flows here and is used in an XPath expression. | tst.go:63:14:63:19 | selection of Form | A user-provided value | | tst.go:72:25:72:83 | ...+... | tst.go:63:14:63:19 | selection of Form : Values | tst.go:72:25:72:83 | ...+... | $@ flows to here and is used in an XPath expression. | tst.go:63:14:63:19 | selection of Form | User-provided value |
| tst.go:75:34:75:92 | ...+... | tst.go:63:14:63:19 | selection of Form : Values | tst.go:75:34:75:92 | ...+... | $@ flows here and is used in an XPath expression. | tst.go:63:14:63:19 | selection of Form | A user-provided value | | tst.go:75:34:75:92 | ...+... | tst.go:63:14:63:19 | selection of Form : Values | tst.go:75:34:75:92 | ...+... | $@ flows to here and is used in an XPath expression. | tst.go:63:14:63:19 | selection of Form | User-provided value |
| tst.go:78:32:78:90 | ...+... | tst.go:63:14:63:19 | selection of Form : Values | tst.go:78:32:78:90 | ...+... | $@ flows here and is used in an XPath expression. | tst.go:63:14:63:19 | selection of Form | A user-provided value | | tst.go:78:32:78:90 | ...+... | tst.go:63:14:63:19 | selection of Form : Values | tst.go:78:32:78:90 | ...+... | $@ flows to here and is used in an XPath expression. | tst.go:63:14:63:19 | selection of Form | User-provided value |
| tst.go:81:29:81:87 | ...+... | tst.go:63:14:63:19 | selection of Form : Values | tst.go:81:29:81:87 | ...+... | $@ flows here and is used in an XPath expression. | tst.go:63:14:63:19 | selection of Form | A user-provided value | | tst.go:81:29:81:87 | ...+... | tst.go:63:14:63:19 | selection of Form : Values | tst.go:81:29:81:87 | ...+... | $@ flows to here and is used in an XPath expression. | tst.go:63:14:63:19 | selection of Form | User-provided value |
| tst.go:84:23:84:85 | ...+... | tst.go:63:14:63:19 | selection of Form : Values | tst.go:84:23:84:85 | ...+... | $@ flows here and is used in an XPath expression. | tst.go:63:14:63:19 | selection of Form | A user-provided value | | tst.go:84:23:84:85 | ...+... | tst.go:63:14:63:19 | selection of Form : Values | tst.go:84:23:84:85 | ...+... | $@ flows to here and is used in an XPath expression. | tst.go:63:14:63:19 | selection of Form | User-provided value |
| tst.go:87:22:87:84 | ...+... | tst.go:63:14:63:19 | selection of Form : Values | tst.go:87:22:87:84 | ...+... | $@ flows here and is used in an XPath expression. | tst.go:63:14:63:19 | selection of Form | A user-provided value | | tst.go:87:22:87:84 | ...+... | tst.go:63:14:63:19 | selection of Form : Values | tst.go:87:22:87:84 | ...+... | $@ flows to here and is used in an XPath expression. | tst.go:63:14:63:19 | selection of Form | User-provided value |
| tst.go:95:26:95:84 | ...+... | tst.go:92:14:92:19 | selection of Form : Values | tst.go:95:26:95:84 | ...+... | $@ flows here and is used in an XPath expression. | tst.go:92:14:92:19 | selection of Form | A user-provided value | | tst.go:95:26:95:84 | ...+... | tst.go:92:14:92:19 | selection of Form : Values | tst.go:95:26:95:84 | ...+... | $@ flows to here and is used in an XPath expression. | tst.go:92:14:92:19 | selection of Form | User-provided value |
| tst.go:98:29:98:87 | ...+... | tst.go:92:14:92:19 | selection of Form : Values | tst.go:98:29:98:87 | ...+... | $@ flows here and is used in an XPath expression. | tst.go:92:14:92:19 | selection of Form | A user-provided value | | tst.go:98:29:98:87 | ...+... | tst.go:92:14:92:19 | selection of Form : Values | tst.go:98:29:98:87 | ...+... | $@ flows to here and is used in an XPath expression. | tst.go:92:14:92:19 | selection of Form | User-provided value |
| tst.go:101:33:101:91 | ...+... | tst.go:92:14:92:19 | selection of Form : Values | tst.go:101:33:101:91 | ...+... | $@ flows here and is used in an XPath expression. | tst.go:92:14:92:19 | selection of Form | A user-provided value | | tst.go:101:33:101:91 | ...+... | tst.go:92:14:92:19 | selection of Form : Values | tst.go:101:33:101:91 | ...+... | $@ flows to here and is used in an XPath expression. | tst.go:92:14:92:19 | selection of Form | User-provided value |
| tst.go:104:30:104:88 | ...+... | tst.go:92:14:92:19 | selection of Form : Values | tst.go:104:30:104:88 | ...+... | $@ flows here and is used in an XPath expression. | tst.go:92:14:92:19 | selection of Form | A user-provided value | | tst.go:104:30:104:88 | ...+... | tst.go:92:14:92:19 | selection of Form : Values | tst.go:104:30:104:88 | ...+... | $@ flows to here and is used in an XPath expression. | tst.go:92:14:92:19 | selection of Form | User-provided value |
| tst.go:112:25:112:87 | ...+... | tst.go:109:14:109:19 | selection of Form : Values | tst.go:112:25:112:87 | ...+... | $@ flows here and is used in an XPath expression. | tst.go:109:14:109:19 | selection of Form | A user-provided value | | tst.go:112:25:112:87 | ...+... | tst.go:109:14:109:19 | selection of Form : Values | tst.go:112:25:112:87 | ...+... | $@ flows to here and is used in an XPath expression. | tst.go:109:14:109:19 | selection of Form | User-provided value |
| tst.go:115:26:115:88 | ...+... | tst.go:109:14:109:19 | selection of Form : Values | tst.go:115:26:115:88 | ...+... | $@ flows here and is used in an XPath expression. | tst.go:109:14:109:19 | selection of Form | A user-provided value | | tst.go:115:26:115:88 | ...+... | tst.go:109:14:109:19 | selection of Form : Values | tst.go:115:26:115:88 | ...+... | $@ flows to here and is used in an XPath expression. | tst.go:109:14:109:19 | selection of Form | User-provided value |
| tst.go:124:23:124:126 | ...+... | tst.go:120:14:120:19 | selection of Form : Values | tst.go:124:23:124:126 | ...+... | $@ flows here and is used in an XPath expression. | tst.go:120:14:120:19 | selection of Form | A user-provided value | | tst.go:124:23:124:126 | ...+... | tst.go:120:14:120:19 | selection of Form : Values | tst.go:124:23:124:126 | ...+... | $@ flows to here and is used in an XPath expression. | tst.go:120:14:120:19 | selection of Form | User-provided value |
| tst.go:124:23:124:126 | ...+... | tst.go:121:14:121:19 | selection of Form : Values | tst.go:124:23:124:126 | ...+... | $@ flows here and is used in an XPath expression. | tst.go:121:14:121:19 | selection of Form | A user-provided value | | tst.go:124:23:124:126 | ...+... | tst.go:121:14:121:19 | selection of Form : Values | tst.go:124:23:124:126 | ...+... | $@ flows to here and is used in an XPath expression. | tst.go:121:14:121:19 | selection of Form | User-provided value |
| tst.go:127:24:127:127 | ...+... | tst.go:120:14:120:19 | selection of Form : Values | tst.go:127:24:127:127 | ...+... | $@ flows here and is used in an XPath expression. | tst.go:120:14:120:19 | selection of Form | A user-provided value | | tst.go:127:24:127:127 | ...+... | tst.go:120:14:120:19 | selection of Form : Values | tst.go:127:24:127:127 | ...+... | $@ flows to here and is used in an XPath expression. | tst.go:120:14:120:19 | selection of Form | User-provided value |
| tst.go:127:24:127:127 | ...+... | tst.go:121:14:121:19 | selection of Form : Values | tst.go:127:24:127:127 | ...+... | $@ flows here and is used in an XPath expression. | tst.go:121:14:121:19 | selection of Form | A user-provided value | | tst.go:127:24:127:127 | ...+... | tst.go:121:14:121:19 | selection of Form : Values | tst.go:127:24:127:127 | ...+... | $@ flows to here and is used in an XPath expression. | tst.go:121:14:121:19 | selection of Form | User-provided value |
| tst.go:130:27:130:122 | ...+... | tst.go:120:14:120:19 | selection of Form : Values | tst.go:130:27:130:122 | ...+... | $@ flows here and is used in an XPath expression. | tst.go:120:14:120:19 | selection of Form | A user-provided value | | tst.go:130:27:130:122 | ...+... | tst.go:120:14:120:19 | selection of Form : Values | tst.go:130:27:130:122 | ...+... | $@ flows to here and is used in an XPath expression. | tst.go:120:14:120:19 | selection of Form | User-provided value |
| tst.go:130:27:130:122 | ...+... | tst.go:121:14:121:19 | selection of Form : Values | tst.go:130:27:130:122 | ...+... | $@ flows here and is used in an XPath expression. | tst.go:121:14:121:19 | selection of Form | A user-provided value | | tst.go:130:27:130:122 | ...+... | tst.go:121:14:121:19 | selection of Form : Values | tst.go:130:27:130:122 | ...+... | $@ flows to here and is used in an XPath expression. | tst.go:121:14:121:19 | selection of Form | User-provided value |
| tst.go:141:27:141:89 | ...+... | tst.go:138:14:138:19 | selection of Form : Values | tst.go:141:27:141:89 | ...+... | $@ flows here and is used in an XPath expression. | tst.go:138:14:138:19 | selection of Form | A user-provided value | | tst.go:141:27:141:89 | ...+... | tst.go:138:14:138:19 | selection of Form : Values | tst.go:141:27:141:89 | ...+... | $@ flows to here and is used in an XPath expression. | tst.go:138:14:138:19 | selection of Form | User-provided value |
| tst.go:144:28:144:90 | ...+... | tst.go:138:14:138:19 | selection of Form : Values | tst.go:144:28:144:90 | ...+... | $@ flows here and is used in an XPath expression. | tst.go:138:14:138:19 | selection of Form | A user-provided value | | tst.go:144:28:144:90 | ...+... | tst.go:138:14:138:19 | selection of Form : Values | tst.go:144:28:144:90 | ...+... | $@ flows to here and is used in an XPath expression. | tst.go:138:14:138:19 | selection of Form | User-provided value |
| tst.go:153:33:153:136 | ...+... | tst.go:149:14:149:19 | selection of Form : Values | tst.go:153:33:153:136 | ...+... | $@ flows here and is used in an XPath expression. | tst.go:149:14:149:19 | selection of Form | A user-provided value | | tst.go:153:33:153:136 | ...+... | tst.go:149:14:149:19 | selection of Form : Values | tst.go:153:33:153:136 | ...+... | $@ flows to here and is used in an XPath expression. | tst.go:149:14:149:19 | selection of Form | User-provided value |
| tst.go:153:33:153:136 | ...+... | tst.go:150:14:150:19 | selection of Form : Values | tst.go:153:33:153:136 | ...+... | $@ flows here and is used in an XPath expression. | tst.go:150:14:150:19 | selection of Form | A user-provided value | | tst.go:153:33:153:136 | ...+... | tst.go:150:14:150:19 | selection of Form : Values | tst.go:153:33:153:136 | ...+... | $@ flows to here and is used in an XPath expression. | tst.go:150:14:150:19 | selection of Form | User-provided value |
| tst.go:156:18:156:121 | ...+... | tst.go:149:14:149:19 | selection of Form : Values | tst.go:156:18:156:121 | ...+... | $@ flows here and is used in an XPath expression. | tst.go:149:14:149:19 | selection of Form | A user-provided value | | tst.go:156:18:156:121 | ...+... | tst.go:149:14:149:19 | selection of Form : Values | tst.go:156:18:156:121 | ...+... | $@ flows to here and is used in an XPath expression. | tst.go:149:14:149:19 | selection of Form | User-provided value |
| tst.go:156:18:156:121 | ...+... | tst.go:150:14:150:19 | selection of Form : Values | tst.go:156:18:156:121 | ...+... | $@ flows here and is used in an XPath expression. | tst.go:150:14:150:19 | selection of Form | A user-provided value | | tst.go:156:18:156:121 | ...+... | tst.go:150:14:150:19 | selection of Form : Values | tst.go:156:18:156:121 | ...+... | $@ flows to here and is used in an XPath expression. | tst.go:150:14:150:19 | selection of Form | User-provided value |
| tst.go:162:31:162:126 | ...+... | tst.go:149:14:149:19 | selection of Form : Values | tst.go:162:31:162:126 | ...+... | $@ flows here and is used in an XPath expression. | tst.go:149:14:149:19 | selection of Form | A user-provided value | | tst.go:162:31:162:126 | ...+... | tst.go:149:14:149:19 | selection of Form : Values | tst.go:162:31:162:126 | ...+... | $@ flows to here and is used in an XPath expression. | tst.go:149:14:149:19 | selection of Form | User-provided value |
| tst.go:162:31:162:126 | ...+... | tst.go:150:14:150:19 | selection of Form : Values | tst.go:162:31:162:126 | ...+... | $@ flows here and is used in an XPath expression. | tst.go:150:14:150:19 | selection of Form | A user-provided value | | tst.go:162:31:162:126 | ...+... | tst.go:150:14:150:19 | selection of Form : Values | tst.go:162:31:162:126 | ...+... | $@ flows to here and is used in an XPath expression. | tst.go:150:14:150:19 | selection of Form | User-provided value |
| tst.go:171:21:171:116 | ...+... | tst.go:149:14:149:19 | selection of Form : Values | tst.go:171:21:171:116 | ...+... | $@ flows here and is used in an XPath expression. | tst.go:149:14:149:19 | selection of Form | A user-provided value | | tst.go:171:21:171:116 | ...+... | tst.go:149:14:149:19 | selection of Form : Values | tst.go:171:21:171:116 | ...+... | $@ flows to here and is used in an XPath expression. | tst.go:149:14:149:19 | selection of Form | User-provided value |
| tst.go:171:21:171:116 | ...+... | tst.go:150:14:150:19 | selection of Form : Values | tst.go:171:21:171:116 | ...+... | $@ flows here and is used in an XPath expression. | tst.go:150:14:150:19 | selection of Form | A user-provided value | | tst.go:171:21:171:116 | ...+... | tst.go:150:14:150:19 | selection of Form : Values | tst.go:171:21:171:116 | ...+... | $@ flows to here and is used in an XPath expression. | tst.go:150:14:150:19 | selection of Form | User-provided value |
| tst.go:180:27:180:122 | ...+... | tst.go:149:14:149:19 | selection of Form : Values | tst.go:180:27:180:122 | ...+... | $@ flows here and is used in an XPath expression. | tst.go:149:14:149:19 | selection of Form | A user-provided value | | tst.go:180:27:180:122 | ...+... | tst.go:149:14:149:19 | selection of Form : Values | tst.go:180:27:180:122 | ...+... | $@ flows to here and is used in an XPath expression. | tst.go:149:14:149:19 | selection of Form | User-provided value |
| tst.go:180:27:180:122 | ...+... | tst.go:150:14:150:19 | selection of Form : Values | tst.go:180:27:180:122 | ...+... | $@ flows here and is used in an XPath expression. | tst.go:150:14:150:19 | selection of Form | A user-provided value | | tst.go:180:27:180:122 | ...+... | tst.go:150:14:150:19 | selection of Form : Values | tst.go:180:27:180:122 | ...+... | $@ flows to here and is used in an XPath expression. | tst.go:150:14:150:19 | selection of Form | User-provided value |

View File

@@ -1584,7 +1584,7 @@ open class KotlinFileExtractor(
} }
} }
private fun findFunction(cls: IrClass, name: String): IrFunction? = cls.declarations.find { it is IrFunction && it.name.asString() == name } as IrFunction? private fun findFunction(cls: IrClass, name: String): IrFunction? = cls.declarations.findSubType<IrFunction> { it.name.asString() == name }
val jvmIntrinsicsClass by lazy { val jvmIntrinsicsClass by lazy {
val result = pluginContext.referenceClass(FqName("kotlin.jvm.internal.Intrinsics"))?.owner val result = pluginContext.referenceClass(FqName("kotlin.jvm.internal.Intrinsics"))?.owner
@@ -1641,12 +1641,11 @@ open class KotlinFileExtractor(
} }
val stringValueOfObjectMethod by lazy { val stringValueOfObjectMethod by lazy {
val result = javaLangString?.declarations?.find { val result = javaLangString?.declarations?.findSubType<IrFunction> {
it is IrFunction &&
it.name.asString() == "valueOf" && it.name.asString() == "valueOf" &&
it.valueParameters.size == 1 && it.valueParameters.size == 1 &&
it.valueParameters[0].type == pluginContext.irBuiltIns.anyNType it.valueParameters[0].type == pluginContext.irBuiltIns.anyNType
} as IrFunction? }
if (result == null) { if (result == null) {
logger.error("Couldn't find declaration java.lang.String.valueOf(Object)") logger.error("Couldn't find declaration java.lang.String.valueOf(Object)")
} }
@@ -1654,9 +1653,9 @@ open class KotlinFileExtractor(
} }
val objectCloneMethod by lazy { val objectCloneMethod by lazy {
val result = javaLangObject?.declarations?.find { val result = javaLangObject?.declarations?.findSubType<IrFunction> {
it is IrFunction && it.name.asString() == "clone" it.name.asString() == "clone"
} as IrFunction? }
if (result == null) { if (result == null) {
logger.error("Couldn't find declaration java.lang.Object.clone(...)") logger.error("Couldn't find declaration java.lang.Object.clone(...)")
} }
@@ -1670,10 +1669,9 @@ open class KotlinFileExtractor(
} }
val kotlinNoWhenBranchMatchedConstructor by lazy { val kotlinNoWhenBranchMatchedConstructor by lazy {
val result = kotlinNoWhenBranchMatchedExn?.declarations?.find { val result = kotlinNoWhenBranchMatchedExn?.declarations?.findSubType<IrConstructor> {
it is IrConstructor &&
it.valueParameters.isEmpty() it.valueParameters.isEmpty()
} as IrConstructor? }
if (result == null) { if (result == null) {
logger.error("Couldn't find no-arg constructor for kotlin.NoWhenBranchMatchedException") logger.error("Couldn't find no-arg constructor for kotlin.NoWhenBranchMatchedException")
} }
@@ -1798,13 +1796,13 @@ open class KotlinFileExtractor(
return return
} }
val func = ((c.getTypeArgument(0) as? IrSimpleType)?.classifier?.owner as? IrClass)?.declarations?.find { it is IrFunction && it.name.asString() == fnName } val func = ((c.getTypeArgument(0) as? IrSimpleType)?.classifier?.owner as? IrClass)?.declarations?.findSubType<IrFunction> { it.name.asString() == fnName }
if (func == null) { if (func == null) {
logger.errorElement("Couldn't find function $fnName on enum type", c) logger.errorElement("Couldn't find function $fnName on enum type", c)
return return
} }
extractMethodAccess(func as IrFunction, false) extractMethodAccess(func, false)
} }
fun binopReceiver(id: Label<out DbExpr>, receiver: IrExpression?, receiverDescription: String) { fun binopReceiver(id: Label<out DbExpr>, receiver: IrExpression?, receiverDescription: String) {
@@ -2273,10 +2271,10 @@ open class KotlinFileExtractor(
logger.errorElement("Argument to dataClassArrayMemberToString not a class", c) logger.errorElement("Argument to dataClassArrayMemberToString not a class", c)
return return
} }
val realCallee = javaUtilArrays?.declarations?.find { decl -> val realCallee = javaUtilArrays?.declarations?.findSubType<IrFunction> { decl ->
decl is IrFunction && decl.name.asString() == "toString" && decl.valueParameters.size == 1 && decl.name.asString() == "toString" && decl.valueParameters.size == 1 &&
decl.valueParameters[0].type.classOrNull?.let { it == realArrayClass } == true decl.valueParameters[0].type.classOrNull?.let { it == realArrayClass } == true
} as IrFunction? }
if (realCallee == null) { if (realCallee == null) {
logger.errorElement("Couldn't find a java.lang.Arrays.toString method matching class ${realArrayClass.owner.name}", c) logger.errorElement("Couldn't find a java.lang.Arrays.toString method matching class ${realArrayClass.owner.name}", c)
} else { } else {
@@ -2300,10 +2298,10 @@ open class KotlinFileExtractor(
logger.errorElement("Argument to dataClassArrayMemberHashCode not a class", c) logger.errorElement("Argument to dataClassArrayMemberHashCode not a class", c)
return return
} }
val realCallee = javaUtilArrays?.declarations?.find { decl -> val realCallee = javaUtilArrays?.declarations?.findSubType<IrFunction> { decl ->
decl is IrFunction && decl.name.asString() == "hashCode" && decl.valueParameters.size == 1 && decl.name.asString() == "hashCode" && decl.valueParameters.size == 1 &&
decl.valueParameters[0].type.classOrNull?.let { it == realArrayClass } == true decl.valueParameters[0].type.classOrNull?.let { it == realArrayClass } == true
} as IrFunction? }
if (realCallee == null) { if (realCallee == null) {
logger.errorElement("Couldn't find a java.lang.Arrays.hashCode method matching class ${realArrayClass.owner.name}", c) logger.errorElement("Couldn't find a java.lang.Arrays.hashCode method matching class ${realArrayClass.owner.name}", c)
} else { } else {
@@ -4452,7 +4450,7 @@ open class KotlinFileExtractor(
return return
} }
val invokeMethod = functionType.classOrNull?.owner?.declarations?.filterIsInstance<IrFunction>()?.find { it.name.asString() == OperatorNameConventions.INVOKE.asString()} val invokeMethod = functionType.classOrNull?.owner?.declarations?.findSubType<IrFunction> { it.name.asString() == OperatorNameConventions.INVOKE.asString()}
if (invokeMethod == null) { if (invokeMethod == null) {
logger.errorElement("Couldn't find `invoke` method on functional interface.", e) logger.errorElement("Couldn't find `invoke` method on functional interface.", e)
return return
@@ -4463,7 +4461,7 @@ open class KotlinFileExtractor(
logger.errorElement("Expected to find SAM conversion to IrClass. Found '${typeOwner.javaClass}' instead. Can't implement SAM interface.", e) logger.errorElement("Expected to find SAM conversion to IrClass. Found '${typeOwner.javaClass}' instead. Can't implement SAM interface.", e)
return return
} }
val samMember = typeOwner.declarations.filterIsInstance<IrFunction>().find { it is IrOverridableMember && it.modality == Modality.ABSTRACT } val samMember = typeOwner.declarations.findSubType<IrFunction> { it is IrOverridableMember && it.modality == Modality.ABSTRACT }
if (samMember == null) { if (samMember == null) {
logger.errorElement("Couldn't find SAM member in type '${typeOwner.kotlinFqName.asString()}'. Can't implement SAM interface.", e) logger.errorElement("Couldn't find SAM member in type '${typeOwner.kotlinFqName.asString()}'. Can't implement SAM interface.", e)
return return
@@ -4652,7 +4650,7 @@ open class KotlinFileExtractor(
val superCallId = tw.getFreshIdLabel<DbSuperconstructorinvocationstmt>() val superCallId = tw.getFreshIdLabel<DbSuperconstructorinvocationstmt>()
tw.writeStmts_superconstructorinvocationstmt(superCallId, constructorBlockId, 0, ids.constructor) tw.writeStmts_superconstructorinvocationstmt(superCallId, constructorBlockId, 0, ids.constructor)
val baseConstructor = baseClass.owner.declarations.find { it is IrFunction && it.symbol is IrConstructorSymbol } val baseConstructor = baseClass.owner.declarations.findSubType<IrFunction> { it.symbol is IrConstructorSymbol }
val baseConstructorId = useFunction<DbConstructor>(baseConstructor as IrFunction) val baseConstructorId = useFunction<DbConstructor>(baseConstructor as IrFunction)
tw.writeHasLocation(superCallId, locId) tw.writeHasLocation(superCallId, locId)

View File

@@ -326,11 +326,11 @@ open class KotlinUsesExtractor(
if (replacementClass === parentClass) if (replacementClass === parentClass)
return f return f
return globalExtensionState.syntheticToRealFunctionMap.getOrPut(f) { return globalExtensionState.syntheticToRealFunctionMap.getOrPut(f) {
val result = replacementClass.declarations.find { replacementDecl -> val result = replacementClass.declarations.findSubType<IrSimpleFunction> { replacementDecl ->
replacementDecl is IrSimpleFunction && replacementDecl.name == f.name && replacementDecl.valueParameters.size == f.valueParameters.size && replacementDecl.valueParameters.zip(f.valueParameters).all { replacementDecl is IrSimpleFunction && replacementDecl.name == f.name && replacementDecl.valueParameters.size == f.valueParameters.size && replacementDecl.valueParameters.zip(f.valueParameters).all {
erase(it.first.type) == erase(it.second.type) erase(it.first.type) == erase(it.second.type)
} }
} as IrFunction? }
if (result == null) { if (result == null) {
logger.warn("Failed to replace synthetic class function ${f.name}") logger.warn("Failed to replace synthetic class function ${f.name}")
} else { } else {
@@ -351,9 +351,9 @@ open class KotlinUsesExtractor(
if (replacementClass === parentClass) if (replacementClass === parentClass)
return f return f
return globalExtensionState.syntheticToRealFieldMap.getOrPut(f) { return globalExtensionState.syntheticToRealFieldMap.getOrPut(f) {
val result = replacementClass.declarations.find { replacementDecl -> val result = replacementClass.declarations.findSubType<IrField> { replacementDecl ->
replacementDecl is IrField && replacementDecl.name == f.name replacementDecl.name == f.name
} as IrField? }
if (result == null) { if (result == null) {
logger.warn("Failed to replace synthetic class field ${f.name}") logger.warn("Failed to replace synthetic class field ${f.name}")
} else { } else {
@@ -1097,7 +1097,7 @@ open class KotlinUsesExtractor(
return f.returnType return f.returnType
} }
val otherKeySet = parentClass.declarations.filterIsInstance<IrFunction>().find { it.name.asString() == "keySet" && it.valueParameters.size == 1 } val otherKeySet = parentClass.declarations.findSubType<IrFunction> { it.name.asString() == "keySet" && it.valueParameters.size == 1 }
?: return f.returnType ?: return f.returnType
return otherKeySet.returnType.codeQlWithHasQuestionMark(false) return otherKeySet.returnType.codeQlWithHasQuestionMark(false)
@@ -1177,8 +1177,7 @@ open class KotlinUsesExtractor(
getJavaEquivalentClass(parentClass)?.let { javaClass -> getJavaEquivalentClass(parentClass)?.let { javaClass ->
if (javaClass != parentClass) if (javaClass != parentClass)
// Look for an exact type match... // Look for an exact type match...
javaClass.declarations.find { decl -> javaClass.declarations.findSubType<IrFunction> { decl ->
decl is IrFunction &&
decl.name == f.name && decl.name == f.name &&
decl.valueParameters.size == f.valueParameters.size && decl.valueParameters.size == f.valueParameters.size &&
// Note matching by classifier not the whole type so that generic arguments are allowed to differ, // Note matching by classifier not the whole type so that generic arguments are allowed to differ,
@@ -1194,7 +1193,7 @@ open class KotlinUsesExtractor(
} ?: } ?:
// Or check property accessors: // Or check property accessors:
if (f.isAccessor) { if (f.isAccessor) {
val prop = javaClass.declarations.filterIsInstance<IrProperty>().find { decl -> val prop = javaClass.declarations.findSubType<IrProperty> { decl ->
decl.name == (f.propertyIfAccessor as IrProperty).name decl.name == (f.propertyIfAccessor as IrProperty).name
} }
if (prop?.getter?.name == f.name) if (prop?.getter?.name == f.name)

View File

@@ -0,0 +1,15 @@
package com.github.codeql
import org.jetbrains.kotlin.ir.declarations.IrDeclaration
/**
* This behaves the same as Iterable<IrDeclaration>.find, but requires
* that the value found is of the subtype S, and it casts
* the result for you appropriately.
*/
inline fun <reified S: IrDeclaration> Iterable<IrDeclaration>.findSubType(
predicate: (S) -> Boolean
): S? {
return this.find { it is S && predicate(it) } as S?
}

View File

@@ -93,8 +93,6 @@ class RegExpRoot extends RegExpTerm {
* Holds if this root term is relevant to the ReDoS analysis. * Holds if this root term is relevant to the ReDoS analysis.
*/ */
predicate isRelevant() { predicate isRelevant() {
// there is at least one repetition
getRoot(any(InfiniteRepetitionQuantifier q)) = this and
// is actually used as a RegExp // is actually used as a RegExp
this.isUsedAsRegExp() and this.isUsedAsRegExp() and
// not excluded for library specific reasons // not excluded for library specific reasons
@@ -878,42 +876,14 @@ predicate isStartState(State state) {
signature predicate isCandidateSig(State state, string pump); signature predicate isCandidateSig(State state, string pump);
/** /**
* A module for pruning candidate ReDoS states. * Holds if `state` is a candidate for ReDoS.
* The candidates are specified by the `isCandidate` signature predicate.
* The candidates are checked for rejecting suffixes and deduplicated,
* and the resulting ReDoS states are read by the `hasReDoSResult` predicate.
*/ */
module ReDoSPruning<isCandidateSig/2 isCandidate> { signature predicate isCandidateSig(State state);
/**
* Holds if repeating `pump` starting at `state` is a candidate for causing backtracking.
* No check whether a rejected suffix exists has been made.
*/
private predicate isReDoSCandidate(State state, string pump) {
isCandidate(state, pump) and
not state = acceptsAnySuffix() and // pruning early - these can never get stuck in a rejecting state.
(
not isCandidate(epsilonSucc+(state), _)
or
epsilonSucc+(state) = state and
state =
max(State s, Location l |
s = epsilonSucc+(state) and
l = s.getRepr().getLocation() and
isCandidate(s, _) and
s.getRepr() instanceof InfiniteRepetitionQuantifier
|
s order by l.getStartLine(), l.getStartColumn(), l.getEndColumn(), l.getEndLine()
)
)
}
/** Gets a state that can reach the `accept-any` state using only epsilon steps. */ /**
private State acceptsAnySuffix() { epsilonSucc*(result) = AcceptAnySuffix(_) }
/**
* Predicates for constructing a prefix string that leads to a given state. * Predicates for constructing a prefix string that leads to a given state.
*/ */
private module PrefixConstruction { module PrefixConstruction<isCandidateSig/1 isCandidate> {
/** /**
* Holds if `state` is the textually last start state for the regular expression. * Holds if `state` is the textually last start state for the regular expression.
*/ */
@@ -921,7 +891,7 @@ module ReDoSPruning<isCandidateSig/2 isCandidate> {
exists(RegExpRoot root | exists(RegExpRoot root |
state = state =
max(State s, Location l | max(State s, Location l |
s = stateInPumpableRegexp() and s = stateInRelevantRegexp() and
isStartState(s) and isStartState(s) and
getRoot(s.getRepr()) = root and getRoot(s.getRepr()) = root and
l = s.getRepr().getLocation() l = s.getRepr().getLocation()
@@ -962,7 +932,7 @@ module ReDoSPruning<isCandidateSig/2 isCandidate> {
result = "" result = ""
or or
// the search stops past the last redos candidate state. // the search stops past the last redos candidate state.
lengthFromStart(state) <= max(lengthFromStart(any(State s | isReDoSCandidate(s, _)))) and lengthFromStart(state) <= max(lengthFromStart(any(State s | isCandidate(s)))) and
exists(State prev | exists(State prev |
// select a unique predecessor (by an arbitrary measure) // select a unique predecessor (by an arbitrary measure)
prev = prev =
@@ -993,13 +963,50 @@ module ReDoSPruning<isCandidateSig/2 isCandidate> {
min(string c | delta(prev, any(InputSymbol symbol | c = intersect(Any(), symbol)), next)) min(string c | delta(prev, any(InputSymbol symbol | c = intersect(Any(), symbol)), next))
} }
/** Gets a state within a regular expression that has a pumpable state. */ /** Gets a state within a regular expression that contains a candidate state. */
pragma[noinline] pragma[noinline]
State stateInPumpableRegexp() { State stateInRelevantRegexp() {
exists(State s | isReDoSCandidate(s, _) | getRoot(s.getRepr()) = getRoot(result.getRepr())) exists(State s | isCandidate(s) | getRoot(s.getRepr()) = getRoot(result.getRepr()))
} }
}
/**
* A module for pruning candidate ReDoS states.
* The candidates are specified by the `isCandidate` signature predicate.
* The candidates are checked for rejecting suffixes and deduplicated,
* and the resulting ReDoS states are read by the `hasReDoSResult` predicate.
*/
module ReDoSPruning<isCandidateSig/2 isCandidate> {
/**
* Holds if repeating `pump` starting at `state` is a candidate for causing backtracking.
* No check whether a rejected suffix exists has been made.
*/
private predicate isReDoSCandidate(State state, string pump) {
isCandidate(state, pump) and
not state = acceptsAnySuffix() and // pruning early - these can never get stuck in a rejecting state.
(
not isCandidate(epsilonSucc+(state), _)
or
epsilonSucc+(state) = state and
state =
max(State s, Location l |
s = epsilonSucc+(state) and
l = s.getRepr().getLocation() and
isCandidate(s, _) and
s.getRepr() instanceof InfiniteRepetitionQuantifier
|
s order by l.getStartLine(), l.getStartColumn(), l.getEndColumn(), l.getEndLine()
)
)
} }
/** Gets a state that can reach the `accept-any` state using only epsilon steps. */
private State acceptsAnySuffix() { epsilonSucc*(result) = AcceptAnySuffix(_) }
predicate isCandidateState(State s) { isReDoSCandidate(s, _) }
import PrefixConstruction<isCandidateState/1> as Prefix
/** /**
* Predicates for testing the presence of a rejecting suffix. * Predicates for testing the presence of a rejecting suffix.
* *
@@ -1018,8 +1025,6 @@ module ReDoSPruning<isCandidateSig/2 isCandidate> {
* using epsilon transitions. But any attempt at repeating `w` will end in a state that accepts all suffixes. * using epsilon transitions. But any attempt at repeating `w` will end in a state that accepts all suffixes.
*/ */
private module SuffixConstruction { private module SuffixConstruction {
import PrefixConstruction
/** /**
* Holds if all states reachable from `fork` by repeating `w` * Holds if all states reachable from `fork` by repeating `w`
* are likely rejectable by appending some suffix. * are likely rejectable by appending some suffix.
@@ -1036,7 +1041,7 @@ module ReDoSPruning<isCandidateSig/2 isCandidate> {
*/ */
pragma[noinline] pragma[noinline]
private predicate isLikelyRejectable(State s) { private predicate isLikelyRejectable(State s) {
s = stateInPumpableRegexp() and s = Prefix::stateInRelevantRegexp() and
( (
// exists a reject edge with some char. // exists a reject edge with some char.
hasRejectEdge(s) hasRejectEdge(s)
@@ -1052,7 +1057,7 @@ module ReDoSPruning<isCandidateSig/2 isCandidate> {
* Holds if `s` is not an accept state, and there is no epsilon transition to an accept state. * Holds if `s` is not an accept state, and there is no epsilon transition to an accept state.
*/ */
predicate isRejectState(State s) { predicate isRejectState(State s) {
s = stateInPumpableRegexp() and not epsilonSucc*(s) = Accept(_) s = Prefix::stateInRelevantRegexp() and not epsilonSucc*(s) = Accept(_)
} }
/** /**
@@ -1060,7 +1065,7 @@ module ReDoSPruning<isCandidateSig/2 isCandidate> {
*/ */
pragma[noopt] pragma[noopt]
predicate hasEdgeToLikelyRejectable(State s) { predicate hasEdgeToLikelyRejectable(State s) {
s = stateInPumpableRegexp() and s = Prefix::stateInRelevantRegexp() and
// all edges (at least one) with some char leads to another state that is rejectable. // all edges (at least one) with some char leads to another state that is rejectable.
// the `next` states might not share a common suffix, which can cause FPs. // the `next` states might not share a common suffix, which can cause FPs.
exists(string char | char = hasEdgeToLikelyRejectableHelper(s) | exists(string char | char = hasEdgeToLikelyRejectableHelper(s) |
@@ -1076,7 +1081,7 @@ module ReDoSPruning<isCandidateSig/2 isCandidate> {
*/ */
pragma[noinline] pragma[noinline]
private string hasEdgeToLikelyRejectableHelper(State s) { private string hasEdgeToLikelyRejectableHelper(State s) {
s = stateInPumpableRegexp() and s = Prefix::stateInRelevantRegexp() and
not hasRejectEdge(s) and not hasRejectEdge(s) and
not isRejectState(s) and not isRejectState(s) and
deltaClosedChar(s, result, _) deltaClosedChar(s, result, _)
@@ -1088,8 +1093,8 @@ module ReDoSPruning<isCandidateSig/2 isCandidate> {
* `prev` to `next` that the character symbol `char`. * `prev` to `next` that the character symbol `char`.
*/ */
predicate deltaClosedChar(State prev, string char, State next) { predicate deltaClosedChar(State prev, string char, State next) {
prev = stateInPumpableRegexp() and prev = Prefix::stateInRelevantRegexp() and
next = stateInPumpableRegexp() and next = Prefix::stateInRelevantRegexp() and
deltaClosed(prev, getAnInputSymbolMatchingRelevant(char), next) deltaClosed(prev, getAnInputSymbolMatchingRelevant(char), next)
} }
@@ -1099,11 +1104,20 @@ module ReDoSPruning<isCandidateSig/2 isCandidate> {
result = getAnInputSymbolMatching(char) result = getAnInputSymbolMatching(char)
} }
pragma[noinline]
RegExpRoot relevantRoot() {
exists(RegExpTerm term, State s |
s.getRepr() = term and isCandidateState(s) and result = term.getRootTerm()
)
}
/** /**
* Gets a char used for finding possible suffixes inside `root`. * Gets a char used for finding possible suffixes inside `root`.
*/ */
pragma[noinline] pragma[noinline]
private string relevant(RegExpRoot root) { private string relevant(RegExpRoot root) {
root = relevantRoot() and
(
exists(ascii(result)) and exists(root) exists(ascii(result)) and exists(root)
or or
exists(InputSymbol s | belongsTo(s, root) | result = intersect(s, _)) exists(InputSymbol s | belongsTo(s, root) | result = intersect(s, _))
@@ -1111,6 +1125,7 @@ module ReDoSPruning<isCandidateSig/2 isCandidate> {
// The characters from `hasSimpleRejectEdge`. Only `\n` is really needed (as `\n` is not in the `ascii` relation). // The characters from `hasSimpleRejectEdge`. Only `\n` is really needed (as `\n` is not in the `ascii` relation).
// The three chars must be kept in sync with `hasSimpleRejectEdge`. // The three chars must be kept in sync with `hasSimpleRejectEdge`.
result = ["|", "\n", "Z"] and exists(root) result = ["|", "\n", "Z"] and exists(root)
)
} }
/** /**
@@ -1208,12 +1223,12 @@ module ReDoSPruning<isCandidateSig/2 isCandidate> {
predicate hasReDoSResult(RegExpTerm t, string pump, State s, string prefixMsg) { predicate hasReDoSResult(RegExpTerm t, string pump, State s, string prefixMsg) {
isReDoSAttackable(t, pump, s) and isReDoSAttackable(t, pump, s) and
( (
prefixMsg = "starting with '" + escape(PrefixConstruction::prefix(s)) + "' and " and prefixMsg = "starting with '" + escape(Prefix::prefix(s)) + "' and " and
not PrefixConstruction::prefix(s) = "" not Prefix::prefix(s) = ""
or or
PrefixConstruction::prefix(s) = "" and prefixMsg = "" Prefix::prefix(s) = "" and prefixMsg = ""
or or
not exists(PrefixConstruction::prefix(s)) and prefixMsg = "" not exists(Prefix::prefix(s)) and prefixMsg = ""
) )
} }

View File

@@ -14,4 +14,4 @@ import semmle.code.java.deadcode.DeadCode
from RootdefCallable c from RootdefCallable c
where not c.whitelisted() where not c.whitelisted()
select c.unusedParameter() as p, "The parameter " + p + " is unused." select c.unusedParameter() as p, "The parameter '" + p + "' is never used."

View File

@@ -16,4 +16,4 @@ where
e.isStrict() and e.isStrict() and
e.getGreaterOperand() instanceof BitwiseExpr and e.getGreaterOperand() instanceof BitwiseExpr and
e.getLesserOperand().(IntegerLiteral).getIntValue() = 0 e.getLesserOperand().(IntegerLiteral).getIntValue() = 0
select e, "Sign check of a bitwise operation." select e, "Potentially unsafe sign check of a bitwise operation."

View File

@@ -77,4 +77,4 @@ where
// Exclude `equals` methods that implement reference-equality. // Exclude `equals` methods that implement reference-equality.
not m instanceof ReferenceEquals and not m instanceof ReferenceEquals and
not m instanceof UnimplementedEquals not m instanceof UnimplementedEquals
select m, "equals() method does not seem to check argument type." select m, "equals() method does not check argument type."

View File

@@ -19,4 +19,5 @@ import DataFlow::PathGraph
from QueryInjectionSink query, DataFlow::PathNode source, DataFlow::PathNode sink from QueryInjectionSink query, DataFlow::PathNode source, DataFlow::PathNode sink
where queryTaintedBy(query, source, sink) where queryTaintedBy(query, source, sink)
select query, source, sink, "Query might include code from $@.", source.getNode(), "this user input" select query, source, sink, "This SQL query depends on $@.", source.getNode(),
"a user-provided value"

View File

@@ -51,5 +51,6 @@ class XxeConfig extends TaintTracking::Configuration {
from DataFlow::PathNode source, DataFlow::PathNode sink, XxeConfig conf from DataFlow::PathNode source, DataFlow::PathNode sink, XxeConfig conf
where conf.hasFlowPath(source, sink) where conf.hasFlowPath(source, sink)
select sink.getNode(), source, sink, "Unsafe parsing of XML file from $@.", source.getNode(), select sink.getNode(), source, sink,
"user input" "A $@ is parsed as XML without guarding against external entity expansion.", source.getNode(),
"user-provided value"

View File

@@ -17,4 +17,4 @@ from JavadocText c
where where
c.getText().matches("%TODO%") or c.getText().matches("%TODO%") or
c.getText().matches("%FIXME%") c.getText().matches("%FIXME%")
select c, "TODO/FIXME comment." select c, "TODO comments should be addressed."

View File

@@ -21,4 +21,4 @@ where
read(v) and read(v) and
not def.(AssignExpr).getSource() instanceof NullLiteral and not def.(AssignExpr).getSource() instanceof NullLiteral and
(def instanceof Assignment or def.(UnaryAssignExpr).getParent() instanceof ExprStmt) (def instanceof Assignment or def.(UnaryAssignExpr).getParent() instanceof ExprStmt)
select def, "This assignment to " + v.getName() + " is useless: the value is never read." select def, "This definition of " + v.getName() + " is never used."

View File

@@ -86,5 +86,6 @@ where
) and ) and
// Exclude special VM classes. // Exclude special VM classes.
not isVMObserver(f.getDeclaringType()) not isVMObserver(f.getDeclaringType())
select f, "Field " + f.getName() + " never assigned non-null value, yet it is read at $@.", fr, select f,
fr.getFile().getStem() + ".java:" + fr.getLocation().getStartLine() "The field '" + f.getName() + "' is never explicitly assigned a value, yet it is read $@.", fr,
"here"

View File

@@ -41,4 +41,4 @@ where
f.getType() instanceof Array and f.getType() instanceof Array and
f.fromSource() and f.fromSource() and
forall(AssignExpr a | a.getDest() = f.getAnAccess() | nonEmptyArrayLiteralOrNull(a.getSource())) forall(AssignExpr a | a.getDest() = f.getAnAccess() | nonEmptyArrayLiteralOrNull(a.getSource()))
select f, "The array constant " + f.getName() + " is vulnerable to mutation." select f, "The array constant '" + f.getName() + "' is vulnerable to mutation."

View File

@@ -71,4 +71,4 @@ where
not neededImport(i) and not neededImport(i) and
not i instanceof ImportStaticOnDemand and not i instanceof ImportStaticOnDemand and
not i instanceof ImportStaticTypeMember not i instanceof ImportStaticTypeMember
select i, "The statement '" + i + "' is unnecessary." select i, "Import of '" + i + "' is not used."

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

@@ -48,4 +48,4 @@ where
) )
or or
hasEmbeddedPassword(nameAttr.getValue().trim()) // Attribute value matches password pattern hasEmbeddedPassword(nameAttr.getValue().trim()) // Attribute value matches password pattern
select nameAttr, "Plaintext password in configuration file." select nameAttr, "Avoid plaintext passwords in configuration files."

View File

@@ -85,5 +85,5 @@ class RegexInjectionConfiguration extends TaintTracking::Configuration {
from DataFlow::PathNode source, DataFlow::PathNode sink, RegexInjectionConfiguration c from DataFlow::PathNode source, DataFlow::PathNode sink, RegexInjectionConfiguration c
where c.hasFlowPath(source, sink) where c.hasFlowPath(source, sink)
select sink.getNode(), source, sink, "$@ is user controlled.", source.getNode(), select sink.getNode(), source, sink, "This regular expression is constructed from a $@.",
"This regular expression pattern" source.getNode(), "user-provided value"

View File

@@ -1,3 +1,3 @@
| applicationContext.xml:9:3:9:48 | name=password | Plaintext password in configuration file. | | applicationContext.xml:9:3:9:48 | name=password | Avoid plaintext passwords in configuration files. |
| context.xml:4:2:8:50 | password=1234 | Plaintext password in configuration file. | | context.xml:4:2:8:50 | password=1234 | Avoid plaintext passwords in configuration files. |
| custom-config.xml:3:2:3:137 | value=server=myoracle.example.com;port=1521;database=testdb;username=root;password=test1234 | Plaintext password in configuration file. | | custom-config.xml:3:2:3:137 | value=server=myoracle.example.com;port=1521;database=testdb;username=root;password=test1234 | Avoid plaintext passwords in configuration files. |

View File

@@ -56,18 +56,18 @@ nodes
subpaths subpaths
| RegexInjection.java:68:36:68:42 | pattern : String | RegexInjection.java:71:14:71:23 | str : String | RegexInjection.java:72:12:72:14 | str : String | RegexInjection.java:68:32:68:43 | foo(...) : String | | RegexInjection.java:68:36:68:42 | pattern : String | RegexInjection.java:71:14:71:23 | str : String | RegexInjection.java:72:12:72:14 | str : String | RegexInjection.java:68:32:68:43 | foo(...) : String |
#select #select
| RegexInjection.java:16:26:16:47 | ... + ... | RegexInjection.java:13:22:13:52 | getParameter(...) : String | RegexInjection.java:16:26:16:47 | ... + ... | $@ is user controlled. | RegexInjection.java:13:22:13:52 | getParameter(...) | This regular expression pattern | | RegexInjection.java:16:26:16:47 | ... + ... | RegexInjection.java:13:22:13:52 | getParameter(...) : String | RegexInjection.java:16:26:16:47 | ... + ... | This regular expression is constructed from a $@. | RegexInjection.java:13:22:13:52 | getParameter(...) | user-provided value |
| RegexInjection.java:23:24:23:30 | pattern | RegexInjection.java:20:22:20:52 | getParameter(...) : String | RegexInjection.java:23:24:23:30 | pattern | $@ is user controlled. | RegexInjection.java:20:22:20:52 | getParameter(...) | This regular expression pattern | | RegexInjection.java:23:24:23:30 | pattern | RegexInjection.java:20:22:20:52 | getParameter(...) : String | RegexInjection.java:23:24:23:30 | pattern | This regular expression is constructed from a $@. | RegexInjection.java:20:22:20:52 | getParameter(...) | user-provided value |
| RegexInjection.java:30:31:30:37 | pattern | RegexInjection.java:27:22:27:52 | getParameter(...) : String | RegexInjection.java:30:31:30:37 | pattern | $@ is user controlled. | RegexInjection.java:27:22:27:52 | getParameter(...) | This regular expression pattern | | RegexInjection.java:30:31:30:37 | pattern | RegexInjection.java:27:22:27:52 | getParameter(...) : String | RegexInjection.java:30:31:30:37 | pattern | This regular expression is constructed from a $@. | RegexInjection.java:27:22:27:52 | getParameter(...) | user-provided value |
| RegexInjection.java:37:29:37:35 | pattern | RegexInjection.java:34:22:34:52 | getParameter(...) : String | RegexInjection.java:37:29:37:35 | pattern | $@ is user controlled. | RegexInjection.java:34:22:34:52 | getParameter(...) | This regular expression pattern | | RegexInjection.java:37:29:37:35 | pattern | RegexInjection.java:34:22:34:52 | getParameter(...) : String | RegexInjection.java:37:29:37:35 | pattern | This regular expression is constructed from a $@. | RegexInjection.java:34:22:34:52 | getParameter(...) | user-provided value |
| RegexInjection.java:44:34:44:40 | pattern | RegexInjection.java:41:22:41:52 | getParameter(...) : String | RegexInjection.java:44:34:44:40 | pattern | $@ is user controlled. | RegexInjection.java:41:22:41:52 | getParameter(...) | This regular expression pattern | | RegexInjection.java:44:34:44:40 | pattern | RegexInjection.java:41:22:41:52 | getParameter(...) : String | RegexInjection.java:44:34:44:40 | pattern | This regular expression is constructed from a $@. | RegexInjection.java:41:22:41:52 | getParameter(...) | user-provided value |
| RegexInjection.java:54:28:54:34 | pattern | RegexInjection.java:51:22:51:52 | getParameter(...) : String | RegexInjection.java:54:28:54:34 | pattern | $@ is user controlled. | RegexInjection.java:51:22:51:52 | getParameter(...) | This regular expression pattern | | RegexInjection.java:54:28:54:34 | pattern | RegexInjection.java:51:22:51:52 | getParameter(...) : String | RegexInjection.java:54:28:54:34 | pattern | This regular expression is constructed from a $@. | RegexInjection.java:51:22:51:52 | getParameter(...) | user-provided value |
| RegexInjection.java:61:28:61:34 | pattern | RegexInjection.java:58:22:58:52 | getParameter(...) : String | RegexInjection.java:61:28:61:34 | pattern | $@ is user controlled. | RegexInjection.java:58:22:58:52 | getParameter(...) | This regular expression pattern | | RegexInjection.java:61:28:61:34 | pattern | RegexInjection.java:58:22:58:52 | getParameter(...) : String | RegexInjection.java:61:28:61:34 | pattern | This regular expression is constructed from a $@. | RegexInjection.java:58:22:58:52 | getParameter(...) | user-provided value |
| RegexInjection.java:68:26:68:52 | ... + ... | RegexInjection.java:65:22:65:52 | getParameter(...) : String | RegexInjection.java:68:26:68:52 | ... + ... | $@ is user controlled. | RegexInjection.java:65:22:65:52 | getParameter(...) | This regular expression pattern | | RegexInjection.java:68:26:68:52 | ... + ... | RegexInjection.java:65:22:65:52 | getParameter(...) : String | RegexInjection.java:68:26:68:52 | ... + ... | This regular expression is constructed from a $@. | RegexInjection.java:65:22:65:52 | getParameter(...) | user-provided value |
| RegexInjection.java:90:26:90:47 | ... + ... | RegexInjection.java:84:22:84:52 | getParameter(...) : String | RegexInjection.java:90:26:90:47 | ... + ... | $@ is user controlled. | RegexInjection.java:84:22:84:52 | getParameter(...) | This regular expression pattern | | RegexInjection.java:90:26:90:47 | ... + ... | RegexInjection.java:84:22:84:52 | getParameter(...) : String | RegexInjection.java:90:26:90:47 | ... + ... | This regular expression is constructed from a $@. | RegexInjection.java:84:22:84:52 | getParameter(...) | user-provided value |
| RegexInjection.java:103:40:103:46 | pattern | RegexInjection.java:100:22:100:52 | getParameter(...) : String | RegexInjection.java:103:40:103:46 | pattern | $@ is user controlled. | RegexInjection.java:100:22:100:52 | getParameter(...) | This regular expression pattern | | RegexInjection.java:103:40:103:46 | pattern | RegexInjection.java:100:22:100:52 | getParameter(...) : String | RegexInjection.java:103:40:103:46 | pattern | This regular expression is constructed from a $@. | RegexInjection.java:100:22:100:52 | getParameter(...) | user-provided value |
| RegexInjection.java:110:42:110:48 | pattern | RegexInjection.java:107:22:107:52 | getParameter(...) : String | RegexInjection.java:110:42:110:48 | pattern | $@ is user controlled. | RegexInjection.java:107:22:107:52 | getParameter(...) | This regular expression pattern | | RegexInjection.java:110:42:110:48 | pattern | RegexInjection.java:107:22:107:52 | getParameter(...) : String | RegexInjection.java:110:42:110:48 | pattern | This regular expression is constructed from a $@. | RegexInjection.java:107:22:107:52 | getParameter(...) | user-provided value |
| RegexInjection.java:117:44:117:50 | pattern | RegexInjection.java:114:22:114:52 | getParameter(...) : String | RegexInjection.java:117:44:117:50 | pattern | $@ is user controlled. | RegexInjection.java:114:22:114:52 | getParameter(...) | This regular expression pattern | | RegexInjection.java:117:44:117:50 | pattern | RegexInjection.java:114:22:114:52 | getParameter(...) : String | RegexInjection.java:117:44:117:50 | pattern | This regular expression is constructed from a $@. | RegexInjection.java:114:22:114:52 | getParameter(...) | user-provided value |
| RegexInjection.java:124:41:124:47 | pattern | RegexInjection.java:121:22:121:52 | getParameter(...) : String | RegexInjection.java:124:41:124:47 | pattern | $@ is user controlled. | RegexInjection.java:121:22:121:52 | getParameter(...) | This regular expression pattern | | RegexInjection.java:124:41:124:47 | pattern | RegexInjection.java:121:22:121:52 | getParameter(...) : String | RegexInjection.java:124:41:124:47 | pattern | This regular expression is constructed from a $@. | RegexInjection.java:121:22:121:52 | getParameter(...) | user-provided value |
| RegexInjection.java:131:43:131:49 | pattern | RegexInjection.java:128:22:128:52 | getParameter(...) : String | RegexInjection.java:131:43:131:49 | pattern | $@ is user controlled. | RegexInjection.java:128:22:128:52 | getParameter(...) | This regular expression pattern | | RegexInjection.java:131:43:131:49 | pattern | RegexInjection.java:128:22:128:52 | getParameter(...) : String | RegexInjection.java:131:43:131:49 | pattern | This regular expression is constructed from a $@. | RegexInjection.java:128:22:128:52 | getParameter(...) | user-provided value |
| RegexInjection.java:146:45:146:51 | pattern | RegexInjection.java:143:22:143:52 | getParameter(...) : String | RegexInjection.java:146:45:146:51 | pattern | $@ is user controlled. | RegexInjection.java:143:22:143:52 | getParameter(...) | This regular expression pattern | | RegexInjection.java:146:45:146:51 | pattern | RegexInjection.java:143:22:143:52 | getParameter(...) : String | RegexInjection.java:146:45:146:51 | pattern | This regular expression is constructed from a $@. | RegexInjection.java:143:22:143:52 | getParameter(...) | user-provided value |

View File

@@ -1 +1 @@
| Bad.java:13:17:13:22 | equals | equals() method does not seem to check argument type. | | Bad.java:13:17:13:22 | equals | equals() method does not check argument type. |

View File

@@ -1,5 +1,5 @@
| StaticArray.java:3:31:3:33 | bad | The array constant bad is vulnerable to mutation. | | StaticArray.java:3:31:3:33 | bad | The array constant 'bad' is vulnerable to mutation. |
| StaticArray.java:14:35:14:54 | bad_multidimensional | The array constant bad_multidimensional is vulnerable to mutation. | | StaticArray.java:14:35:14:54 | bad_multidimensional | The array constant 'bad_multidimensional' is vulnerable to mutation. |
| StaticArray.java:15:35:15:67 | bad_multidimensional_partial_init | The array constant bad_multidimensional_partial_init is vulnerable to mutation. | | StaticArray.java:15:35:15:67 | bad_multidimensional_partial_init | The array constant 'bad_multidimensional_partial_init' is vulnerable to mutation. |
| StaticArray.java:17:31:17:47 | bad_separate_init | The array constant bad_separate_init is vulnerable to mutation. | | StaticArray.java:17:31:17:47 | bad_separate_init | The array constant 'bad_separate_init' is vulnerable to mutation. |
| StaticArray.java:26:33:26:44 | bad_nonempty | The array constant bad_nonempty is vulnerable to mutation. | | StaticArray.java:26:33:26:44 | bad_nonempty | The array constant 'bad_nonempty' is vulnerable to mutation. |

View File

@@ -1,2 +1,2 @@
| A.java:29:13:29:21 | ...=... | This assignment to x is useless: the value is never read. | | A.java:29:13:29:21 | ...=... | This definition of x is never used. |
| UnreadLocal/ImplicitReads.java:38:5:38:9 | ...=... | This assignment to c is useless: the value is never read. | | UnreadLocal/ImplicitReads.java:38:5:38:9 | ...=... | This definition of c is never used. |

View File

@@ -1 +1 @@
| Test.java:6:11:6:15 | x | The parameter x is unused. | | Test.java:6:11:6:15 | x | The parameter 'x' is never used. |

View File

@@ -251,101 +251,101 @@ nodes
| XmlInputFactoryTests.java:56:34:56:54 | getInputStream(...) | semmle.label | getInputStream(...) | | XmlInputFactoryTests.java:56:34:56:54 | getInputStream(...) | semmle.label | getInputStream(...) |
subpaths subpaths
#select #select
| DocumentBuilderTests.java:14:19:14:39 | getInputStream(...) | DocumentBuilderTests.java:14:19:14:39 | getInputStream(...) | DocumentBuilderTests.java:14:19:14:39 | getInputStream(...) | Unsafe parsing of XML file from $@. | DocumentBuilderTests.java:14:19:14:39 | getInputStream(...) | user input | | DocumentBuilderTests.java:14:19:14:39 | getInputStream(...) | DocumentBuilderTests.java:14:19:14:39 | getInputStream(...) | DocumentBuilderTests.java:14:19:14:39 | getInputStream(...) | A $@ is parsed as XML without guarding against external entity expansion. | DocumentBuilderTests.java:14:19:14:39 | getInputStream(...) | user-provided value |
| DocumentBuilderTests.java:28:19:28:39 | getInputStream(...) | DocumentBuilderTests.java:28:19:28:39 | getInputStream(...) | DocumentBuilderTests.java:28:19:28:39 | getInputStream(...) | Unsafe parsing of XML file from $@. | DocumentBuilderTests.java:28:19:28:39 | getInputStream(...) | user input | | DocumentBuilderTests.java:28:19:28:39 | getInputStream(...) | DocumentBuilderTests.java:28:19:28:39 | getInputStream(...) | DocumentBuilderTests.java:28:19:28:39 | getInputStream(...) | A $@ is parsed as XML without guarding against external entity expansion. | DocumentBuilderTests.java:28:19:28:39 | getInputStream(...) | user-provided value |
| DocumentBuilderTests.java:35:19:35:39 | getInputStream(...) | DocumentBuilderTests.java:35:19:35:39 | getInputStream(...) | DocumentBuilderTests.java:35:19:35:39 | getInputStream(...) | Unsafe parsing of XML file from $@. | DocumentBuilderTests.java:35:19:35:39 | getInputStream(...) | user input | | DocumentBuilderTests.java:35:19:35:39 | getInputStream(...) | DocumentBuilderTests.java:35:19:35:39 | getInputStream(...) | DocumentBuilderTests.java:35:19:35:39 | getInputStream(...) | A $@ is parsed as XML without guarding against external entity expansion. | DocumentBuilderTests.java:35:19:35:39 | getInputStream(...) | user-provided value |
| DocumentBuilderTests.java:42:19:42:39 | getInputStream(...) | DocumentBuilderTests.java:42:19:42:39 | getInputStream(...) | DocumentBuilderTests.java:42:19:42:39 | getInputStream(...) | Unsafe parsing of XML file from $@. | DocumentBuilderTests.java:42:19:42:39 | getInputStream(...) | user input | | DocumentBuilderTests.java:42:19:42:39 | getInputStream(...) | DocumentBuilderTests.java:42:19:42:39 | getInputStream(...) | DocumentBuilderTests.java:42:19:42:39 | getInputStream(...) | A $@ is parsed as XML without guarding against external entity expansion. | DocumentBuilderTests.java:42:19:42:39 | getInputStream(...) | user-provided value |
| DocumentBuilderTests.java:49:19:49:39 | getInputStream(...) | DocumentBuilderTests.java:49:19:49:39 | getInputStream(...) | DocumentBuilderTests.java:49:19:49:39 | getInputStream(...) | Unsafe parsing of XML file from $@. | DocumentBuilderTests.java:49:19:49:39 | getInputStream(...) | user input | | DocumentBuilderTests.java:49:19:49:39 | getInputStream(...) | DocumentBuilderTests.java:49:19:49:39 | getInputStream(...) | DocumentBuilderTests.java:49:19:49:39 | getInputStream(...) | A $@ is parsed as XML without guarding against external entity expansion. | DocumentBuilderTests.java:49:19:49:39 | getInputStream(...) | user-provided value |
| DocumentBuilderTests.java:64:19:64:39 | getInputStream(...) | DocumentBuilderTests.java:64:19:64:39 | getInputStream(...) | DocumentBuilderTests.java:64:19:64:39 | getInputStream(...) | Unsafe parsing of XML file from $@. | DocumentBuilderTests.java:64:19:64:39 | getInputStream(...) | user input | | DocumentBuilderTests.java:64:19:64:39 | getInputStream(...) | DocumentBuilderTests.java:64:19:64:39 | getInputStream(...) | DocumentBuilderTests.java:64:19:64:39 | getInputStream(...) | A $@ is parsed as XML without guarding against external entity expansion. | DocumentBuilderTests.java:64:19:64:39 | getInputStream(...) | user-provided value |
| DocumentBuilderTests.java:71:19:71:39 | getInputStream(...) | DocumentBuilderTests.java:71:19:71:39 | getInputStream(...) | DocumentBuilderTests.java:71:19:71:39 | getInputStream(...) | Unsafe parsing of XML file from $@. | DocumentBuilderTests.java:71:19:71:39 | getInputStream(...) | user input | | DocumentBuilderTests.java:71:19:71:39 | getInputStream(...) | DocumentBuilderTests.java:71:19:71:39 | getInputStream(...) | DocumentBuilderTests.java:71:19:71:39 | getInputStream(...) | A $@ is parsed as XML without guarding against external entity expansion. | DocumentBuilderTests.java:71:19:71:39 | getInputStream(...) | user-provided value |
| DocumentBuilderTests.java:79:19:79:39 | getInputStream(...) | DocumentBuilderTests.java:79:19:79:39 | getInputStream(...) | DocumentBuilderTests.java:79:19:79:39 | getInputStream(...) | Unsafe parsing of XML file from $@. | DocumentBuilderTests.java:79:19:79:39 | getInputStream(...) | user input | | DocumentBuilderTests.java:79:19:79:39 | getInputStream(...) | DocumentBuilderTests.java:79:19:79:39 | getInputStream(...) | DocumentBuilderTests.java:79:19:79:39 | getInputStream(...) | A $@ is parsed as XML without guarding against external entity expansion. | DocumentBuilderTests.java:79:19:79:39 | getInputStream(...) | user-provided value |
| DocumentBuilderTests.java:87:19:87:39 | getInputStream(...) | DocumentBuilderTests.java:87:19:87:39 | getInputStream(...) | DocumentBuilderTests.java:87:19:87:39 | getInputStream(...) | Unsafe parsing of XML file from $@. | DocumentBuilderTests.java:87:19:87:39 | getInputStream(...) | user input | | DocumentBuilderTests.java:87:19:87:39 | getInputStream(...) | DocumentBuilderTests.java:87:19:87:39 | getInputStream(...) | DocumentBuilderTests.java:87:19:87:39 | getInputStream(...) | A $@ is parsed as XML without guarding against external entity expansion. | DocumentBuilderTests.java:87:19:87:39 | getInputStream(...) | user-provided value |
| DocumentBuilderTests.java:94:16:94:38 | getInputSource(...) | DocumentBuilderTests.java:93:51:93:71 | getInputStream(...) : InputStream | DocumentBuilderTests.java:94:16:94:38 | getInputSource(...) | Unsafe parsing of XML file from $@. | DocumentBuilderTests.java:93:51:93:71 | getInputStream(...) | user input | | DocumentBuilderTests.java:94:16:94:38 | getInputSource(...) | DocumentBuilderTests.java:93:51:93:71 | getInputStream(...) : InputStream | DocumentBuilderTests.java:94:16:94:38 | getInputSource(...) | A $@ is parsed as XML without guarding against external entity expansion. | DocumentBuilderTests.java:93:51:93:71 | getInputStream(...) | user-provided value |
| DocumentBuilderTests.java:101:16:101:52 | sourceToInputSource(...) | DocumentBuilderTests.java:100:41:100:61 | getInputStream(...) : InputStream | DocumentBuilderTests.java:101:16:101:52 | sourceToInputSource(...) | Unsafe parsing of XML file from $@. | DocumentBuilderTests.java:100:41:100:61 | getInputStream(...) | user input | | DocumentBuilderTests.java:101:16:101:52 | sourceToInputSource(...) | DocumentBuilderTests.java:100:41:100:61 | getInputStream(...) : InputStream | DocumentBuilderTests.java:101:16:101:52 | sourceToInputSource(...) | A $@ is parsed as XML without guarding against external entity expansion. | DocumentBuilderTests.java:100:41:100:61 | getInputStream(...) | user-provided value |
| DocumentBuilderTests.java:102:16:102:38 | getInputStream(...) | DocumentBuilderTests.java:100:41:100:61 | getInputStream(...) : InputStream | DocumentBuilderTests.java:102:16:102:38 | getInputStream(...) | Unsafe parsing of XML file from $@. | DocumentBuilderTests.java:100:41:100:61 | getInputStream(...) | user input | | DocumentBuilderTests.java:102:16:102:38 | getInputStream(...) | DocumentBuilderTests.java:100:41:100:61 | getInputStream(...) : InputStream | DocumentBuilderTests.java:102:16:102:38 | getInputStream(...) | A $@ is parsed as XML without guarding against external entity expansion. | DocumentBuilderTests.java:100:41:100:61 | getInputStream(...) | user-provided value |
| SAXBuilderTests.java:8:19:8:39 | getInputStream(...) | SAXBuilderTests.java:8:19:8:39 | getInputStream(...) | SAXBuilderTests.java:8:19:8:39 | getInputStream(...) | Unsafe parsing of XML file from $@. | SAXBuilderTests.java:8:19:8:39 | getInputStream(...) | user input | | SAXBuilderTests.java:8:19:8:39 | getInputStream(...) | SAXBuilderTests.java:8:19:8:39 | getInputStream(...) | SAXBuilderTests.java:8:19:8:39 | getInputStream(...) | A $@ is parsed as XML without guarding against external entity expansion. | SAXBuilderTests.java:8:19:8:39 | getInputStream(...) | user-provided value |
| SAXBuilderTests.java:20:19:20:39 | getInputStream(...) | SAXBuilderTests.java:20:19:20:39 | getInputStream(...) | SAXBuilderTests.java:20:19:20:39 | getInputStream(...) | Unsafe parsing of XML file from $@. | SAXBuilderTests.java:20:19:20:39 | getInputStream(...) | user input | | SAXBuilderTests.java:20:19:20:39 | getInputStream(...) | SAXBuilderTests.java:20:19:20:39 | getInputStream(...) | SAXBuilderTests.java:20:19:20:39 | getInputStream(...) | A $@ is parsed as XML without guarding against external entity expansion. | SAXBuilderTests.java:20:19:20:39 | getInputStream(...) | user-provided value |
| SAXParserTests.java:13:18:13:38 | getInputStream(...) | SAXParserTests.java:13:18:13:38 | getInputStream(...) | SAXParserTests.java:13:18:13:38 | getInputStream(...) | Unsafe parsing of XML file from $@. | SAXParserTests.java:13:18:13:38 | getInputStream(...) | user input | | SAXParserTests.java:13:18:13:38 | getInputStream(...) | SAXParserTests.java:13:18:13:38 | getInputStream(...) | SAXParserTests.java:13:18:13:38 | getInputStream(...) | A $@ is parsed as XML without guarding against external entity expansion. | SAXParserTests.java:13:18:13:38 | getInputStream(...) | user-provided value |
| SAXParserTests.java:30:18:30:38 | getInputStream(...) | SAXParserTests.java:30:18:30:38 | getInputStream(...) | SAXParserTests.java:30:18:30:38 | getInputStream(...) | Unsafe parsing of XML file from $@. | SAXParserTests.java:30:18:30:38 | getInputStream(...) | user input | | SAXParserTests.java:30:18:30:38 | getInputStream(...) | SAXParserTests.java:30:18:30:38 | getInputStream(...) | SAXParserTests.java:30:18:30:38 | getInputStream(...) | A $@ is parsed as XML without guarding against external entity expansion. | SAXParserTests.java:30:18:30:38 | getInputStream(...) | user-provided value |
| SAXParserTests.java:38:18:38:38 | getInputStream(...) | SAXParserTests.java:38:18:38:38 | getInputStream(...) | SAXParserTests.java:38:18:38:38 | getInputStream(...) | Unsafe parsing of XML file from $@. | SAXParserTests.java:38:18:38:38 | getInputStream(...) | user input | | SAXParserTests.java:38:18:38:38 | getInputStream(...) | SAXParserTests.java:38:18:38:38 | getInputStream(...) | SAXParserTests.java:38:18:38:38 | getInputStream(...) | A $@ is parsed as XML without guarding against external entity expansion. | SAXParserTests.java:38:18:38:38 | getInputStream(...) | user-provided value |
| SAXParserTests.java:46:18:46:38 | getInputStream(...) | SAXParserTests.java:46:18:46:38 | getInputStream(...) | SAXParserTests.java:46:18:46:38 | getInputStream(...) | Unsafe parsing of XML file from $@. | SAXParserTests.java:46:18:46:38 | getInputStream(...) | user input | | SAXParserTests.java:46:18:46:38 | getInputStream(...) | SAXParserTests.java:46:18:46:38 | getInputStream(...) | SAXParserTests.java:46:18:46:38 | getInputStream(...) | A $@ is parsed as XML without guarding against external entity expansion. | SAXParserTests.java:46:18:46:38 | getInputStream(...) | user-provided value |
| SAXParserTests.java:55:18:55:38 | getInputStream(...) | SAXParserTests.java:55:18:55:38 | getInputStream(...) | SAXParserTests.java:55:18:55:38 | getInputStream(...) | Unsafe parsing of XML file from $@. | SAXParserTests.java:55:18:55:38 | getInputStream(...) | user input | | SAXParserTests.java:55:18:55:38 | getInputStream(...) | SAXParserTests.java:55:18:55:38 | getInputStream(...) | SAXParserTests.java:55:18:55:38 | getInputStream(...) | A $@ is parsed as XML without guarding against external entity expansion. | SAXParserTests.java:55:18:55:38 | getInputStream(...) | user-provided value |
| SAXParserTests.java:64:18:64:38 | getInputStream(...) | SAXParserTests.java:64:18:64:38 | getInputStream(...) | SAXParserTests.java:64:18:64:38 | getInputStream(...) | Unsafe parsing of XML file from $@. | SAXParserTests.java:64:18:64:38 | getInputStream(...) | user input | | SAXParserTests.java:64:18:64:38 | getInputStream(...) | SAXParserTests.java:64:18:64:38 | getInputStream(...) | SAXParserTests.java:64:18:64:38 | getInputStream(...) | A $@ is parsed as XML without guarding against external entity expansion. | SAXParserTests.java:64:18:64:38 | getInputStream(...) | user-provided value |
| SAXParserTests.java:73:18:73:38 | getInputStream(...) | SAXParserTests.java:73:18:73:38 | getInputStream(...) | SAXParserTests.java:73:18:73:38 | getInputStream(...) | Unsafe parsing of XML file from $@. | SAXParserTests.java:73:18:73:38 | getInputStream(...) | user input | | SAXParserTests.java:73:18:73:38 | getInputStream(...) | SAXParserTests.java:73:18:73:38 | getInputStream(...) | SAXParserTests.java:73:18:73:38 | getInputStream(...) | A $@ is parsed as XML without guarding against external entity expansion. | SAXParserTests.java:73:18:73:38 | getInputStream(...) | user-provided value |
| SAXReaderTests.java:8:17:8:37 | getInputStream(...) | SAXReaderTests.java:8:17:8:37 | getInputStream(...) | SAXReaderTests.java:8:17:8:37 | getInputStream(...) | Unsafe parsing of XML file from $@. | SAXReaderTests.java:8:17:8:37 | getInputStream(...) | user input | | SAXReaderTests.java:8:17:8:37 | getInputStream(...) | SAXReaderTests.java:8:17:8:37 | getInputStream(...) | SAXReaderTests.java:8:17:8:37 | getInputStream(...) | A $@ is parsed as XML without guarding against external entity expansion. | SAXReaderTests.java:8:17:8:37 | getInputStream(...) | user-provided value |
| SAXReaderTests.java:23:17:23:37 | getInputStream(...) | SAXReaderTests.java:23:17:23:37 | getInputStream(...) | SAXReaderTests.java:23:17:23:37 | getInputStream(...) | Unsafe parsing of XML file from $@. | SAXReaderTests.java:23:17:23:37 | getInputStream(...) | user input | | SAXReaderTests.java:23:17:23:37 | getInputStream(...) | SAXReaderTests.java:23:17:23:37 | getInputStream(...) | SAXReaderTests.java:23:17:23:37 | getInputStream(...) | A $@ is parsed as XML without guarding against external entity expansion. | SAXReaderTests.java:23:17:23:37 | getInputStream(...) | user-provided value |
| SAXReaderTests.java:30:17:30:37 | getInputStream(...) | SAXReaderTests.java:30:17:30:37 | getInputStream(...) | SAXReaderTests.java:30:17:30:37 | getInputStream(...) | Unsafe parsing of XML file from $@. | SAXReaderTests.java:30:17:30:37 | getInputStream(...) | user input | | SAXReaderTests.java:30:17:30:37 | getInputStream(...) | SAXReaderTests.java:30:17:30:37 | getInputStream(...) | SAXReaderTests.java:30:17:30:37 | getInputStream(...) | A $@ is parsed as XML without guarding against external entity expansion. | SAXReaderTests.java:30:17:30:37 | getInputStream(...) | user-provided value |
| SAXReaderTests.java:37:17:37:37 | getInputStream(...) | SAXReaderTests.java:37:17:37:37 | getInputStream(...) | SAXReaderTests.java:37:17:37:37 | getInputStream(...) | Unsafe parsing of XML file from $@. | SAXReaderTests.java:37:17:37:37 | getInputStream(...) | user input | | SAXReaderTests.java:37:17:37:37 | getInputStream(...) | SAXReaderTests.java:37:17:37:37 | getInputStream(...) | SAXReaderTests.java:37:17:37:37 | getInputStream(...) | A $@ is parsed as XML without guarding against external entity expansion. | SAXReaderTests.java:37:17:37:37 | getInputStream(...) | user-provided value |
| SAXReaderTests.java:45:17:45:37 | getInputStream(...) | SAXReaderTests.java:45:17:45:37 | getInputStream(...) | SAXReaderTests.java:45:17:45:37 | getInputStream(...) | Unsafe parsing of XML file from $@. | SAXReaderTests.java:45:17:45:37 | getInputStream(...) | user input | | SAXReaderTests.java:45:17:45:37 | getInputStream(...) | SAXReaderTests.java:45:17:45:37 | getInputStream(...) | SAXReaderTests.java:45:17:45:37 | getInputStream(...) | A $@ is parsed as XML without guarding against external entity expansion. | SAXReaderTests.java:45:17:45:37 | getInputStream(...) | user-provided value |
| SAXReaderTests.java:53:17:53:37 | getInputStream(...) | SAXReaderTests.java:53:17:53:37 | getInputStream(...) | SAXReaderTests.java:53:17:53:37 | getInputStream(...) | Unsafe parsing of XML file from $@. | SAXReaderTests.java:53:17:53:37 | getInputStream(...) | user input | | SAXReaderTests.java:53:17:53:37 | getInputStream(...) | SAXReaderTests.java:53:17:53:37 | getInputStream(...) | SAXReaderTests.java:53:17:53:37 | getInputStream(...) | A $@ is parsed as XML without guarding against external entity expansion. | SAXReaderTests.java:53:17:53:37 | getInputStream(...) | user-provided value |
| SAXReaderTests.java:61:17:61:37 | getInputStream(...) | SAXReaderTests.java:61:17:61:37 | getInputStream(...) | SAXReaderTests.java:61:17:61:37 | getInputStream(...) | Unsafe parsing of XML file from $@. | SAXReaderTests.java:61:17:61:37 | getInputStream(...) | user input | | SAXReaderTests.java:61:17:61:37 | getInputStream(...) | SAXReaderTests.java:61:17:61:37 | getInputStream(...) | SAXReaderTests.java:61:17:61:37 | getInputStream(...) | A $@ is parsed as XML without guarding against external entity expansion. | SAXReaderTests.java:61:17:61:37 | getInputStream(...) | user-provided value |
| SAXSourceTests.java:20:18:20:23 | source | SAXSourceTests.java:17:62:17:82 | getInputStream(...) : InputStream | SAXSourceTests.java:20:18:20:23 | source | Unsafe parsing of XML file from $@. | SAXSourceTests.java:17:62:17:82 | getInputStream(...) | user input | | SAXSourceTests.java:20:18:20:23 | source | SAXSourceTests.java:17:62:17:82 | getInputStream(...) : InputStream | SAXSourceTests.java:20:18:20:23 | source | A $@ is parsed as XML without guarding against external entity expansion. | SAXSourceTests.java:17:62:17:82 | getInputStream(...) | user-provided value |
| SchemaTests.java:12:39:12:77 | new StreamSource(...) | SchemaTests.java:12:56:12:76 | getInputStream(...) : InputStream | SchemaTests.java:12:39:12:77 | new StreamSource(...) | Unsafe parsing of XML file from $@. | SchemaTests.java:12:56:12:76 | getInputStream(...) | user input | | SchemaTests.java:12:39:12:77 | new StreamSource(...) | SchemaTests.java:12:56:12:76 | getInputStream(...) : InputStream | SchemaTests.java:12:39:12:77 | new StreamSource(...) | A $@ is parsed as XML without guarding against external entity expansion. | SchemaTests.java:12:56:12:76 | getInputStream(...) | user-provided value |
| SchemaTests.java:25:39:25:77 | new StreamSource(...) | SchemaTests.java:25:56:25:76 | getInputStream(...) : InputStream | SchemaTests.java:25:39:25:77 | new StreamSource(...) | Unsafe parsing of XML file from $@. | SchemaTests.java:25:56:25:76 | getInputStream(...) | user input | | SchemaTests.java:25:39:25:77 | new StreamSource(...) | SchemaTests.java:25:56:25:76 | getInputStream(...) : InputStream | SchemaTests.java:25:39:25:77 | new StreamSource(...) | A $@ is parsed as XML without guarding against external entity expansion. | SchemaTests.java:25:56:25:76 | getInputStream(...) | user-provided value |
| SchemaTests.java:31:39:31:77 | new StreamSource(...) | SchemaTests.java:31:56:31:76 | getInputStream(...) : InputStream | SchemaTests.java:31:39:31:77 | new StreamSource(...) | Unsafe parsing of XML file from $@. | SchemaTests.java:31:56:31:76 | getInputStream(...) | user input | | SchemaTests.java:31:39:31:77 | new StreamSource(...) | SchemaTests.java:31:56:31:76 | getInputStream(...) : InputStream | SchemaTests.java:31:39:31:77 | new StreamSource(...) | A $@ is parsed as XML without guarding against external entity expansion. | SchemaTests.java:31:56:31:76 | getInputStream(...) | user-provided value |
| SchemaTests.java:38:39:38:77 | new StreamSource(...) | SchemaTests.java:38:56:38:76 | getInputStream(...) : InputStream | SchemaTests.java:38:39:38:77 | new StreamSource(...) | Unsafe parsing of XML file from $@. | SchemaTests.java:38:56:38:76 | getInputStream(...) | user input | | SchemaTests.java:38:39:38:77 | new StreamSource(...) | SchemaTests.java:38:56:38:76 | getInputStream(...) : InputStream | SchemaTests.java:38:39:38:77 | new StreamSource(...) | A $@ is parsed as XML without guarding against external entity expansion. | SchemaTests.java:38:56:38:76 | getInputStream(...) | user-provided value |
| SchemaTests.java:45:39:45:77 | new StreamSource(...) | SchemaTests.java:45:56:45:76 | getInputStream(...) : InputStream | SchemaTests.java:45:39:45:77 | new StreamSource(...) | Unsafe parsing of XML file from $@. | SchemaTests.java:45:56:45:76 | getInputStream(...) | user input | | SchemaTests.java:45:39:45:77 | new StreamSource(...) | SchemaTests.java:45:56:45:76 | getInputStream(...) : InputStream | SchemaTests.java:45:39:45:77 | new StreamSource(...) | A $@ is parsed as XML without guarding against external entity expansion. | SchemaTests.java:45:56:45:76 | getInputStream(...) | user-provided value |
| SimpleXMLTests.java:14:41:14:61 | getInputStream(...) | SimpleXMLTests.java:14:41:14:61 | getInputStream(...) | SimpleXMLTests.java:14:41:14:61 | getInputStream(...) | Unsafe parsing of XML file from $@. | SimpleXMLTests.java:14:41:14:61 | getInputStream(...) | user input | | SimpleXMLTests.java:14:41:14:61 | getInputStream(...) | SimpleXMLTests.java:14:41:14:61 | getInputStream(...) | SimpleXMLTests.java:14:41:14:61 | getInputStream(...) | A $@ is parsed as XML without guarding against external entity expansion. | SimpleXMLTests.java:14:41:14:61 | getInputStream(...) | user-provided value |
| SimpleXMLTests.java:19:41:19:61 | getInputStream(...) | SimpleXMLTests.java:19:41:19:61 | getInputStream(...) | SimpleXMLTests.java:19:41:19:61 | getInputStream(...) | Unsafe parsing of XML file from $@. | SimpleXMLTests.java:19:41:19:61 | getInputStream(...) | user input | | SimpleXMLTests.java:19:41:19:61 | getInputStream(...) | SimpleXMLTests.java:19:41:19:61 | getInputStream(...) | SimpleXMLTests.java:19:41:19:61 | getInputStream(...) | A $@ is parsed as XML without guarding against external entity expansion. | SimpleXMLTests.java:19:41:19:61 | getInputStream(...) | user-provided value |
| SimpleXMLTests.java:24:41:24:84 | new InputStreamReader(...) | SimpleXMLTests.java:24:63:24:83 | getInputStream(...) : InputStream | SimpleXMLTests.java:24:41:24:84 | new InputStreamReader(...) | Unsafe parsing of XML file from $@. | SimpleXMLTests.java:24:63:24:83 | getInputStream(...) | user input | | SimpleXMLTests.java:24:41:24:84 | new InputStreamReader(...) | SimpleXMLTests.java:24:63:24:83 | getInputStream(...) : InputStream | SimpleXMLTests.java:24:41:24:84 | new InputStreamReader(...) | A $@ is parsed as XML without guarding against external entity expansion. | SimpleXMLTests.java:24:63:24:83 | getInputStream(...) | user-provided value |
| SimpleXMLTests.java:31:41:31:53 | new String(...) | SimpleXMLTests.java:30:5:30:25 | getInputStream(...) : InputStream | SimpleXMLTests.java:31:41:31:53 | new String(...) | Unsafe parsing of XML file from $@. | SimpleXMLTests.java:30:5:30:25 | getInputStream(...) | user input | | SimpleXMLTests.java:31:41:31:53 | new String(...) | SimpleXMLTests.java:30:5:30:25 | getInputStream(...) : InputStream | SimpleXMLTests.java:31:41:31:53 | new String(...) | A $@ is parsed as XML without guarding against external entity expansion. | SimpleXMLTests.java:30:5:30:25 | getInputStream(...) | user-provided value |
| SimpleXMLTests.java:38:41:38:53 | new String(...) | SimpleXMLTests.java:37:5:37:25 | getInputStream(...) : InputStream | SimpleXMLTests.java:38:41:38:53 | new String(...) | Unsafe parsing of XML file from $@. | SimpleXMLTests.java:37:5:37:25 | getInputStream(...) | user input | | SimpleXMLTests.java:38:41:38:53 | new String(...) | SimpleXMLTests.java:37:5:37:25 | getInputStream(...) : InputStream | SimpleXMLTests.java:38:41:38:53 | new String(...) | A $@ is parsed as XML without guarding against external entity expansion. | SimpleXMLTests.java:37:5:37:25 | getInputStream(...) | user-provided value |
| SimpleXMLTests.java:43:41:43:84 | new InputStreamReader(...) | SimpleXMLTests.java:43:63:43:83 | getInputStream(...) : InputStream | SimpleXMLTests.java:43:41:43:84 | new InputStreamReader(...) | Unsafe parsing of XML file from $@. | SimpleXMLTests.java:43:63:43:83 | getInputStream(...) | user input | | SimpleXMLTests.java:43:41:43:84 | new InputStreamReader(...) | SimpleXMLTests.java:43:63:43:83 | getInputStream(...) : InputStream | SimpleXMLTests.java:43:41:43:84 | new InputStreamReader(...) | A $@ is parsed as XML without guarding against external entity expansion. | SimpleXMLTests.java:43:63:43:83 | getInputStream(...) | user-provided value |
| SimpleXMLTests.java:48:37:48:57 | getInputStream(...) | SimpleXMLTests.java:48:37:48:57 | getInputStream(...) | SimpleXMLTests.java:48:37:48:57 | getInputStream(...) | Unsafe parsing of XML file from $@. | SimpleXMLTests.java:48:37:48:57 | getInputStream(...) | user input | | SimpleXMLTests.java:48:37:48:57 | getInputStream(...) | SimpleXMLTests.java:48:37:48:57 | getInputStream(...) | SimpleXMLTests.java:48:37:48:57 | getInputStream(...) | A $@ is parsed as XML without guarding against external entity expansion. | SimpleXMLTests.java:48:37:48:57 | getInputStream(...) | user-provided value |
| SimpleXMLTests.java:53:37:53:57 | getInputStream(...) | SimpleXMLTests.java:53:37:53:57 | getInputStream(...) | SimpleXMLTests.java:53:37:53:57 | getInputStream(...) | Unsafe parsing of XML file from $@. | SimpleXMLTests.java:53:37:53:57 | getInputStream(...) | user input | | SimpleXMLTests.java:53:37:53:57 | getInputStream(...) | SimpleXMLTests.java:53:37:53:57 | getInputStream(...) | SimpleXMLTests.java:53:37:53:57 | getInputStream(...) | A $@ is parsed as XML without guarding against external entity expansion. | SimpleXMLTests.java:53:37:53:57 | getInputStream(...) | user-provided value |
| SimpleXMLTests.java:58:26:58:46 | getInputStream(...) | SimpleXMLTests.java:58:26:58:46 | getInputStream(...) | SimpleXMLTests.java:58:26:58:46 | getInputStream(...) | Unsafe parsing of XML file from $@. | SimpleXMLTests.java:58:26:58:46 | getInputStream(...) | user input | | SimpleXMLTests.java:58:26:58:46 | getInputStream(...) | SimpleXMLTests.java:58:26:58:46 | getInputStream(...) | SimpleXMLTests.java:58:26:58:46 | getInputStream(...) | A $@ is parsed as XML without guarding against external entity expansion. | SimpleXMLTests.java:58:26:58:46 | getInputStream(...) | user-provided value |
| SimpleXMLTests.java:63:26:63:46 | getInputStream(...) | SimpleXMLTests.java:63:26:63:46 | getInputStream(...) | SimpleXMLTests.java:63:26:63:46 | getInputStream(...) | Unsafe parsing of XML file from $@. | SimpleXMLTests.java:63:26:63:46 | getInputStream(...) | user input | | SimpleXMLTests.java:63:26:63:46 | getInputStream(...) | SimpleXMLTests.java:63:26:63:46 | getInputStream(...) | SimpleXMLTests.java:63:26:63:46 | getInputStream(...) | A $@ is parsed as XML without guarding against external entity expansion. | SimpleXMLTests.java:63:26:63:46 | getInputStream(...) | user-provided value |
| SimpleXMLTests.java:68:37:68:80 | new InputStreamReader(...) | SimpleXMLTests.java:68:59:68:79 | getInputStream(...) : InputStream | SimpleXMLTests.java:68:37:68:80 | new InputStreamReader(...) | Unsafe parsing of XML file from $@. | SimpleXMLTests.java:68:59:68:79 | getInputStream(...) | user input | | SimpleXMLTests.java:68:37:68:80 | new InputStreamReader(...) | SimpleXMLTests.java:68:59:68:79 | getInputStream(...) : InputStream | SimpleXMLTests.java:68:37:68:80 | new InputStreamReader(...) | A $@ is parsed as XML without guarding against external entity expansion. | SimpleXMLTests.java:68:59:68:79 | getInputStream(...) | user-provided value |
| SimpleXMLTests.java:73:37:73:80 | new InputStreamReader(...) | SimpleXMLTests.java:73:59:73:79 | getInputStream(...) : InputStream | SimpleXMLTests.java:73:37:73:80 | new InputStreamReader(...) | Unsafe parsing of XML file from $@. | SimpleXMLTests.java:73:59:73:79 | getInputStream(...) | user input | | SimpleXMLTests.java:73:37:73:80 | new InputStreamReader(...) | SimpleXMLTests.java:73:59:73:79 | getInputStream(...) : InputStream | SimpleXMLTests.java:73:37:73:80 | new InputStreamReader(...) | A $@ is parsed as XML without guarding against external entity expansion. | SimpleXMLTests.java:73:59:73:79 | getInputStream(...) | user-provided value |
| SimpleXMLTests.java:78:26:78:69 | new InputStreamReader(...) | SimpleXMLTests.java:78:48:78:68 | getInputStream(...) : InputStream | SimpleXMLTests.java:78:26:78:69 | new InputStreamReader(...) | Unsafe parsing of XML file from $@. | SimpleXMLTests.java:78:48:78:68 | getInputStream(...) | user input | | SimpleXMLTests.java:78:26:78:69 | new InputStreamReader(...) | SimpleXMLTests.java:78:48:78:68 | getInputStream(...) : InputStream | SimpleXMLTests.java:78:26:78:69 | new InputStreamReader(...) | A $@ is parsed as XML without guarding against external entity expansion. | SimpleXMLTests.java:78:48:78:68 | getInputStream(...) | user-provided value |
| SimpleXMLTests.java:83:26:83:69 | new InputStreamReader(...) | SimpleXMLTests.java:83:48:83:68 | getInputStream(...) : InputStream | SimpleXMLTests.java:83:26:83:69 | new InputStreamReader(...) | Unsafe parsing of XML file from $@. | SimpleXMLTests.java:83:48:83:68 | getInputStream(...) | user input | | SimpleXMLTests.java:83:26:83:69 | new InputStreamReader(...) | SimpleXMLTests.java:83:48:83:68 | getInputStream(...) : InputStream | SimpleXMLTests.java:83:26:83:69 | new InputStreamReader(...) | A $@ is parsed as XML without guarding against external entity expansion. | SimpleXMLTests.java:83:48:83:68 | getInputStream(...) | user-provided value |
| SimpleXMLTests.java:90:37:90:49 | new String(...) | SimpleXMLTests.java:89:5:89:25 | getInputStream(...) : InputStream | SimpleXMLTests.java:90:37:90:49 | new String(...) | Unsafe parsing of XML file from $@. | SimpleXMLTests.java:89:5:89:25 | getInputStream(...) | user input | | SimpleXMLTests.java:90:37:90:49 | new String(...) | SimpleXMLTests.java:89:5:89:25 | getInputStream(...) : InputStream | SimpleXMLTests.java:90:37:90:49 | new String(...) | A $@ is parsed as XML without guarding against external entity expansion. | SimpleXMLTests.java:89:5:89:25 | getInputStream(...) | user-provided value |
| SimpleXMLTests.java:97:37:97:49 | new String(...) | SimpleXMLTests.java:96:5:96:25 | getInputStream(...) : InputStream | SimpleXMLTests.java:97:37:97:49 | new String(...) | Unsafe parsing of XML file from $@. | SimpleXMLTests.java:96:5:96:25 | getInputStream(...) | user input | | SimpleXMLTests.java:97:37:97:49 | new String(...) | SimpleXMLTests.java:96:5:96:25 | getInputStream(...) : InputStream | SimpleXMLTests.java:97:37:97:49 | new String(...) | A $@ is parsed as XML without guarding against external entity expansion. | SimpleXMLTests.java:96:5:96:25 | getInputStream(...) | user-provided value |
| SimpleXMLTests.java:104:26:104:38 | new String(...) | SimpleXMLTests.java:103:5:103:25 | getInputStream(...) : InputStream | SimpleXMLTests.java:104:26:104:38 | new String(...) | Unsafe parsing of XML file from $@. | SimpleXMLTests.java:103:5:103:25 | getInputStream(...) | user input | | SimpleXMLTests.java:104:26:104:38 | new String(...) | SimpleXMLTests.java:103:5:103:25 | getInputStream(...) : InputStream | SimpleXMLTests.java:104:26:104:38 | new String(...) | A $@ is parsed as XML without guarding against external entity expansion. | SimpleXMLTests.java:103:5:103:25 | getInputStream(...) | user-provided value |
| SimpleXMLTests.java:111:26:111:38 | new String(...) | SimpleXMLTests.java:110:5:110:25 | getInputStream(...) : InputStream | SimpleXMLTests.java:111:26:111:38 | new String(...) | Unsafe parsing of XML file from $@. | SimpleXMLTests.java:110:5:110:25 | getInputStream(...) | user input | | SimpleXMLTests.java:111:26:111:38 | new String(...) | SimpleXMLTests.java:110:5:110:25 | getInputStream(...) : InputStream | SimpleXMLTests.java:111:26:111:38 | new String(...) | A $@ is parsed as XML without guarding against external entity expansion. | SimpleXMLTests.java:110:5:110:25 | getInputStream(...) | user-provided value |
| SimpleXMLTests.java:115:22:115:42 | getInputStream(...) | SimpleXMLTests.java:115:22:115:42 | getInputStream(...) | SimpleXMLTests.java:115:22:115:42 | getInputStream(...) | Unsafe parsing of XML file from $@. | SimpleXMLTests.java:115:22:115:42 | getInputStream(...) | user input | | SimpleXMLTests.java:115:22:115:42 | getInputStream(...) | SimpleXMLTests.java:115:22:115:42 | getInputStream(...) | SimpleXMLTests.java:115:22:115:42 | getInputStream(...) | A $@ is parsed as XML without guarding against external entity expansion. | SimpleXMLTests.java:115:22:115:42 | getInputStream(...) | user-provided value |
| SimpleXMLTests.java:119:22:119:65 | new InputStreamReader(...) | SimpleXMLTests.java:119:44:119:64 | getInputStream(...) : InputStream | SimpleXMLTests.java:119:22:119:65 | new InputStreamReader(...) | Unsafe parsing of XML file from $@. | SimpleXMLTests.java:119:44:119:64 | getInputStream(...) | user input | | SimpleXMLTests.java:119:22:119:65 | new InputStreamReader(...) | SimpleXMLTests.java:119:44:119:64 | getInputStream(...) : InputStream | SimpleXMLTests.java:119:22:119:65 | new InputStreamReader(...) | A $@ is parsed as XML without guarding against external entity expansion. | SimpleXMLTests.java:119:44:119:64 | getInputStream(...) | user-provided value |
| SimpleXMLTests.java:124:22:124:42 | getInputStream(...) | SimpleXMLTests.java:124:22:124:42 | getInputStream(...) | SimpleXMLTests.java:124:22:124:42 | getInputStream(...) | Unsafe parsing of XML file from $@. | SimpleXMLTests.java:124:22:124:42 | getInputStream(...) | user input | | SimpleXMLTests.java:124:22:124:42 | getInputStream(...) | SimpleXMLTests.java:124:22:124:42 | getInputStream(...) | SimpleXMLTests.java:124:22:124:42 | getInputStream(...) | A $@ is parsed as XML without guarding against external entity expansion. | SimpleXMLTests.java:124:22:124:42 | getInputStream(...) | user-provided value |
| SimpleXMLTests.java:129:22:129:65 | new InputStreamReader(...) | SimpleXMLTests.java:129:44:129:64 | getInputStream(...) : InputStream | SimpleXMLTests.java:129:22:129:65 | new InputStreamReader(...) | Unsafe parsing of XML file from $@. | SimpleXMLTests.java:129:44:129:64 | getInputStream(...) | user input | | SimpleXMLTests.java:129:22:129:65 | new InputStreamReader(...) | SimpleXMLTests.java:129:44:129:64 | getInputStream(...) : InputStream | SimpleXMLTests.java:129:22:129:65 | new InputStreamReader(...) | A $@ is parsed as XML without guarding against external entity expansion. | SimpleXMLTests.java:129:44:129:64 | getInputStream(...) | user-provided value |
| SimpleXMLTests.java:134:22:134:42 | getInputStream(...) | SimpleXMLTests.java:134:22:134:42 | getInputStream(...) | SimpleXMLTests.java:134:22:134:42 | getInputStream(...) | Unsafe parsing of XML file from $@. | SimpleXMLTests.java:134:22:134:42 | getInputStream(...) | user input | | SimpleXMLTests.java:134:22:134:42 | getInputStream(...) | SimpleXMLTests.java:134:22:134:42 | getInputStream(...) | SimpleXMLTests.java:134:22:134:42 | getInputStream(...) | A $@ is parsed as XML without guarding against external entity expansion. | SimpleXMLTests.java:134:22:134:42 | getInputStream(...) | user-provided value |
| SimpleXMLTests.java:139:22:139:65 | new InputStreamReader(...) | SimpleXMLTests.java:139:44:139:64 | getInputStream(...) : InputStream | SimpleXMLTests.java:139:22:139:65 | new InputStreamReader(...) | Unsafe parsing of XML file from $@. | SimpleXMLTests.java:139:44:139:64 | getInputStream(...) | user input | | SimpleXMLTests.java:139:22:139:65 | new InputStreamReader(...) | SimpleXMLTests.java:139:44:139:64 | getInputStream(...) : InputStream | SimpleXMLTests.java:139:22:139:65 | new InputStreamReader(...) | A $@ is parsed as XML without guarding against external entity expansion. | SimpleXMLTests.java:139:44:139:64 | getInputStream(...) | user-provided value |
| SimpleXMLTests.java:146:22:146:34 | new String(...) | SimpleXMLTests.java:145:5:145:25 | getInputStream(...) : InputStream | SimpleXMLTests.java:146:22:146:34 | new String(...) | Unsafe parsing of XML file from $@. | SimpleXMLTests.java:145:5:145:25 | getInputStream(...) | user input | | SimpleXMLTests.java:146:22:146:34 | new String(...) | SimpleXMLTests.java:145:5:145:25 | getInputStream(...) : InputStream | SimpleXMLTests.java:146:22:146:34 | new String(...) | A $@ is parsed as XML without guarding against external entity expansion. | SimpleXMLTests.java:145:5:145:25 | getInputStream(...) | user-provided value |
| SimpleXMLTests.java:153:22:153:34 | new String(...) | SimpleXMLTests.java:152:5:152:25 | getInputStream(...) : InputStream | SimpleXMLTests.java:153:22:153:34 | new String(...) | Unsafe parsing of XML file from $@. | SimpleXMLTests.java:152:5:152:25 | getInputStream(...) | user input | | SimpleXMLTests.java:153:22:153:34 | new String(...) | SimpleXMLTests.java:152:5:152:25 | getInputStream(...) : InputStream | SimpleXMLTests.java:153:22:153:34 | new String(...) | A $@ is parsed as XML without guarding against external entity expansion. | SimpleXMLTests.java:152:5:152:25 | getInputStream(...) | user-provided value |
| TransformerTests.java:20:27:20:65 | new StreamSource(...) | TransformerTests.java:20:44:20:64 | getInputStream(...) : InputStream | TransformerTests.java:20:27:20:65 | new StreamSource(...) | Unsafe parsing of XML file from $@. | TransformerTests.java:20:44:20:64 | getInputStream(...) | user input | | TransformerTests.java:20:27:20:65 | new StreamSource(...) | TransformerTests.java:20:44:20:64 | getInputStream(...) : InputStream | TransformerTests.java:20:27:20:65 | new StreamSource(...) | A $@ is parsed as XML without guarding against external entity expansion. | TransformerTests.java:20:44:20:64 | getInputStream(...) | user-provided value |
| TransformerTests.java:21:23:21:61 | new StreamSource(...) | TransformerTests.java:21:40:21:60 | getInputStream(...) : InputStream | TransformerTests.java:21:23:21:61 | new StreamSource(...) | Unsafe parsing of XML file from $@. | TransformerTests.java:21:40:21:60 | getInputStream(...) | user input | | TransformerTests.java:21:23:21:61 | new StreamSource(...) | TransformerTests.java:21:40:21:60 | getInputStream(...) : InputStream | TransformerTests.java:21:23:21:61 | new StreamSource(...) | A $@ is parsed as XML without guarding against external entity expansion. | TransformerTests.java:21:40:21:60 | getInputStream(...) | user-provided value |
| TransformerTests.java:71:27:71:65 | new StreamSource(...) | TransformerTests.java:71:44:71:64 | getInputStream(...) : InputStream | TransformerTests.java:71:27:71:65 | new StreamSource(...) | Unsafe parsing of XML file from $@. | TransformerTests.java:71:44:71:64 | getInputStream(...) | user input | | TransformerTests.java:71:27:71:65 | new StreamSource(...) | TransformerTests.java:71:44:71:64 | getInputStream(...) : InputStream | TransformerTests.java:71:27:71:65 | new StreamSource(...) | A $@ is parsed as XML without guarding against external entity expansion. | TransformerTests.java:71:44:71:64 | getInputStream(...) | user-provided value |
| TransformerTests.java:72:23:72:61 | new StreamSource(...) | TransformerTests.java:72:40:72:60 | getInputStream(...) : InputStream | TransformerTests.java:72:23:72:61 | new StreamSource(...) | Unsafe parsing of XML file from $@. | TransformerTests.java:72:40:72:60 | getInputStream(...) | user input | | TransformerTests.java:72:23:72:61 | new StreamSource(...) | TransformerTests.java:72:40:72:60 | getInputStream(...) : InputStream | TransformerTests.java:72:23:72:61 | new StreamSource(...) | A $@ is parsed as XML without guarding against external entity expansion. | TransformerTests.java:72:40:72:60 | getInputStream(...) | user-provided value |
| TransformerTests.java:79:27:79:65 | new StreamSource(...) | TransformerTests.java:79:44:79:64 | getInputStream(...) : InputStream | TransformerTests.java:79:27:79:65 | new StreamSource(...) | Unsafe parsing of XML file from $@. | TransformerTests.java:79:44:79:64 | getInputStream(...) | user input | | TransformerTests.java:79:27:79:65 | new StreamSource(...) | TransformerTests.java:79:44:79:64 | getInputStream(...) : InputStream | TransformerTests.java:79:27:79:65 | new StreamSource(...) | A $@ is parsed as XML without guarding against external entity expansion. | TransformerTests.java:79:44:79:64 | getInputStream(...) | user-provided value |
| TransformerTests.java:80:23:80:61 | new StreamSource(...) | TransformerTests.java:80:40:80:60 | getInputStream(...) : InputStream | TransformerTests.java:80:23:80:61 | new StreamSource(...) | Unsafe parsing of XML file from $@. | TransformerTests.java:80:40:80:60 | getInputStream(...) | user input | | TransformerTests.java:80:23:80:61 | new StreamSource(...) | TransformerTests.java:80:40:80:60 | getInputStream(...) : InputStream | TransformerTests.java:80:23:80:61 | new StreamSource(...) | A $@ is parsed as XML without guarding against external entity expansion. | TransformerTests.java:80:40:80:60 | getInputStream(...) | user-provided value |
| TransformerTests.java:88:27:88:65 | new StreamSource(...) | TransformerTests.java:88:44:88:64 | getInputStream(...) : InputStream | TransformerTests.java:88:27:88:65 | new StreamSource(...) | Unsafe parsing of XML file from $@. | TransformerTests.java:88:44:88:64 | getInputStream(...) | user input | | TransformerTests.java:88:27:88:65 | new StreamSource(...) | TransformerTests.java:88:44:88:64 | getInputStream(...) : InputStream | TransformerTests.java:88:27:88:65 | new StreamSource(...) | A $@ is parsed as XML without guarding against external entity expansion. | TransformerTests.java:88:44:88:64 | getInputStream(...) | user-provided value |
| TransformerTests.java:89:23:89:61 | new StreamSource(...) | TransformerTests.java:89:40:89:60 | getInputStream(...) : InputStream | TransformerTests.java:89:23:89:61 | new StreamSource(...) | Unsafe parsing of XML file from $@. | TransformerTests.java:89:40:89:60 | getInputStream(...) | user input | | TransformerTests.java:89:23:89:61 | new StreamSource(...) | TransformerTests.java:89:40:89:60 | getInputStream(...) : InputStream | TransformerTests.java:89:23:89:61 | new StreamSource(...) | A $@ is parsed as XML without guarding against external entity expansion. | TransformerTests.java:89:40:89:60 | getInputStream(...) | user-provided value |
| TransformerTests.java:97:27:97:65 | new StreamSource(...) | TransformerTests.java:97:44:97:64 | getInputStream(...) : InputStream | TransformerTests.java:97:27:97:65 | new StreamSource(...) | Unsafe parsing of XML file from $@. | TransformerTests.java:97:44:97:64 | getInputStream(...) | user input | | TransformerTests.java:97:27:97:65 | new StreamSource(...) | TransformerTests.java:97:44:97:64 | getInputStream(...) : InputStream | TransformerTests.java:97:27:97:65 | new StreamSource(...) | A $@ is parsed as XML without guarding against external entity expansion. | TransformerTests.java:97:44:97:64 | getInputStream(...) | user-provided value |
| TransformerTests.java:98:23:98:61 | new StreamSource(...) | TransformerTests.java:98:40:98:60 | getInputStream(...) : InputStream | TransformerTests.java:98:23:98:61 | new StreamSource(...) | Unsafe parsing of XML file from $@. | TransformerTests.java:98:40:98:60 | getInputStream(...) | user input | | TransformerTests.java:98:23:98:61 | new StreamSource(...) | TransformerTests.java:98:40:98:60 | getInputStream(...) : InputStream | TransformerTests.java:98:23:98:61 | new StreamSource(...) | A $@ is parsed as XML without guarding against external entity expansion. | TransformerTests.java:98:40:98:60 | getInputStream(...) | user-provided value |
| TransformerTests.java:103:21:103:59 | new StreamSource(...) | TransformerTests.java:103:38:103:58 | getInputStream(...) : InputStream | TransformerTests.java:103:21:103:59 | new StreamSource(...) | Unsafe parsing of XML file from $@. | TransformerTests.java:103:38:103:58 | getInputStream(...) | user input | | TransformerTests.java:103:21:103:59 | new StreamSource(...) | TransformerTests.java:103:38:103:58 | getInputStream(...) : InputStream | TransformerTests.java:103:21:103:59 | new StreamSource(...) | A $@ is parsed as XML without guarding against external entity expansion. | TransformerTests.java:103:38:103:58 | getInputStream(...) | user-provided value |
| TransformerTests.java:116:21:116:59 | new StreamSource(...) | TransformerTests.java:116:38:116:58 | getInputStream(...) : InputStream | TransformerTests.java:116:21:116:59 | new StreamSource(...) | Unsafe parsing of XML file from $@. | TransformerTests.java:116:38:116:58 | getInputStream(...) | user input | | TransformerTests.java:116:21:116:59 | new StreamSource(...) | TransformerTests.java:116:38:116:58 | getInputStream(...) : InputStream | TransformerTests.java:116:21:116:59 | new StreamSource(...) | A $@ is parsed as XML without guarding against external entity expansion. | TransformerTests.java:116:38:116:58 | getInputStream(...) | user-provided value |
| TransformerTests.java:122:21:122:59 | new StreamSource(...) | TransformerTests.java:122:38:122:58 | getInputStream(...) : InputStream | TransformerTests.java:122:21:122:59 | new StreamSource(...) | Unsafe parsing of XML file from $@. | TransformerTests.java:122:38:122:58 | getInputStream(...) | user input | | TransformerTests.java:122:21:122:59 | new StreamSource(...) | TransformerTests.java:122:38:122:58 | getInputStream(...) : InputStream | TransformerTests.java:122:21:122:59 | new StreamSource(...) | A $@ is parsed as XML without guarding against external entity expansion. | TransformerTests.java:122:38:122:58 | getInputStream(...) | user-provided value |
| TransformerTests.java:129:21:129:59 | new StreamSource(...) | TransformerTests.java:129:38:129:58 | getInputStream(...) : InputStream | TransformerTests.java:129:21:129:59 | new StreamSource(...) | Unsafe parsing of XML file from $@. | TransformerTests.java:129:38:129:58 | getInputStream(...) | user input | | TransformerTests.java:129:21:129:59 | new StreamSource(...) | TransformerTests.java:129:38:129:58 | getInputStream(...) : InputStream | TransformerTests.java:129:21:129:59 | new StreamSource(...) | A $@ is parsed as XML without guarding against external entity expansion. | TransformerTests.java:129:38:129:58 | getInputStream(...) | user-provided value |
| TransformerTests.java:136:21:136:59 | new StreamSource(...) | TransformerTests.java:136:38:136:58 | getInputStream(...) : InputStream | TransformerTests.java:136:21:136:59 | new StreamSource(...) | Unsafe parsing of XML file from $@. | TransformerTests.java:136:38:136:58 | getInputStream(...) | user input | | TransformerTests.java:136:21:136:59 | new StreamSource(...) | TransformerTests.java:136:38:136:58 | getInputStream(...) : InputStream | TransformerTests.java:136:21:136:59 | new StreamSource(...) | A $@ is parsed as XML without guarding against external entity expansion. | TransformerTests.java:136:38:136:58 | getInputStream(...) | user-provided value |
| TransformerTests.java:141:18:141:70 | new SAXSource(...) | TransformerTests.java:141:48:141:68 | getInputStream(...) : InputStream | TransformerTests.java:141:18:141:70 | new SAXSource(...) | Unsafe parsing of XML file from $@. | TransformerTests.java:141:48:141:68 | getInputStream(...) | user input | | TransformerTests.java:141:18:141:70 | new SAXSource(...) | TransformerTests.java:141:48:141:68 | getInputStream(...) : InputStream | TransformerTests.java:141:18:141:70 | new SAXSource(...) | A $@ is parsed as XML without guarding against external entity expansion. | TransformerTests.java:141:48:141:68 | getInputStream(...) | user-provided value |
| UnmarshallerTests.java:28:18:28:38 | getInputStream(...) | UnmarshallerTests.java:28:18:28:38 | getInputStream(...) | UnmarshallerTests.java:28:18:28:38 | getInputStream(...) | Unsafe parsing of XML file from $@. | UnmarshallerTests.java:28:18:28:38 | getInputStream(...) | user input | | UnmarshallerTests.java:28:18:28:38 | getInputStream(...) | UnmarshallerTests.java:28:18:28:38 | getInputStream(...) | UnmarshallerTests.java:28:18:28:38 | getInputStream(...) | A $@ is parsed as XML without guarding against external entity expansion. | UnmarshallerTests.java:28:18:28:38 | getInputStream(...) | user-provided value |
| XMLReaderTests.java:16:18:16:55 | new InputSource(...) | XMLReaderTests.java:16:34:16:54 | getInputStream(...) : InputStream | XMLReaderTests.java:16:18:16:55 | new InputSource(...) | Unsafe parsing of XML file from $@. | XMLReaderTests.java:16:34:16:54 | getInputStream(...) | user input | | XMLReaderTests.java:16:18:16:55 | new InputSource(...) | XMLReaderTests.java:16:34:16:54 | getInputStream(...) : InputStream | XMLReaderTests.java:16:18:16:55 | new InputSource(...) | A $@ is parsed as XML without guarding against external entity expansion. | XMLReaderTests.java:16:34:16:54 | getInputStream(...) | user-provided value |
| XMLReaderTests.java:56:18:56:55 | new InputSource(...) | XMLReaderTests.java:56:34:56:54 | getInputStream(...) : InputStream | XMLReaderTests.java:56:18:56:55 | new InputSource(...) | Unsafe parsing of XML file from $@. | XMLReaderTests.java:56:34:56:54 | getInputStream(...) | user input | | XMLReaderTests.java:56:18:56:55 | new InputSource(...) | XMLReaderTests.java:56:34:56:54 | getInputStream(...) : InputStream | XMLReaderTests.java:56:18:56:55 | new InputSource(...) | A $@ is parsed as XML without guarding against external entity expansion. | XMLReaderTests.java:56:34:56:54 | getInputStream(...) | user-provided value |
| XMLReaderTests.java:63:18:63:55 | new InputSource(...) | XMLReaderTests.java:63:34:63:54 | getInputStream(...) : InputStream | XMLReaderTests.java:63:18:63:55 | new InputSource(...) | Unsafe parsing of XML file from $@. | XMLReaderTests.java:63:34:63:54 | getInputStream(...) | user input | | XMLReaderTests.java:63:18:63:55 | new InputSource(...) | XMLReaderTests.java:63:34:63:54 | getInputStream(...) : InputStream | XMLReaderTests.java:63:18:63:55 | new InputSource(...) | A $@ is parsed as XML without guarding against external entity expansion. | XMLReaderTests.java:63:34:63:54 | getInputStream(...) | user-provided value |
| XMLReaderTests.java:70:18:70:55 | new InputSource(...) | XMLReaderTests.java:70:34:70:54 | getInputStream(...) : InputStream | XMLReaderTests.java:70:18:70:55 | new InputSource(...) | Unsafe parsing of XML file from $@. | XMLReaderTests.java:70:34:70:54 | getInputStream(...) | user input | | XMLReaderTests.java:70:18:70:55 | new InputSource(...) | XMLReaderTests.java:70:34:70:54 | getInputStream(...) : InputStream | XMLReaderTests.java:70:18:70:55 | new InputSource(...) | A $@ is parsed as XML without guarding against external entity expansion. | XMLReaderTests.java:70:34:70:54 | getInputStream(...) | user-provided value |
| XMLReaderTests.java:78:18:78:55 | new InputSource(...) | XMLReaderTests.java:78:34:78:54 | getInputStream(...) : InputStream | XMLReaderTests.java:78:18:78:55 | new InputSource(...) | Unsafe parsing of XML file from $@. | XMLReaderTests.java:78:34:78:54 | getInputStream(...) | user input | | XMLReaderTests.java:78:18:78:55 | new InputSource(...) | XMLReaderTests.java:78:34:78:54 | getInputStream(...) : InputStream | XMLReaderTests.java:78:18:78:55 | new InputSource(...) | A $@ is parsed as XML without guarding against external entity expansion. | XMLReaderTests.java:78:34:78:54 | getInputStream(...) | user-provided value |
| XMLReaderTests.java:86:18:86:55 | new InputSource(...) | XMLReaderTests.java:86:34:86:54 | getInputStream(...) : InputStream | XMLReaderTests.java:86:18:86:55 | new InputSource(...) | Unsafe parsing of XML file from $@. | XMLReaderTests.java:86:34:86:54 | getInputStream(...) | user input | | XMLReaderTests.java:86:18:86:55 | new InputSource(...) | XMLReaderTests.java:86:34:86:54 | getInputStream(...) : InputStream | XMLReaderTests.java:86:18:86:55 | new InputSource(...) | A $@ is parsed as XML without guarding against external entity expansion. | XMLReaderTests.java:86:34:86:54 | getInputStream(...) | user-provided value |
| XMLReaderTests.java:94:18:94:55 | new InputSource(...) | XMLReaderTests.java:94:34:94:54 | getInputStream(...) : InputStream | XMLReaderTests.java:94:18:94:55 | new InputSource(...) | Unsafe parsing of XML file from $@. | XMLReaderTests.java:94:34:94:54 | getInputStream(...) | user input | | XMLReaderTests.java:94:18:94:55 | new InputSource(...) | XMLReaderTests.java:94:34:94:54 | getInputStream(...) : InputStream | XMLReaderTests.java:94:18:94:55 | new InputSource(...) | A $@ is parsed as XML without guarding against external entity expansion. | XMLReaderTests.java:94:34:94:54 | getInputStream(...) | user-provided value |
| XMLReaderTests.java:100:18:100:55 | new InputSource(...) | XMLReaderTests.java:100:34:100:54 | getInputStream(...) : InputStream | XMLReaderTests.java:100:18:100:55 | new InputSource(...) | Unsafe parsing of XML file from $@. | XMLReaderTests.java:100:34:100:54 | getInputStream(...) | user input | | XMLReaderTests.java:100:18:100:55 | new InputSource(...) | XMLReaderTests.java:100:34:100:54 | getInputStream(...) : InputStream | XMLReaderTests.java:100:18:100:55 | new InputSource(...) | A $@ is parsed as XML without guarding against external entity expansion. | XMLReaderTests.java:100:34:100:54 | getInputStream(...) | user-provided value |
| XPathExpressionTests.java:27:21:27:58 | new InputSource(...) | XPathExpressionTests.java:27:37:27:57 | getInputStream(...) : InputStream | XPathExpressionTests.java:27:21:27:58 | new InputSource(...) | Unsafe parsing of XML file from $@. | XPathExpressionTests.java:27:37:27:57 | getInputStream(...) | user input | | XPathExpressionTests.java:27:21:27:58 | new InputSource(...) | XPathExpressionTests.java:27:37:27:57 | getInputStream(...) : InputStream | XPathExpressionTests.java:27:21:27:58 | new InputSource(...) | A $@ is parsed as XML without guarding against external entity expansion. | XPathExpressionTests.java:27:37:27:57 | getInputStream(...) | user-provided value |
| XmlInputFactoryTests.java:9:35:9:55 | getInputStream(...) | XmlInputFactoryTests.java:9:35:9:55 | getInputStream(...) | XmlInputFactoryTests.java:9:35:9:55 | getInputStream(...) | Unsafe parsing of XML file from $@. | XmlInputFactoryTests.java:9:35:9:55 | getInputStream(...) | user input | | XmlInputFactoryTests.java:9:35:9:55 | getInputStream(...) | XmlInputFactoryTests.java:9:35:9:55 | getInputStream(...) | XmlInputFactoryTests.java:9:35:9:55 | getInputStream(...) | A $@ is parsed as XML without guarding against external entity expansion. | XmlInputFactoryTests.java:9:35:9:55 | getInputStream(...) | user-provided value |
| XmlInputFactoryTests.java:10:34:10:54 | getInputStream(...) | XmlInputFactoryTests.java:10:34:10:54 | getInputStream(...) | XmlInputFactoryTests.java:10:34:10:54 | getInputStream(...) | Unsafe parsing of XML file from $@. | XmlInputFactoryTests.java:10:34:10:54 | getInputStream(...) | user input | | XmlInputFactoryTests.java:10:34:10:54 | getInputStream(...) | XmlInputFactoryTests.java:10:34:10:54 | getInputStream(...) | XmlInputFactoryTests.java:10:34:10:54 | getInputStream(...) | A $@ is parsed as XML without guarding against external entity expansion. | XmlInputFactoryTests.java:10:34:10:54 | getInputStream(...) | user-provided value |
| XmlInputFactoryTests.java:24:35:24:55 | getInputStream(...) | XmlInputFactoryTests.java:24:35:24:55 | getInputStream(...) | XmlInputFactoryTests.java:24:35:24:55 | getInputStream(...) | Unsafe parsing of XML file from $@. | XmlInputFactoryTests.java:24:35:24:55 | getInputStream(...) | user input | | XmlInputFactoryTests.java:24:35:24:55 | getInputStream(...) | XmlInputFactoryTests.java:24:35:24:55 | getInputStream(...) | XmlInputFactoryTests.java:24:35:24:55 | getInputStream(...) | A $@ is parsed as XML without guarding against external entity expansion. | XmlInputFactoryTests.java:24:35:24:55 | getInputStream(...) | user-provided value |
| XmlInputFactoryTests.java:25:34:25:54 | getInputStream(...) | XmlInputFactoryTests.java:25:34:25:54 | getInputStream(...) | XmlInputFactoryTests.java:25:34:25:54 | getInputStream(...) | Unsafe parsing of XML file from $@. | XmlInputFactoryTests.java:25:34:25:54 | getInputStream(...) | user input | | XmlInputFactoryTests.java:25:34:25:54 | getInputStream(...) | XmlInputFactoryTests.java:25:34:25:54 | getInputStream(...) | XmlInputFactoryTests.java:25:34:25:54 | getInputStream(...) | A $@ is parsed as XML without guarding against external entity expansion. | XmlInputFactoryTests.java:25:34:25:54 | getInputStream(...) | user-provided value |
| XmlInputFactoryTests.java:31:35:31:55 | getInputStream(...) | XmlInputFactoryTests.java:31:35:31:55 | getInputStream(...) | XmlInputFactoryTests.java:31:35:31:55 | getInputStream(...) | Unsafe parsing of XML file from $@. | XmlInputFactoryTests.java:31:35:31:55 | getInputStream(...) | user input | | XmlInputFactoryTests.java:31:35:31:55 | getInputStream(...) | XmlInputFactoryTests.java:31:35:31:55 | getInputStream(...) | XmlInputFactoryTests.java:31:35:31:55 | getInputStream(...) | A $@ is parsed as XML without guarding against external entity expansion. | XmlInputFactoryTests.java:31:35:31:55 | getInputStream(...) | user-provided value |
| XmlInputFactoryTests.java:32:34:32:54 | getInputStream(...) | XmlInputFactoryTests.java:32:34:32:54 | getInputStream(...) | XmlInputFactoryTests.java:32:34:32:54 | getInputStream(...) | Unsafe parsing of XML file from $@. | XmlInputFactoryTests.java:32:34:32:54 | getInputStream(...) | user input | | XmlInputFactoryTests.java:32:34:32:54 | getInputStream(...) | XmlInputFactoryTests.java:32:34:32:54 | getInputStream(...) | XmlInputFactoryTests.java:32:34:32:54 | getInputStream(...) | A $@ is parsed as XML without guarding against external entity expansion. | XmlInputFactoryTests.java:32:34:32:54 | getInputStream(...) | user-provided value |
| XmlInputFactoryTests.java:39:35:39:55 | getInputStream(...) | XmlInputFactoryTests.java:39:35:39:55 | getInputStream(...) | XmlInputFactoryTests.java:39:35:39:55 | getInputStream(...) | Unsafe parsing of XML file from $@. | XmlInputFactoryTests.java:39:35:39:55 | getInputStream(...) | user input | | XmlInputFactoryTests.java:39:35:39:55 | getInputStream(...) | XmlInputFactoryTests.java:39:35:39:55 | getInputStream(...) | XmlInputFactoryTests.java:39:35:39:55 | getInputStream(...) | A $@ is parsed as XML without guarding against external entity expansion. | XmlInputFactoryTests.java:39:35:39:55 | getInputStream(...) | user-provided value |
| XmlInputFactoryTests.java:40:34:40:54 | getInputStream(...) | XmlInputFactoryTests.java:40:34:40:54 | getInputStream(...) | XmlInputFactoryTests.java:40:34:40:54 | getInputStream(...) | Unsafe parsing of XML file from $@. | XmlInputFactoryTests.java:40:34:40:54 | getInputStream(...) | user input | | XmlInputFactoryTests.java:40:34:40:54 | getInputStream(...) | XmlInputFactoryTests.java:40:34:40:54 | getInputStream(...) | XmlInputFactoryTests.java:40:34:40:54 | getInputStream(...) | A $@ is parsed as XML without guarding against external entity expansion. | XmlInputFactoryTests.java:40:34:40:54 | getInputStream(...) | user-provided value |
| XmlInputFactoryTests.java:47:35:47:55 | getInputStream(...) | XmlInputFactoryTests.java:47:35:47:55 | getInputStream(...) | XmlInputFactoryTests.java:47:35:47:55 | getInputStream(...) | Unsafe parsing of XML file from $@. | XmlInputFactoryTests.java:47:35:47:55 | getInputStream(...) | user input | | XmlInputFactoryTests.java:47:35:47:55 | getInputStream(...) | XmlInputFactoryTests.java:47:35:47:55 | getInputStream(...) | XmlInputFactoryTests.java:47:35:47:55 | getInputStream(...) | A $@ is parsed as XML without guarding against external entity expansion. | XmlInputFactoryTests.java:47:35:47:55 | getInputStream(...) | user-provided value |
| XmlInputFactoryTests.java:48:34:48:54 | getInputStream(...) | XmlInputFactoryTests.java:48:34:48:54 | getInputStream(...) | XmlInputFactoryTests.java:48:34:48:54 | getInputStream(...) | Unsafe parsing of XML file from $@. | XmlInputFactoryTests.java:48:34:48:54 | getInputStream(...) | user input | | XmlInputFactoryTests.java:48:34:48:54 | getInputStream(...) | XmlInputFactoryTests.java:48:34:48:54 | getInputStream(...) | XmlInputFactoryTests.java:48:34:48:54 | getInputStream(...) | A $@ is parsed as XML without guarding against external entity expansion. | XmlInputFactoryTests.java:48:34:48:54 | getInputStream(...) | user-provided value |
| XmlInputFactoryTests.java:55:35:55:55 | getInputStream(...) | XmlInputFactoryTests.java:55:35:55:55 | getInputStream(...) | XmlInputFactoryTests.java:55:35:55:55 | getInputStream(...) | Unsafe parsing of XML file from $@. | XmlInputFactoryTests.java:55:35:55:55 | getInputStream(...) | user input | | XmlInputFactoryTests.java:55:35:55:55 | getInputStream(...) | XmlInputFactoryTests.java:55:35:55:55 | getInputStream(...) | XmlInputFactoryTests.java:55:35:55:55 | getInputStream(...) | A $@ is parsed as XML without guarding against external entity expansion. | XmlInputFactoryTests.java:55:35:55:55 | getInputStream(...) | user-provided value |
| XmlInputFactoryTests.java:56:34:56:54 | getInputStream(...) | XmlInputFactoryTests.java:56:34:56:54 | getInputStream(...) | XmlInputFactoryTests.java:56:34:56:54 | getInputStream(...) | Unsafe parsing of XML file from $@. | XmlInputFactoryTests.java:56:34:56:54 | getInputStream(...) | user input | | XmlInputFactoryTests.java:56:34:56:54 | getInputStream(...) | XmlInputFactoryTests.java:56:34:56:54 | getInputStream(...) | XmlInputFactoryTests.java:56:34:56:54 | getInputStream(...) | A $@ is parsed as XML without guarding against external entity expansion. | XmlInputFactoryTests.java:56:34:56:54 | getInputStream(...) | user-provided value |

View File

@@ -93,8 +93,6 @@ class RegExpRoot extends RegExpTerm {
* Holds if this root term is relevant to the ReDoS analysis. * Holds if this root term is relevant to the ReDoS analysis.
*/ */
predicate isRelevant() { predicate isRelevant() {
// there is at least one repetition
getRoot(any(InfiniteRepetitionQuantifier q)) = this and
// is actually used as a RegExp // is actually used as a RegExp
this.isUsedAsRegExp() and this.isUsedAsRegExp() and
// not excluded for library specific reasons // not excluded for library specific reasons
@@ -878,42 +876,14 @@ predicate isStartState(State state) {
signature predicate isCandidateSig(State state, string pump); signature predicate isCandidateSig(State state, string pump);
/** /**
* A module for pruning candidate ReDoS states. * Holds if `state` is a candidate for ReDoS.
* The candidates are specified by the `isCandidate` signature predicate.
* The candidates are checked for rejecting suffixes and deduplicated,
* and the resulting ReDoS states are read by the `hasReDoSResult` predicate.
*/ */
module ReDoSPruning<isCandidateSig/2 isCandidate> { signature predicate isCandidateSig(State state);
/**
* Holds if repeating `pump` starting at `state` is a candidate for causing backtracking.
* No check whether a rejected suffix exists has been made.
*/
private predicate isReDoSCandidate(State state, string pump) {
isCandidate(state, pump) and
not state = acceptsAnySuffix() and // pruning early - these can never get stuck in a rejecting state.
(
not isCandidate(epsilonSucc+(state), _)
or
epsilonSucc+(state) = state and
state =
max(State s, Location l |
s = epsilonSucc+(state) and
l = s.getRepr().getLocation() and
isCandidate(s, _) and
s.getRepr() instanceof InfiniteRepetitionQuantifier
|
s order by l.getStartLine(), l.getStartColumn(), l.getEndColumn(), l.getEndLine()
)
)
}
/** Gets a state that can reach the `accept-any` state using only epsilon steps. */ /**
private State acceptsAnySuffix() { epsilonSucc*(result) = AcceptAnySuffix(_) }
/**
* Predicates for constructing a prefix string that leads to a given state. * Predicates for constructing a prefix string that leads to a given state.
*/ */
private module PrefixConstruction { module PrefixConstruction<isCandidateSig/1 isCandidate> {
/** /**
* Holds if `state` is the textually last start state for the regular expression. * Holds if `state` is the textually last start state for the regular expression.
*/ */
@@ -921,7 +891,7 @@ module ReDoSPruning<isCandidateSig/2 isCandidate> {
exists(RegExpRoot root | exists(RegExpRoot root |
state = state =
max(State s, Location l | max(State s, Location l |
s = stateInPumpableRegexp() and s = stateInRelevantRegexp() and
isStartState(s) and isStartState(s) and
getRoot(s.getRepr()) = root and getRoot(s.getRepr()) = root and
l = s.getRepr().getLocation() l = s.getRepr().getLocation()
@@ -962,7 +932,7 @@ module ReDoSPruning<isCandidateSig/2 isCandidate> {
result = "" result = ""
or or
// the search stops past the last redos candidate state. // the search stops past the last redos candidate state.
lengthFromStart(state) <= max(lengthFromStart(any(State s | isReDoSCandidate(s, _)))) and lengthFromStart(state) <= max(lengthFromStart(any(State s | isCandidate(s)))) and
exists(State prev | exists(State prev |
// select a unique predecessor (by an arbitrary measure) // select a unique predecessor (by an arbitrary measure)
prev = prev =
@@ -993,13 +963,50 @@ module ReDoSPruning<isCandidateSig/2 isCandidate> {
min(string c | delta(prev, any(InputSymbol symbol | c = intersect(Any(), symbol)), next)) min(string c | delta(prev, any(InputSymbol symbol | c = intersect(Any(), symbol)), next))
} }
/** Gets a state within a regular expression that has a pumpable state. */ /** Gets a state within a regular expression that contains a candidate state. */
pragma[noinline] pragma[noinline]
State stateInPumpableRegexp() { State stateInRelevantRegexp() {
exists(State s | isReDoSCandidate(s, _) | getRoot(s.getRepr()) = getRoot(result.getRepr())) exists(State s | isCandidate(s) | getRoot(s.getRepr()) = getRoot(result.getRepr()))
} }
}
/**
* A module for pruning candidate ReDoS states.
* The candidates are specified by the `isCandidate` signature predicate.
* The candidates are checked for rejecting suffixes and deduplicated,
* and the resulting ReDoS states are read by the `hasReDoSResult` predicate.
*/
module ReDoSPruning<isCandidateSig/2 isCandidate> {
/**
* Holds if repeating `pump` starting at `state` is a candidate for causing backtracking.
* No check whether a rejected suffix exists has been made.
*/
private predicate isReDoSCandidate(State state, string pump) {
isCandidate(state, pump) and
not state = acceptsAnySuffix() and // pruning early - these can never get stuck in a rejecting state.
(
not isCandidate(epsilonSucc+(state), _)
or
epsilonSucc+(state) = state and
state =
max(State s, Location l |
s = epsilonSucc+(state) and
l = s.getRepr().getLocation() and
isCandidate(s, _) and
s.getRepr() instanceof InfiniteRepetitionQuantifier
|
s order by l.getStartLine(), l.getStartColumn(), l.getEndColumn(), l.getEndLine()
)
)
} }
/** Gets a state that can reach the `accept-any` state using only epsilon steps. */
private State acceptsAnySuffix() { epsilonSucc*(result) = AcceptAnySuffix(_) }
predicate isCandidateState(State s) { isReDoSCandidate(s, _) }
import PrefixConstruction<isCandidateState/1> as Prefix
/** /**
* Predicates for testing the presence of a rejecting suffix. * Predicates for testing the presence of a rejecting suffix.
* *
@@ -1018,8 +1025,6 @@ module ReDoSPruning<isCandidateSig/2 isCandidate> {
* using epsilon transitions. But any attempt at repeating `w` will end in a state that accepts all suffixes. * using epsilon transitions. But any attempt at repeating `w` will end in a state that accepts all suffixes.
*/ */
private module SuffixConstruction { private module SuffixConstruction {
import PrefixConstruction
/** /**
* Holds if all states reachable from `fork` by repeating `w` * Holds if all states reachable from `fork` by repeating `w`
* are likely rejectable by appending some suffix. * are likely rejectable by appending some suffix.
@@ -1036,7 +1041,7 @@ module ReDoSPruning<isCandidateSig/2 isCandidate> {
*/ */
pragma[noinline] pragma[noinline]
private predicate isLikelyRejectable(State s) { private predicate isLikelyRejectable(State s) {
s = stateInPumpableRegexp() and s = Prefix::stateInRelevantRegexp() and
( (
// exists a reject edge with some char. // exists a reject edge with some char.
hasRejectEdge(s) hasRejectEdge(s)
@@ -1052,7 +1057,7 @@ module ReDoSPruning<isCandidateSig/2 isCandidate> {
* Holds if `s` is not an accept state, and there is no epsilon transition to an accept state. * Holds if `s` is not an accept state, and there is no epsilon transition to an accept state.
*/ */
predicate isRejectState(State s) { predicate isRejectState(State s) {
s = stateInPumpableRegexp() and not epsilonSucc*(s) = Accept(_) s = Prefix::stateInRelevantRegexp() and not epsilonSucc*(s) = Accept(_)
} }
/** /**
@@ -1060,7 +1065,7 @@ module ReDoSPruning<isCandidateSig/2 isCandidate> {
*/ */
pragma[noopt] pragma[noopt]
predicate hasEdgeToLikelyRejectable(State s) { predicate hasEdgeToLikelyRejectable(State s) {
s = stateInPumpableRegexp() and s = Prefix::stateInRelevantRegexp() and
// all edges (at least one) with some char leads to another state that is rejectable. // all edges (at least one) with some char leads to another state that is rejectable.
// the `next` states might not share a common suffix, which can cause FPs. // the `next` states might not share a common suffix, which can cause FPs.
exists(string char | char = hasEdgeToLikelyRejectableHelper(s) | exists(string char | char = hasEdgeToLikelyRejectableHelper(s) |
@@ -1076,7 +1081,7 @@ module ReDoSPruning<isCandidateSig/2 isCandidate> {
*/ */
pragma[noinline] pragma[noinline]
private string hasEdgeToLikelyRejectableHelper(State s) { private string hasEdgeToLikelyRejectableHelper(State s) {
s = stateInPumpableRegexp() and s = Prefix::stateInRelevantRegexp() and
not hasRejectEdge(s) and not hasRejectEdge(s) and
not isRejectState(s) and not isRejectState(s) and
deltaClosedChar(s, result, _) deltaClosedChar(s, result, _)
@@ -1088,8 +1093,8 @@ module ReDoSPruning<isCandidateSig/2 isCandidate> {
* `prev` to `next` that the character symbol `char`. * `prev` to `next` that the character symbol `char`.
*/ */
predicate deltaClosedChar(State prev, string char, State next) { predicate deltaClosedChar(State prev, string char, State next) {
prev = stateInPumpableRegexp() and prev = Prefix::stateInRelevantRegexp() and
next = stateInPumpableRegexp() and next = Prefix::stateInRelevantRegexp() and
deltaClosed(prev, getAnInputSymbolMatchingRelevant(char), next) deltaClosed(prev, getAnInputSymbolMatchingRelevant(char), next)
} }
@@ -1099,11 +1104,20 @@ module ReDoSPruning<isCandidateSig/2 isCandidate> {
result = getAnInputSymbolMatching(char) result = getAnInputSymbolMatching(char)
} }
pragma[noinline]
RegExpRoot relevantRoot() {
exists(RegExpTerm term, State s |
s.getRepr() = term and isCandidateState(s) and result = term.getRootTerm()
)
}
/** /**
* Gets a char used for finding possible suffixes inside `root`. * Gets a char used for finding possible suffixes inside `root`.
*/ */
pragma[noinline] pragma[noinline]
private string relevant(RegExpRoot root) { private string relevant(RegExpRoot root) {
root = relevantRoot() and
(
exists(ascii(result)) and exists(root) exists(ascii(result)) and exists(root)
or or
exists(InputSymbol s | belongsTo(s, root) | result = intersect(s, _)) exists(InputSymbol s | belongsTo(s, root) | result = intersect(s, _))
@@ -1111,6 +1125,7 @@ module ReDoSPruning<isCandidateSig/2 isCandidate> {
// The characters from `hasSimpleRejectEdge`. Only `\n` is really needed (as `\n` is not in the `ascii` relation). // The characters from `hasSimpleRejectEdge`. Only `\n` is really needed (as `\n` is not in the `ascii` relation).
// The three chars must be kept in sync with `hasSimpleRejectEdge`. // The three chars must be kept in sync with `hasSimpleRejectEdge`.
result = ["|", "\n", "Z"] and exists(root) result = ["|", "\n", "Z"] and exists(root)
)
} }
/** /**
@@ -1208,12 +1223,12 @@ module ReDoSPruning<isCandidateSig/2 isCandidate> {
predicate hasReDoSResult(RegExpTerm t, string pump, State s, string prefixMsg) { predicate hasReDoSResult(RegExpTerm t, string pump, State s, string prefixMsg) {
isReDoSAttackable(t, pump, s) and isReDoSAttackable(t, pump, s) and
( (
prefixMsg = "starting with '" + escape(PrefixConstruction::prefix(s)) + "' and " and prefixMsg = "starting with '" + escape(Prefix::prefix(s)) + "' and " and
not PrefixConstruction::prefix(s) = "" not Prefix::prefix(s) = ""
or or
PrefixConstruction::prefix(s) = "" and prefixMsg = "" Prefix::prefix(s) = "" and prefixMsg = ""
or or
not exists(PrefixConstruction::prefix(s)) and prefixMsg = "" not exists(Prefix::prefix(s)) and prefixMsg = ""
) )
} }

View File

@@ -13,4 +13,4 @@ import UnusedParameter
from Parameter p from Parameter p
where isAnAccidentallyUnusedParameter(p) where isAnAccidentallyUnusedParameter(p)
select p, "Unused parameter " + p.getAVariable().getName() + "." select p, "The parameter '" + p.getVariable().getName() + "' is never used."

View File

@@ -53,4 +53,4 @@ where
not e instanceof EqualityTest and not e instanceof EqualityTest and
e.getRightOperand().getIntValue() = 0 and e.getRightOperand().getIntValue() = 0 and
not acceptableSignCheck(b) not acceptableSignCheck(b)
select e, "Sign check of a bitwise operation" select e, "Potentially unsafe sign check of a bitwise operation."

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