From d5c8ea38b121575a8c1bbfd4b18a8474c29649f5 Mon Sep 17 00:00:00 2001
From: Pavel Avgustinov
Date: Thu, 1 Nov 2018 14:01:55 +0000
Subject: [PATCH 01/71] SuspiciousCallToMemset: Simplify pointer indirection
computation
---
.../Memory Management/SuspiciousCallToMemset.ql | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/cpp/ql/src/Likely Bugs/Memory Management/SuspiciousCallToMemset.ql b/cpp/ql/src/Likely Bugs/Memory Management/SuspiciousCallToMemset.ql
index 6e9b11cf37f..bcbec1bd961 100644
--- a/cpp/ql/src/Likely Bugs/Memory Management/SuspiciousCallToMemset.ql
+++ b/cpp/ql/src/Likely Bugs/Memory Management/SuspiciousCallToMemset.ql
@@ -52,13 +52,13 @@ Type stripType(Type t) {
/**
* Holds if `t` points to `base` via a specified number of levels of pointer
- * indirection. Intermediate typedefs and array types are allowed.
+ * indirection. Intermediate typedefs and array types are allowed. Note that
+ * `base` is a stripped type (via `stripType`).
*/
predicate pointerIndirection(Type t, int indirection, Type base) {
- exists(Type u |
- u = stripType(t) and
- u = stripType(base) and
- not u instanceof PointerType and
+ (
+ base = stripType(t) and
+ not base instanceof PointerType and
indirection = 0
) or (
pointerIndirection(stripType(t).(PointerType).getBaseType(), indirection - 1, base)
From bfa4c307840d36a7d18aa58b9bca767b9a00abde Mon Sep 17 00:00:00 2001
From: Aditya Sharad
Date: Mon, 5 Nov 2018 16:43:35 +0000
Subject: [PATCH 02/71] C++: Improve performance of
`ExprEvaluator::getFunctionValue`.
Changes the `forex` range to join on both `this` (the current `ExprEvaluator`) and `ret` (the expected function return value),
so that we look at the relevant return values rather than all interesting functions.
---
.../code/cpp/controlflow/internal/ConstantExprs.qll | 11 ++++++++---
1 file changed, 8 insertions(+), 3 deletions(-)
diff --git a/cpp/ql/src/semmle/code/cpp/controlflow/internal/ConstantExprs.qll b/cpp/ql/src/semmle/code/cpp/controlflow/internal/ConstantExprs.qll
index c70e06b0e76..01ceef5fff1 100644
--- a/cpp/ql/src/semmle/code/cpp/controlflow/internal/ConstantExprs.qll
+++ b/cpp/ql/src/semmle/code/cpp/controlflow/internal/ConstantExprs.qll
@@ -419,12 +419,17 @@ library class ExprEvaluator extends int {
)
}
+ /** Holds if the function `f` is considered by the analysis and may return `ret`. */
+ pragma[noinline]
+ private predicate interestingReturnValue(Function f, Expr ret) {
+ interestingFunction(_, f) and
+ returnStmt(f, ret)
+ }
+
private int getFunctionValue(Function f) {
- interestingFunction(_, f)
- and
// All returns must have the same int value
// And it must have at least one return
- forex(Expr ret | returnStmt(f, ret) | result = getValueInternalNonSubExpr(ret))
+ forex(Expr ret | interestingReturnValue(f, ret) | result = getValueInternalNonSubExpr(ret))
}
/**
From a3c6b8e575ca8869214e403ef8ea48f6a38ff304 Mon Sep 17 00:00:00 2001
From: Robert Marsh
Date: Mon, 17 Sep 2018 14:52:55 -0700
Subject: [PATCH 03/71] C++: port sign analysis library from Java
---
.../code/cpp/rangeanalysis/SignAnalysis.qll | 361 ++++++++++++++++
.../signanalysis/inline_assembly.c | 24 ++
.../rangeanalysis/signanalysis/minmax.c | 27 ++
.../signanalysis/negative.expected | 55 +++
.../rangeanalysis/signanalysis/negative.ql | 6 +
.../signanalysis/positive.expected | 136 ++++++
.../rangeanalysis/signanalysis/positive.ql | 6 +
.../signanalysis/strictlyNegative.expected | 64 +++
.../signanalysis/strictlyNegative.ql | 6 +
.../signanalysis/strictlyPositive.expected | 136 ++++++
.../signanalysis/strictlyPositive.ql | 6 +
.../rangeanalysis/signanalysis/test.c | 400 ++++++++++++++++++
.../rangeanalysis/signanalysis/test.cpp | 70 +++
13 files changed, 1297 insertions(+)
create mode 100644 cpp/ql/src/semmle/code/cpp/rangeanalysis/SignAnalysis.qll
create mode 100644 cpp/ql/test/library-tests/rangeanalysis/signanalysis/inline_assembly.c
create mode 100644 cpp/ql/test/library-tests/rangeanalysis/signanalysis/minmax.c
create mode 100644 cpp/ql/test/library-tests/rangeanalysis/signanalysis/negative.expected
create mode 100644 cpp/ql/test/library-tests/rangeanalysis/signanalysis/negative.ql
create mode 100644 cpp/ql/test/library-tests/rangeanalysis/signanalysis/positive.expected
create mode 100644 cpp/ql/test/library-tests/rangeanalysis/signanalysis/positive.ql
create mode 100644 cpp/ql/test/library-tests/rangeanalysis/signanalysis/strictlyNegative.expected
create mode 100644 cpp/ql/test/library-tests/rangeanalysis/signanalysis/strictlyNegative.ql
create mode 100644 cpp/ql/test/library-tests/rangeanalysis/signanalysis/strictlyPositive.expected
create mode 100644 cpp/ql/test/library-tests/rangeanalysis/signanalysis/strictlyPositive.ql
create mode 100644 cpp/ql/test/library-tests/rangeanalysis/signanalysis/test.c
create mode 100644 cpp/ql/test/library-tests/rangeanalysis/signanalysis/test.cpp
diff --git a/cpp/ql/src/semmle/code/cpp/rangeanalysis/SignAnalysis.qll b/cpp/ql/src/semmle/code/cpp/rangeanalysis/SignAnalysis.qll
new file mode 100644
index 00000000000..bb26241a977
--- /dev/null
+++ b/cpp/ql/src/semmle/code/cpp/rangeanalysis/SignAnalysis.qll
@@ -0,0 +1,361 @@
+/**
+ * Provides sign analysis to determine whether expression are always positive
+ * or negative.
+ *
+ * The analysis is implemented as an abstract interpretation over the
+ * three-valued domain `{negative, zero, positive}`.
+ */
+import cpp
+private import semmle.code.cpp.ir.IR
+private import semmle.code.cpp.controlflow.IRGuards
+
+private newtype TSign = TNeg() or TZero() or TPos()
+private class Sign extends TSign {
+ string toString() {
+ result = "-" and this = TNeg() or
+ result = "0" and this = TZero() or
+ result = "+" and this = TPos()
+ }
+ Sign inc() {
+ this = TNeg() and result = TNeg() or
+ this = TNeg() and result = TZero() or
+ this = TZero() and result = TPos() or
+ this = TPos() and result = TPos()
+ }
+ Sign dec() {
+ result.inc() = this
+ }
+ Sign neg() {
+ this = TNeg() and result = TPos() or
+ this = TZero() and result = TZero() or
+ this = TPos() and result = TNeg()
+ }
+ Sign bitnot() {
+ this = TNeg() and result = TPos() or
+ this = TNeg() and result = TZero() or
+ this = TZero() and result = TNeg() or
+ this = TPos() and result = TNeg()
+ }
+ Sign add(Sign s) {
+ this = TZero() and result = s or
+ s = TZero() and result = this or
+ this = s and this = result or
+ this = TPos() and s = TNeg() or
+ this = TNeg() and s = TPos()
+ }
+ Sign mul(Sign s) {
+ result = TZero() and this = TZero() or
+ result = TZero() and s = TZero() or
+ result = TNeg() and this = TPos() and s = TNeg() or
+ result = TNeg() and this = TNeg() and s = TPos() or
+ result = TPos() and this = TPos() and s = TPos() or
+ result = TPos() and this = TNeg() and s = TNeg()
+ }
+ Sign div(Sign s) {
+ result = TZero() and s = TNeg() or
+ result = TZero() and s = TPos() or
+ result = TNeg() and this = TPos() and s = TNeg() or
+ result = TNeg() and this = TNeg() and s = TPos() or
+ result = TPos() and this = TPos() and s = TPos() or
+ result = TPos() and this = TNeg() and s = TNeg()
+ }
+ Sign rem(Sign s) {
+ result = TZero() and s = TNeg() or
+ result = TZero() and s = TPos() or
+ result = this and s = TNeg() or
+ result = this and s = TPos()
+ }
+ Sign bitand(Sign s) {
+ result = TZero() and this = TZero() or
+ result = TZero() and s = TZero() or
+ result = TZero() and this = TPos() or
+ result = TZero() and s = TPos() or
+ result = TNeg() and this = TNeg() and s = TNeg() or
+ result = TPos() and this = TNeg() and s = TPos() or
+ result = TPos() and this = TPos() and s = TNeg() or
+ result = TPos() and this = TPos() and s = TPos()
+ }
+ Sign bitor(Sign s) {
+ result = TZero() and this = TZero() and s = TZero() or
+ result = TNeg() and this = TNeg() or
+ result = TNeg() and s = TNeg() or
+ result = TPos() and this = TPos() and s = TZero() or
+ result = TPos() and this = TZero() and s = TPos() or
+ result = TPos() and this = TPos() and s = TPos()
+ }
+ Sign bitxor(Sign s) {
+ result = TZero() and this = s or
+ result = this and s = TZero() or
+ result = s and this = TZero() or
+ result = TPos() and this = TPos() and s = TPos() or
+ result = TNeg() and this = TNeg() and s = TPos() or
+ result = TNeg() and this = TPos() and s = TNeg() or
+ result = TPos() and this = TNeg() and s = TNeg()
+ }
+ Sign lshift(Sign s) {
+ result = TZero() and this = TZero() or
+ result = this and s = TZero() or
+ this != TZero() and s != TZero()
+ }
+ Sign rshift(Sign s) {
+ result = TZero() and this = TZero() or
+ result = this and s = TZero() or
+ result = TNeg() and this = TNeg() or
+ result != TNeg() and this = TPos() and s != TZero()
+ }
+ Sign urshift(Sign s) {
+ result = TZero() and this = TZero() or
+ result = this and s = TZero() or
+ result != TZero() and this = TNeg() and s != TZero() or
+ result != TNeg() and this = TPos() and s != TZero()
+ }
+}
+
+private Sign certainInstructionSign(Instruction inst) {
+ exists(int i | inst.(IntegerConstantInstruction).getValue().toInt() = i |
+ i < 0 and result = TNeg() or
+ i = 0 and result = TZero() or
+ i > 0 and result = TPos()
+ )
+ or
+ not inst instanceof IntegerConstantInstruction and
+ exists(float f | f = inst.(FloatConstantInstruction).getValue().toFloat() |
+ f < 0 and result = TNeg() or
+ f = 0 and result = TZero() or
+ f > 0 and result = TPos()
+ )
+}
+
+
+/** Holds if the sign of `e` is too complicated to determine. */
+private predicate unknownSign(Instruction i) {
+ (
+ i instanceof UnmodeledDefinitionInstruction or
+ i instanceof UninitializedInstruction or
+ i instanceof InitializeParameterInstruction or
+ i instanceof BuiltInInstruction or
+ i instanceof CallInstruction
+ )
+}
+
+/**
+ * Holds if `lowerbound` is a lower bound for `compared` at `pos`. This is restricted
+ * to only include bounds for which we might determine a sign.
+ */
+private predicate lowerBound(Instruction lowerbound, Instruction compared, Instruction pos, boolean isStrict) {
+ exists(int adjustment, IRGuardCondition comp |
+ pos.getAnOperand() = compared and
+ /*
+ * Java library uses guardControlsSsaRead here. I think that the phi node logic doesn't need to
+ * be duplicated but the implication predicates may need to be ported
+ */
+ (
+ isStrict = true and
+ adjustment = 0
+ or
+ isStrict = false and
+ adjustment = 1
+ ) and
+ comp.ensuresLt(lowerbound, compared, 0, pos.getBlock(), true)
+ )
+}
+
+
+/**
+ * Holds if `upperbound` is an upper bound for `compared` at `pos`. This is restricted
+ * to only include bounds for which we might determine a sign.
+ */
+private predicate upperBound(Instruction upperbound, Instruction compared, Instruction pos, boolean isStrict) {
+ exists(int adjustment, IRGuardCondition comp |
+ pos.getAnOperand() = compared and
+ /*
+ * Java library uses guardControlsSsaRead here. I think that the phi node logic doesn't need to
+ * be duplicated but the implication predicates may need to be ported
+ */
+ (
+ isStrict = true and
+ adjustment = 0
+ or
+ isStrict = false and
+ adjustment = 1
+ ) and
+ comp.ensuresLt(compared, upperbound, 0, pos.getBlock(), true)
+ )
+}
+
+/**
+ * Holds if `eqbound` is an equality/inequality for `v` at `pos`. This is
+ * restricted to only include bounds for which we might determine a sign. The
+ * boolean `isEq` gives the polarity:
+ * - `isEq = true` : `v = eqbound`
+ * - `isEq = false` : `v != eqbound`
+ */
+private predicate eqBound(Instruction eqbound, Instruction compared, Instruction pos, boolean isEq) {
+ exists(IRGuardCondition guard |
+ pos.getAnOperand() = compared and
+ guard.ensuresEq(compared, eqbound, 0, pos.getBlock(), isEq)
+ )
+}
+
+
+
+/**
+ * Holds if `bound` is a bound for `v` at `pos` that needs to be positive in
+ * order for `v` to be positive.
+ */
+private predicate posBound(Instruction bound, Instruction v, Instruction pos) {
+ upperBound(bound, v, pos, _) or
+ eqBound(bound, v, pos, true)
+}
+
+/**
+ * Holds if `bound` is a bound for `v` at `pos` that needs to be negative in
+ * order for `v` to be negative.
+ */
+private predicate negBound(Instruction bound, Instruction v, Instruction pos) {
+ lowerBound(bound, v, pos, _) or
+ eqBound(bound, v, pos, true)
+}
+
+/**
+ * Holds if `bound` is a bound for `v` at `pos` that can restrict whether `v`
+ * can be zero.
+ */
+private predicate zeroBound(Instruction bound, Instruction v, Instruction pos) {
+ lowerBound(bound, v, pos, _) or
+ upperBound(bound, v, pos, _) or
+ eqBound(bound, v, pos, _)
+}
+
+/** Holds if `bound` allows `v` to be positive at `pos`. */
+private predicate posBoundOk(Instruction bound, Instruction v, Instruction pos) {
+ posBound(bound, v, pos) and TPos() = instructionSign(bound)
+}
+
+/** Holds if `bound` allows `v` to be negative at `pos`. */
+private predicate negBoundOk(Instruction bound, Instruction v, Instruction pos) {
+ negBound(bound, v, pos) and TNeg() = instructionSign(bound)
+}
+
+/** Holds if `bound` allows `v` to be zero at `pos`. */
+private predicate zeroBoundOk(Instruction bound, Instruction v, Instruction pos) {
+ lowerBound(bound, v, pos, _) and TNeg() = instructionSign(bound) or
+ lowerBound(bound, v, pos, false) and TZero() = instructionSign(bound) or
+ upperBound(bound, v, pos, _) and TPos() = instructionSign(bound) or
+ upperBound(bound, v, pos, false) and TZero() = instructionSign(bound) or
+ eqBound(bound, v, pos, true) and TZero() = instructionSign(bound) or
+ eqBound(bound, v, pos, false) and TZero() != instructionSign(bound)
+}
+
+private Sign binaryOpLhsSign(Instruction i) {
+ result = operandSign(i, i.(BinaryInstruction).getLeftOperand())
+}
+
+private Sign binaryOpRhsSign(Instruction i) {
+ result = operandSign(i, i.(BinaryInstruction).getRightOperand())
+}
+pragma[noinline]
+private predicate binaryOpSigns(Instruction i, Sign lhs, Sign rhs) {
+ lhs = binaryOpLhsSign(i) and
+ rhs = binaryOpRhsSign(i)
+}
+
+/**
+ * Holds if there is a bound that might restrict whether `v` has the sign `s`
+ * at `pos`.
+ */
+private predicate hasGuard(Instruction v, Instruction pos, Sign s) {
+ s = TPos() and posBound(_, v, pos) or
+ s = TNeg() and negBound(_, v, pos) or
+ s = TZero() and zeroBound(_, v, pos)
+}
+
+cached
+private Sign operandSign(Instruction pos, Instruction operand) {
+ hasGuard(operand, pos, result)
+ or
+ not hasGuard(operand, pos, _) and
+ result = instructionSign(operand)
+}
+
+cached
+private Sign instructionSign(Instruction i) {
+ result = certainInstructionSign(i)
+ or
+ not exists(certainInstructionSign(i)) and
+ (
+ unknownSign(i)
+ or
+ exists(Instruction prior |
+ prior = i.(CopyInstruction).getSourceValue()
+ |
+ hasGuard(prior, i, result)
+ or
+ not exists(Sign s | hasGuard(prior, i, s)) and
+ result = instructionSign(prior)
+ )
+ or
+ result = instructionSign(i.(BitComplementInstruction).getOperand()).bitnot()
+ or
+ result = instructionSign(i.(AddInstruction))
+ or
+ exists(Sign s1, Sign s2 |
+ binaryOpSigns(i, s1, s2)
+ |
+ i instanceof AddInstruction and result = s1.add(s2)
+ or
+ i instanceof SubInstruction and result = s1.add(s2.neg())
+ or
+ i instanceof MulInstruction and result = s1.mul(s2)
+ or
+ i instanceof DivInstruction and result = s1.div(s2)
+ or
+ i instanceof RemInstruction and result = s1.rem(s2)
+ or
+ i instanceof BitAndInstruction and result = s1.bitand(s2)
+ or
+ i instanceof BitOrInstruction and result = s1.bitor(s2)
+ or
+ i instanceof BitXorInstruction and result = s1.bitxor(s2)
+ or
+ i instanceof ShiftLeftInstruction and result = s1.lshift(s2)
+ or
+ i instanceof ShiftRightInstruction and
+ i.getResultType().(IntegralType).isSigned() and
+ result = s1.rshift(s2)
+ or
+ i instanceof ShiftRightInstruction and
+ not i.getResultType().(IntegralType).isSigned() and
+ result = s1.urshift(s2)
+ )
+ or
+ // use hasGuard here?
+ result = operandSign(i, i.(PhiInstruction).getAnOperand())
+ )
+}
+
+/** Holds if `e` can be positive and cannot be negative. */
+predicate positive(Instruction i) {
+ instructionSign(i) = TPos() and
+ not instructionSign(i) = TNeg()
+}
+
+/** Holds if `e` can be negative and cannot be positive. */
+predicate negative(Instruction i) {
+ instructionSign(i) = TNeg() and
+ not instructionSign(i) = TPos()
+}
+
+/** Holds if `e` is strictly positive. */
+predicate strictlyPositive(Instruction i) {
+ instructionSign(i) = TPos() and
+ not instructionSign(i) = TNeg() and
+ not instructionSign(i) = TZero()
+}
+
+/** Holds if `e` is strictly negative. */
+predicate strictlyNegative(Instruction i) {
+ instructionSign(i) = TNeg() and
+ not instructionSign(i) = TPos() and
+ not instructionSign(i) = TZero()
+}
diff --git a/cpp/ql/test/library-tests/rangeanalysis/signanalysis/inline_assembly.c b/cpp/ql/test/library-tests/rangeanalysis/signanalysis/inline_assembly.c
new file mode 100644
index 00000000000..430838d7736
--- /dev/null
+++ b/cpp/ql/test/library-tests/rangeanalysis/signanalysis/inline_assembly.c
@@ -0,0 +1,24 @@
+// The ASM statements are
+// causing problems, because our SSA analysis does not notice that they
+// might change the value of `x`. This was a latent bug that came out
+// of the woodwork when we added support for statement expressions.
+
+int printf(const char *format, ...);
+
+int main() {
+ unsigned int x = 0, y;
+ y = 1;
+
+ printf("x = %i y = %i\n", x, y); // 0, 1
+
+ // exchange x and y
+ asm volatile ( "xchg %0, %1\n"
+ : "+r" (x), "+a" (y) // outputs (x and y)
+ :
+ :
+ );
+
+ printf("x = %i y = %i\n", x, y); // 1, 0 (but without analysing the ASM: unknown, unknown)
+
+ return 0;
+}
diff --git a/cpp/ql/test/library-tests/rangeanalysis/signanalysis/minmax.c b/cpp/ql/test/library-tests/rangeanalysis/signanalysis/minmax.c
new file mode 100644
index 00000000000..460167ccb4c
--- /dev/null
+++ b/cpp/ql/test/library-tests/rangeanalysis/signanalysis/minmax.c
@@ -0,0 +1,27 @@
+// semmle-extractor-options: --gnu_version 40400
+// Note: this file uses statement expressions, which are a GNU extension,
+// so it has an options file to specify the compiler version. The statement
+// expression extension is described here:
+// https://gcc.gnu.org/onlinedocs/gcc/Statement-Exprs.html
+
+int printf(const char *format, ...);
+
+// The & operator is
+// causing problems, because it disables SSA. Also, range analysis did not
+// have support for the statement expression language feature that is used
+// here.
+
+void minmax()
+{
+ int x = 1, y = 2, z = 3;
+
+ printf("x = %i, y = %i, z = %i\n", x, y, z); // 1, 2, 3
+
+ z = ({
+ int t = 0;
+ if (&x != &y) {t = x;} // t = 1
+ t;
+ });
+
+ printf("x = %i, y = %i, z = %i\n", x, y, z); // 1, 2, 1
+}
diff --git a/cpp/ql/test/library-tests/rangeanalysis/signanalysis/negative.expected b/cpp/ql/test/library-tests/rangeanalysis/signanalysis/negative.expected
new file mode 100644
index 00000000000..4c0f7da72a3
--- /dev/null
+++ b/cpp/ql/test/library-tests/rangeanalysis/signanalysis/negative.expected
@@ -0,0 +1,55 @@
+| test.c:67:7:67:11 | r0_6(int) = Constant[-1000] | test.c:67:7:67:11 | - ... |
+| test.c:154:39:154:40 | r3_0(long long) = Constant[-1] | test.c:154:39:154:40 | (long long)... |
+| test.c:171:7:171:8 | r16_1(int) = Constant[-7] | test.c:171:7:171:8 | - ... |
+| test.c:176:7:176:8 | r1_1(int) = Constant[-7] | test.c:176:7:176:8 | - ... |
+| test.c:181:7:181:8 | r4_1(int) = Constant[-7] | test.c:181:7:181:8 | - ... |
+| test.c:186:7:186:8 | r7_1(int) = Constant[-7] | test.c:186:7:186:8 | - ... |
+| test.c:186:23:186:24 | r9_2(int) = Constant[-2] | test.c:186:23:186:24 | - ... |
+| test.c:208:28:208:30 | r25_0(int) = Constant[-13] | test.c:208:28:208:30 | - ... |
+| test.c:212:28:212:30 | r5_0(int) = Constant[-13] | test.c:212:28:212:30 | - ... |
+| test.c:216:28:216:30 | r10_0(int) = Constant[-13] | test.c:216:28:216:30 | - ... |
+| test.c:216:45:216:46 | r11_2(int) = Constant[-7] | test.c:216:45:216:46 | - ... |
+| test.c:236:28:236:30 | r25_0(int) = Constant[-13] | test.c:236:28:236:30 | - ... |
+| test.c:240:28:240:30 | r5_0(int) = Constant[-13] | test.c:240:28:240:30 | - ... |
+| test.c:244:28:244:30 | r10_0(int) = Constant[-13] | test.c:244:28:244:30 | - ... |
+| test.c:244:45:244:46 | r11_2(int) = Constant[-7] | test.c:244:45:244:46 | - ... |
+| test.c:256:7:256:9 | r0_9(int) = Constant[-17] | test.c:256:7:256:9 | - ... |
+| test.c:260:7:260:9 | r18_1(int) = Constant[-17] | test.c:260:7:260:9 | - ... |
+| test.c:264:7:264:9 | r23_1(int) = Constant[-17] | test.c:264:7:264:9 | - ... |
+| test.c:264:30:264:32 | r25_0(int) = Constant[-13] | test.c:264:30:264:32 | - ... |
+| test.c:268:7:268:9 | r3_1(int) = Constant[-17] | test.c:268:7:268:9 | - ... |
+| test.c:268:30:268:32 | r5_0(int) = Constant[-13] | test.c:268:30:268:32 | - ... |
+| test.c:272:7:272:9 | r8_1(int) = Constant[-17] | test.c:272:7:272:9 | - ... |
+| test.c:272:30:272:32 | r10_0(int) = Constant[-13] | test.c:272:30:272:32 | - ... |
+| test.c:272:47:272:48 | r11_2(int) = Constant[-7] | test.c:272:47:272:48 | - ... |
+| test.c:284:7:284:9 | r0_9(int) = Constant[-17] | test.c:284:7:284:9 | - ... |
+| test.c:288:7:288:9 | r18_1(int) = Constant[-17] | test.c:288:7:288:9 | - ... |
+| test.c:292:7:292:9 | r23_1(int) = Constant[-17] | test.c:292:7:292:9 | - ... |
+| test.c:292:29:292:31 | r25_0(int) = Constant[-13] | test.c:292:29:292:31 | - ... |
+| test.c:296:7:296:9 | r3_1(int) = Constant[-17] | test.c:296:7:296:9 | - ... |
+| test.c:296:29:296:31 | r5_0(int) = Constant[-13] | test.c:296:29:296:31 | - ... |
+| test.c:300:7:300:9 | r8_1(int) = Constant[-17] | test.c:300:7:300:9 | - ... |
+| test.c:300:29:300:31 | r10_0(int) = Constant[-13] | test.c:300:29:300:31 | - ... |
+| test.c:300:46:300:47 | r11_2(int) = Constant[-7] | test.c:300:46:300:47 | - ... |
+| test.c:312:7:312:9 | r0_9(int) = Constant[-17] | test.c:312:7:312:9 | - ... |
+| test.c:312:24:312:25 | r14_2(int) = Constant[-2] | test.c:312:24:312:25 | - ... |
+| test.c:316:7:316:9 | r18_1(int) = Constant[-17] | test.c:316:7:316:9 | - ... |
+| test.c:316:24:316:25 | r19_2(int) = Constant[-2] | test.c:316:24:316:25 | - ... |
+| test.c:320:7:320:9 | r23_1(int) = Constant[-17] | test.c:320:7:320:9 | - ... |
+| test.c:320:24:320:25 | r24_2(int) = Constant[-2] | test.c:320:24:320:25 | - ... |
+| test.c:320:30:320:32 | r25_0(int) = Constant[-13] | test.c:320:30:320:32 | - ... |
+| test.c:324:7:324:9 | r3_1(int) = Constant[-17] | test.c:324:7:324:9 | - ... |
+| test.c:324:24:324:25 | r4_2(int) = Constant[-2] | test.c:324:24:324:25 | - ... |
+| test.c:324:30:324:32 | r5_0(int) = Constant[-13] | test.c:324:30:324:32 | - ... |
+| test.c:328:7:328:9 | r8_1(int) = Constant[-17] | test.c:328:7:328:9 | - ... |
+| test.c:328:24:328:25 | r9_2(int) = Constant[-2] | test.c:328:24:328:25 | - ... |
+| test.c:328:30:328:32 | r10_0(int) = Constant[-13] | test.c:328:30:328:32 | - ... |
+| test.c:328:47:328:48 | r11_2(int) = Constant[-7] | test.c:328:47:328:48 | - ... |
+| test.c:339:12:339:13 | r2_1(int) = Constant[-1] | test.c:339:12:339:13 | - ... |
+| test.cpp:9:11:9:12 | r0_7(int) = Constant[-1] | test.cpp:9:11:9:12 | - ... |
+| test.cpp:30:12:30:13 | r11_3(int) = Constant[-1] | test.cpp:30:12:30:13 | - ... |
+| test.cpp:31:9:31:10 | r12_0(int) = Constant[-1] | test.cpp:31:9:31:10 | - ... |
+| test.cpp:36:12:36:15 | r15_3(int) = Constant[-128] | test.cpp:36:12:36:15 | - ... |
+| test.cpp:37:9:37:12 | r16_0(int) = Constant[-128] | test.cpp:37:9:37:12 | - ... |
+| test.cpp:42:12:42:16 | r19_3(int) = Constant[-1024] | test.cpp:42:12:42:16 | - ... |
+| test.cpp:43:9:43:13 | r20_0(int) = Constant[-1024] | test.cpp:43:9:43:13 | - ... |
diff --git a/cpp/ql/test/library-tests/rangeanalysis/signanalysis/negative.ql b/cpp/ql/test/library-tests/rangeanalysis/signanalysis/negative.ql
new file mode 100644
index 00000000000..2239669cf87
--- /dev/null
+++ b/cpp/ql/test/library-tests/rangeanalysis/signanalysis/negative.ql
@@ -0,0 +1,6 @@
+import semmle.code.cpp.rangeanalysis.SignAnalysis
+import semmle.code.cpp.ir.IR
+
+from Instruction i
+where negative(i)
+select i, i.getAST()
\ No newline at end of file
diff --git a/cpp/ql/test/library-tests/rangeanalysis/signanalysis/positive.expected b/cpp/ql/test/library-tests/rangeanalysis/signanalysis/positive.expected
new file mode 100644
index 00000000000..64dad2b3ceb
--- /dev/null
+++ b/cpp/ql/test/library-tests/rangeanalysis/signanalysis/positive.expected
@@ -0,0 +1,136 @@
+| inline_assembly.c:10:7:10:7 | r0_7(unsigned int) = Constant[1] | inline_assembly.c:10:7:10:7 | (unsigned int)... |
+| minmax.c:16:9:16:10 | r0_3(int) = Constant[1] | minmax.c:16:9:16:10 | 1 |
+| minmax.c:16:16:16:17 | r0_6(int) = Constant[2] | minmax.c:16:16:16:17 | 2 |
+| minmax.c:16:23:16:24 | r0_9(int) = Constant[3] | minmax.c:16:23:16:24 | 3 |
+| test.c:8:19:8:19 | r2_2(int) = Constant[1] | test.c:8:19:8:19 | 1 |
+| test.c:16:20:16:20 | r2_2(int) = Constant[1] | test.c:16:20:16:20 | 1 |
+| test.c:16:25:16:26 | r2_4(int) = Constant[10] | test.c:16:25:16:26 | 10 |
+| test.c:24:5:24:11 | r2_2(int) = Constant[1] | test.c:24:5:24:11 | ... ++ |
+| test.c:25:21:25:22 | r2_7(int) = Constant[10] | test.c:25:21:25:22 | 10 |
+| test.c:33:19:33:19 | r1_4(int) = Constant[2] | test.c:33:19:33:19 | 2 |
+| test.c:33:28:33:28 | r2_8(int) = Constant[1] | test.c:33:28:33:28 | 1 |
+| test.c:42:19:42:19 | r1_4(int) = Constant[2] | test.c:42:19:42:19 | 2 |
+| test.c:42:22:42:24 | r2_8(int) = Constant[1] | test.c:42:22:42:24 | ... ++ |
+| test.c:51:17:51:17 | r1_4(int) = Constant[2] | test.c:51:17:51:17 | 2 |
+| test.c:51:21:51:21 | r1_6(int) = Constant[4] | test.c:51:21:51:21 | 4 |
+| test.c:51:30:51:30 | r2_8(int) = Constant[1] | test.c:51:30:51:30 | 1 |
+| test.c:58:11:58:11 | r0_6(int) = Constant[4] | test.c:58:11:58:11 | 4 |
+| test.c:59:13:59:13 | r2_2(int) = Constant[5] | test.c:59:13:59:13 | 5 |
+| test.c:63:10:63:10 | r4_1(int) = Constant[1] | test.c:63:10:63:10 | 1 |
+| test.c:67:24:67:25 | r2_2(int) = Constant[10] | test.c:67:24:67:25 | 10 |
+| test.c:68:15:68:15 | r3_4(int) = Constant[2] | test.c:68:15:68:15 | 2 |
+| test.c:77:13:77:13 | r2_2(int) = Constant[4] | test.c:77:13:77:13 | 4 |
+| test.c:81:13:81:13 | r4_2(int) = Constant[4] | test.c:81:13:81:13 | 4 |
+| test.c:82:14:82:14 | r5_1(int) = Constant[1] | test.c:82:14:82:14 | 1 |
+| test.c:89:11:89:11 | r0_8(int) = Constant[7] | test.c:89:11:89:11 | 7 |
+| test.c:95:10:95:10 | r5_1(int) = Constant[1] | test.c:95:10:95:10 | 1 |
+| test.c:102:6:102:8 | r2_3(int) = Constant[1] | test.c:102:6:102:8 | ... ++ |
+| test.c:104:12:104:14 | r3_4(int) = Constant[58] | test.c:104:12:104:14 | 58 |
+| test.c:107:8:107:10 | r5_3(int) = Constant[1] | test.c:107:8:107:10 | ... ++ |
+| test.c:109:14:109:16 | r6_3(int) = Constant[44] | test.c:109:14:109:16 | 44 |
+| test.c:110:14:110:14 | r7_1(int) = Constant[1] | test.c:110:14:110:14 | 1 |
+| test.c:119:10:119:12 | r0_8(unsigned long long) = Constant[1] | test.c:119:10:119:12 | ... ++ |
+| test.c:124:36:124:36 | r1_5(unsigned long long) = Constant[1] | test.c:124:36:124:36 | (unsigned long long)... |
+| test.c:127:24:127:24 | r2_6(unsigned long long) = Constant[1] | test.c:127:24:127:24 | (unsigned long long)... |
+| test.c:130:11:130:11 | r3_1(int) = Constant[1] | test.c:130:11:130:11 | 1 |
+| test.c:137:22:137:22 | r0_17(unsigned int) = Constant[1] | test.c:137:22:137:22 | (unsigned int)... |
+| test.c:138:13:138:13 | r0_23(int) = Constant[1] | test.c:138:13:138:13 | 1 |
+| test.c:161:7:161:7 | r0_7(int) = Constant[3] | test.c:161:7:161:7 | 3 |
+| test.c:161:22:161:23 | r8_2(int) = Constant[11] | test.c:161:22:161:23 | 11 |
+| test.c:166:22:166:23 | r14_2(int) = Constant[11] | test.c:166:22:166:23 | 11 |
+| test.c:171:23:171:24 | r17_2(int) = Constant[11] | test.c:171:23:171:24 | 11 |
+| test.c:176:23:176:23 | r2_2(int) = Constant[1] | test.c:176:23:176:23 | 1 |
+| test.c:200:7:200:7 | r0_9(int) = Constant[3] | test.c:200:7:200:7 | 3 |
+| test.c:200:22:200:23 | r14_2(int) = Constant[11] | test.c:200:22:200:23 | 11 |
+| test.c:200:28:200:28 | r15_0(int) = Constant[5] | test.c:200:28:200:28 | 5 |
+| test.c:200:43:200:44 | r16_2(int) = Constant[23] | test.c:200:43:200:44 | 23 |
+| test.c:204:7:204:7 | r18_1(int) = Constant[3] | test.c:204:7:204:7 | 3 |
+| test.c:204:22:204:23 | r19_2(int) = Constant[11] | test.c:204:22:204:23 | 11 |
+| test.c:204:43:204:44 | r21_2(int) = Constant[23] | test.c:204:43:204:44 | 23 |
+| test.c:208:7:208:7 | r23_1(int) = Constant[3] | test.c:208:7:208:7 | 3 |
+| test.c:208:22:208:23 | r24_2(int) = Constant[11] | test.c:208:22:208:23 | 11 |
+| test.c:208:45:208:46 | r1_2(int) = Constant[23] | test.c:208:45:208:46 | 23 |
+| test.c:212:7:212:7 | r3_1(int) = Constant[3] | test.c:212:7:212:7 | 3 |
+| test.c:212:22:212:23 | r4_2(int) = Constant[11] | test.c:212:22:212:23 | 11 |
+| test.c:216:7:216:7 | r8_1(int) = Constant[3] | test.c:216:7:216:7 | 3 |
+| test.c:216:22:216:23 | r9_2(int) = Constant[11] | test.c:216:22:216:23 | 11 |
+| test.c:228:22:228:23 | r14_2(int) = Constant[11] | test.c:228:22:228:23 | 11 |
+| test.c:228:28:228:28 | r15_0(int) = Constant[5] | test.c:228:28:228:28 | 5 |
+| test.c:228:43:228:44 | r16_2(int) = Constant[23] | test.c:228:43:228:44 | 23 |
+| test.c:232:22:232:23 | r19_2(int) = Constant[11] | test.c:232:22:232:23 | 11 |
+| test.c:232:43:232:44 | r21_2(int) = Constant[23] | test.c:232:43:232:44 | 23 |
+| test.c:236:22:236:23 | r24_2(int) = Constant[11] | test.c:236:22:236:23 | 11 |
+| test.c:236:45:236:46 | r1_2(int) = Constant[23] | test.c:236:45:236:46 | 23 |
+| test.c:240:22:240:23 | r4_2(int) = Constant[11] | test.c:240:22:240:23 | 11 |
+| test.c:244:22:244:23 | r9_2(int) = Constant[11] | test.c:244:22:244:23 | 11 |
+| test.c:256:24:256:25 | r14_2(int) = Constant[11] | test.c:256:24:256:25 | 11 |
+| test.c:256:30:256:30 | r15_0(int) = Constant[5] | test.c:256:30:256:30 | 5 |
+| test.c:256:45:256:46 | r16_2(int) = Constant[23] | test.c:256:45:256:46 | 23 |
+| test.c:260:24:260:25 | r19_2(int) = Constant[11] | test.c:260:24:260:25 | 11 |
+| test.c:260:45:260:46 | r21_2(int) = Constant[23] | test.c:260:45:260:46 | 23 |
+| test.c:264:24:264:25 | r24_2(int) = Constant[11] | test.c:264:24:264:25 | 11 |
+| test.c:264:47:264:48 | r1_2(int) = Constant[23] | test.c:264:47:264:48 | 23 |
+| test.c:268:24:268:25 | r4_2(int) = Constant[11] | test.c:268:24:268:25 | 11 |
+| test.c:272:24:272:25 | r9_2(int) = Constant[11] | test.c:272:24:272:25 | 11 |
+| test.c:284:29:284:29 | r15_0(int) = Constant[5] | test.c:284:29:284:29 | 5 |
+| test.c:284:44:284:45 | r16_2(int) = Constant[23] | test.c:284:44:284:45 | 23 |
+| test.c:288:44:288:45 | r21_2(int) = Constant[23] | test.c:288:44:288:45 | 23 |
+| test.c:292:46:292:47 | r1_2(int) = Constant[23] | test.c:292:46:292:47 | 23 |
+| test.c:312:30:312:30 | r15_0(int) = Constant[5] | test.c:312:30:312:30 | 5 |
+| test.c:312:45:312:46 | r16_2(int) = Constant[23] | test.c:312:45:312:46 | 23 |
+| test.c:316:45:316:46 | r21_2(int) = Constant[23] | test.c:316:45:316:46 | 23 |
+| test.c:320:47:320:48 | r1_2(int) = Constant[23] | test.c:320:47:320:48 | 23 |
+| test.c:342:14:342:14 | r3_3(int) = Constant[3] | test.c:342:14:342:14 | 3 |
+| test.c:343:5:343:7 | r4_2(int) = Constant[1] | test.c:343:5:343:7 | ... ++ |
+| test.c:348:14:348:14 | r7_1(int) = Constant[1] | test.c:348:14:348:14 | 1 |
+| test.c:357:12:357:14 | r0_22(unsigned int) = Constant[100] | test.c:357:12:357:14 | (unsigned int)... |
+| test.c:357:22:357:23 | r22_0(unsigned int) = Constant[10] | test.c:357:22:357:23 | (unsigned int)... |
+| test.c:358:13:358:15 | r17_7(unsigned int) = Constant[100] | test.c:358:13:358:15 | (unsigned int)... |
+| test.c:358:19:358:20 | r24_0(unsigned int) = Constant[10] | test.c:358:19:358:20 | (unsigned int)... |
+| test.c:365:11:365:13 | r23_25(unsigned int) = Constant[300] | test.c:365:11:365:13 | (unsigned int)... |
+| test.c:366:15:366:15 | r38_0(unsigned int) = Constant[5] | test.c:366:15:366:15 | (unsigned int)... |
+| test.c:366:15:366:15 | r40_0(unsigned int) = Constant[5] | test.c:366:15:366:15 | (unsigned int)... |
+| test.c:367:15:367:17 | r48_0(unsigned int) = Constant[500] | test.c:367:15:367:17 | (unsigned int)... |
+| test.c:367:15:367:17 | r50_0(unsigned int) = Constant[500] | test.c:367:15:367:17 | (unsigned int)... |
+| test.c:368:13:368:13 | r27_0(unsigned int) = Constant[1] | test.c:368:13:368:13 | (unsigned int)... |
+| test.c:368:13:368:13 | r54_0(unsigned int) = Constant[1] | test.c:368:13:368:13 | (unsigned int)... |
+| test.c:368:19:368:21 | r55_0(unsigned int) = Constant[500] | test.c:368:19:368:21 | (unsigned int)... |
+| test.c:369:29:369:29 | r4_0(unsigned int) = Constant[1] | test.c:369:29:369:29 | (unsigned int)... |
+| test.c:369:29:369:29 | r41_0(unsigned int) = Constant[1] | test.c:369:29:369:29 | (unsigned int)... |
+| test.c:369:36:369:36 | r5_0(int) = Constant[5] | test.c:369:36:369:36 | 5 |
+| test.c:370:29:370:29 | r9_0(unsigned int) = Constant[1] | test.c:370:29:370:29 | (unsigned int)... |
+| test.c:370:29:370:29 | r41_0(unsigned int) = Constant[1] | test.c:370:29:370:29 | (unsigned int)... |
+| test.c:370:36:370:38 | r10_0(int) = Constant[500] | test.c:370:36:370:38 | 500 |
+| test.c:371:30:371:30 | r14_0(unsigned int) = Constant[1] | test.c:371:30:371:30 | (unsigned int)... |
+| test.c:371:30:371:30 | r41_0(unsigned int) = Constant[1] | test.c:371:30:371:30 | (unsigned int)... |
+| test.c:371:37:371:39 | r15_0(int) = Constant[500] | test.c:371:37:371:39 | 500 |
+| test.c:379:12:379:14 | r0_16(unsigned int) = Constant[100] | test.c:379:12:379:14 | (unsigned int)... |
+| test.c:379:22:379:24 | r5_0(unsigned int) = Constant[110] | test.c:379:22:379:24 | (unsigned int)... |
+| test.c:380:13:380:15 | r1_7(unsigned int) = Constant[100] | test.c:380:13:380:15 | (unsigned int)... |
+| test.c:380:19:380:21 | r7_0(unsigned int) = Constant[110] | test.c:380:19:380:21 | (unsigned int)... |
+| test.c:381:8:381:11 | r6_5(unsigned int) = Constant[1000] | test.c:381:8:381:11 | (unsigned int)... |
+| test.c:382:8:382:11 | r6_8(unsigned int) = Constant[1000] | test.c:382:8:382:11 | (unsigned int)... |
+| test.c:383:8:383:11 | r6_11(unsigned int) = Constant[1000] | test.c:383:8:383:11 | (unsigned int)... |
+| test.c:384:12:384:14 | r6_16(unsigned int) = Constant[300] | test.c:384:12:384:14 | (unsigned int)... |
+| test.c:385:13:385:15 | r11_0(unsigned int) = Constant[300] | test.c:385:13:385:15 | (unsigned int)... |
+| test.c:385:13:385:15 | r18_0(unsigned int) = Constant[300] | test.c:385:13:385:15 | (unsigned int)... |
+| test.c:385:21:385:21 | r19_0(unsigned int) = Constant[5] | test.c:385:21:385:21 | (unsigned int)... |
+| test.c:386:13:386:15 | r11_0(unsigned int) = Constant[200] | test.c:386:13:386:15 | (unsigned int)... |
+| test.c:386:13:386:15 | r24_0(unsigned int) = Constant[200] | test.c:386:13:386:15 | (unsigned int)... |
+| test.c:386:21:386:21 | r25_0(unsigned int) = Constant[5] | test.c:386:21:386:21 | (unsigned int)... |
+| test.c:387:29:387:31 | r28_0(unsigned int) = Constant[200] | test.c:387:29:387:31 | (unsigned int)... |
+| test.c:387:29:387:31 | r30_0(unsigned int) = Constant[200] | test.c:387:29:387:31 | (unsigned int)... |
+| test.c:387:38:387:38 | r31_0(int) = Constant[5] | test.c:387:38:387:38 | 5 |
+| test.c:394:24:394:26 | r0_7(unsigned int) = Constant[100] | test.c:394:24:394:26 | (unsigned int)... |
+| test.c:394:34:394:36 | r2_0(unsigned int) = Constant[100] | test.c:394:34:394:36 | (unsigned int)... |
+| test.c:397:9:397:11 | r3_10(unsigned int) = Constant[1] | test.c:397:9:397:11 | ++ ... |
+| test.c:398:9:398:11 | r3_19(unsigned int) = Constant[1] | test.c:398:9:398:11 | ... ++ |
+| test.c:398:19:398:19 | r3_22(unsigned int) = Constant[3] | test.c:398:19:398:19 | (unsigned int)... |
+| test.cpp:11:13:11:13 | r1_2(int) = Constant[3] | test.cpp:11:13:11:13 | 3 |
+| test.cpp:33:12:33:12 | r13_3(int) = Constant[1] | test.cpp:33:12:33:12 | 1 |
+| test.cpp:34:9:34:9 | r14_0(int) = Constant[1] | test.cpp:34:9:34:9 | 1 |
+| test.cpp:39:12:39:14 | r17_3(int) = Constant[128] | test.cpp:39:12:39:14 | 128 |
+| test.cpp:40:9:40:11 | r18_0(int) = Constant[128] | test.cpp:40:9:40:11 | 128 |
+| test.cpp:45:12:45:15 | r21_3(int) = Constant[1024] | test.cpp:45:12:45:15 | 1024 |
+| test.cpp:46:9:46:12 | r22_0(int) = Constant[1024] | test.cpp:46:9:46:12 | 1024 |
+| test.cpp:69:10:69:21 | r9_1(bool) = Constant[1] | test.cpp:69:10:69:21 | ... \|\| ... |
diff --git a/cpp/ql/test/library-tests/rangeanalysis/signanalysis/positive.ql b/cpp/ql/test/library-tests/rangeanalysis/signanalysis/positive.ql
new file mode 100644
index 00000000000..f57a29493ab
--- /dev/null
+++ b/cpp/ql/test/library-tests/rangeanalysis/signanalysis/positive.ql
@@ -0,0 +1,6 @@
+import semmle.code.cpp.rangeanalysis.SignAnalysis
+import semmle.code.cpp.ir.IR
+
+from Instruction i
+where positive(i)
+select i, i.getAST()
\ No newline at end of file
diff --git a/cpp/ql/test/library-tests/rangeanalysis/signanalysis/strictlyNegative.expected b/cpp/ql/test/library-tests/rangeanalysis/signanalysis/strictlyNegative.expected
new file mode 100644
index 00000000000..409def9f448
--- /dev/null
+++ b/cpp/ql/test/library-tests/rangeanalysis/signanalysis/strictlyNegative.expected
@@ -0,0 +1,64 @@
+| test.c:67:7:67:11 | r0_6(int) = Constant[-1000] | test.c:67:7:67:11 | - ... |
+| test.c:137:20:137:22 | m0_19(unsigned int) = Store r0_14, r0_18 | test.c:137:20:137:22 | ... - ... |
+| test.c:137:20:137:22 | r0_18(unsigned int) = Sub r0_16, r0_17 | test.c:137:20:137:22 | ... - ... |
+| test.c:139:36:139:36 | r0_42(unsigned int) = Load r0_41, m0_19 | test.c:139:36:139:36 | y |
+| test.c:154:10:154:40 | m3_2(long long) = Store r3_1, r3_0 | test.c:154:10:154:40 | ... ? ... : ... |
+| test.c:154:39:154:40 | r3_0(long long) = Constant[-1] | test.c:154:39:154:40 | (long long)... |
+| test.c:171:7:171:8 | r16_1(int) = Constant[-7] | test.c:171:7:171:8 | - ... |
+| test.c:176:7:176:8 | r1_1(int) = Constant[-7] | test.c:176:7:176:8 | - ... |
+| test.c:181:7:181:8 | r4_1(int) = Constant[-7] | test.c:181:7:181:8 | - ... |
+| test.c:186:7:186:8 | r7_1(int) = Constant[-7] | test.c:186:7:186:8 | - ... |
+| test.c:186:23:186:24 | r9_2(int) = Constant[-2] | test.c:186:23:186:24 | - ... |
+| test.c:208:28:208:30 | r25_0(int) = Constant[-13] | test.c:208:28:208:30 | - ... |
+| test.c:212:28:212:30 | r5_0(int) = Constant[-13] | test.c:212:28:212:30 | - ... |
+| test.c:216:28:216:30 | r10_0(int) = Constant[-13] | test.c:216:28:216:30 | - ... |
+| test.c:216:45:216:46 | r11_2(int) = Constant[-7] | test.c:216:45:216:46 | - ... |
+| test.c:236:28:236:30 | r25_0(int) = Constant[-13] | test.c:236:28:236:30 | - ... |
+| test.c:240:28:240:30 | r5_0(int) = Constant[-13] | test.c:240:28:240:30 | - ... |
+| test.c:244:28:244:30 | r10_0(int) = Constant[-13] | test.c:244:28:244:30 | - ... |
+| test.c:244:45:244:46 | r11_2(int) = Constant[-7] | test.c:244:45:244:46 | - ... |
+| test.c:256:7:256:9 | r0_9(int) = Constant[-17] | test.c:256:7:256:9 | - ... |
+| test.c:260:7:260:9 | r18_1(int) = Constant[-17] | test.c:260:7:260:9 | - ... |
+| test.c:264:7:264:9 | r23_1(int) = Constant[-17] | test.c:264:7:264:9 | - ... |
+| test.c:264:30:264:32 | r25_0(int) = Constant[-13] | test.c:264:30:264:32 | - ... |
+| test.c:268:7:268:9 | r3_1(int) = Constant[-17] | test.c:268:7:268:9 | - ... |
+| test.c:268:30:268:32 | r5_0(int) = Constant[-13] | test.c:268:30:268:32 | - ... |
+| test.c:272:7:272:9 | r8_1(int) = Constant[-17] | test.c:272:7:272:9 | - ... |
+| test.c:272:30:272:32 | r10_0(int) = Constant[-13] | test.c:272:30:272:32 | - ... |
+| test.c:272:47:272:48 | r11_2(int) = Constant[-7] | test.c:272:47:272:48 | - ... |
+| test.c:284:7:284:9 | r0_9(int) = Constant[-17] | test.c:284:7:284:9 | - ... |
+| test.c:288:7:288:9 | r18_1(int) = Constant[-17] | test.c:288:7:288:9 | - ... |
+| test.c:292:7:292:9 | r23_1(int) = Constant[-17] | test.c:292:7:292:9 | - ... |
+| test.c:292:29:292:31 | r25_0(int) = Constant[-13] | test.c:292:29:292:31 | - ... |
+| test.c:296:7:296:9 | r3_1(int) = Constant[-17] | test.c:296:7:296:9 | - ... |
+| test.c:296:29:296:31 | r5_0(int) = Constant[-13] | test.c:296:29:296:31 | - ... |
+| test.c:300:7:300:9 | r8_1(int) = Constant[-17] | test.c:300:7:300:9 | - ... |
+| test.c:300:29:300:31 | r10_0(int) = Constant[-13] | test.c:300:29:300:31 | - ... |
+| test.c:300:46:300:47 | r11_2(int) = Constant[-7] | test.c:300:46:300:47 | - ... |
+| test.c:312:7:312:9 | r0_9(int) = Constant[-17] | test.c:312:7:312:9 | - ... |
+| test.c:312:24:312:25 | r14_2(int) = Constant[-2] | test.c:312:24:312:25 | - ... |
+| test.c:316:7:316:9 | r18_1(int) = Constant[-17] | test.c:316:7:316:9 | - ... |
+| test.c:316:24:316:25 | r19_2(int) = Constant[-2] | test.c:316:24:316:25 | - ... |
+| test.c:320:7:320:9 | r23_1(int) = Constant[-17] | test.c:320:7:320:9 | - ... |
+| test.c:320:24:320:25 | r24_2(int) = Constant[-2] | test.c:320:24:320:25 | - ... |
+| test.c:320:30:320:32 | r25_0(int) = Constant[-13] | test.c:320:30:320:32 | - ... |
+| test.c:324:7:324:9 | r3_1(int) = Constant[-17] | test.c:324:7:324:9 | - ... |
+| test.c:324:24:324:25 | r4_2(int) = Constant[-2] | test.c:324:24:324:25 | - ... |
+| test.c:324:30:324:32 | r5_0(int) = Constant[-13] | test.c:324:30:324:32 | - ... |
+| test.c:328:7:328:9 | r8_1(int) = Constant[-17] | test.c:328:7:328:9 | - ... |
+| test.c:328:24:328:25 | r9_2(int) = Constant[-2] | test.c:328:24:328:25 | - ... |
+| test.c:328:30:328:32 | r10_0(int) = Constant[-13] | test.c:328:30:328:32 | - ... |
+| test.c:328:47:328:48 | r11_2(int) = Constant[-7] | test.c:328:47:328:48 | - ... |
+| test.c:339:12:339:13 | m2_2(int) = Store r2_0, r2_1 | test.c:339:12:339:13 | - ... |
+| test.c:339:12:339:13 | r2_1(int) = Constant[-1] | test.c:339:12:339:13 | - ... |
+| test.cpp:9:11:9:12 | m0_8(int) = Store r0_6, r0_7 | test.cpp:9:11:9:12 | - ... |
+| test.cpp:9:11:9:12 | r0_7(int) = Constant[-1] | test.cpp:9:11:9:12 | - ... |
+| test.cpp:30:12:30:13 | r11_3(int) = Constant[-1] | test.cpp:30:12:30:13 | - ... |
+| test.cpp:31:5:31:10 | m12_2(int) = Store r12_1, r12_0 | test.cpp:31:5:31:10 | ... = ... |
+| test.cpp:31:9:31:10 | r12_0(int) = Constant[-1] | test.cpp:31:9:31:10 | - ... |
+| test.cpp:36:12:36:15 | r15_3(int) = Constant[-128] | test.cpp:36:12:36:15 | - ... |
+| test.cpp:37:5:37:12 | m16_2(int) = Store r16_1, r16_0 | test.cpp:37:5:37:12 | ... = ... |
+| test.cpp:37:9:37:12 | r16_0(int) = Constant[-128] | test.cpp:37:9:37:12 | - ... |
+| test.cpp:42:12:42:16 | r19_3(int) = Constant[-1024] | test.cpp:42:12:42:16 | - ... |
+| test.cpp:43:5:43:13 | m20_2(int) = Store r20_1, r20_0 | test.cpp:43:5:43:13 | ... = ... |
+| test.cpp:43:9:43:13 | r20_0(int) = Constant[-1024] | test.cpp:43:9:43:13 | - ... |
diff --git a/cpp/ql/test/library-tests/rangeanalysis/signanalysis/strictlyNegative.ql b/cpp/ql/test/library-tests/rangeanalysis/signanalysis/strictlyNegative.ql
new file mode 100644
index 00000000000..b13fdd5638c
--- /dev/null
+++ b/cpp/ql/test/library-tests/rangeanalysis/signanalysis/strictlyNegative.ql
@@ -0,0 +1,6 @@
+import semmle.code.cpp.rangeanalysis.SignAnalysis
+import semmle.code.cpp.ir.IR
+
+from Instruction i
+where strictlyNegative(i)
+select i, i.getAST()
\ No newline at end of file
diff --git a/cpp/ql/test/library-tests/rangeanalysis/signanalysis/strictlyPositive.expected b/cpp/ql/test/library-tests/rangeanalysis/signanalysis/strictlyPositive.expected
new file mode 100644
index 00000000000..64dad2b3ceb
--- /dev/null
+++ b/cpp/ql/test/library-tests/rangeanalysis/signanalysis/strictlyPositive.expected
@@ -0,0 +1,136 @@
+| inline_assembly.c:10:7:10:7 | r0_7(unsigned int) = Constant[1] | inline_assembly.c:10:7:10:7 | (unsigned int)... |
+| minmax.c:16:9:16:10 | r0_3(int) = Constant[1] | minmax.c:16:9:16:10 | 1 |
+| minmax.c:16:16:16:17 | r0_6(int) = Constant[2] | minmax.c:16:16:16:17 | 2 |
+| minmax.c:16:23:16:24 | r0_9(int) = Constant[3] | minmax.c:16:23:16:24 | 3 |
+| test.c:8:19:8:19 | r2_2(int) = Constant[1] | test.c:8:19:8:19 | 1 |
+| test.c:16:20:16:20 | r2_2(int) = Constant[1] | test.c:16:20:16:20 | 1 |
+| test.c:16:25:16:26 | r2_4(int) = Constant[10] | test.c:16:25:16:26 | 10 |
+| test.c:24:5:24:11 | r2_2(int) = Constant[1] | test.c:24:5:24:11 | ... ++ |
+| test.c:25:21:25:22 | r2_7(int) = Constant[10] | test.c:25:21:25:22 | 10 |
+| test.c:33:19:33:19 | r1_4(int) = Constant[2] | test.c:33:19:33:19 | 2 |
+| test.c:33:28:33:28 | r2_8(int) = Constant[1] | test.c:33:28:33:28 | 1 |
+| test.c:42:19:42:19 | r1_4(int) = Constant[2] | test.c:42:19:42:19 | 2 |
+| test.c:42:22:42:24 | r2_8(int) = Constant[1] | test.c:42:22:42:24 | ... ++ |
+| test.c:51:17:51:17 | r1_4(int) = Constant[2] | test.c:51:17:51:17 | 2 |
+| test.c:51:21:51:21 | r1_6(int) = Constant[4] | test.c:51:21:51:21 | 4 |
+| test.c:51:30:51:30 | r2_8(int) = Constant[1] | test.c:51:30:51:30 | 1 |
+| test.c:58:11:58:11 | r0_6(int) = Constant[4] | test.c:58:11:58:11 | 4 |
+| test.c:59:13:59:13 | r2_2(int) = Constant[5] | test.c:59:13:59:13 | 5 |
+| test.c:63:10:63:10 | r4_1(int) = Constant[1] | test.c:63:10:63:10 | 1 |
+| test.c:67:24:67:25 | r2_2(int) = Constant[10] | test.c:67:24:67:25 | 10 |
+| test.c:68:15:68:15 | r3_4(int) = Constant[2] | test.c:68:15:68:15 | 2 |
+| test.c:77:13:77:13 | r2_2(int) = Constant[4] | test.c:77:13:77:13 | 4 |
+| test.c:81:13:81:13 | r4_2(int) = Constant[4] | test.c:81:13:81:13 | 4 |
+| test.c:82:14:82:14 | r5_1(int) = Constant[1] | test.c:82:14:82:14 | 1 |
+| test.c:89:11:89:11 | r0_8(int) = Constant[7] | test.c:89:11:89:11 | 7 |
+| test.c:95:10:95:10 | r5_1(int) = Constant[1] | test.c:95:10:95:10 | 1 |
+| test.c:102:6:102:8 | r2_3(int) = Constant[1] | test.c:102:6:102:8 | ... ++ |
+| test.c:104:12:104:14 | r3_4(int) = Constant[58] | test.c:104:12:104:14 | 58 |
+| test.c:107:8:107:10 | r5_3(int) = Constant[1] | test.c:107:8:107:10 | ... ++ |
+| test.c:109:14:109:16 | r6_3(int) = Constant[44] | test.c:109:14:109:16 | 44 |
+| test.c:110:14:110:14 | r7_1(int) = Constant[1] | test.c:110:14:110:14 | 1 |
+| test.c:119:10:119:12 | r0_8(unsigned long long) = Constant[1] | test.c:119:10:119:12 | ... ++ |
+| test.c:124:36:124:36 | r1_5(unsigned long long) = Constant[1] | test.c:124:36:124:36 | (unsigned long long)... |
+| test.c:127:24:127:24 | r2_6(unsigned long long) = Constant[1] | test.c:127:24:127:24 | (unsigned long long)... |
+| test.c:130:11:130:11 | r3_1(int) = Constant[1] | test.c:130:11:130:11 | 1 |
+| test.c:137:22:137:22 | r0_17(unsigned int) = Constant[1] | test.c:137:22:137:22 | (unsigned int)... |
+| test.c:138:13:138:13 | r0_23(int) = Constant[1] | test.c:138:13:138:13 | 1 |
+| test.c:161:7:161:7 | r0_7(int) = Constant[3] | test.c:161:7:161:7 | 3 |
+| test.c:161:22:161:23 | r8_2(int) = Constant[11] | test.c:161:22:161:23 | 11 |
+| test.c:166:22:166:23 | r14_2(int) = Constant[11] | test.c:166:22:166:23 | 11 |
+| test.c:171:23:171:24 | r17_2(int) = Constant[11] | test.c:171:23:171:24 | 11 |
+| test.c:176:23:176:23 | r2_2(int) = Constant[1] | test.c:176:23:176:23 | 1 |
+| test.c:200:7:200:7 | r0_9(int) = Constant[3] | test.c:200:7:200:7 | 3 |
+| test.c:200:22:200:23 | r14_2(int) = Constant[11] | test.c:200:22:200:23 | 11 |
+| test.c:200:28:200:28 | r15_0(int) = Constant[5] | test.c:200:28:200:28 | 5 |
+| test.c:200:43:200:44 | r16_2(int) = Constant[23] | test.c:200:43:200:44 | 23 |
+| test.c:204:7:204:7 | r18_1(int) = Constant[3] | test.c:204:7:204:7 | 3 |
+| test.c:204:22:204:23 | r19_2(int) = Constant[11] | test.c:204:22:204:23 | 11 |
+| test.c:204:43:204:44 | r21_2(int) = Constant[23] | test.c:204:43:204:44 | 23 |
+| test.c:208:7:208:7 | r23_1(int) = Constant[3] | test.c:208:7:208:7 | 3 |
+| test.c:208:22:208:23 | r24_2(int) = Constant[11] | test.c:208:22:208:23 | 11 |
+| test.c:208:45:208:46 | r1_2(int) = Constant[23] | test.c:208:45:208:46 | 23 |
+| test.c:212:7:212:7 | r3_1(int) = Constant[3] | test.c:212:7:212:7 | 3 |
+| test.c:212:22:212:23 | r4_2(int) = Constant[11] | test.c:212:22:212:23 | 11 |
+| test.c:216:7:216:7 | r8_1(int) = Constant[3] | test.c:216:7:216:7 | 3 |
+| test.c:216:22:216:23 | r9_2(int) = Constant[11] | test.c:216:22:216:23 | 11 |
+| test.c:228:22:228:23 | r14_2(int) = Constant[11] | test.c:228:22:228:23 | 11 |
+| test.c:228:28:228:28 | r15_0(int) = Constant[5] | test.c:228:28:228:28 | 5 |
+| test.c:228:43:228:44 | r16_2(int) = Constant[23] | test.c:228:43:228:44 | 23 |
+| test.c:232:22:232:23 | r19_2(int) = Constant[11] | test.c:232:22:232:23 | 11 |
+| test.c:232:43:232:44 | r21_2(int) = Constant[23] | test.c:232:43:232:44 | 23 |
+| test.c:236:22:236:23 | r24_2(int) = Constant[11] | test.c:236:22:236:23 | 11 |
+| test.c:236:45:236:46 | r1_2(int) = Constant[23] | test.c:236:45:236:46 | 23 |
+| test.c:240:22:240:23 | r4_2(int) = Constant[11] | test.c:240:22:240:23 | 11 |
+| test.c:244:22:244:23 | r9_2(int) = Constant[11] | test.c:244:22:244:23 | 11 |
+| test.c:256:24:256:25 | r14_2(int) = Constant[11] | test.c:256:24:256:25 | 11 |
+| test.c:256:30:256:30 | r15_0(int) = Constant[5] | test.c:256:30:256:30 | 5 |
+| test.c:256:45:256:46 | r16_2(int) = Constant[23] | test.c:256:45:256:46 | 23 |
+| test.c:260:24:260:25 | r19_2(int) = Constant[11] | test.c:260:24:260:25 | 11 |
+| test.c:260:45:260:46 | r21_2(int) = Constant[23] | test.c:260:45:260:46 | 23 |
+| test.c:264:24:264:25 | r24_2(int) = Constant[11] | test.c:264:24:264:25 | 11 |
+| test.c:264:47:264:48 | r1_2(int) = Constant[23] | test.c:264:47:264:48 | 23 |
+| test.c:268:24:268:25 | r4_2(int) = Constant[11] | test.c:268:24:268:25 | 11 |
+| test.c:272:24:272:25 | r9_2(int) = Constant[11] | test.c:272:24:272:25 | 11 |
+| test.c:284:29:284:29 | r15_0(int) = Constant[5] | test.c:284:29:284:29 | 5 |
+| test.c:284:44:284:45 | r16_2(int) = Constant[23] | test.c:284:44:284:45 | 23 |
+| test.c:288:44:288:45 | r21_2(int) = Constant[23] | test.c:288:44:288:45 | 23 |
+| test.c:292:46:292:47 | r1_2(int) = Constant[23] | test.c:292:46:292:47 | 23 |
+| test.c:312:30:312:30 | r15_0(int) = Constant[5] | test.c:312:30:312:30 | 5 |
+| test.c:312:45:312:46 | r16_2(int) = Constant[23] | test.c:312:45:312:46 | 23 |
+| test.c:316:45:316:46 | r21_2(int) = Constant[23] | test.c:316:45:316:46 | 23 |
+| test.c:320:47:320:48 | r1_2(int) = Constant[23] | test.c:320:47:320:48 | 23 |
+| test.c:342:14:342:14 | r3_3(int) = Constant[3] | test.c:342:14:342:14 | 3 |
+| test.c:343:5:343:7 | r4_2(int) = Constant[1] | test.c:343:5:343:7 | ... ++ |
+| test.c:348:14:348:14 | r7_1(int) = Constant[1] | test.c:348:14:348:14 | 1 |
+| test.c:357:12:357:14 | r0_22(unsigned int) = Constant[100] | test.c:357:12:357:14 | (unsigned int)... |
+| test.c:357:22:357:23 | r22_0(unsigned int) = Constant[10] | test.c:357:22:357:23 | (unsigned int)... |
+| test.c:358:13:358:15 | r17_7(unsigned int) = Constant[100] | test.c:358:13:358:15 | (unsigned int)... |
+| test.c:358:19:358:20 | r24_0(unsigned int) = Constant[10] | test.c:358:19:358:20 | (unsigned int)... |
+| test.c:365:11:365:13 | r23_25(unsigned int) = Constant[300] | test.c:365:11:365:13 | (unsigned int)... |
+| test.c:366:15:366:15 | r38_0(unsigned int) = Constant[5] | test.c:366:15:366:15 | (unsigned int)... |
+| test.c:366:15:366:15 | r40_0(unsigned int) = Constant[5] | test.c:366:15:366:15 | (unsigned int)... |
+| test.c:367:15:367:17 | r48_0(unsigned int) = Constant[500] | test.c:367:15:367:17 | (unsigned int)... |
+| test.c:367:15:367:17 | r50_0(unsigned int) = Constant[500] | test.c:367:15:367:17 | (unsigned int)... |
+| test.c:368:13:368:13 | r27_0(unsigned int) = Constant[1] | test.c:368:13:368:13 | (unsigned int)... |
+| test.c:368:13:368:13 | r54_0(unsigned int) = Constant[1] | test.c:368:13:368:13 | (unsigned int)... |
+| test.c:368:19:368:21 | r55_0(unsigned int) = Constant[500] | test.c:368:19:368:21 | (unsigned int)... |
+| test.c:369:29:369:29 | r4_0(unsigned int) = Constant[1] | test.c:369:29:369:29 | (unsigned int)... |
+| test.c:369:29:369:29 | r41_0(unsigned int) = Constant[1] | test.c:369:29:369:29 | (unsigned int)... |
+| test.c:369:36:369:36 | r5_0(int) = Constant[5] | test.c:369:36:369:36 | 5 |
+| test.c:370:29:370:29 | r9_0(unsigned int) = Constant[1] | test.c:370:29:370:29 | (unsigned int)... |
+| test.c:370:29:370:29 | r41_0(unsigned int) = Constant[1] | test.c:370:29:370:29 | (unsigned int)... |
+| test.c:370:36:370:38 | r10_0(int) = Constant[500] | test.c:370:36:370:38 | 500 |
+| test.c:371:30:371:30 | r14_0(unsigned int) = Constant[1] | test.c:371:30:371:30 | (unsigned int)... |
+| test.c:371:30:371:30 | r41_0(unsigned int) = Constant[1] | test.c:371:30:371:30 | (unsigned int)... |
+| test.c:371:37:371:39 | r15_0(int) = Constant[500] | test.c:371:37:371:39 | 500 |
+| test.c:379:12:379:14 | r0_16(unsigned int) = Constant[100] | test.c:379:12:379:14 | (unsigned int)... |
+| test.c:379:22:379:24 | r5_0(unsigned int) = Constant[110] | test.c:379:22:379:24 | (unsigned int)... |
+| test.c:380:13:380:15 | r1_7(unsigned int) = Constant[100] | test.c:380:13:380:15 | (unsigned int)... |
+| test.c:380:19:380:21 | r7_0(unsigned int) = Constant[110] | test.c:380:19:380:21 | (unsigned int)... |
+| test.c:381:8:381:11 | r6_5(unsigned int) = Constant[1000] | test.c:381:8:381:11 | (unsigned int)... |
+| test.c:382:8:382:11 | r6_8(unsigned int) = Constant[1000] | test.c:382:8:382:11 | (unsigned int)... |
+| test.c:383:8:383:11 | r6_11(unsigned int) = Constant[1000] | test.c:383:8:383:11 | (unsigned int)... |
+| test.c:384:12:384:14 | r6_16(unsigned int) = Constant[300] | test.c:384:12:384:14 | (unsigned int)... |
+| test.c:385:13:385:15 | r11_0(unsigned int) = Constant[300] | test.c:385:13:385:15 | (unsigned int)... |
+| test.c:385:13:385:15 | r18_0(unsigned int) = Constant[300] | test.c:385:13:385:15 | (unsigned int)... |
+| test.c:385:21:385:21 | r19_0(unsigned int) = Constant[5] | test.c:385:21:385:21 | (unsigned int)... |
+| test.c:386:13:386:15 | r11_0(unsigned int) = Constant[200] | test.c:386:13:386:15 | (unsigned int)... |
+| test.c:386:13:386:15 | r24_0(unsigned int) = Constant[200] | test.c:386:13:386:15 | (unsigned int)... |
+| test.c:386:21:386:21 | r25_0(unsigned int) = Constant[5] | test.c:386:21:386:21 | (unsigned int)... |
+| test.c:387:29:387:31 | r28_0(unsigned int) = Constant[200] | test.c:387:29:387:31 | (unsigned int)... |
+| test.c:387:29:387:31 | r30_0(unsigned int) = Constant[200] | test.c:387:29:387:31 | (unsigned int)... |
+| test.c:387:38:387:38 | r31_0(int) = Constant[5] | test.c:387:38:387:38 | 5 |
+| test.c:394:24:394:26 | r0_7(unsigned int) = Constant[100] | test.c:394:24:394:26 | (unsigned int)... |
+| test.c:394:34:394:36 | r2_0(unsigned int) = Constant[100] | test.c:394:34:394:36 | (unsigned int)... |
+| test.c:397:9:397:11 | r3_10(unsigned int) = Constant[1] | test.c:397:9:397:11 | ++ ... |
+| test.c:398:9:398:11 | r3_19(unsigned int) = Constant[1] | test.c:398:9:398:11 | ... ++ |
+| test.c:398:19:398:19 | r3_22(unsigned int) = Constant[3] | test.c:398:19:398:19 | (unsigned int)... |
+| test.cpp:11:13:11:13 | r1_2(int) = Constant[3] | test.cpp:11:13:11:13 | 3 |
+| test.cpp:33:12:33:12 | r13_3(int) = Constant[1] | test.cpp:33:12:33:12 | 1 |
+| test.cpp:34:9:34:9 | r14_0(int) = Constant[1] | test.cpp:34:9:34:9 | 1 |
+| test.cpp:39:12:39:14 | r17_3(int) = Constant[128] | test.cpp:39:12:39:14 | 128 |
+| test.cpp:40:9:40:11 | r18_0(int) = Constant[128] | test.cpp:40:9:40:11 | 128 |
+| test.cpp:45:12:45:15 | r21_3(int) = Constant[1024] | test.cpp:45:12:45:15 | 1024 |
+| test.cpp:46:9:46:12 | r22_0(int) = Constant[1024] | test.cpp:46:9:46:12 | 1024 |
+| test.cpp:69:10:69:21 | r9_1(bool) = Constant[1] | test.cpp:69:10:69:21 | ... \|\| ... |
diff --git a/cpp/ql/test/library-tests/rangeanalysis/signanalysis/strictlyPositive.ql b/cpp/ql/test/library-tests/rangeanalysis/signanalysis/strictlyPositive.ql
new file mode 100644
index 00000000000..271b17ff9f3
--- /dev/null
+++ b/cpp/ql/test/library-tests/rangeanalysis/signanalysis/strictlyPositive.ql
@@ -0,0 +1,6 @@
+import semmle.code.cpp.rangeanalysis.SignAnalysis
+import semmle.code.cpp.ir.IR
+
+from Instruction i
+where strictlyPositive(i)
+select i, i.getAST()
\ No newline at end of file
diff --git a/cpp/ql/test/library-tests/rangeanalysis/signanalysis/test.c b/cpp/ql/test/library-tests/rangeanalysis/signanalysis/test.c
new file mode 100644
index 00000000000..fa294a67823
--- /dev/null
+++ b/cpp/ql/test/library-tests/rangeanalysis/signanalysis/test.c
@@ -0,0 +1,400 @@
+struct List {
+ struct List* next;
+};
+
+int test1(struct List* p) {
+ int count = 0;
+ for (; p; p = p->next) {
+ count = count+1;
+ }
+ return count;
+}
+
+int test2(struct List* p) {
+ int count = 0;
+ for (; p; p = p->next) {
+ count = (count+1) % 10;
+ }
+ return count;
+}
+
+int test3(struct List* p) {
+ int count = 0;
+ for (; p; p = p->next) {
+ count++;
+ count = count % 10;
+ }
+ return count;
+}
+
+int test4() {
+ int i = 0;
+ int total = 0;
+ for (i = 0; i < 2; i = i+1) {
+ total += i;
+ }
+ return total + i;
+}
+
+int test5() {
+ int i = 0;
+ int total = 0;
+ for (i = 0; i < 2; i++) {
+ total += i;
+ }
+ return total + i;
+}
+
+int test6() {
+ int i = 0;
+ int total = 0;
+ for (i = 0; i+2 < 4; i = i+1) {
+ total += i;
+ }
+ return total + i;
+}
+
+int test7(int i) {
+ if (i < 4) {
+ if (i < 5) {
+ return i;
+ }
+ }
+ return 1;
+}
+
+int test8(int x, int y) {
+ if (-1000 < y && y < 10) {
+ if (x < y-2) {
+ return x;
+ }
+ }
+ return y;
+}
+
+int test9(int x, int y) {
+ if (y == 0) {
+ if (x < 4) {
+ return 0;
+ }
+ } else {
+ if (x < 4) {
+ return 1;
+ }
+ }
+ return x;
+}
+
+int test10(int x, int y) {
+ if (y > 7) {
+ if (x < y) {
+ return 0;
+ }
+ return x;
+ }
+ return 1;
+}
+
+int test11(char *p) {
+ char c;
+ c = *p;
+ if (c != '\0')
+ *p++ = '\0';
+
+ if (c == ':') {
+ c = *p;
+ if (c != '\0')
+ *p++ = '\0';
+
+ if (c != ',')
+ return 1;
+ }
+ return 0;
+}
+
+typedef unsigned long long size_type;
+
+size_type test12_helper() {
+ static size_type n = 0;
+ return n++;
+}
+
+int test12() {
+ size_type Start = 0;
+ while (Start <= test12_helper()-1)
+ {
+ const size_type Length = test12_helper();
+ Start += Length + 1;
+ }
+
+ return 1;
+}
+
+// Tests for overflow conditions.
+int test13(char c, int i) {
+ unsigned char uc = c;
+ unsigned int x = 0;
+ unsigned int y = x-1;
+ int z = i+1;
+ return (double)(c + i + uc + x + y + z);
+}
+
+// Regression test for ODASA-6013.
+int test14(int x) {
+ int x0 = (int)(char)x;
+ int x1 = (int)(unsigned char)x;
+ int x2 = (int)(unsigned short)x;
+ int x3 = (int)(unsigned int)x;
+ char c0 = x;
+ unsigned short s0 = x;
+ return x0 + x1 + x2 + x3 + c0 + s0;
+}
+
+long long test15(long long x) {
+ return (x > 0 && x == (int)x) ? x : -1;
+}
+
+// Tests for unary operators.
+int test_unary(int a) {
+ int total = 0;
+
+ if (3 <= a && a <= 11) {
+ int b = +a;
+ int c = -a;
+ total += b+c;
+ }
+ if (0 <= a && a <= 11) {
+ int b = +a;
+ int c = -a;
+ total += b+c;
+ }
+ if (-7 <= a && a <= 11) {
+ int b = +a;
+ int c = -a;
+ total += b+c;
+ }
+ if (-7 <= a && a <= 1) {
+ int b = +a;
+ int c = -a;
+ total += b+c;
+ }
+ if (-7 <= a && a <= 0) {
+ int b = +a;
+ int c = -a;
+ total += b+c;
+ }
+ if (-7 <= a && a <= -2) {
+ int b = +a;
+ int c = -a;
+ total += b+c;
+ }
+
+ return total;
+}
+
+
+// Tests for multiplication.
+int test_mult01(int a, int b) {
+ int total = 0;
+
+ if (3 <= a && a <= 11 && 5 <= b && b <= 23) {
+ int r = a*b; // 15 .. 253
+ total += r;
+ }
+ if (3 <= a && a <= 11 && 0 <= b && b <= 23) {
+ int r = a*b; // 0 .. 253
+ total += r;
+ }
+ if (3 <= a && a <= 11 && -13 <= b && b <= 23) {
+ int r = a*b; // -143 .. 253
+ total += r;
+ }
+ if (3 <= a && a <= 11 && -13 <= b && b <= 0) {
+ int r = a*b; // -143 .. 0
+ total += r;
+ }
+ if (3 <= a && a <= 11 && -13 <= b && b <= -7) {
+ int r = a*b; // -143 .. -21
+ total += r;
+ }
+
+ return total;
+}
+
+// Tests for multiplication.
+int test_mult02(int a, int b) {
+ int total = 0;
+
+ if (0 <= a && a <= 11 && 5 <= b && b <= 23) {
+ int r = a*b; // 0 .. 253
+ total += r;
+ }
+ if (0 <= a && a <= 11 && 0 <= b && b <= 23) {
+ int r = a*b; // 0 .. 253
+ total += r;
+ }
+ if (0 <= a && a <= 11 && -13 <= b && b <= 23) {
+ int r = a*b; // -143 .. 253
+ total += r;
+ }
+ if (0 <= a && a <= 11 && -13 <= b && b <= 0) {
+ int r = a*b; // -143 .. 0
+ total += r;
+ }
+ if (0 <= a && a <= 11 && -13 <= b && b <= -7) {
+ int r = a*b; // -143 .. 0
+ total += r;
+ }
+
+ return total;
+}
+
+// Tests for multiplication.
+int test_mult03(int a, int b) {
+ int total = 0;
+
+ if (-17 <= a && a <= 11 && 5 <= b && b <= 23) {
+ int r = a*b; // -391 .. 253
+ total += r;
+ }
+ if (-17 <= a && a <= 11 && 0 <= b && b <= 23) {
+ int r = a*b; // -391 .. 253
+ total += r;
+ }
+ if (-17 <= a && a <= 11 && -13 <= b && b <= 23) {
+ int r = a*b; // -391 .. 253
+ total += r;
+ }
+ if (-17 <= a && a <= 11 && -13 <= b && b <= 0) {
+ int r = a*b; // -143 .. 221
+ total += r;
+ }
+ if (-17 <= a && a <= 11 && -13 <= b && b <= -7) {
+ int r = a*b; // -143 .. 221
+ total += r;
+ }
+
+ return total;
+}
+
+// Tests for multiplication.
+int test_mult04(int a, int b) {
+ int total = 0;
+
+ if (-17 <= a && a <= 0 && 5 <= b && b <= 23) {
+ int r = a*b; // -391 .. 0
+ total += r;
+ }
+ if (-17 <= a && a <= 0 && 0 <= b && b <= 23) {
+ int r = a*b; // -391 .. 0
+ total += r;
+ }
+ if (-17 <= a && a <= 0 && -13 <= b && b <= 23) {
+ int r = a*b; // -391 .. 221
+ total += r;
+ }
+ if (-17 <= a && a <= 0 && -13 <= b && b <= 0) {
+ int r = a*b; // 0 .. 221
+ total += r;
+ }
+ if (-17 <= a && a <= 0 && -13 <= b && b <= -7) {
+ int r = a*b; // 0 .. 221
+ total += r;
+ }
+
+ return total;
+}
+
+// Tests for multiplication.
+int test_mult05(int a, int b) {
+ int total = 0;
+
+ if (-17 <= a && a <= -2 && 5 <= b && b <= 23) {
+ int r = a*b; // -391 .. -10
+ total += r;
+ }
+ if (-17 <= a && a <= -2 && 0 <= b && b <= 23) {
+ int r = a*b; // -391 .. 0
+ total += r;
+ }
+ if (-17 <= a && a <= -2 && -13 <= b && b <= 23) {
+ int r = a*b; // -391 .. 221
+ total += r;
+ }
+ if (-17 <= a && a <= -2 && -13 <= b && b <= 0) {
+ int r = a*b; // 0 .. 221
+ total += r;
+ }
+ if (-17 <= a && a <= -2 && -13 <= b && b <= -7) {
+ int r = a*b; // 14 .. 221
+ total += r;
+ }
+
+ return total;
+}
+
+int test16(int x) {
+ int d, i = 0;
+ if (x < 0) {
+ return -1;
+ }
+
+ while (i < 3) {
+ i++;
+ }
+ d = i;
+ if (x < 0) { // Comparison is always false.
+ if (d > -x) { // Unreachable code.
+ return 1;
+ }
+ }
+ return 0;
+}
+
+// Test ternary expression upper bounds.
+unsigned int test_ternary01(unsigned int x) {
+ unsigned int y1, y2, y3, y4, y5, y6, y7, y8;
+ y1 = x < 100 ? x : 10; // y1 < 100
+ y2 = x >= 100 ? 10 : x; // y2 < 100
+ y3 = 0;
+ y4 = 0;
+ y5 = 0;
+ y6 = 0;
+ y7 = 0;
+ y8 = 0;
+ if (x < 300) {
+ y3 = x ?: 5; // y3 < 300
+ y4 = x ?: 500; // y4 <= 500
+ y5 = (x+1) ?: 500; // y5 <= 300
+ y6 = ((unsigned char)(x+1)) ?: 5; // y6 < 256
+ y7 = ((unsigned char)(x+1)) ?: 500; // y7 <= 500
+ y8 = ((unsigned short)(x+1)) ?: 500; // y8 <= 300
+ }
+ return y1 + y2 + y3 + y4 + y5 + y6 + y7 + y8;
+}
+
+// Test ternary expression lower bounds.
+unsigned int test_ternary02(unsigned int x) {
+ unsigned int y1, y2, y3, y4, y5;
+ y1 = x > 100 ? x : 110; // y1 > 100
+ y2 = x <= 100 ? 110 : x; // y2 > 100
+ y3 = 1000;
+ y4 = 1000;
+ y5 = 1000;
+ if (x >= 300) {
+ y3 = (x-300) ?: 5; // y3 >= 0
+ y4 = (x-200) ?: 5; // y4 >= 100
+ y5 = ((unsigned char)(x-200)) ?: 5; // y6 >= 0
+ }
+ return y1 + y2 + y3 + y4 + y5;
+}
+
+// Test the comma expression.
+unsigned int test_comma01(unsigned int x) {
+ unsigned int y = x < 100 ? x : 100;
+ unsigned int y1;
+ unsigned int y2;
+ y1 = (++y, y);
+ y2 = (y++, y += 3, y);
+ return y1 + y2;
+}
diff --git a/cpp/ql/test/library-tests/rangeanalysis/signanalysis/test.cpp b/cpp/ql/test/library-tests/rangeanalysis/signanalysis/test.cpp
new file mode 100644
index 00000000000..9a930772b8d
--- /dev/null
+++ b/cpp/ql/test/library-tests/rangeanalysis/signanalysis/test.cpp
@@ -0,0 +1,70 @@
+template
+class vector {
+public:
+ T& operator[](int);
+ const T& operator[](int) const;
+};
+
+int test1(vector vec, int b) {
+ int x = -1;
+ if (b) {
+ x = vec[3];
+ }
+ return x;
+}
+
+// Regression test for ODASA-6013.
+int test2(int x) {
+ int x0 = static_cast(x);
+ return x0;
+}
+
+// Tests for conversion to bool
+bool test3(bool b, int x, int y) {
+ // The purpose the assignments to `x` below is to generate a lot of
+ // potential upper and lower bounds for `x`, so that the logic in
+ // boolConversionLowerBound and boolConversionUpperBound gets exercized.
+ if (y == 0) {
+ x = 0;
+ }
+ if (y == -1) {
+ x = -1;
+ }
+ if (y == 1) {
+ x = 1;
+ }
+ if (y == -128) {
+ x = -128;
+ }
+ if (y == 128) {
+ x = 128;
+ }
+ if (y == -1024) {
+ x = -1024;
+ }
+ if (y == 1024) {
+ x = 1024;
+ }
+
+ int t = 0;
+
+ if (x == 0) {
+ bool xb = (bool)x; // (bool)x == false
+ t += (int)xb;
+ }
+
+ if (x > 0) {
+ bool xb = (bool)x; // (bool)x == true
+ t += (int)xb;
+ }
+
+ if (x < 0) {
+ bool xb = (bool)x; // (bool)x == true
+ t += (int)xb;
+ }
+
+ bool xb = (bool)x; // Value of (bool)x is unknown.
+ t += (int)xb;
+
+ return b || (bool)t;
+}
From 08e9eea1f2e76b610f425e91af325dcd0f338031 Mon Sep 17 00:00:00 2001
From: Robert Marsh
Date: Wed, 19 Sep 2018 12:01:21 -0700
Subject: [PATCH 04/71] Add NegateInstruction
---
.../code/cpp/ir/implementation/aliased_ssa/Instruction.qll | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/Instruction.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/Instruction.qll
index c95cb23814e..99255b8ffa5 100644
--- a/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/Instruction.qll
+++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/Instruction.qll
@@ -761,6 +761,12 @@ class RemInstruction extends BinaryInstruction {
}
}
+class NegateInstruction extends UnaryInstruction {
+ NegateInstruction() {
+ opcode instanceof Opcode::Negate
+ }
+}
+
class BitAndInstruction extends BinaryInstruction {
BitAndInstruction() {
opcode instanceof Opcode::BitAnd
From d1ae939c9cf224b58bcd8a43eb59c370db357f2e Mon Sep 17 00:00:00 2001
From: Robert Marsh
Date: Wed, 19 Sep 2018 12:06:20 -0700
Subject: [PATCH 05/71] C++: use guards and operands in sign analysis
---
.../code/cpp/rangeanalysis/SignAnalysis.qll | 161 ++++--
.../signanalysis/SignAnalysis.expected | 544 ++++++++++++++++++
.../signanalysis/SignAnalysis.ql | 19 +
.../signanalysis/negative.expected | 55 --
.../rangeanalysis/signanalysis/negative.ql | 6 -
.../signanalysis/positive.expected | 136 -----
.../rangeanalysis/signanalysis/positive.ql | 6 -
.../signanalysis/strictlyNegative.expected | 64 ---
.../signanalysis/strictlyNegative.ql | 6 -
.../signanalysis/strictlyPositive.expected | 136 -----
.../signanalysis/strictlyPositive.ql | 6 -
11 files changed, 671 insertions(+), 468 deletions(-)
create mode 100644 cpp/ql/test/library-tests/rangeanalysis/signanalysis/SignAnalysis.expected
create mode 100644 cpp/ql/test/library-tests/rangeanalysis/signanalysis/SignAnalysis.ql
delete mode 100644 cpp/ql/test/library-tests/rangeanalysis/signanalysis/negative.expected
delete mode 100644 cpp/ql/test/library-tests/rangeanalysis/signanalysis/negative.ql
delete mode 100644 cpp/ql/test/library-tests/rangeanalysis/signanalysis/positive.expected
delete mode 100644 cpp/ql/test/library-tests/rangeanalysis/signanalysis/positive.ql
delete mode 100644 cpp/ql/test/library-tests/rangeanalysis/signanalysis/strictlyNegative.expected
delete mode 100644 cpp/ql/test/library-tests/rangeanalysis/signanalysis/strictlyNegative.ql
delete mode 100644 cpp/ql/test/library-tests/rangeanalysis/signanalysis/strictlyPositive.expected
delete mode 100644 cpp/ql/test/library-tests/rangeanalysis/signanalysis/strictlyPositive.ql
diff --git a/cpp/ql/src/semmle/code/cpp/rangeanalysis/SignAnalysis.qll b/cpp/ql/src/semmle/code/cpp/rangeanalysis/SignAnalysis.qll
index bb26241a977..16cb2c647a6 100644
--- a/cpp/ql/src/semmle/code/cpp/rangeanalysis/SignAnalysis.qll
+++ b/cpp/ql/src/semmle/code/cpp/rangeanalysis/SignAnalysis.qll
@@ -8,6 +8,7 @@
import cpp
private import semmle.code.cpp.ir.IR
private import semmle.code.cpp.controlflow.IRGuards
+private import semmle.code.cpp.ir.ValueNumbering
private newtype TSign = TNeg() or TZero() or TPos()
private class Sign extends TSign {
@@ -130,21 +131,29 @@ private Sign certainInstructionSign(Instruction inst) {
/** Holds if the sign of `e` is too complicated to determine. */
private predicate unknownSign(Instruction i) {
(
- i instanceof UnmodeledDefinitionInstruction or
- i instanceof UninitializedInstruction or
- i instanceof InitializeParameterInstruction or
- i instanceof BuiltInInstruction or
+ i instanceof UnmodeledDefinitionInstruction
+ or
+ i instanceof UninitializedInstruction
+ or
+ i instanceof InitializeParameterInstruction
+ or
+ i instanceof BuiltInInstruction
+ or
i instanceof CallInstruction
+ or
+ i instanceof ConvertInstruction and
+ i.getResultType().(IntegralType).isSigned()
)
}
/**
- * Holds if `lowerbound` is a lower bound for `compared` at `pos`. This is restricted
+ * Holds if `lowerbound` is a lower bound for `bounded` at `pos`. This is restricted
* to only include bounds for which we might determine a sign.
*/
-private predicate lowerBound(Instruction lowerbound, Instruction compared, Instruction pos, boolean isStrict) {
- exists(int adjustment, IRGuardCondition comp |
- pos.getAnOperand() = compared and
+private predicate lowerBound(IRGuardCondition comp, Instruction lowerbound, Instruction bounded, Instruction pos, boolean isStrict) {
+ exists(int adjustment, Instruction compared |
+ valueNumber(bounded) = valueNumber(compared) and
+ bounded = pos.getAnOperand() and
/*
* Java library uses guardControlsSsaRead here. I think that the phi node logic doesn't need to
* be duplicated but the implication predicates may need to be ported
@@ -156,18 +165,19 @@ private predicate lowerBound(Instruction lowerbound, Instruction compared, Instr
isStrict = false and
adjustment = 1
) and
- comp.ensuresLt(lowerbound, compared, 0, pos.getBlock(), true)
+ comp.ensuresLt(lowerbound, compared, adjustment, pos.getBlock(), true)
)
}
/**
- * Holds if `upperbound` is an upper bound for `compared` at `pos`. This is restricted
+ * Holds if `upperbound` is an upper bound for `bounded` at `pos`. This is restricted
* to only include bounds for which we might determine a sign.
*/
-private predicate upperBound(Instruction upperbound, Instruction compared, Instruction pos, boolean isStrict) {
- exists(int adjustment, IRGuardCondition comp |
- pos.getAnOperand() = compared and
+private predicate upperBound(IRGuardCondition comp, Instruction upperbound, Instruction bounded, Instruction pos, boolean isStrict) {
+ exists(int adjustment, Instruction compared |
+ valueNumber(bounded) = valueNumber(compared) and
+ bounded = pos.getAnOperand() and
/*
* Java library uses guardControlsSsaRead here. I think that the phi node logic doesn't need to
* be duplicated but the implication predicates may need to be ported
@@ -179,20 +189,21 @@ private predicate upperBound(Instruction upperbound, Instruction compared, Instr
isStrict = false and
adjustment = 1
) and
- comp.ensuresLt(compared, upperbound, 0, pos.getBlock(), true)
+ comp.ensuresLt(compared, upperbound, adjustment, pos.getBlock(), true)
)
}
/**
- * Holds if `eqbound` is an equality/inequality for `v` at `pos`. This is
+ * Holds if `eqbound` is an equality/inequality for `bounded` at `pos`. This is
* restricted to only include bounds for which we might determine a sign. The
* boolean `isEq` gives the polarity:
- * - `isEq = true` : `v = eqbound`
- * - `isEq = false` : `v != eqbound`
+ * - `isEq = true` : `bounded = eqbound`
+ * - `isEq = false` : `bounded != eqbound`
*/
-private predicate eqBound(Instruction eqbound, Instruction compared, Instruction pos, boolean isEq) {
- exists(IRGuardCondition guard |
- pos.getAnOperand() = compared and
+private predicate eqBound(IRGuardCondition guard, Instruction eqbound, Instruction bounded, Instruction pos, boolean isEq) {
+ exists(Instruction compared |
+ valueNumber(bounded) = valueNumber(compared) and
+ bounded = pos.getAnOperand() and
guard.ensuresEq(compared, eqbound, 0, pos.getBlock(), isEq)
)
}
@@ -203,48 +214,48 @@ private predicate eqBound(Instruction eqbound, Instruction compared, Instruction
* Holds if `bound` is a bound for `v` at `pos` that needs to be positive in
* order for `v` to be positive.
*/
-private predicate posBound(Instruction bound, Instruction v, Instruction pos) {
- upperBound(bound, v, pos, _) or
- eqBound(bound, v, pos, true)
+private predicate posBound(IRGuardCondition comp, Instruction bound, Instruction v, Instruction pos) {
+ upperBound(comp, bound, v, pos, _) or
+ eqBound(comp, bound, v, pos, true)
}
/**
* Holds if `bound` is a bound for `v` at `pos` that needs to be negative in
* order for `v` to be negative.
*/
-private predicate negBound(Instruction bound, Instruction v, Instruction pos) {
- lowerBound(bound, v, pos, _) or
- eqBound(bound, v, pos, true)
+private predicate negBound(IRGuardCondition comp, Instruction bound, Instruction v, Instruction pos) {
+ lowerBound(comp, bound, v, pos, _) or
+ eqBound(comp, bound, v, pos, true)
}
/**
* Holds if `bound` is a bound for `v` at `pos` that can restrict whether `v`
* can be zero.
*/
-private predicate zeroBound(Instruction bound, Instruction v, Instruction pos) {
- lowerBound(bound, v, pos, _) or
- upperBound(bound, v, pos, _) or
- eqBound(bound, v, pos, _)
+private predicate zeroBound(IRGuardCondition comp, Instruction bound, Instruction v, Instruction pos) {
+ lowerBound(comp, bound, v, pos, _) or
+ upperBound(comp, bound, v, pos, _) or
+ eqBound(comp, bound, v, pos, _)
}
/** Holds if `bound` allows `v` to be positive at `pos`. */
-private predicate posBoundOk(Instruction bound, Instruction v, Instruction pos) {
- posBound(bound, v, pos) and TPos() = instructionSign(bound)
+private predicate posBoundOk(IRGuardCondition comp, Instruction bound, Instruction v, Instruction pos) {
+ posBound(comp, bound, v, pos) and TPos() = operandSign(comp, bound)
}
/** Holds if `bound` allows `v` to be negative at `pos`. */
-private predicate negBoundOk(Instruction bound, Instruction v, Instruction pos) {
- negBound(bound, v, pos) and TNeg() = instructionSign(bound)
+private predicate negBoundOk(IRGuardCondition comp, Instruction bound, Instruction v, Instruction pos) {
+ negBound(comp, bound, v, pos) and TNeg() = operandSign(comp, bound)
}
/** Holds if `bound` allows `v` to be zero at `pos`. */
-private predicate zeroBoundOk(Instruction bound, Instruction v, Instruction pos) {
- lowerBound(bound, v, pos, _) and TNeg() = instructionSign(bound) or
- lowerBound(bound, v, pos, false) and TZero() = instructionSign(bound) or
- upperBound(bound, v, pos, _) and TPos() = instructionSign(bound) or
- upperBound(bound, v, pos, false) and TZero() = instructionSign(bound) or
- eqBound(bound, v, pos, true) and TZero() = instructionSign(bound) or
- eqBound(bound, v, pos, false) and TZero() != instructionSign(bound)
+private predicate zeroBoundOk(IRGuardCondition comp, Instruction bound, Instruction v, Instruction pos) {
+ lowerBound(comp, bound, v, pos, _) and TNeg() = operandSign(comp, bound) or
+ lowerBound(comp, bound, v, pos, false) and TZero() = operandSign(comp, bound) or
+ upperBound(comp, bound, v, pos, _) and TPos() = operandSign(comp, bound) or
+ upperBound(comp, bound, v, pos, false) and TZero() = operandSign(comp, bound) or
+ eqBound(comp, bound, v, pos, true) and TZero() = operandSign(comp, bound) or
+ eqBound(comp, bound, v, pos, false) and TZero() != operandSign(comp, bound)
}
private Sign binaryOpLhsSign(Instruction i) {
@@ -254,28 +265,50 @@ private Sign binaryOpLhsSign(Instruction i) {
private Sign binaryOpRhsSign(Instruction i) {
result = operandSign(i, i.(BinaryInstruction).getRightOperand())
}
+
pragma[noinline]
private predicate binaryOpSigns(Instruction i, Sign lhs, Sign rhs) {
lhs = binaryOpLhsSign(i) and
rhs = binaryOpRhsSign(i)
}
+private Sign unguardedOperandSign(Instruction pos, Instruction operand) {
+ result = instructionSign(operand) and
+ not hasGuard(operand, pos, result)
+}
+
+private Sign guardedOperandSign(Instruction pos, Instruction operand) {
+ result = instructionSign(operand) and
+ hasGuard(operand, pos, result)
+}
+
+private Sign guardedOperandSignOk(Instruction pos, Instruction operand) {
+ result = TPos() and forex(IRGuardCondition guard, Instruction bound | posBound(guard, bound, operand, pos) | posBoundOk(guard, bound, operand, pos)) or
+ result = TNeg() and forex(IRGuardCondition guard, Instruction bound | negBound(guard, bound, operand, pos) | negBoundOk(guard, bound, operand, pos)) or
+ result = TZero() and forex(IRGuardCondition guard, Instruction bound | zeroBound(guard, bound, operand, pos) | zeroBoundOk(guard, bound, operand, pos))
+}
+
/**
* Holds if there is a bound that might restrict whether `v` has the sign `s`
* at `pos`.
*/
private predicate hasGuard(Instruction v, Instruction pos, Sign s) {
- s = TPos() and posBound(_, v, pos) or
- s = TNeg() and negBound(_, v, pos) or
- s = TZero() and zeroBound(_, v, pos)
+ s = TPos() and posBound(_, _, v, pos)
+ or
+ s = TNeg() and negBound(_, _, v, pos)
+ or
+ s = TZero() and zeroBound(_, _, v, pos)
}
+/**
+ * Gets a sign that `operand` may have at `pos`, taking guards into account.
+ */
cached
private Sign operandSign(Instruction pos, Instruction operand) {
- hasGuard(operand, pos, result)
+ result = unguardedOperandSign(pos, operand)
or
- not hasGuard(operand, pos, _) and
- result = instructionSign(operand)
+ result = guardedOperandSign(pos, operand) and
+ result = guardedOperandSignOk(pos, operand)
}
cached
@@ -289,15 +322,12 @@ private Sign instructionSign(Instruction i) {
exists(Instruction prior |
prior = i.(CopyInstruction).getSourceValue()
|
- hasGuard(prior, i, result)
- or
- not exists(Sign s | hasGuard(prior, i, s)) and
- result = instructionSign(prior)
+ result = operandSign(i, prior)
)
or
- result = instructionSign(i.(BitComplementInstruction).getOperand()).bitnot()
+ result = operandSign(i, i.(BitComplementInstruction).getOperand()).bitnot()
or
- result = instructionSign(i.(AddInstruction))
+ result = operandSign(i, i.(NegateInstruction).getOperand()).neg()
or
exists(Sign s1, Sign s2 |
binaryOpSigns(i, s1, s2)
@@ -340,12 +370,23 @@ predicate positive(Instruction i) {
not instructionSign(i) = TNeg()
}
+predicate positive(Instruction i, Instruction pos) {
+ operandSign(pos, i) = TPos() and
+ not operandSign(pos, i) = TNeg()
+}
+
/** Holds if `e` can be negative and cannot be positive. */
predicate negative(Instruction i) {
instructionSign(i) = TNeg() and
not instructionSign(i) = TPos()
}
+/** Holds if `e` can be negative and cannot be positive. */
+predicate negative(Instruction i, Instruction pos) {
+ operandSign(pos, i) = TNeg() and
+ not operandSign(pos, i) = TPos()
+}
+
/** Holds if `e` is strictly positive. */
predicate strictlyPositive(Instruction i) {
instructionSign(i) = TPos() and
@@ -353,9 +394,23 @@ predicate strictlyPositive(Instruction i) {
not instructionSign(i) = TZero()
}
+/** Holds if `e` is strictly positive. */
+predicate strictlyPositive(Instruction i, Instruction pos) {
+ operandSign(pos, i) = TPos() and
+ not operandSign(pos, i) = TNeg() and
+ not operandSign(pos, i) = TZero()
+}
/** Holds if `e` is strictly negative. */
predicate strictlyNegative(Instruction i) {
instructionSign(i) = TNeg() and
not instructionSign(i) = TPos() and
not instructionSign(i) = TZero()
}
+
+
+/** Holds if `e` can be negative and cannot be positive. */
+predicate strictlyNegative(Instruction i, Instruction pos) {
+ operandSign(pos, i) = TNeg() and
+ not operandSign(pos, i) = TPos() and
+ not operandSign(pos, i) = TZero()
+}
diff --git a/cpp/ql/test/library-tests/rangeanalysis/signanalysis/SignAnalysis.expected b/cpp/ql/test/library-tests/rangeanalysis/signanalysis/SignAnalysis.expected
new file mode 100644
index 00000000000..7c7d797d245
--- /dev/null
+++ b/cpp/ql/test/library-tests/rangeanalysis/signanalysis/SignAnalysis.expected
@@ -0,0 +1,544 @@
+| inline_assembly.c:10:3:10:7 | m0_9(unsigned int) = Store r0_8, r0_7 | inline_assembly.c:10:3:10:7 | ... = ... | positive strictlyPositive |
+| inline_assembly.c:10:7:10:7 | r0_7(unsigned int) = Constant[1] | inline_assembly.c:10:7:10:7 | (unsigned int)... | positive strictlyPositive |
+| inline_assembly.c:12:32:12:32 | r0_17(unsigned int) = Load r0_16, m0_9 | inline_assembly.c:12:32:12:32 | y | positive strictlyPositive |
+| minmax.c:16:9:16:10 | m0_4(int) = Store r0_2, r0_3 | minmax.c:16:9:16:10 | 1 | positive strictlyPositive |
+| minmax.c:16:9:16:10 | r0_3(int) = Constant[1] | minmax.c:16:9:16:10 | 1 | positive strictlyPositive |
+| minmax.c:16:16:16:17 | m0_7(int) = Store r0_5, r0_6 | minmax.c:16:16:16:17 | 2 | positive strictlyPositive |
+| minmax.c:16:16:16:17 | r0_6(int) = Constant[2] | minmax.c:16:16:16:17 | 2 | positive strictlyPositive |
+| minmax.c:16:23:16:24 | m0_10(int) = Store r0_8, r0_9 | minmax.c:16:23:16:24 | 3 | positive strictlyPositive |
+| minmax.c:16:23:16:24 | r0_9(int) = Constant[3] | minmax.c:16:23:16:24 | 3 | positive strictlyPositive |
+| minmax.c:18:37:18:37 | r0_16(int) = Load r0_15, m0_4 | minmax.c:18:37:18:37 | x | positive strictlyPositive |
+| minmax.c:18:40:18:40 | r0_18(int) = Load r0_17, m0_7 | minmax.c:18:40:18:40 | y | positive strictlyPositive |
+| minmax.c:18:43:18:43 | r0_20(int) = Load r0_19, m0_10 | minmax.c:18:43:18:43 | z | positive strictlyPositive |
+| test.c:7:10:7:10 | m1_0(int) = Phi from 0:m0_6, from 2:m2_5 | test.c:7:10:7:10 | p | positive |
+| test.c:8:5:8:19 | m2_5(int) = Store r2_4, r2_3 | test.c:8:5:8:19 | ... = ... | positive strictlyPositive |
+| test.c:8:13:8:17 | r2_1(int) = Load r2_0, m1_0 | test.c:8:13:8:17 | count | positive |
+| test.c:8:13:8:19 | r2_3(int) = Add r2_1, r2_2 | test.c:8:13:8:19 | ... + ... | positive strictlyPositive |
+| test.c:8:19:8:19 | r2_2(int) = Constant[1] | test.c:8:19:8:19 | 1 | positive strictlyPositive |
+| test.c:10:10:10:14 | m3_3(int) = Store r3_0, r3_2 | test.c:10:10:10:14 | count | positive |
+| test.c:10:10:10:14 | r3_2(int) = Load r3_1, m1_0 | test.c:10:10:10:14 | count | positive |
+| test.c:15:10:15:10 | m1_0(int) = Phi from 0:m0_6, from 2:m2_7 | test.c:15:10:15:10 | p | positive |
+| test.c:16:5:16:26 | m2_7(int) = Store r2_6, r2_5 | test.c:16:5:16:26 | ... = ... | positive |
+| test.c:16:13:16:26 | r2_5(int) = Rem r2_3, r2_4 | test.c:16:13:16:26 | ... % ... | positive |
+| test.c:16:14:16:18 | r2_1(int) = Load r2_0, m1_0 | test.c:16:14:16:18 | count | positive |
+| test.c:16:14:16:20 | r2_3(int) = Add r2_1, r2_2 | test.c:16:14:16:20 | ... + ... | positive strictlyPositive |
+| test.c:16:20:16:20 | r2_2(int) = Constant[1] | test.c:16:20:16:20 | 1 | positive strictlyPositive |
+| test.c:16:25:16:26 | r2_4(int) = Constant[10] | test.c:16:25:16:26 | 10 | positive strictlyPositive |
+| test.c:18:10:18:14 | m3_3(int) = Store r3_0, r3_2 | test.c:18:10:18:14 | count | positive |
+| test.c:18:10:18:14 | r3_2(int) = Load r3_1, m1_0 | test.c:18:10:18:14 | count | positive |
+| test.c:23:10:23:10 | m1_0(int) = Phi from 0:m0_6, from 2:m2_10 | test.c:23:10:23:10 | p | positive |
+| test.c:24:5:24:11 | m2_4(int) = Store r2_0, r2_3 | test.c:24:5:24:11 | ... ++ | positive strictlyPositive |
+| test.c:24:5:24:11 | r2_1(int) = Load r2_0, m1_0 | test.c:24:5:24:11 | ... ++ | positive |
+| test.c:24:5:24:11 | r2_2(int) = Constant[1] | test.c:24:5:24:11 | ... ++ | positive strictlyPositive |
+| test.c:24:5:24:11 | r2_3(int) = Add r2_1, r2_2 | test.c:24:5:24:11 | ... ++ | positive strictlyPositive |
+| test.c:25:5:25:22 | m2_10(int) = Store r2_9, r2_8 | test.c:25:5:25:22 | ... = ... | positive |
+| test.c:25:13:25:17 | r2_6(int) = Load r2_5, m2_4 | test.c:25:13:25:17 | count | positive strictlyPositive |
+| test.c:25:13:25:22 | r2_8(int) = Rem r2_6, r2_7 | test.c:25:13:25:22 | ... % ... | positive |
+| test.c:25:21:25:22 | r2_7(int) = Constant[10] | test.c:25:21:25:22 | 10 | positive strictlyPositive |
+| test.c:27:10:27:14 | m3_3(int) = Store r3_0, r3_2 | test.c:27:10:27:14 | count | positive |
+| test.c:27:10:27:14 | r3_2(int) = Load r3_1, m1_0 | test.c:27:10:27:14 | count | positive |
+| test.c:33:15:33:15 | m1_0(int) = Phi from 0:m0_10, from 2:m2_11 | test.c:33:15:33:15 | i | positive |
+| test.c:33:15:33:15 | m1_1(int) = Phi from 0:m0_7, from 2:m2_5 | test.c:33:15:33:15 | i | positive |
+| test.c:33:15:33:15 | r1_3(int) = Load r1_2, m1_0 | test.c:33:15:33:15 | i | positive |
+| test.c:33:19:33:19 | r1_4(int) = Constant[2] | test.c:33:19:33:19 | 2 | positive strictlyPositive |
+| test.c:33:22:33:28 | m2_11(int) = Store r2_10, r2_9 | test.c:33:22:33:28 | ... = ... | positive strictlyPositive |
+| test.c:33:26:33:26 | r2_7(int) = Load r2_6, m1_0 | test.c:33:26:33:26 | i | positive |
+| test.c:33:26:33:28 | r2_9(int) = Add r2_7, r2_8 | test.c:33:26:33:28 | ... + ... | positive strictlyPositive |
+| test.c:33:28:33:28 | r2_8(int) = Constant[1] | test.c:33:28:33:28 | 1 | positive strictlyPositive |
+| test.c:34:5:34:14 | m2_5(int) = Store r2_2, r2_4 | test.c:34:5:34:14 | ... += ... | positive |
+| test.c:34:5:34:14 | r2_3(int) = Load r2_2, m1_1 | test.c:34:5:34:14 | ... += ... | positive |
+| test.c:34:5:34:14 | r2_4(int) = Add r2_3, r2_1 | test.c:34:5:34:14 | ... += ... | positive |
+| test.c:34:14:34:14 | r2_1(int) = Load r2_0, m1_0 | test.c:34:14:34:14 | i | positive |
+| test.c:36:10:36:14 | r3_2(int) = Load r3_1, m1_1 | test.c:36:10:36:14 | total | positive |
+| test.c:36:10:36:18 | m3_6(int) = Store r3_0, r3_5 | test.c:36:10:36:18 | ... + ... | positive |
+| test.c:36:10:36:18 | r3_5(int) = Add r3_2, r3_4 | test.c:36:10:36:18 | ... + ... | positive |
+| test.c:36:18:36:18 | r3_4(int) = Load r3_3, m1_0 | test.c:36:18:36:18 | i | positive |
+| test.c:42:15:42:15 | m1_0(int) = Phi from 0:m0_10, from 2:m2_10 | test.c:42:15:42:15 | i | positive |
+| test.c:42:15:42:15 | m1_1(int) = Phi from 0:m0_7, from 2:m2_5 | test.c:42:15:42:15 | i | positive |
+| test.c:42:15:42:15 | r1_3(int) = Load r1_2, m1_0 | test.c:42:15:42:15 | i | positive |
+| test.c:42:19:42:19 | r1_4(int) = Constant[2] | test.c:42:19:42:19 | 2 | positive strictlyPositive |
+| test.c:42:22:42:24 | m2_10(int) = Store r2_6, r2_9 | test.c:42:22:42:24 | ... ++ | positive strictlyPositive |
+| test.c:42:22:42:24 | r2_7(int) = Load r2_6, m1_0 | test.c:42:22:42:24 | ... ++ | positive |
+| test.c:42:22:42:24 | r2_8(int) = Constant[1] | test.c:42:22:42:24 | ... ++ | positive strictlyPositive |
+| test.c:42:22:42:24 | r2_9(int) = Add r2_7, r2_8 | test.c:42:22:42:24 | ... ++ | positive strictlyPositive |
+| test.c:43:5:43:14 | m2_5(int) = Store r2_2, r2_4 | test.c:43:5:43:14 | ... += ... | positive |
+| test.c:43:5:43:14 | r2_3(int) = Load r2_2, m1_1 | test.c:43:5:43:14 | ... += ... | positive |
+| test.c:43:5:43:14 | r2_4(int) = Add r2_3, r2_1 | test.c:43:5:43:14 | ... += ... | positive |
+| test.c:43:14:43:14 | r2_1(int) = Load r2_0, m1_0 | test.c:43:14:43:14 | i | positive |
+| test.c:45:10:45:14 | r3_2(int) = Load r3_1, m1_1 | test.c:45:10:45:14 | total | positive |
+| test.c:45:10:45:18 | m3_6(int) = Store r3_0, r3_5 | test.c:45:10:45:18 | ... + ... | positive |
+| test.c:45:10:45:18 | r3_5(int) = Add r3_2, r3_4 | test.c:45:10:45:18 | ... + ... | positive |
+| test.c:45:18:45:18 | r3_4(int) = Load r3_3, m1_0 | test.c:45:18:45:18 | i | positive |
+| test.c:51:15:51:15 | m1_0(int) = Phi from 0:m0_10, from 2:m2_11 | test.c:51:15:51:15 | i | positive |
+| test.c:51:15:51:15 | m1_1(int) = Phi from 0:m0_7, from 2:m2_5 | test.c:51:15:51:15 | i | positive |
+| test.c:51:15:51:15 | r1_3(int) = Load r1_2, m1_0 | test.c:51:15:51:15 | i | positive |
+| test.c:51:15:51:17 | r1_5(int) = Add r1_3, r1_4 | test.c:51:15:51:17 | ... + ... | positive strictlyPositive |
+| test.c:51:17:51:17 | r1_4(int) = Constant[2] | test.c:51:17:51:17 | 2 | positive strictlyPositive |
+| test.c:51:21:51:21 | r1_6(int) = Constant[4] | test.c:51:21:51:21 | 4 | positive strictlyPositive |
+| test.c:51:24:51:30 | m2_11(int) = Store r2_10, r2_9 | test.c:51:24:51:30 | ... = ... | positive strictlyPositive |
+| test.c:51:28:51:28 | r2_7(int) = Load r2_6, m1_0 | test.c:51:28:51:28 | i | positive |
+| test.c:51:28:51:30 | r2_9(int) = Add r2_7, r2_8 | test.c:51:28:51:30 | ... + ... | positive strictlyPositive |
+| test.c:51:30:51:30 | r2_8(int) = Constant[1] | test.c:51:30:51:30 | 1 | positive strictlyPositive |
+| test.c:52:5:52:14 | m2_5(int) = Store r2_2, r2_4 | test.c:52:5:52:14 | ... += ... | positive |
+| test.c:52:5:52:14 | r2_3(int) = Load r2_2, m1_1 | test.c:52:5:52:14 | ... += ... | positive |
+| test.c:52:5:52:14 | r2_4(int) = Add r2_3, r2_1 | test.c:52:5:52:14 | ... += ... | positive |
+| test.c:52:14:52:14 | r2_1(int) = Load r2_0, m1_0 | test.c:52:14:52:14 | i | positive |
+| test.c:54:10:54:14 | r3_2(int) = Load r3_1, m1_1 | test.c:54:10:54:14 | total | positive |
+| test.c:54:10:54:18 | m3_6(int) = Store r3_0, r3_5 | test.c:54:10:54:18 | ... + ... | positive |
+| test.c:54:10:54:18 | r3_5(int) = Add r3_2, r3_4 | test.c:54:10:54:18 | ... + ... | positive |
+| test.c:54:18:54:18 | r3_4(int) = Load r3_3, m1_0 | test.c:54:18:54:18 | i | positive |
+| test.c:58:11:58:11 | r0_6(int) = Constant[4] | test.c:58:11:58:11 | 4 | positive strictlyPositive |
+| test.c:59:13:59:13 | r2_2(int) = Constant[5] | test.c:59:13:59:13 | 5 | positive strictlyPositive |
+| test.c:63:10:63:10 | m4_2(int) = Store r4_0, r4_1 | test.c:63:10:63:10 | 1 | positive strictlyPositive |
+| test.c:63:10:63:10 | r4_1(int) = Constant[1] | test.c:63:10:63:10 | 1 | positive strictlyPositive |
+| test.c:67:7:67:11 | r0_6(int) = Constant[-1000] | test.c:67:7:67:11 | - ... | negative strictlyNegative |
+| test.c:67:24:67:25 | r2_2(int) = Constant[10] | test.c:67:24:67:25 | 10 | positive strictlyPositive |
+| test.c:68:15:68:15 | r3_4(int) = Constant[2] | test.c:68:15:68:15 | 2 | positive strictlyPositive |
+| test.c:77:13:77:13 | r2_2(int) = Constant[4] | test.c:77:13:77:13 | 4 | positive strictlyPositive |
+| test.c:81:13:81:13 | r4_2(int) = Constant[4] | test.c:81:13:81:13 | 4 | positive strictlyPositive |
+| test.c:82:14:82:14 | m5_2(int) = Store r5_0, r5_1 | test.c:82:14:82:14 | 1 | positive strictlyPositive |
+| test.c:82:14:82:14 | r5_1(int) = Constant[1] | test.c:82:14:82:14 | 1 | positive strictlyPositive |
+| test.c:88:5:88:10 | m1_0(int) = Phi from 3:m3_2, from 4:m4_3, from 5:m5_2 | test.c:88:5:88:10 | test10 | positive |
+| test.c:89:11:89:11 | r0_8(int) = Constant[7] | test.c:89:11:89:11 | 7 | positive strictlyPositive |
+| test.c:90:13:90:13 | r2_3(int) = Load r2_2, m0_5 | test.c:90:13:90:13 | y | positive strictlyPositive |
+| test.c:93:12:93:12 | m4_3(int) = Store r4_0, r4_2 | test.c:93:12:93:12 | x | positive strictlyPositive |
+| test.c:93:12:93:12 | r4_2(int) = Load r4_1, m0_3 | test.c:93:12:93:12 | x | positive strictlyPositive |
+| test.c:95:10:95:10 | m5_2(int) = Store r5_0, r5_1 | test.c:95:10:95:10 | 1 | positive strictlyPositive |
+| test.c:95:10:95:10 | r5_1(int) = Constant[1] | test.c:95:10:95:10 | 1 | positive strictlyPositive |
+| test.c:98:5:98:10 | m1_0(int) = Phi from 7:m7_2, from 8:m8_2 | test.c:98:5:98:10 | test11 | positive |
+| test.c:102:6:102:8 | r2_3(int) = Constant[1] | test.c:102:6:102:8 | ... ++ | positive strictlyPositive |
+| test.c:104:12:104:14 | r3_4(int) = Constant[58] | test.c:104:12:104:14 | 58 | positive strictlyPositive |
+| test.c:107:8:107:10 | r5_3(int) = Constant[1] | test.c:107:8:107:10 | ... ++ | positive strictlyPositive |
+| test.c:109:14:109:16 | r6_3(int) = Constant[44] | test.c:109:14:109:16 | 44 | positive strictlyPositive |
+| test.c:110:14:110:14 | m7_2(int) = Store r7_0, r7_1 | test.c:110:14:110:14 | 1 | positive strictlyPositive |
+| test.c:110:14:110:14 | r7_1(int) = Constant[1] | test.c:110:14:110:14 | 1 | positive strictlyPositive |
+| test.c:119:10:119:12 | m0_10(unsigned long long) = Store r0_6, r0_9 | test.c:119:10:119:12 | ... ++ | positive strictlyPositive |
+| test.c:119:10:119:12 | r0_8(unsigned long long) = Constant[1] | test.c:119:10:119:12 | ... ++ | positive strictlyPositive |
+| test.c:119:10:119:12 | r0_9(unsigned long long) = Add r0_7, r0_8 | test.c:119:10:119:12 | ... ++ | positive strictlyPositive |
+| test.c:124:36:124:36 | r1_5(unsigned long long) = Constant[1] | test.c:124:36:124:36 | (unsigned long long)... | positive strictlyPositive |
+| test.c:127:24:127:24 | r2_6(unsigned long long) = Constant[1] | test.c:127:24:127:24 | (unsigned long long)... | positive strictlyPositive |
+| test.c:130:11:130:11 | m3_2(int) = Store r3_0, r3_1 | test.c:130:11:130:11 | 1 | positive strictlyPositive |
+| test.c:130:11:130:11 | r3_1(int) = Constant[1] | test.c:130:11:130:11 | 1 | positive strictlyPositive |
+| test.c:137:20:137:22 | m0_19(unsigned int) = Store r0_14, r0_18 | test.c:137:20:137:22 | ... - ... | negative strictlyNegative |
+| test.c:137:20:137:22 | r0_18(unsigned int) = Sub r0_16, r0_17 | test.c:137:20:137:22 | ... - ... | negative strictlyNegative |
+| test.c:137:22:137:22 | r0_17(unsigned int) = Constant[1] | test.c:137:22:137:22 | (unsigned int)... | positive strictlyPositive |
+| test.c:138:13:138:13 | r0_23(int) = Constant[1] | test.c:138:13:138:13 | 1 | positive strictlyPositive |
+| test.c:139:36:139:36 | r0_42(unsigned int) = Load r0_41, m0_19 | test.c:139:36:139:36 | y | negative strictlyNegative |
+| test.c:154:10:154:40 | m2_3(long long) = Store r2_2, r2_1 | test.c:154:10:154:40 | ... ? ... : ... | positive strictlyPositive |
+| test.c:154:10:154:40 | m3_2(long long) = Store r3_1, r3_0 | test.c:154:10:154:40 | ... ? ... : ... | negative strictlyNegative |
+| test.c:154:20:154:20 | r1_1(long long) = Load r1_0, m0_3 | test.c:154:20:154:20 | x | positive strictlyPositive |
+| test.c:154:30:154:30 | r1_3(long long) = Load r1_2, m0_3 | test.c:154:30:154:30 | x | positive strictlyPositive |
+| test.c:154:35:154:35 | r2_1(long long) = Load r2_0, m0_3 | test.c:154:35:154:35 | x | positive strictlyPositive |
+| test.c:154:39:154:40 | r3_0(long long) = Constant[-1] | test.c:154:39:154:40 | (long long)... | negative strictlyNegative |
+| test.c:161:7:161:7 | r0_7(int) = Constant[3] | test.c:161:7:161:7 | 3 | positive strictlyPositive |
+| test.c:161:17:161:17 | r8_1(int) = Load r8_0, m0_3 | test.c:161:17:161:17 | a | positive strictlyPositive |
+| test.c:161:22:161:23 | r8_2(int) = Constant[11] | test.c:161:22:161:23 | 11 | positive strictlyPositive |
+| test.c:162:13:162:14 | m12_4(int) = Store r12_0, r12_3 | test.c:162:13:162:14 | + ... | positive strictlyPositive |
+| test.c:162:13:162:14 | r12_3(int) = CopyValue r12_2 | test.c:162:13:162:14 | + ... | positive strictlyPositive |
+| test.c:162:14:162:14 | r12_2(int) = Load r12_1, m0_3 | test.c:162:14:162:14 | a | positive strictlyPositive |
+| test.c:163:13:163:14 | m12_9(int) = Store r12_5, r12_8 | test.c:163:13:163:14 | - ... | negative strictlyNegative |
+| test.c:163:13:163:14 | r12_8(int) = Negate r12_7 | test.c:163:13:163:14 | - ... | negative strictlyNegative |
+| test.c:163:14:163:14 | r12_7(int) = Load r12_6, m0_3 | test.c:163:14:163:14 | a | positive strictlyPositive |
+| test.c:164:14:164:14 | r12_11(int) = Load r12_10, m12_4 | test.c:164:14:164:14 | b | positive strictlyPositive |
+| test.c:164:16:164:16 | r12_13(int) = Load r12_12, m12_9 | test.c:164:16:164:16 | c | negative strictlyNegative |
+| test.c:166:17:166:17 | r14_1(int) = Load r14_0, m0_3 | test.c:166:17:166:17 | a | positive |
+| test.c:166:22:166:23 | r14_2(int) = Constant[11] | test.c:166:22:166:23 | 11 | positive strictlyPositive |
+| test.c:167:13:167:14 | m15_4(int) = Store r15_0, r15_3 | test.c:167:13:167:14 | + ... | positive |
+| test.c:167:13:167:14 | r15_3(int) = CopyValue r15_2 | test.c:167:13:167:14 | + ... | positive |
+| test.c:167:14:167:14 | r15_2(int) = Load r15_1, m0_3 | test.c:167:14:167:14 | a | positive |
+| test.c:168:13:168:14 | m15_9(int) = Store r15_5, r15_8 | test.c:168:13:168:14 | - ... | negative |
+| test.c:168:13:168:14 | r15_8(int) = Negate r15_7 | test.c:168:13:168:14 | - ... | negative |
+| test.c:168:14:168:14 | r15_7(int) = Load r15_6, m0_3 | test.c:168:14:168:14 | a | positive |
+| test.c:169:14:169:14 | r15_11(int) = Load r15_10, m15_4 | test.c:169:14:169:14 | b | positive |
+| test.c:169:16:169:16 | r15_13(int) = Load r15_12, m15_9 | test.c:169:16:169:16 | c | negative |
+| test.c:171:7:171:8 | r16_1(int) = Constant[-7] | test.c:171:7:171:8 | - ... | negative strictlyNegative |
+| test.c:171:23:171:24 | r17_2(int) = Constant[11] | test.c:171:23:171:24 | 11 | positive strictlyPositive |
+| test.c:176:7:176:8 | r1_1(int) = Constant[-7] | test.c:176:7:176:8 | - ... | negative strictlyNegative |
+| test.c:176:23:176:23 | r2_2(int) = Constant[1] | test.c:176:23:176:23 | 1 | positive strictlyPositive |
+| test.c:181:7:181:8 | r4_1(int) = Constant[-7] | test.c:181:7:181:8 | - ... | negative strictlyNegative |
+| test.c:182:13:182:14 | m6_4(int) = Store r6_0, r6_3 | test.c:182:13:182:14 | + ... | negative |
+| test.c:182:13:182:14 | r6_3(int) = CopyValue r6_2 | test.c:182:13:182:14 | + ... | negative |
+| test.c:182:14:182:14 | r6_2(int) = Load r6_1, m0_3 | test.c:182:14:182:14 | a | negative |
+| test.c:183:13:183:14 | m6_9(int) = Store r6_5, r6_8 | test.c:183:13:183:14 | - ... | positive |
+| test.c:183:13:183:14 | r6_8(int) = Negate r6_7 | test.c:183:13:183:14 | - ... | positive |
+| test.c:183:14:183:14 | r6_7(int) = Load r6_6, m0_3 | test.c:183:14:183:14 | a | negative |
+| test.c:184:14:184:14 | r6_11(int) = Load r6_10, m6_4 | test.c:184:14:184:14 | b | negative |
+| test.c:184:16:184:16 | r6_13(int) = Load r6_12, m6_9 | test.c:184:16:184:16 | c | positive |
+| test.c:186:7:186:8 | r7_1(int) = Constant[-7] | test.c:186:7:186:8 | - ... | negative strictlyNegative |
+| test.c:186:23:186:24 | r9_2(int) = Constant[-2] | test.c:186:23:186:24 | - ... | negative strictlyNegative |
+| test.c:187:13:187:14 | m10_4(int) = Store r10_0, r10_3 | test.c:187:13:187:14 | + ... | negative strictlyNegative |
+| test.c:187:13:187:14 | r10_3(int) = CopyValue r10_2 | test.c:187:13:187:14 | + ... | negative strictlyNegative |
+| test.c:187:14:187:14 | r10_2(int) = Load r10_1, m0_3 | test.c:187:14:187:14 | a | negative strictlyNegative |
+| test.c:188:13:188:14 | m10_9(int) = Store r10_5, r10_8 | test.c:188:13:188:14 | - ... | positive strictlyPositive |
+| test.c:188:13:188:14 | r10_8(int) = Negate r10_7 | test.c:188:13:188:14 | - ... | positive strictlyPositive |
+| test.c:188:14:188:14 | r10_7(int) = Load r10_6, m0_3 | test.c:188:14:188:14 | a | negative strictlyNegative |
+| test.c:189:14:189:14 | r10_11(int) = Load r10_10, m10_4 | test.c:189:14:189:14 | b | negative strictlyNegative |
+| test.c:189:16:189:16 | r10_13(int) = Load r10_12, m10_9 | test.c:189:16:189:16 | c | positive strictlyPositive |
+| test.c:200:7:200:7 | r0_9(int) = Constant[3] | test.c:200:7:200:7 | 3 | positive strictlyPositive |
+| test.c:200:17:200:17 | r14_1(int) = Load r14_0, m0_3 | test.c:200:17:200:17 | a | positive strictlyPositive |
+| test.c:200:22:200:23 | r14_2(int) = Constant[11] | test.c:200:22:200:23 | 11 | positive strictlyPositive |
+| test.c:200:28:200:28 | r15_0(int) = Constant[5] | test.c:200:28:200:28 | 5 | positive strictlyPositive |
+| test.c:200:38:200:38 | r16_1(int) = Load r16_0, m0_5 | test.c:200:38:200:38 | b | positive strictlyPositive |
+| test.c:200:43:200:44 | r16_2(int) = Constant[23] | test.c:200:43:200:44 | 23 | positive strictlyPositive |
+| test.c:201:13:201:13 | r17_2(int) = Load r17_1, m0_3 | test.c:201:13:201:13 | a | positive strictlyPositive |
+| test.c:201:13:201:15 | m17_6(int) = Store r17_0, r17_5 | test.c:201:13:201:15 | ... * ... | positive strictlyPositive |
+| test.c:201:13:201:15 | r17_5(int) = Mul r17_2, r17_4 | test.c:201:13:201:15 | ... * ... | positive strictlyPositive |
+| test.c:201:15:201:15 | r17_4(int) = Load r17_3, m0_5 | test.c:201:15:201:15 | b | positive strictlyPositive |
+| test.c:202:5:202:14 | m17_12(int) = Store r17_9, r17_11 | test.c:202:5:202:14 | ... += ... | positive strictlyPositive |
+| test.c:202:5:202:14 | r17_11(int) = Add r17_10, r17_8 | test.c:202:5:202:14 | ... += ... | positive strictlyPositive |
+| test.c:202:14:202:14 | r17_8(int) = Load r17_7, m17_6 | test.c:202:14:202:14 | r | positive strictlyPositive |
+| test.c:204:7:204:7 | m18_0(int) = Phi from 0:m0_8, from 14:m0_8, from 15:m0_8, from 16:m0_8, from 17:m17_12 | test.c:204:7:204:7 | 3 | positive |
+| test.c:204:7:204:7 | r18_1(int) = Constant[3] | test.c:204:7:204:7 | 3 | positive strictlyPositive |
+| test.c:204:17:204:17 | r19_1(int) = Load r19_0, m0_3 | test.c:204:17:204:17 | a | positive strictlyPositive |
+| test.c:204:22:204:23 | r19_2(int) = Constant[11] | test.c:204:22:204:23 | 11 | positive strictlyPositive |
+| test.c:204:38:204:38 | r21_1(int) = Load r21_0, m0_5 | test.c:204:38:204:38 | b | positive |
+| test.c:204:43:204:44 | r21_2(int) = Constant[23] | test.c:204:43:204:44 | 23 | positive strictlyPositive |
+| test.c:205:13:205:13 | r22_2(int) = Load r22_1, m0_3 | test.c:205:13:205:13 | a | positive strictlyPositive |
+| test.c:205:13:205:15 | m22_6(int) = Store r22_0, r22_5 | test.c:205:13:205:15 | ... * ... | positive |
+| test.c:205:13:205:15 | r22_5(int) = Mul r22_2, r22_4 | test.c:205:13:205:15 | ... * ... | positive |
+| test.c:205:15:205:15 | r22_4(int) = Load r22_3, m0_5 | test.c:205:15:205:15 | b | positive |
+| test.c:206:5:206:14 | m22_12(int) = Store r22_9, r22_11 | test.c:206:5:206:14 | ... += ... | positive |
+| test.c:206:5:206:14 | r22_10(int) = Load r22_9, m18_0 | test.c:206:5:206:14 | ... += ... | positive |
+| test.c:206:5:206:14 | r22_11(int) = Add r22_10, r22_8 | test.c:206:5:206:14 | ... += ... | positive |
+| test.c:206:14:206:14 | r22_8(int) = Load r22_7, m22_6 | test.c:206:14:206:14 | r | positive |
+| test.c:208:7:208:7 | m23_0(int) = Phi from 18:m18_0, from 19:m18_0, from 20:m18_0, from 21:m18_0, from 22:m22_12 | test.c:208:7:208:7 | 3 | positive |
+| test.c:208:7:208:7 | r23_1(int) = Constant[3] | test.c:208:7:208:7 | 3 | positive strictlyPositive |
+| test.c:208:17:208:17 | r24_1(int) = Load r24_0, m0_3 | test.c:208:17:208:17 | a | positive strictlyPositive |
+| test.c:208:22:208:23 | r24_2(int) = Constant[11] | test.c:208:22:208:23 | 11 | positive strictlyPositive |
+| test.c:208:28:208:30 | r25_0(int) = Constant[-13] | test.c:208:28:208:30 | - ... | negative strictlyNegative |
+| test.c:208:45:208:46 | r1_2(int) = Constant[23] | test.c:208:45:208:46 | 23 | positive strictlyPositive |
+| test.c:209:13:209:13 | r2_2(int) = Load r2_1, m0_3 | test.c:209:13:209:13 | a | positive strictlyPositive |
+| test.c:210:5:210:14 | r2_10(int) = Load r2_9, m23_0 | test.c:210:5:210:14 | ... += ... | positive |
+| test.c:212:7:212:7 | r3_1(int) = Constant[3] | test.c:212:7:212:7 | 3 | positive strictlyPositive |
+| test.c:212:17:212:17 | r4_1(int) = Load r4_0, m0_3 | test.c:212:17:212:17 | a | positive strictlyPositive |
+| test.c:212:22:212:23 | r4_2(int) = Constant[11] | test.c:212:22:212:23 | 11 | positive strictlyPositive |
+| test.c:212:28:212:30 | r5_0(int) = Constant[-13] | test.c:212:28:212:30 | - ... | negative strictlyNegative |
+| test.c:213:13:213:13 | r7_2(int) = Load r7_1, m0_3 | test.c:213:13:213:13 | a | positive strictlyPositive |
+| test.c:213:13:213:15 | m7_6(int) = Store r7_0, r7_5 | test.c:213:13:213:15 | ... * ... | negative |
+| test.c:213:13:213:15 | r7_5(int) = Mul r7_2, r7_4 | test.c:213:13:213:15 | ... * ... | negative |
+| test.c:213:15:213:15 | r7_4(int) = Load r7_3, m0_5 | test.c:213:15:213:15 | b | negative |
+| test.c:214:14:214:14 | r7_8(int) = Load r7_7, m7_6 | test.c:214:14:214:14 | r | negative |
+| test.c:216:7:216:7 | r8_1(int) = Constant[3] | test.c:216:7:216:7 | 3 | positive strictlyPositive |
+| test.c:216:17:216:17 | r9_1(int) = Load r9_0, m0_3 | test.c:216:17:216:17 | a | positive strictlyPositive |
+| test.c:216:22:216:23 | r9_2(int) = Constant[11] | test.c:216:22:216:23 | 11 | positive strictlyPositive |
+| test.c:216:28:216:30 | r10_0(int) = Constant[-13] | test.c:216:28:216:30 | - ... | negative strictlyNegative |
+| test.c:216:45:216:46 | r11_2(int) = Constant[-7] | test.c:216:45:216:46 | - ... | negative strictlyNegative |
+| test.c:217:13:217:13 | r12_2(int) = Load r12_1, m0_3 | test.c:217:13:217:13 | a | positive strictlyPositive |
+| test.c:217:13:217:15 | m12_6(int) = Store r12_0, r12_5 | test.c:217:13:217:15 | ... * ... | negative strictlyNegative |
+| test.c:217:13:217:15 | r12_5(int) = Mul r12_2, r12_4 | test.c:217:13:217:15 | ... * ... | negative strictlyNegative |
+| test.c:217:15:217:15 | r12_4(int) = Load r12_3, m0_5 | test.c:217:15:217:15 | b | negative strictlyNegative |
+| test.c:218:14:218:14 | r12_8(int) = Load r12_7, m12_6 | test.c:218:14:218:14 | r | negative strictlyNegative |
+| test.c:228:17:228:17 | r14_1(int) = Load r14_0, m0_3 | test.c:228:17:228:17 | a | positive |
+| test.c:228:22:228:23 | r14_2(int) = Constant[11] | test.c:228:22:228:23 | 11 | positive strictlyPositive |
+| test.c:228:28:228:28 | r15_0(int) = Constant[5] | test.c:228:28:228:28 | 5 | positive strictlyPositive |
+| test.c:228:38:228:38 | r16_1(int) = Load r16_0, m0_5 | test.c:228:38:228:38 | b | positive strictlyPositive |
+| test.c:228:43:228:44 | r16_2(int) = Constant[23] | test.c:228:43:228:44 | 23 | positive strictlyPositive |
+| test.c:229:13:229:13 | r17_2(int) = Load r17_1, m0_3 | test.c:229:13:229:13 | a | positive |
+| test.c:229:13:229:15 | m17_6(int) = Store r17_0, r17_5 | test.c:229:13:229:15 | ... * ... | positive |
+| test.c:229:13:229:15 | r17_5(int) = Mul r17_2, r17_4 | test.c:229:13:229:15 | ... * ... | positive |
+| test.c:229:15:229:15 | r17_4(int) = Load r17_3, m0_5 | test.c:229:15:229:15 | b | positive strictlyPositive |
+| test.c:230:5:230:14 | m17_12(int) = Store r17_9, r17_11 | test.c:230:5:230:14 | ... += ... | positive |
+| test.c:230:5:230:14 | r17_11(int) = Add r17_10, r17_8 | test.c:230:5:230:14 | ... += ... | positive |
+| test.c:230:14:230:14 | r17_8(int) = Load r17_7, m17_6 | test.c:230:14:230:14 | r | positive |
+| test.c:232:7:232:7 | m18_0(int) = Phi from 0:m0_8, from 14:m0_8, from 15:m0_8, from 16:m0_8, from 17:m17_12 | test.c:232:7:232:7 | 0 | positive |
+| test.c:232:17:232:17 | r19_1(int) = Load r19_0, m0_3 | test.c:232:17:232:17 | a | positive |
+| test.c:232:22:232:23 | r19_2(int) = Constant[11] | test.c:232:22:232:23 | 11 | positive strictlyPositive |
+| test.c:232:38:232:38 | r21_1(int) = Load r21_0, m0_5 | test.c:232:38:232:38 | b | positive |
+| test.c:232:43:232:44 | r21_2(int) = Constant[23] | test.c:232:43:232:44 | 23 | positive strictlyPositive |
+| test.c:233:13:233:13 | r22_2(int) = Load r22_1, m0_3 | test.c:233:13:233:13 | a | positive |
+| test.c:233:13:233:15 | m22_6(int) = Store r22_0, r22_5 | test.c:233:13:233:15 | ... * ... | positive |
+| test.c:233:13:233:15 | r22_5(int) = Mul r22_2, r22_4 | test.c:233:13:233:15 | ... * ... | positive |
+| test.c:233:15:233:15 | r22_4(int) = Load r22_3, m0_5 | test.c:233:15:233:15 | b | positive |
+| test.c:234:5:234:14 | m22_12(int) = Store r22_9, r22_11 | test.c:234:5:234:14 | ... += ... | positive |
+| test.c:234:5:234:14 | r22_10(int) = Load r22_9, m18_0 | test.c:234:5:234:14 | ... += ... | positive |
+| test.c:234:5:234:14 | r22_11(int) = Add r22_10, r22_8 | test.c:234:5:234:14 | ... += ... | positive |
+| test.c:234:14:234:14 | r22_8(int) = Load r22_7, m22_6 | test.c:234:14:234:14 | r | positive |
+| test.c:236:7:236:7 | m23_0(int) = Phi from 18:m18_0, from 19:m18_0, from 20:m18_0, from 21:m18_0, from 22:m22_12 | test.c:236:7:236:7 | 0 | positive |
+| test.c:236:17:236:17 | r24_1(int) = Load r24_0, m0_3 | test.c:236:17:236:17 | a | positive |
+| test.c:236:22:236:23 | r24_2(int) = Constant[11] | test.c:236:22:236:23 | 11 | positive strictlyPositive |
+| test.c:236:28:236:30 | r25_0(int) = Constant[-13] | test.c:236:28:236:30 | - ... | negative strictlyNegative |
+| test.c:236:45:236:46 | r1_2(int) = Constant[23] | test.c:236:45:236:46 | 23 | positive strictlyPositive |
+| test.c:237:13:237:13 | r2_2(int) = Load r2_1, m0_3 | test.c:237:13:237:13 | a | positive |
+| test.c:238:5:238:14 | r2_10(int) = Load r2_9, m23_0 | test.c:238:5:238:14 | ... += ... | positive |
+| test.c:240:17:240:17 | r4_1(int) = Load r4_0, m0_3 | test.c:240:17:240:17 | a | positive |
+| test.c:240:22:240:23 | r4_2(int) = Constant[11] | test.c:240:22:240:23 | 11 | positive strictlyPositive |
+| test.c:240:28:240:30 | r5_0(int) = Constant[-13] | test.c:240:28:240:30 | - ... | negative strictlyNegative |
+| test.c:241:13:241:13 | r7_2(int) = Load r7_1, m0_3 | test.c:241:13:241:13 | a | positive |
+| test.c:241:13:241:15 | m7_6(int) = Store r7_0, r7_5 | test.c:241:13:241:15 | ... * ... | negative |
+| test.c:241:13:241:15 | r7_5(int) = Mul r7_2, r7_4 | test.c:241:13:241:15 | ... * ... | negative |
+| test.c:241:15:241:15 | r7_4(int) = Load r7_3, m0_5 | test.c:241:15:241:15 | b | negative |
+| test.c:242:14:242:14 | r7_8(int) = Load r7_7, m7_6 | test.c:242:14:242:14 | r | negative |
+| test.c:244:17:244:17 | r9_1(int) = Load r9_0, m0_3 | test.c:244:17:244:17 | a | positive |
+| test.c:244:22:244:23 | r9_2(int) = Constant[11] | test.c:244:22:244:23 | 11 | positive strictlyPositive |
+| test.c:244:28:244:30 | r10_0(int) = Constant[-13] | test.c:244:28:244:30 | - ... | negative strictlyNegative |
+| test.c:244:45:244:46 | r11_2(int) = Constant[-7] | test.c:244:45:244:46 | - ... | negative strictlyNegative |
+| test.c:245:13:245:13 | r12_2(int) = Load r12_1, m0_3 | test.c:245:13:245:13 | a | positive |
+| test.c:245:13:245:15 | m12_6(int) = Store r12_0, r12_5 | test.c:245:13:245:15 | ... * ... | negative |
+| test.c:245:13:245:15 | r12_5(int) = Mul r12_2, r12_4 | test.c:245:13:245:15 | ... * ... | negative |
+| test.c:245:15:245:15 | r12_4(int) = Load r12_3, m0_5 | test.c:245:15:245:15 | b | negative strictlyNegative |
+| test.c:246:14:246:14 | r12_8(int) = Load r12_7, m12_6 | test.c:246:14:246:14 | r | negative |
+| test.c:256:7:256:9 | r0_9(int) = Constant[-17] | test.c:256:7:256:9 | - ... | negative strictlyNegative |
+| test.c:256:24:256:25 | r14_2(int) = Constant[11] | test.c:256:24:256:25 | 11 | positive strictlyPositive |
+| test.c:256:30:256:30 | r15_0(int) = Constant[5] | test.c:256:30:256:30 | 5 | positive strictlyPositive |
+| test.c:256:40:256:40 | r16_1(int) = Load r16_0, m0_5 | test.c:256:40:256:40 | b | positive strictlyPositive |
+| test.c:256:45:256:46 | r16_2(int) = Constant[23] | test.c:256:45:256:46 | 23 | positive strictlyPositive |
+| test.c:257:15:257:15 | r17_4(int) = Load r17_3, m0_5 | test.c:257:15:257:15 | b | positive strictlyPositive |
+| test.c:260:7:260:9 | r18_1(int) = Constant[-17] | test.c:260:7:260:9 | - ... | negative strictlyNegative |
+| test.c:260:24:260:25 | r19_2(int) = Constant[11] | test.c:260:24:260:25 | 11 | positive strictlyPositive |
+| test.c:260:40:260:40 | r21_1(int) = Load r21_0, m0_5 | test.c:260:40:260:40 | b | positive |
+| test.c:260:45:260:46 | r21_2(int) = Constant[23] | test.c:260:45:260:46 | 23 | positive strictlyPositive |
+| test.c:261:15:261:15 | r22_4(int) = Load r22_3, m0_5 | test.c:261:15:261:15 | b | positive |
+| test.c:264:7:264:9 | r23_1(int) = Constant[-17] | test.c:264:7:264:9 | - ... | negative strictlyNegative |
+| test.c:264:24:264:25 | r24_2(int) = Constant[11] | test.c:264:24:264:25 | 11 | positive strictlyPositive |
+| test.c:264:30:264:32 | r25_0(int) = Constant[-13] | test.c:264:30:264:32 | - ... | negative strictlyNegative |
+| test.c:264:47:264:48 | r1_2(int) = Constant[23] | test.c:264:47:264:48 | 23 | positive strictlyPositive |
+| test.c:268:7:268:9 | r3_1(int) = Constant[-17] | test.c:268:7:268:9 | - ... | negative strictlyNegative |
+| test.c:268:24:268:25 | r4_2(int) = Constant[11] | test.c:268:24:268:25 | 11 | positive strictlyPositive |
+| test.c:268:30:268:32 | r5_0(int) = Constant[-13] | test.c:268:30:268:32 | - ... | negative strictlyNegative |
+| test.c:269:15:269:15 | r7_4(int) = Load r7_3, m0_5 | test.c:269:15:269:15 | b | negative |
+| test.c:272:7:272:9 | r8_1(int) = Constant[-17] | test.c:272:7:272:9 | - ... | negative strictlyNegative |
+| test.c:272:24:272:25 | r9_2(int) = Constant[11] | test.c:272:24:272:25 | 11 | positive strictlyPositive |
+| test.c:272:30:272:32 | r10_0(int) = Constant[-13] | test.c:272:30:272:32 | - ... | negative strictlyNegative |
+| test.c:272:47:272:48 | r11_2(int) = Constant[-7] | test.c:272:47:272:48 | - ... | negative strictlyNegative |
+| test.c:273:15:273:15 | r12_4(int) = Load r12_3, m0_5 | test.c:273:15:273:15 | b | negative strictlyNegative |
+| test.c:284:7:284:9 | r0_9(int) = Constant[-17] | test.c:284:7:284:9 | - ... | negative strictlyNegative |
+| test.c:284:29:284:29 | r15_0(int) = Constant[5] | test.c:284:29:284:29 | 5 | positive strictlyPositive |
+| test.c:284:39:284:39 | r16_1(int) = Load r16_0, m0_5 | test.c:284:39:284:39 | b | positive strictlyPositive |
+| test.c:284:44:284:45 | r16_2(int) = Constant[23] | test.c:284:44:284:45 | 23 | positive strictlyPositive |
+| test.c:285:13:285:13 | r17_2(int) = Load r17_1, m0_3 | test.c:285:13:285:13 | a | negative |
+| test.c:285:13:285:15 | m17_6(int) = Store r17_0, r17_5 | test.c:285:13:285:15 | ... * ... | negative |
+| test.c:285:13:285:15 | r17_5(int) = Mul r17_2, r17_4 | test.c:285:13:285:15 | ... * ... | negative |
+| test.c:285:15:285:15 | r17_4(int) = Load r17_3, m0_5 | test.c:285:15:285:15 | b | positive strictlyPositive |
+| test.c:286:5:286:14 | m17_12(int) = Store r17_9, r17_11 | test.c:286:5:286:14 | ... += ... | negative |
+| test.c:286:5:286:14 | r17_11(int) = Add r17_10, r17_8 | test.c:286:5:286:14 | ... += ... | negative |
+| test.c:286:14:286:14 | r17_8(int) = Load r17_7, m17_6 | test.c:286:14:286:14 | r | negative |
+| test.c:288:7:288:9 | m18_0(int) = Phi from 0:m0_8, from 14:m0_8, from 15:m0_8, from 16:m0_8, from 17:m17_12 | test.c:288:7:288:9 | - ... | negative |
+| test.c:288:7:288:9 | r18_1(int) = Constant[-17] | test.c:288:7:288:9 | - ... | negative strictlyNegative |
+| test.c:288:39:288:39 | r21_1(int) = Load r21_0, m0_5 | test.c:288:39:288:39 | b | positive |
+| test.c:288:44:288:45 | r21_2(int) = Constant[23] | test.c:288:44:288:45 | 23 | positive strictlyPositive |
+| test.c:289:13:289:13 | r22_2(int) = Load r22_1, m0_3 | test.c:289:13:289:13 | a | negative |
+| test.c:289:13:289:15 | m22_6(int) = Store r22_0, r22_5 | test.c:289:13:289:15 | ... * ... | negative |
+| test.c:289:13:289:15 | r22_5(int) = Mul r22_2, r22_4 | test.c:289:13:289:15 | ... * ... | negative |
+| test.c:289:15:289:15 | r22_4(int) = Load r22_3, m0_5 | test.c:289:15:289:15 | b | positive |
+| test.c:290:5:290:14 | m22_12(int) = Store r22_9, r22_11 | test.c:290:5:290:14 | ... += ... | negative |
+| test.c:290:5:290:14 | r22_10(int) = Load r22_9, m18_0 | test.c:290:5:290:14 | ... += ... | negative |
+| test.c:290:5:290:14 | r22_11(int) = Add r22_10, r22_8 | test.c:290:5:290:14 | ... += ... | negative |
+| test.c:290:14:290:14 | r22_8(int) = Load r22_7, m22_6 | test.c:290:14:290:14 | r | negative |
+| test.c:292:7:292:9 | m23_0(int) = Phi from 18:m18_0, from 19:m18_0, from 20:m18_0, from 21:m18_0, from 22:m22_12 | test.c:292:7:292:9 | - ... | negative |
+| test.c:292:7:292:9 | r23_1(int) = Constant[-17] | test.c:292:7:292:9 | - ... | negative strictlyNegative |
+| test.c:292:29:292:31 | r25_0(int) = Constant[-13] | test.c:292:29:292:31 | - ... | negative strictlyNegative |
+| test.c:292:46:292:47 | r1_2(int) = Constant[23] | test.c:292:46:292:47 | 23 | positive strictlyPositive |
+| test.c:293:13:293:13 | r2_2(int) = Load r2_1, m0_3 | test.c:293:13:293:13 | a | negative |
+| test.c:294:5:294:14 | r2_10(int) = Load r2_9, m23_0 | test.c:294:5:294:14 | ... += ... | negative |
+| test.c:296:7:296:9 | r3_1(int) = Constant[-17] | test.c:296:7:296:9 | - ... | negative strictlyNegative |
+| test.c:296:29:296:31 | r5_0(int) = Constant[-13] | test.c:296:29:296:31 | - ... | negative strictlyNegative |
+| test.c:297:13:297:13 | r7_2(int) = Load r7_1, m0_3 | test.c:297:13:297:13 | a | negative |
+| test.c:297:13:297:15 | m7_6(int) = Store r7_0, r7_5 | test.c:297:13:297:15 | ... * ... | positive |
+| test.c:297:13:297:15 | r7_5(int) = Mul r7_2, r7_4 | test.c:297:13:297:15 | ... * ... | positive |
+| test.c:297:15:297:15 | r7_4(int) = Load r7_3, m0_5 | test.c:297:15:297:15 | b | negative |
+| test.c:298:14:298:14 | r7_8(int) = Load r7_7, m7_6 | test.c:298:14:298:14 | r | positive |
+| test.c:300:7:300:9 | r8_1(int) = Constant[-17] | test.c:300:7:300:9 | - ... | negative strictlyNegative |
+| test.c:300:29:300:31 | r10_0(int) = Constant[-13] | test.c:300:29:300:31 | - ... | negative strictlyNegative |
+| test.c:300:46:300:47 | r11_2(int) = Constant[-7] | test.c:300:46:300:47 | - ... | negative strictlyNegative |
+| test.c:301:13:301:13 | r12_2(int) = Load r12_1, m0_3 | test.c:301:13:301:13 | a | negative |
+| test.c:301:13:301:15 | m12_6(int) = Store r12_0, r12_5 | test.c:301:13:301:15 | ... * ... | positive |
+| test.c:301:13:301:15 | r12_5(int) = Mul r12_2, r12_4 | test.c:301:13:301:15 | ... * ... | positive |
+| test.c:301:15:301:15 | r12_4(int) = Load r12_3, m0_5 | test.c:301:15:301:15 | b | negative strictlyNegative |
+| test.c:302:14:302:14 | r12_8(int) = Load r12_7, m12_6 | test.c:302:14:302:14 | r | positive |
+| test.c:312:7:312:9 | r0_9(int) = Constant[-17] | test.c:312:7:312:9 | - ... | negative strictlyNegative |
+| test.c:312:24:312:25 | r14_2(int) = Constant[-2] | test.c:312:24:312:25 | - ... | negative strictlyNegative |
+| test.c:312:30:312:30 | r15_0(int) = Constant[5] | test.c:312:30:312:30 | 5 | positive strictlyPositive |
+| test.c:312:40:312:40 | r16_1(int) = Load r16_0, m0_5 | test.c:312:40:312:40 | b | positive strictlyPositive |
+| test.c:312:45:312:46 | r16_2(int) = Constant[23] | test.c:312:45:312:46 | 23 | positive strictlyPositive |
+| test.c:313:13:313:13 | r17_2(int) = Load r17_1, m0_3 | test.c:313:13:313:13 | a | negative strictlyNegative |
+| test.c:313:13:313:15 | m17_6(int) = Store r17_0, r17_5 | test.c:313:13:313:15 | ... * ... | negative strictlyNegative |
+| test.c:313:13:313:15 | r17_5(int) = Mul r17_2, r17_4 | test.c:313:13:313:15 | ... * ... | negative strictlyNegative |
+| test.c:313:15:313:15 | r17_4(int) = Load r17_3, m0_5 | test.c:313:15:313:15 | b | positive strictlyPositive |
+| test.c:314:5:314:14 | m17_12(int) = Store r17_9, r17_11 | test.c:314:5:314:14 | ... += ... | negative strictlyNegative |
+| test.c:314:5:314:14 | r17_11(int) = Add r17_10, r17_8 | test.c:314:5:314:14 | ... += ... | negative strictlyNegative |
+| test.c:314:14:314:14 | r17_8(int) = Load r17_7, m17_6 | test.c:314:14:314:14 | r | negative strictlyNegative |
+| test.c:316:7:316:9 | m18_0(int) = Phi from 0:m0_8, from 14:m0_8, from 15:m0_8, from 16:m0_8, from 17:m17_12 | test.c:316:7:316:9 | - ... | negative |
+| test.c:316:7:316:9 | r18_1(int) = Constant[-17] | test.c:316:7:316:9 | - ... | negative strictlyNegative |
+| test.c:316:24:316:25 | r19_2(int) = Constant[-2] | test.c:316:24:316:25 | - ... | negative strictlyNegative |
+| test.c:316:40:316:40 | r21_1(int) = Load r21_0, m0_5 | test.c:316:40:316:40 | b | positive |
+| test.c:316:45:316:46 | r21_2(int) = Constant[23] | test.c:316:45:316:46 | 23 | positive strictlyPositive |
+| test.c:317:13:317:13 | r22_2(int) = Load r22_1, m0_3 | test.c:317:13:317:13 | a | negative strictlyNegative |
+| test.c:317:13:317:15 | m22_6(int) = Store r22_0, r22_5 | test.c:317:13:317:15 | ... * ... | negative |
+| test.c:317:13:317:15 | r22_5(int) = Mul r22_2, r22_4 | test.c:317:13:317:15 | ... * ... | negative |
+| test.c:317:15:317:15 | r22_4(int) = Load r22_3, m0_5 | test.c:317:15:317:15 | b | positive |
+| test.c:318:5:318:14 | m22_12(int) = Store r22_9, r22_11 | test.c:318:5:318:14 | ... += ... | negative |
+| test.c:318:5:318:14 | r22_10(int) = Load r22_9, m18_0 | test.c:318:5:318:14 | ... += ... | negative |
+| test.c:318:5:318:14 | r22_11(int) = Add r22_10, r22_8 | test.c:318:5:318:14 | ... += ... | negative |
+| test.c:318:14:318:14 | r22_8(int) = Load r22_7, m22_6 | test.c:318:14:318:14 | r | negative |
+| test.c:320:7:320:9 | m23_0(int) = Phi from 18:m18_0, from 19:m18_0, from 20:m18_0, from 21:m18_0, from 22:m22_12 | test.c:320:7:320:9 | - ... | negative |
+| test.c:320:7:320:9 | r23_1(int) = Constant[-17] | test.c:320:7:320:9 | - ... | negative strictlyNegative |
+| test.c:320:24:320:25 | r24_2(int) = Constant[-2] | test.c:320:24:320:25 | - ... | negative strictlyNegative |
+| test.c:320:30:320:32 | r25_0(int) = Constant[-13] | test.c:320:30:320:32 | - ... | negative strictlyNegative |
+| test.c:320:47:320:48 | r1_2(int) = Constant[23] | test.c:320:47:320:48 | 23 | positive strictlyPositive |
+| test.c:321:13:321:13 | r2_2(int) = Load r2_1, m0_3 | test.c:321:13:321:13 | a | negative strictlyNegative |
+| test.c:322:5:322:14 | r2_10(int) = Load r2_9, m23_0 | test.c:322:5:322:14 | ... += ... | negative |
+| test.c:324:7:324:9 | r3_1(int) = Constant[-17] | test.c:324:7:324:9 | - ... | negative strictlyNegative |
+| test.c:324:24:324:25 | r4_2(int) = Constant[-2] | test.c:324:24:324:25 | - ... | negative strictlyNegative |
+| test.c:324:30:324:32 | r5_0(int) = Constant[-13] | test.c:324:30:324:32 | - ... | negative strictlyNegative |
+| test.c:325:13:325:13 | r7_2(int) = Load r7_1, m0_3 | test.c:325:13:325:13 | a | negative strictlyNegative |
+| test.c:325:13:325:15 | m7_6(int) = Store r7_0, r7_5 | test.c:325:13:325:15 | ... * ... | positive |
+| test.c:325:13:325:15 | r7_5(int) = Mul r7_2, r7_4 | test.c:325:13:325:15 | ... * ... | positive |
+| test.c:325:15:325:15 | r7_4(int) = Load r7_3, m0_5 | test.c:325:15:325:15 | b | negative |
+| test.c:326:14:326:14 | r7_8(int) = Load r7_7, m7_6 | test.c:326:14:326:14 | r | positive |
+| test.c:328:7:328:9 | r8_1(int) = Constant[-17] | test.c:328:7:328:9 | - ... | negative strictlyNegative |
+| test.c:328:24:328:25 | r9_2(int) = Constant[-2] | test.c:328:24:328:25 | - ... | negative strictlyNegative |
+| test.c:328:30:328:32 | r10_0(int) = Constant[-13] | test.c:328:30:328:32 | - ... | negative strictlyNegative |
+| test.c:328:47:328:48 | r11_2(int) = Constant[-7] | test.c:328:47:328:48 | - ... | negative strictlyNegative |
+| test.c:329:13:329:13 | r12_2(int) = Load r12_1, m0_3 | test.c:329:13:329:13 | a | negative strictlyNegative |
+| test.c:329:13:329:15 | m12_6(int) = Store r12_0, r12_5 | test.c:329:13:329:15 | ... * ... | positive strictlyPositive |
+| test.c:329:13:329:15 | r12_5(int) = Mul r12_2, r12_4 | test.c:329:13:329:15 | ... * ... | positive strictlyPositive |
+| test.c:329:15:329:15 | r12_4(int) = Load r12_3, m0_5 | test.c:329:15:329:15 | b | negative strictlyNegative |
+| test.c:330:14:330:14 | r12_8(int) = Load r12_7, m12_6 | test.c:330:14:330:14 | r | positive strictlyPositive |
+| test.c:339:12:339:13 | m2_2(int) = Store r2_0, r2_1 | test.c:339:12:339:13 | - ... | negative strictlyNegative |
+| test.c:339:12:339:13 | r2_1(int) = Constant[-1] | test.c:339:12:339:13 | - ... | negative strictlyNegative |
+| test.c:342:10:342:10 | m3_0(int) = Phi from 0:m0_8, from 4:m4_4 | test.c:342:10:342:10 | i | positive |
+| test.c:342:10:342:10 | r3_2(int) = Load r3_1, m3_0 | test.c:342:10:342:10 | i | positive |
+| test.c:342:14:342:14 | r3_3(int) = Constant[3] | test.c:342:14:342:14 | 3 | positive strictlyPositive |
+| test.c:343:5:343:7 | m4_4(int) = Store r4_0, r4_3 | test.c:343:5:343:7 | ... ++ | positive strictlyPositive |
+| test.c:343:5:343:7 | r4_1(int) = Load r4_0, m3_0 | test.c:343:5:343:7 | ... ++ | positive |
+| test.c:343:5:343:7 | r4_2(int) = Constant[1] | test.c:343:5:343:7 | ... ++ | positive strictlyPositive |
+| test.c:343:5:343:7 | r4_3(int) = Add r4_1, r4_2 | test.c:343:5:343:7 | ... ++ | positive strictlyPositive |
+| test.c:345:3:345:7 | m5_3(int) = Store r5_2, r5_1 | test.c:345:3:345:7 | ... = ... | positive |
+| test.c:345:7:345:7 | r5_1(int) = Load r5_0, m3_0 | test.c:345:7:345:7 | i | positive |
+| test.c:346:7:346:7 | r5_5(int) = Load r5_4, m0_3 | test.c:346:7:346:7 | x | positive |
+| test.c:347:9:347:9 | r6_1(int) = Load r6_0, m5_3 | test.c:347:9:347:9 | d | positive |
+| test.c:348:14:348:14 | m7_2(int) = Store r7_0, r7_1 | test.c:348:14:348:14 | 1 | positive strictlyPositive |
+| test.c:348:14:348:14 | r7_1(int) = Constant[1] | test.c:348:14:348:14 | 1 | positive strictlyPositive |
+| test.c:357:8:357:23 | m22_2(unsigned int) = Store r22_1, r22_0 | test.c:357:8:357:23 | ... ? ... : ... | positive strictlyPositive |
+| test.c:357:12:357:14 | r0_22(unsigned int) = Constant[100] | test.c:357:12:357:14 | (unsigned int)... | positive strictlyPositive |
+| test.c:357:22:357:23 | r22_0(unsigned int) = Constant[10] | test.c:357:22:357:23 | (unsigned int)... | positive strictlyPositive |
+| test.c:358:8:358:24 | m24_2(unsigned int) = Store r24_1, r24_0 | test.c:358:8:358:24 | ... ? ... : ... | positive strictlyPositive |
+| test.c:358:13:358:15 | r17_7(unsigned int) = Constant[100] | test.c:358:13:358:15 | (unsigned int)... | positive strictlyPositive |
+| test.c:358:19:358:20 | r24_0(unsigned int) = Constant[10] | test.c:358:19:358:20 | (unsigned int)... | positive strictlyPositive |
+| test.c:365:11:365:13 | r23_25(unsigned int) = Constant[300] | test.c:365:11:365:13 | (unsigned int)... | positive strictlyPositive |
+| test.c:366:10:366:15 | m38_2(unsigned int) = Store r40_1, r38_1, r40_0, r38_0 | test.c:366:10:366:15 | ... ? ... : ... | positive strictlyPositive |
+| test.c:366:10:366:15 | m40_2(unsigned int) = Store r40_1, r38_1, r40_0, r38_0 | test.c:366:10:366:15 | ... ? ... : ... | positive strictlyPositive |
+| test.c:366:15:366:15 | r38_0(unsigned int) = Constant[5] | test.c:366:15:366:15 | (unsigned int)... | positive strictlyPositive |
+| test.c:366:15:366:15 | r40_0(unsigned int) = Constant[5] | test.c:366:15:366:15 | (unsigned int)... | positive strictlyPositive |
+| test.c:367:10:367:17 | m48_2(unsigned int) = Store r50_1, r48_1, r50_0, r48_0 | test.c:367:10:367:17 | ... ? ... : ... | positive strictlyPositive |
+| test.c:367:10:367:17 | m50_2(unsigned int) = Store r50_1, r48_1, r50_0, r48_0 | test.c:367:10:367:17 | ... ? ... : ... | positive strictlyPositive |
+| test.c:367:15:367:17 | r48_0(unsigned int) = Constant[500] | test.c:367:15:367:17 | (unsigned int)... | positive strictlyPositive |
+| test.c:367:15:367:17 | r50_0(unsigned int) = Constant[500] | test.c:367:15:367:17 | (unsigned int)... | positive strictlyPositive |
+| test.c:368:5:368:21 | m51_4(unsigned int) = Store r51_3, r51_2 | test.c:368:5:368:21 | ... = ... | positive strictlyPositive |
+| test.c:368:10:368:21 | m51_0(unsigned int) = Phi from 52:m52_1, from 55:m55_2 | test.c:368:10:368:21 | ... ? ... : ... | positive strictlyPositive |
+| test.c:368:10:368:21 | m55_2(unsigned int) = Store r55_1, r55_0 | test.c:368:10:368:21 | ... ? ... : ... | positive strictlyPositive |
+| test.c:368:10:368:21 | r51_2(unsigned int) = Load r51_1, m51_0 | test.c:368:10:368:21 | ... ? ... : ... | positive strictlyPositive |
+| test.c:368:13:368:13 | r27_0(unsigned int) = Constant[1] | test.c:368:13:368:13 | (unsigned int)... | positive strictlyPositive |
+| test.c:368:13:368:13 | r54_0(unsigned int) = Constant[1] | test.c:368:13:368:13 | (unsigned int)... | positive strictlyPositive |
+| test.c:368:19:368:21 | r55_0(unsigned int) = Constant[500] | test.c:368:19:368:21 | (unsigned int)... | positive strictlyPositive |
+| test.c:369:10:369:36 | m1_0(int) = Phi from 2:m2_1, from 5:m5_2 | test.c:369:10:369:36 | ... ? ... : ... | positive strictlyPositive |
+| test.c:369:10:369:36 | m5_2(int) = Store r5_1, r5_0 | test.c:369:10:369:36 | ... ? ... : ... | positive strictlyPositive |
+| test.c:369:10:369:36 | r1_2(int) = Load r1_1, m1_0 | test.c:369:10:369:36 | ... ? ... : ... | positive strictlyPositive |
+| test.c:369:29:369:29 | r4_0(unsigned int) = Constant[1] | test.c:369:29:369:29 | (unsigned int)... | positive strictlyPositive |
+| test.c:369:29:369:29 | r41_0(unsigned int) = Constant[1] | test.c:369:29:369:29 | (unsigned int)... | positive strictlyPositive |
+| test.c:369:36:369:36 | r5_0(int) = Constant[5] | test.c:369:36:369:36 | 5 | positive strictlyPositive |
+| test.c:370:10:370:38 | m6_0(int) = Phi from 7:m7_1, from 10:m10_2 | test.c:370:10:370:38 | ... ? ... : ... | positive strictlyPositive |
+| test.c:370:10:370:38 | m10_2(int) = Store r10_1, r10_0 | test.c:370:10:370:38 | ... ? ... : ... | positive strictlyPositive |
+| test.c:370:10:370:38 | r6_2(int) = Load r6_1, m6_0 | test.c:370:10:370:38 | ... ? ... : ... | positive strictlyPositive |
+| test.c:370:29:370:29 | r9_0(unsigned int) = Constant[1] | test.c:370:29:370:29 | (unsigned int)... | positive strictlyPositive |
+| test.c:370:29:370:29 | r41_0(unsigned int) = Constant[1] | test.c:370:29:370:29 | (unsigned int)... | positive strictlyPositive |
+| test.c:370:36:370:38 | r10_0(int) = Constant[500] | test.c:370:36:370:38 | 500 | positive strictlyPositive |
+| test.c:371:10:371:39 | m11_0(int) = Phi from 12:m12_1, from 15:m15_2 | test.c:371:10:371:39 | ... ? ... : ... | positive strictlyPositive |
+| test.c:371:10:371:39 | m15_2(int) = Store r15_1, r15_0 | test.c:371:10:371:39 | ... ? ... : ... | positive strictlyPositive |
+| test.c:371:10:371:39 | r11_2(int) = Load r11_1, m11_0 | test.c:371:10:371:39 | ... ? ... : ... | positive strictlyPositive |
+| test.c:371:30:371:30 | r14_0(unsigned int) = Constant[1] | test.c:371:30:371:30 | (unsigned int)... | positive strictlyPositive |
+| test.c:371:30:371:30 | r41_0(unsigned int) = Constant[1] | test.c:371:30:371:30 | (unsigned int)... | positive strictlyPositive |
+| test.c:371:37:371:39 | r15_0(int) = Constant[500] | test.c:371:37:371:39 | 500 | positive strictlyPositive |
+| test.c:373:3:373:47 | m16_2(unsigned int) = Phi from 11:m51_4, from 23:m23_13 | test.c:373:3:373:47 | return ... | positive |
+| test.c:373:30:373:31 | r16_19(unsigned int) = Load r16_18, m16_2 | test.c:373:30:373:31 | y5 | positive |
+| test.c:379:3:379:24 | m1_4(unsigned int) = Store r1_3, r1_2 | test.c:379:3:379:24 | ... = ... | positive strictlyPositive |
+| test.c:379:8:379:24 | m1_0(unsigned int) = Phi from 2:m2_3, from 5:m5_2 | test.c:379:8:379:24 | ... ? ... : ... | positive strictlyPositive |
+| test.c:379:8:379:24 | m2_3(unsigned int) = Store r2_2, r2_1 | test.c:379:8:379:24 | ... ? ... : ... | positive strictlyPositive |
+| test.c:379:8:379:24 | m5_2(unsigned int) = Store r5_1, r5_0 | test.c:379:8:379:24 | ... ? ... : ... | positive strictlyPositive |
+| test.c:379:8:379:24 | r1_2(unsigned int) = Load r1_1, m1_0 | test.c:379:8:379:24 | ... ? ... : ... | positive strictlyPositive |
+| test.c:379:12:379:14 | r0_16(unsigned int) = Constant[100] | test.c:379:12:379:14 | (unsigned int)... | positive strictlyPositive |
+| test.c:379:18:379:18 | r2_1(unsigned int) = Load r2_0, m0_3 | test.c:379:18:379:18 | x | positive strictlyPositive |
+| test.c:379:22:379:24 | r5_0(unsigned int) = Constant[110] | test.c:379:22:379:24 | (unsigned int)... | positive strictlyPositive |
+| test.c:380:3:380:25 | m6_4(unsigned int) = Store r6_3, r6_2 | test.c:380:3:380:25 | ... = ... | positive strictlyPositive |
+| test.c:380:8:380:25 | m6_0(unsigned int) = Phi from 7:m7_2, from 8:m8_3 | test.c:380:8:380:25 | ... ? ... : ... | positive strictlyPositive |
+| test.c:380:8:380:25 | m7_2(unsigned int) = Store r7_1, r7_0 | test.c:380:8:380:25 | ... ? ... : ... | positive strictlyPositive |
+| test.c:380:8:380:25 | m8_3(unsigned int) = Store r8_2, r8_1 | test.c:380:8:380:25 | ... ? ... : ... | positive strictlyPositive |
+| test.c:380:8:380:25 | r6_2(unsigned int) = Load r6_1, m6_0 | test.c:380:8:380:25 | ... ? ... : ... | positive strictlyPositive |
+| test.c:380:13:380:15 | r1_7(unsigned int) = Constant[100] | test.c:380:13:380:15 | (unsigned int)... | positive strictlyPositive |
+| test.c:380:19:380:21 | r7_0(unsigned int) = Constant[110] | test.c:380:19:380:21 | (unsigned int)... | positive strictlyPositive |
+| test.c:380:25:380:25 | r8_1(unsigned int) = Load r8_0, m0_3 | test.c:380:25:380:25 | x | positive strictlyPositive |
+| test.c:381:3:381:11 | m6_7(unsigned int) = Store r6_6, r6_5 | test.c:381:3:381:11 | ... = ... | positive strictlyPositive |
+| test.c:381:8:381:11 | r6_5(unsigned int) = Constant[1000] | test.c:381:8:381:11 | (unsigned int)... | positive strictlyPositive |
+| test.c:382:3:382:11 | m6_10(unsigned int) = Store r6_9, r6_8 | test.c:382:3:382:11 | ... = ... | positive strictlyPositive |
+| test.c:382:8:382:11 | r6_8(unsigned int) = Constant[1000] | test.c:382:8:382:11 | (unsigned int)... | positive strictlyPositive |
+| test.c:383:3:383:11 | m6_13(unsigned int) = Store r6_12, r6_11 | test.c:383:3:383:11 | ... = ... | positive strictlyPositive |
+| test.c:383:8:383:11 | r6_11(unsigned int) = Constant[1000] | test.c:383:8:383:11 | (unsigned int)... | positive strictlyPositive |
+| test.c:384:12:384:14 | r6_16(unsigned int) = Constant[300] | test.c:384:12:384:14 | (unsigned int)... | positive strictlyPositive |
+| test.c:385:5:385:21 | m14_4(unsigned int) = Store r14_3, r14_2 | test.c:385:5:385:21 | ... = ... | positive strictlyPositive |
+| test.c:385:10:385:21 | m14_0(unsigned int) = Phi from 15:m15_1, from 19:m19_2 | test.c:385:10:385:21 | ... ? ... : ... | positive strictlyPositive |
+| test.c:385:10:385:21 | m19_2(unsigned int) = Store r19_1, r19_0 | test.c:385:10:385:21 | ... ? ... : ... | positive strictlyPositive |
+| test.c:385:10:385:21 | r14_2(unsigned int) = Load r14_1, m14_0 | test.c:385:10:385:21 | ... ? ... : ... | positive strictlyPositive |
+| test.c:385:11:385:11 | r17_1(unsigned int) = Load r17_0, m0_3 | test.c:385:11:385:11 | x | positive strictlyPositive |
+| test.c:385:13:385:15 | r11_0(unsigned int) = Constant[300] | test.c:385:13:385:15 | (unsigned int)... | positive strictlyPositive |
+| test.c:385:13:385:15 | r18_0(unsigned int) = Constant[300] | test.c:385:13:385:15 | (unsigned int)... | positive strictlyPositive |
+| test.c:385:21:385:21 | r19_0(unsigned int) = Constant[5] | test.c:385:21:385:21 | (unsigned int)... | positive strictlyPositive |
+| test.c:386:5:386:21 | m20_4(unsigned int) = Store r20_3, r20_2 | test.c:386:5:386:21 | ... = ... | positive strictlyPositive |
+| test.c:386:10:386:21 | m20_0(unsigned int) = Phi from 21:m21_1, from 25:m25_2 | test.c:386:10:386:21 | ... ? ... : ... | positive strictlyPositive |
+| test.c:386:10:386:21 | m25_2(unsigned int) = Store r25_1, r25_0 | test.c:386:10:386:21 | ... ? ... : ... | positive strictlyPositive |
+| test.c:386:10:386:21 | r20_2(unsigned int) = Load r20_1, m20_0 | test.c:386:10:386:21 | ... ? ... : ... | positive strictlyPositive |
+| test.c:386:11:386:11 | r14_6(unsigned int) = Load r14_5, m0_3 | test.c:386:11:386:11 | x | positive strictlyPositive |
+| test.c:386:13:386:15 | r11_0(unsigned int) = Constant[200] | test.c:386:13:386:15 | (unsigned int)... | positive strictlyPositive |
+| test.c:386:13:386:15 | r24_0(unsigned int) = Constant[200] | test.c:386:13:386:15 | (unsigned int)... | positive strictlyPositive |
+| test.c:386:21:386:21 | r25_0(unsigned int) = Constant[5] | test.c:386:21:386:21 | (unsigned int)... | positive strictlyPositive |
+| test.c:387:10:387:38 | m26_0(int) = Phi from 27:m27_1, from 31:m31_2 | test.c:387:10:387:38 | ... ? ... : ... | positive strictlyPositive |
+| test.c:387:10:387:38 | m31_2(int) = Store r31_1, r31_0 | test.c:387:10:387:38 | ... ? ... : ... | positive strictlyPositive |
+| test.c:387:10:387:38 | r26_2(int) = Load r26_1, m26_0 | test.c:387:10:387:38 | ... ? ... : ... | positive strictlyPositive |
+| test.c:387:27:387:27 | r20_6(unsigned int) = Load r20_5, m0_3 | test.c:387:27:387:27 | x | positive strictlyPositive |
+| test.c:387:29:387:31 | r28_0(unsigned int) = Constant[200] | test.c:387:29:387:31 | (unsigned int)... | positive strictlyPositive |
+| test.c:387:29:387:31 | r30_0(unsigned int) = Constant[200] | test.c:387:29:387:31 | (unsigned int)... | positive strictlyPositive |
+| test.c:387:38:387:38 | r31_0(int) = Constant[5] | test.c:387:38:387:38 | 5 | positive strictlyPositive |
+| test.c:389:3:389:32 | m32_0(unsigned int) = Phi from 6:m6_7, from 26:m14_4 | test.c:389:3:389:32 | return ... | positive strictlyPositive |
+| test.c:389:3:389:32 | m32_1(unsigned int) = Phi from 6:m6_10, from 26:m20_4 | test.c:389:3:389:32 | return ... | positive strictlyPositive |
+| test.c:389:3:389:32 | m32_2(unsigned int) = Phi from 6:m6_13, from 26:m26_5 | test.c:389:3:389:32 | return ... | positive strictlyPositive |
+| test.c:389:10:389:11 | r32_5(unsigned int) = Load r32_4, m1_4 | test.c:389:10:389:11 | y1 | positive strictlyPositive |
+| test.c:389:10:389:16 | r32_8(unsigned int) = Add r32_5, r32_7 | test.c:389:10:389:16 | ... + ... | positive strictlyPositive |
+| test.c:389:10:389:21 | r32_11(unsigned int) = Add r32_8, r32_10 | test.c:389:10:389:21 | ... + ... | positive strictlyPositive |
+| test.c:389:10:389:26 | r32_14(unsigned int) = Add r32_11, r32_13 | test.c:389:10:389:26 | ... + ... | positive strictlyPositive |
+| test.c:389:10:389:31 | m32_18(unsigned int) = Store r32_3, r32_17 | test.c:389:10:389:31 | ... + ... | positive strictlyPositive |
+| test.c:389:10:389:31 | r32_17(unsigned int) = Add r32_14, r32_16 | test.c:389:10:389:31 | ... + ... | positive strictlyPositive |
+| test.c:389:15:389:16 | r32_7(unsigned int) = Load r32_6, m6_4 | test.c:389:15:389:16 | y2 | positive strictlyPositive |
+| test.c:389:20:389:21 | r32_10(unsigned int) = Load r32_9, m32_0 | test.c:389:20:389:21 | y3 | positive strictlyPositive |
+| test.c:389:25:389:26 | r32_13(unsigned int) = Load r32_12, m32_1 | test.c:389:25:389:26 | y4 | positive strictlyPositive |
+| test.c:389:30:389:31 | r32_16(unsigned int) = Load r32_15, m32_2 | test.c:389:30:389:31 | y5 | positive strictlyPositive |
+| test.c:394:20:394:36 | m2_2(unsigned int) = Store r2_1, r2_0 | test.c:394:20:394:36 | ... ? ... : ... | positive strictlyPositive |
+| test.c:394:24:394:26 | r0_7(unsigned int) = Constant[100] | test.c:394:24:394:26 | (unsigned int)... | positive strictlyPositive |
+| test.c:394:34:394:36 | r2_0(unsigned int) = Constant[100] | test.c:394:34:394:36 | (unsigned int)... | positive strictlyPositive |
+| test.c:397:9:397:11 | r3_10(unsigned int) = Constant[1] | test.c:397:9:397:11 | ++ ... | positive strictlyPositive |
+| test.c:398:9:398:11 | r3_19(unsigned int) = Constant[1] | test.c:398:9:398:11 | ... ++ | positive strictlyPositive |
+| test.c:398:19:398:19 | r3_22(unsigned int) = Constant[3] | test.c:398:19:398:19 | (unsigned int)... | positive strictlyPositive |
+| test.cpp:9:11:9:12 | m0_8(int) = Store r0_6, r0_7 | test.cpp:9:11:9:12 | - ... | negative strictlyNegative |
+| test.cpp:9:11:9:12 | r0_7(int) = Constant[-1] | test.cpp:9:11:9:12 | - ... | negative strictlyNegative |
+| test.cpp:11:13:11:13 | r1_2(int) = Constant[3] | test.cpp:11:13:11:13 | 3 | positive strictlyPositive |
+| test.cpp:30:12:30:13 | r11_3(int) = Constant[-1] | test.cpp:30:12:30:13 | - ... | negative strictlyNegative |
+| test.cpp:31:5:31:10 | m12_2(int) = Store r12_1, r12_0 | test.cpp:31:5:31:10 | ... = ... | negative strictlyNegative |
+| test.cpp:31:9:31:10 | r12_0(int) = Constant[-1] | test.cpp:31:9:31:10 | - ... | negative strictlyNegative |
+| test.cpp:33:12:33:12 | r13_3(int) = Constant[1] | test.cpp:33:12:33:12 | 1 | positive strictlyPositive |
+| test.cpp:34:5:34:9 | m14_2(int) = Store r14_1, r14_0 | test.cpp:34:5:34:9 | ... = ... | positive strictlyPositive |
+| test.cpp:34:9:34:9 | r14_0(int) = Constant[1] | test.cpp:34:9:34:9 | 1 | positive strictlyPositive |
+| test.cpp:36:12:36:15 | r15_3(int) = Constant[-128] | test.cpp:36:12:36:15 | - ... | negative strictlyNegative |
+| test.cpp:37:5:37:12 | m16_2(int) = Store r16_1, r16_0 | test.cpp:37:5:37:12 | ... = ... | negative strictlyNegative |
+| test.cpp:37:9:37:12 | r16_0(int) = Constant[-128] | test.cpp:37:9:37:12 | - ... | negative strictlyNegative |
+| test.cpp:39:12:39:14 | r17_3(int) = Constant[128] | test.cpp:39:12:39:14 | 128 | positive strictlyPositive |
+| test.cpp:40:5:40:11 | m18_2(int) = Store r18_1, r18_0 | test.cpp:40:5:40:11 | ... = ... | positive strictlyPositive |
+| test.cpp:40:9:40:11 | r18_0(int) = Constant[128] | test.cpp:40:9:40:11 | 128 | positive strictlyPositive |
+| test.cpp:42:12:42:16 | r19_3(int) = Constant[-1024] | test.cpp:42:12:42:16 | - ... | negative strictlyNegative |
+| test.cpp:43:5:43:13 | m20_2(int) = Store r20_1, r20_0 | test.cpp:43:5:43:13 | ... = ... | negative strictlyNegative |
+| test.cpp:43:9:43:13 | r20_0(int) = Constant[-1024] | test.cpp:43:9:43:13 | - ... | negative strictlyNegative |
+| test.cpp:45:12:45:15 | r21_3(int) = Constant[1024] | test.cpp:45:12:45:15 | 1024 | positive strictlyPositive |
+| test.cpp:46:5:46:12 | m22_2(int) = Store r22_1, r22_0 | test.cpp:46:5:46:12 | ... = ... | positive strictlyPositive |
+| test.cpp:46:9:46:12 | r22_0(int) = Constant[1024] | test.cpp:46:9:46:12 | 1024 | positive strictlyPositive |
+| test.cpp:69:10:69:21 | m8_0(bool) = Phi from 7:m7_2, from 9:m9_2 | test.cpp:69:10:69:21 | ... \|\| ... | positive |
+| test.cpp:69:10:69:21 | m8_3(bool) = Store r6_14, r8_2 | test.cpp:69:10:69:21 | ... \|\| ... | positive |
+| test.cpp:69:10:69:21 | m9_2(bool) = Store r9_0, r9_1 | test.cpp:69:10:69:21 | ... \|\| ... | positive strictlyPositive |
+| test.cpp:69:10:69:21 | r8_2(bool) = Load r8_1, m8_0 | test.cpp:69:10:69:21 | ... \|\| ... | positive |
+| test.cpp:69:10:69:21 | r9_1(bool) = Constant[1] | test.cpp:69:10:69:21 | ... \|\| ... | positive strictlyPositive |
diff --git a/cpp/ql/test/library-tests/rangeanalysis/signanalysis/SignAnalysis.ql b/cpp/ql/test/library-tests/rangeanalysis/signanalysis/SignAnalysis.ql
new file mode 100644
index 00000000000..cab4cea1d84
--- /dev/null
+++ b/cpp/ql/test/library-tests/rangeanalysis/signanalysis/SignAnalysis.ql
@@ -0,0 +1,19 @@
+import semmle.code.cpp.rangeanalysis.SignAnalysis
+import semmle.code.cpp.ir.IR
+
+string getASignString(Instruction i) {
+ positive(i) and
+ result = "positive"
+ or
+ negative(i) and
+ result = "negative"
+ or
+ strictlyPositive(i) and
+ result = "strictlyPositive"
+ or
+ strictlyNegative(i) and
+ result = "strictlyNegative"
+}
+
+from Instruction i
+select i, i.getAST(), strictconcat(string s | s = getASignString(i) | s, " ")
\ No newline at end of file
diff --git a/cpp/ql/test/library-tests/rangeanalysis/signanalysis/negative.expected b/cpp/ql/test/library-tests/rangeanalysis/signanalysis/negative.expected
deleted file mode 100644
index 4c0f7da72a3..00000000000
--- a/cpp/ql/test/library-tests/rangeanalysis/signanalysis/negative.expected
+++ /dev/null
@@ -1,55 +0,0 @@
-| test.c:67:7:67:11 | r0_6(int) = Constant[-1000] | test.c:67:7:67:11 | - ... |
-| test.c:154:39:154:40 | r3_0(long long) = Constant[-1] | test.c:154:39:154:40 | (long long)... |
-| test.c:171:7:171:8 | r16_1(int) = Constant[-7] | test.c:171:7:171:8 | - ... |
-| test.c:176:7:176:8 | r1_1(int) = Constant[-7] | test.c:176:7:176:8 | - ... |
-| test.c:181:7:181:8 | r4_1(int) = Constant[-7] | test.c:181:7:181:8 | - ... |
-| test.c:186:7:186:8 | r7_1(int) = Constant[-7] | test.c:186:7:186:8 | - ... |
-| test.c:186:23:186:24 | r9_2(int) = Constant[-2] | test.c:186:23:186:24 | - ... |
-| test.c:208:28:208:30 | r25_0(int) = Constant[-13] | test.c:208:28:208:30 | - ... |
-| test.c:212:28:212:30 | r5_0(int) = Constant[-13] | test.c:212:28:212:30 | - ... |
-| test.c:216:28:216:30 | r10_0(int) = Constant[-13] | test.c:216:28:216:30 | - ... |
-| test.c:216:45:216:46 | r11_2(int) = Constant[-7] | test.c:216:45:216:46 | - ... |
-| test.c:236:28:236:30 | r25_0(int) = Constant[-13] | test.c:236:28:236:30 | - ... |
-| test.c:240:28:240:30 | r5_0(int) = Constant[-13] | test.c:240:28:240:30 | - ... |
-| test.c:244:28:244:30 | r10_0(int) = Constant[-13] | test.c:244:28:244:30 | - ... |
-| test.c:244:45:244:46 | r11_2(int) = Constant[-7] | test.c:244:45:244:46 | - ... |
-| test.c:256:7:256:9 | r0_9(int) = Constant[-17] | test.c:256:7:256:9 | - ... |
-| test.c:260:7:260:9 | r18_1(int) = Constant[-17] | test.c:260:7:260:9 | - ... |
-| test.c:264:7:264:9 | r23_1(int) = Constant[-17] | test.c:264:7:264:9 | - ... |
-| test.c:264:30:264:32 | r25_0(int) = Constant[-13] | test.c:264:30:264:32 | - ... |
-| test.c:268:7:268:9 | r3_1(int) = Constant[-17] | test.c:268:7:268:9 | - ... |
-| test.c:268:30:268:32 | r5_0(int) = Constant[-13] | test.c:268:30:268:32 | - ... |
-| test.c:272:7:272:9 | r8_1(int) = Constant[-17] | test.c:272:7:272:9 | - ... |
-| test.c:272:30:272:32 | r10_0(int) = Constant[-13] | test.c:272:30:272:32 | - ... |
-| test.c:272:47:272:48 | r11_2(int) = Constant[-7] | test.c:272:47:272:48 | - ... |
-| test.c:284:7:284:9 | r0_9(int) = Constant[-17] | test.c:284:7:284:9 | - ... |
-| test.c:288:7:288:9 | r18_1(int) = Constant[-17] | test.c:288:7:288:9 | - ... |
-| test.c:292:7:292:9 | r23_1(int) = Constant[-17] | test.c:292:7:292:9 | - ... |
-| test.c:292:29:292:31 | r25_0(int) = Constant[-13] | test.c:292:29:292:31 | - ... |
-| test.c:296:7:296:9 | r3_1(int) = Constant[-17] | test.c:296:7:296:9 | - ... |
-| test.c:296:29:296:31 | r5_0(int) = Constant[-13] | test.c:296:29:296:31 | - ... |
-| test.c:300:7:300:9 | r8_1(int) = Constant[-17] | test.c:300:7:300:9 | - ... |
-| test.c:300:29:300:31 | r10_0(int) = Constant[-13] | test.c:300:29:300:31 | - ... |
-| test.c:300:46:300:47 | r11_2(int) = Constant[-7] | test.c:300:46:300:47 | - ... |
-| test.c:312:7:312:9 | r0_9(int) = Constant[-17] | test.c:312:7:312:9 | - ... |
-| test.c:312:24:312:25 | r14_2(int) = Constant[-2] | test.c:312:24:312:25 | - ... |
-| test.c:316:7:316:9 | r18_1(int) = Constant[-17] | test.c:316:7:316:9 | - ... |
-| test.c:316:24:316:25 | r19_2(int) = Constant[-2] | test.c:316:24:316:25 | - ... |
-| test.c:320:7:320:9 | r23_1(int) = Constant[-17] | test.c:320:7:320:9 | - ... |
-| test.c:320:24:320:25 | r24_2(int) = Constant[-2] | test.c:320:24:320:25 | - ... |
-| test.c:320:30:320:32 | r25_0(int) = Constant[-13] | test.c:320:30:320:32 | - ... |
-| test.c:324:7:324:9 | r3_1(int) = Constant[-17] | test.c:324:7:324:9 | - ... |
-| test.c:324:24:324:25 | r4_2(int) = Constant[-2] | test.c:324:24:324:25 | - ... |
-| test.c:324:30:324:32 | r5_0(int) = Constant[-13] | test.c:324:30:324:32 | - ... |
-| test.c:328:7:328:9 | r8_1(int) = Constant[-17] | test.c:328:7:328:9 | - ... |
-| test.c:328:24:328:25 | r9_2(int) = Constant[-2] | test.c:328:24:328:25 | - ... |
-| test.c:328:30:328:32 | r10_0(int) = Constant[-13] | test.c:328:30:328:32 | - ... |
-| test.c:328:47:328:48 | r11_2(int) = Constant[-7] | test.c:328:47:328:48 | - ... |
-| test.c:339:12:339:13 | r2_1(int) = Constant[-1] | test.c:339:12:339:13 | - ... |
-| test.cpp:9:11:9:12 | r0_7(int) = Constant[-1] | test.cpp:9:11:9:12 | - ... |
-| test.cpp:30:12:30:13 | r11_3(int) = Constant[-1] | test.cpp:30:12:30:13 | - ... |
-| test.cpp:31:9:31:10 | r12_0(int) = Constant[-1] | test.cpp:31:9:31:10 | - ... |
-| test.cpp:36:12:36:15 | r15_3(int) = Constant[-128] | test.cpp:36:12:36:15 | - ... |
-| test.cpp:37:9:37:12 | r16_0(int) = Constant[-128] | test.cpp:37:9:37:12 | - ... |
-| test.cpp:42:12:42:16 | r19_3(int) = Constant[-1024] | test.cpp:42:12:42:16 | - ... |
-| test.cpp:43:9:43:13 | r20_0(int) = Constant[-1024] | test.cpp:43:9:43:13 | - ... |
diff --git a/cpp/ql/test/library-tests/rangeanalysis/signanalysis/negative.ql b/cpp/ql/test/library-tests/rangeanalysis/signanalysis/negative.ql
deleted file mode 100644
index 2239669cf87..00000000000
--- a/cpp/ql/test/library-tests/rangeanalysis/signanalysis/negative.ql
+++ /dev/null
@@ -1,6 +0,0 @@
-import semmle.code.cpp.rangeanalysis.SignAnalysis
-import semmle.code.cpp.ir.IR
-
-from Instruction i
-where negative(i)
-select i, i.getAST()
\ No newline at end of file
diff --git a/cpp/ql/test/library-tests/rangeanalysis/signanalysis/positive.expected b/cpp/ql/test/library-tests/rangeanalysis/signanalysis/positive.expected
deleted file mode 100644
index 64dad2b3ceb..00000000000
--- a/cpp/ql/test/library-tests/rangeanalysis/signanalysis/positive.expected
+++ /dev/null
@@ -1,136 +0,0 @@
-| inline_assembly.c:10:7:10:7 | r0_7(unsigned int) = Constant[1] | inline_assembly.c:10:7:10:7 | (unsigned int)... |
-| minmax.c:16:9:16:10 | r0_3(int) = Constant[1] | minmax.c:16:9:16:10 | 1 |
-| minmax.c:16:16:16:17 | r0_6(int) = Constant[2] | minmax.c:16:16:16:17 | 2 |
-| minmax.c:16:23:16:24 | r0_9(int) = Constant[3] | minmax.c:16:23:16:24 | 3 |
-| test.c:8:19:8:19 | r2_2(int) = Constant[1] | test.c:8:19:8:19 | 1 |
-| test.c:16:20:16:20 | r2_2(int) = Constant[1] | test.c:16:20:16:20 | 1 |
-| test.c:16:25:16:26 | r2_4(int) = Constant[10] | test.c:16:25:16:26 | 10 |
-| test.c:24:5:24:11 | r2_2(int) = Constant[1] | test.c:24:5:24:11 | ... ++ |
-| test.c:25:21:25:22 | r2_7(int) = Constant[10] | test.c:25:21:25:22 | 10 |
-| test.c:33:19:33:19 | r1_4(int) = Constant[2] | test.c:33:19:33:19 | 2 |
-| test.c:33:28:33:28 | r2_8(int) = Constant[1] | test.c:33:28:33:28 | 1 |
-| test.c:42:19:42:19 | r1_4(int) = Constant[2] | test.c:42:19:42:19 | 2 |
-| test.c:42:22:42:24 | r2_8(int) = Constant[1] | test.c:42:22:42:24 | ... ++ |
-| test.c:51:17:51:17 | r1_4(int) = Constant[2] | test.c:51:17:51:17 | 2 |
-| test.c:51:21:51:21 | r1_6(int) = Constant[4] | test.c:51:21:51:21 | 4 |
-| test.c:51:30:51:30 | r2_8(int) = Constant[1] | test.c:51:30:51:30 | 1 |
-| test.c:58:11:58:11 | r0_6(int) = Constant[4] | test.c:58:11:58:11 | 4 |
-| test.c:59:13:59:13 | r2_2(int) = Constant[5] | test.c:59:13:59:13 | 5 |
-| test.c:63:10:63:10 | r4_1(int) = Constant[1] | test.c:63:10:63:10 | 1 |
-| test.c:67:24:67:25 | r2_2(int) = Constant[10] | test.c:67:24:67:25 | 10 |
-| test.c:68:15:68:15 | r3_4(int) = Constant[2] | test.c:68:15:68:15 | 2 |
-| test.c:77:13:77:13 | r2_2(int) = Constant[4] | test.c:77:13:77:13 | 4 |
-| test.c:81:13:81:13 | r4_2(int) = Constant[4] | test.c:81:13:81:13 | 4 |
-| test.c:82:14:82:14 | r5_1(int) = Constant[1] | test.c:82:14:82:14 | 1 |
-| test.c:89:11:89:11 | r0_8(int) = Constant[7] | test.c:89:11:89:11 | 7 |
-| test.c:95:10:95:10 | r5_1(int) = Constant[1] | test.c:95:10:95:10 | 1 |
-| test.c:102:6:102:8 | r2_3(int) = Constant[1] | test.c:102:6:102:8 | ... ++ |
-| test.c:104:12:104:14 | r3_4(int) = Constant[58] | test.c:104:12:104:14 | 58 |
-| test.c:107:8:107:10 | r5_3(int) = Constant[1] | test.c:107:8:107:10 | ... ++ |
-| test.c:109:14:109:16 | r6_3(int) = Constant[44] | test.c:109:14:109:16 | 44 |
-| test.c:110:14:110:14 | r7_1(int) = Constant[1] | test.c:110:14:110:14 | 1 |
-| test.c:119:10:119:12 | r0_8(unsigned long long) = Constant[1] | test.c:119:10:119:12 | ... ++ |
-| test.c:124:36:124:36 | r1_5(unsigned long long) = Constant[1] | test.c:124:36:124:36 | (unsigned long long)... |
-| test.c:127:24:127:24 | r2_6(unsigned long long) = Constant[1] | test.c:127:24:127:24 | (unsigned long long)... |
-| test.c:130:11:130:11 | r3_1(int) = Constant[1] | test.c:130:11:130:11 | 1 |
-| test.c:137:22:137:22 | r0_17(unsigned int) = Constant[1] | test.c:137:22:137:22 | (unsigned int)... |
-| test.c:138:13:138:13 | r0_23(int) = Constant[1] | test.c:138:13:138:13 | 1 |
-| test.c:161:7:161:7 | r0_7(int) = Constant[3] | test.c:161:7:161:7 | 3 |
-| test.c:161:22:161:23 | r8_2(int) = Constant[11] | test.c:161:22:161:23 | 11 |
-| test.c:166:22:166:23 | r14_2(int) = Constant[11] | test.c:166:22:166:23 | 11 |
-| test.c:171:23:171:24 | r17_2(int) = Constant[11] | test.c:171:23:171:24 | 11 |
-| test.c:176:23:176:23 | r2_2(int) = Constant[1] | test.c:176:23:176:23 | 1 |
-| test.c:200:7:200:7 | r0_9(int) = Constant[3] | test.c:200:7:200:7 | 3 |
-| test.c:200:22:200:23 | r14_2(int) = Constant[11] | test.c:200:22:200:23 | 11 |
-| test.c:200:28:200:28 | r15_0(int) = Constant[5] | test.c:200:28:200:28 | 5 |
-| test.c:200:43:200:44 | r16_2(int) = Constant[23] | test.c:200:43:200:44 | 23 |
-| test.c:204:7:204:7 | r18_1(int) = Constant[3] | test.c:204:7:204:7 | 3 |
-| test.c:204:22:204:23 | r19_2(int) = Constant[11] | test.c:204:22:204:23 | 11 |
-| test.c:204:43:204:44 | r21_2(int) = Constant[23] | test.c:204:43:204:44 | 23 |
-| test.c:208:7:208:7 | r23_1(int) = Constant[3] | test.c:208:7:208:7 | 3 |
-| test.c:208:22:208:23 | r24_2(int) = Constant[11] | test.c:208:22:208:23 | 11 |
-| test.c:208:45:208:46 | r1_2(int) = Constant[23] | test.c:208:45:208:46 | 23 |
-| test.c:212:7:212:7 | r3_1(int) = Constant[3] | test.c:212:7:212:7 | 3 |
-| test.c:212:22:212:23 | r4_2(int) = Constant[11] | test.c:212:22:212:23 | 11 |
-| test.c:216:7:216:7 | r8_1(int) = Constant[3] | test.c:216:7:216:7 | 3 |
-| test.c:216:22:216:23 | r9_2(int) = Constant[11] | test.c:216:22:216:23 | 11 |
-| test.c:228:22:228:23 | r14_2(int) = Constant[11] | test.c:228:22:228:23 | 11 |
-| test.c:228:28:228:28 | r15_0(int) = Constant[5] | test.c:228:28:228:28 | 5 |
-| test.c:228:43:228:44 | r16_2(int) = Constant[23] | test.c:228:43:228:44 | 23 |
-| test.c:232:22:232:23 | r19_2(int) = Constant[11] | test.c:232:22:232:23 | 11 |
-| test.c:232:43:232:44 | r21_2(int) = Constant[23] | test.c:232:43:232:44 | 23 |
-| test.c:236:22:236:23 | r24_2(int) = Constant[11] | test.c:236:22:236:23 | 11 |
-| test.c:236:45:236:46 | r1_2(int) = Constant[23] | test.c:236:45:236:46 | 23 |
-| test.c:240:22:240:23 | r4_2(int) = Constant[11] | test.c:240:22:240:23 | 11 |
-| test.c:244:22:244:23 | r9_2(int) = Constant[11] | test.c:244:22:244:23 | 11 |
-| test.c:256:24:256:25 | r14_2(int) = Constant[11] | test.c:256:24:256:25 | 11 |
-| test.c:256:30:256:30 | r15_0(int) = Constant[5] | test.c:256:30:256:30 | 5 |
-| test.c:256:45:256:46 | r16_2(int) = Constant[23] | test.c:256:45:256:46 | 23 |
-| test.c:260:24:260:25 | r19_2(int) = Constant[11] | test.c:260:24:260:25 | 11 |
-| test.c:260:45:260:46 | r21_2(int) = Constant[23] | test.c:260:45:260:46 | 23 |
-| test.c:264:24:264:25 | r24_2(int) = Constant[11] | test.c:264:24:264:25 | 11 |
-| test.c:264:47:264:48 | r1_2(int) = Constant[23] | test.c:264:47:264:48 | 23 |
-| test.c:268:24:268:25 | r4_2(int) = Constant[11] | test.c:268:24:268:25 | 11 |
-| test.c:272:24:272:25 | r9_2(int) = Constant[11] | test.c:272:24:272:25 | 11 |
-| test.c:284:29:284:29 | r15_0(int) = Constant[5] | test.c:284:29:284:29 | 5 |
-| test.c:284:44:284:45 | r16_2(int) = Constant[23] | test.c:284:44:284:45 | 23 |
-| test.c:288:44:288:45 | r21_2(int) = Constant[23] | test.c:288:44:288:45 | 23 |
-| test.c:292:46:292:47 | r1_2(int) = Constant[23] | test.c:292:46:292:47 | 23 |
-| test.c:312:30:312:30 | r15_0(int) = Constant[5] | test.c:312:30:312:30 | 5 |
-| test.c:312:45:312:46 | r16_2(int) = Constant[23] | test.c:312:45:312:46 | 23 |
-| test.c:316:45:316:46 | r21_2(int) = Constant[23] | test.c:316:45:316:46 | 23 |
-| test.c:320:47:320:48 | r1_2(int) = Constant[23] | test.c:320:47:320:48 | 23 |
-| test.c:342:14:342:14 | r3_3(int) = Constant[3] | test.c:342:14:342:14 | 3 |
-| test.c:343:5:343:7 | r4_2(int) = Constant[1] | test.c:343:5:343:7 | ... ++ |
-| test.c:348:14:348:14 | r7_1(int) = Constant[1] | test.c:348:14:348:14 | 1 |
-| test.c:357:12:357:14 | r0_22(unsigned int) = Constant[100] | test.c:357:12:357:14 | (unsigned int)... |
-| test.c:357:22:357:23 | r22_0(unsigned int) = Constant[10] | test.c:357:22:357:23 | (unsigned int)... |
-| test.c:358:13:358:15 | r17_7(unsigned int) = Constant[100] | test.c:358:13:358:15 | (unsigned int)... |
-| test.c:358:19:358:20 | r24_0(unsigned int) = Constant[10] | test.c:358:19:358:20 | (unsigned int)... |
-| test.c:365:11:365:13 | r23_25(unsigned int) = Constant[300] | test.c:365:11:365:13 | (unsigned int)... |
-| test.c:366:15:366:15 | r38_0(unsigned int) = Constant[5] | test.c:366:15:366:15 | (unsigned int)... |
-| test.c:366:15:366:15 | r40_0(unsigned int) = Constant[5] | test.c:366:15:366:15 | (unsigned int)... |
-| test.c:367:15:367:17 | r48_0(unsigned int) = Constant[500] | test.c:367:15:367:17 | (unsigned int)... |
-| test.c:367:15:367:17 | r50_0(unsigned int) = Constant[500] | test.c:367:15:367:17 | (unsigned int)... |
-| test.c:368:13:368:13 | r27_0(unsigned int) = Constant[1] | test.c:368:13:368:13 | (unsigned int)... |
-| test.c:368:13:368:13 | r54_0(unsigned int) = Constant[1] | test.c:368:13:368:13 | (unsigned int)... |
-| test.c:368:19:368:21 | r55_0(unsigned int) = Constant[500] | test.c:368:19:368:21 | (unsigned int)... |
-| test.c:369:29:369:29 | r4_0(unsigned int) = Constant[1] | test.c:369:29:369:29 | (unsigned int)... |
-| test.c:369:29:369:29 | r41_0(unsigned int) = Constant[1] | test.c:369:29:369:29 | (unsigned int)... |
-| test.c:369:36:369:36 | r5_0(int) = Constant[5] | test.c:369:36:369:36 | 5 |
-| test.c:370:29:370:29 | r9_0(unsigned int) = Constant[1] | test.c:370:29:370:29 | (unsigned int)... |
-| test.c:370:29:370:29 | r41_0(unsigned int) = Constant[1] | test.c:370:29:370:29 | (unsigned int)... |
-| test.c:370:36:370:38 | r10_0(int) = Constant[500] | test.c:370:36:370:38 | 500 |
-| test.c:371:30:371:30 | r14_0(unsigned int) = Constant[1] | test.c:371:30:371:30 | (unsigned int)... |
-| test.c:371:30:371:30 | r41_0(unsigned int) = Constant[1] | test.c:371:30:371:30 | (unsigned int)... |
-| test.c:371:37:371:39 | r15_0(int) = Constant[500] | test.c:371:37:371:39 | 500 |
-| test.c:379:12:379:14 | r0_16(unsigned int) = Constant[100] | test.c:379:12:379:14 | (unsigned int)... |
-| test.c:379:22:379:24 | r5_0(unsigned int) = Constant[110] | test.c:379:22:379:24 | (unsigned int)... |
-| test.c:380:13:380:15 | r1_7(unsigned int) = Constant[100] | test.c:380:13:380:15 | (unsigned int)... |
-| test.c:380:19:380:21 | r7_0(unsigned int) = Constant[110] | test.c:380:19:380:21 | (unsigned int)... |
-| test.c:381:8:381:11 | r6_5(unsigned int) = Constant[1000] | test.c:381:8:381:11 | (unsigned int)... |
-| test.c:382:8:382:11 | r6_8(unsigned int) = Constant[1000] | test.c:382:8:382:11 | (unsigned int)... |
-| test.c:383:8:383:11 | r6_11(unsigned int) = Constant[1000] | test.c:383:8:383:11 | (unsigned int)... |
-| test.c:384:12:384:14 | r6_16(unsigned int) = Constant[300] | test.c:384:12:384:14 | (unsigned int)... |
-| test.c:385:13:385:15 | r11_0(unsigned int) = Constant[300] | test.c:385:13:385:15 | (unsigned int)... |
-| test.c:385:13:385:15 | r18_0(unsigned int) = Constant[300] | test.c:385:13:385:15 | (unsigned int)... |
-| test.c:385:21:385:21 | r19_0(unsigned int) = Constant[5] | test.c:385:21:385:21 | (unsigned int)... |
-| test.c:386:13:386:15 | r11_0(unsigned int) = Constant[200] | test.c:386:13:386:15 | (unsigned int)... |
-| test.c:386:13:386:15 | r24_0(unsigned int) = Constant[200] | test.c:386:13:386:15 | (unsigned int)... |
-| test.c:386:21:386:21 | r25_0(unsigned int) = Constant[5] | test.c:386:21:386:21 | (unsigned int)... |
-| test.c:387:29:387:31 | r28_0(unsigned int) = Constant[200] | test.c:387:29:387:31 | (unsigned int)... |
-| test.c:387:29:387:31 | r30_0(unsigned int) = Constant[200] | test.c:387:29:387:31 | (unsigned int)... |
-| test.c:387:38:387:38 | r31_0(int) = Constant[5] | test.c:387:38:387:38 | 5 |
-| test.c:394:24:394:26 | r0_7(unsigned int) = Constant[100] | test.c:394:24:394:26 | (unsigned int)... |
-| test.c:394:34:394:36 | r2_0(unsigned int) = Constant[100] | test.c:394:34:394:36 | (unsigned int)... |
-| test.c:397:9:397:11 | r3_10(unsigned int) = Constant[1] | test.c:397:9:397:11 | ++ ... |
-| test.c:398:9:398:11 | r3_19(unsigned int) = Constant[1] | test.c:398:9:398:11 | ... ++ |
-| test.c:398:19:398:19 | r3_22(unsigned int) = Constant[3] | test.c:398:19:398:19 | (unsigned int)... |
-| test.cpp:11:13:11:13 | r1_2(int) = Constant[3] | test.cpp:11:13:11:13 | 3 |
-| test.cpp:33:12:33:12 | r13_3(int) = Constant[1] | test.cpp:33:12:33:12 | 1 |
-| test.cpp:34:9:34:9 | r14_0(int) = Constant[1] | test.cpp:34:9:34:9 | 1 |
-| test.cpp:39:12:39:14 | r17_3(int) = Constant[128] | test.cpp:39:12:39:14 | 128 |
-| test.cpp:40:9:40:11 | r18_0(int) = Constant[128] | test.cpp:40:9:40:11 | 128 |
-| test.cpp:45:12:45:15 | r21_3(int) = Constant[1024] | test.cpp:45:12:45:15 | 1024 |
-| test.cpp:46:9:46:12 | r22_0(int) = Constant[1024] | test.cpp:46:9:46:12 | 1024 |
-| test.cpp:69:10:69:21 | r9_1(bool) = Constant[1] | test.cpp:69:10:69:21 | ... \|\| ... |
diff --git a/cpp/ql/test/library-tests/rangeanalysis/signanalysis/positive.ql b/cpp/ql/test/library-tests/rangeanalysis/signanalysis/positive.ql
deleted file mode 100644
index f57a29493ab..00000000000
--- a/cpp/ql/test/library-tests/rangeanalysis/signanalysis/positive.ql
+++ /dev/null
@@ -1,6 +0,0 @@
-import semmle.code.cpp.rangeanalysis.SignAnalysis
-import semmle.code.cpp.ir.IR
-
-from Instruction i
-where positive(i)
-select i, i.getAST()
\ No newline at end of file
diff --git a/cpp/ql/test/library-tests/rangeanalysis/signanalysis/strictlyNegative.expected b/cpp/ql/test/library-tests/rangeanalysis/signanalysis/strictlyNegative.expected
deleted file mode 100644
index 409def9f448..00000000000
--- a/cpp/ql/test/library-tests/rangeanalysis/signanalysis/strictlyNegative.expected
+++ /dev/null
@@ -1,64 +0,0 @@
-| test.c:67:7:67:11 | r0_6(int) = Constant[-1000] | test.c:67:7:67:11 | - ... |
-| test.c:137:20:137:22 | m0_19(unsigned int) = Store r0_14, r0_18 | test.c:137:20:137:22 | ... - ... |
-| test.c:137:20:137:22 | r0_18(unsigned int) = Sub r0_16, r0_17 | test.c:137:20:137:22 | ... - ... |
-| test.c:139:36:139:36 | r0_42(unsigned int) = Load r0_41, m0_19 | test.c:139:36:139:36 | y |
-| test.c:154:10:154:40 | m3_2(long long) = Store r3_1, r3_0 | test.c:154:10:154:40 | ... ? ... : ... |
-| test.c:154:39:154:40 | r3_0(long long) = Constant[-1] | test.c:154:39:154:40 | (long long)... |
-| test.c:171:7:171:8 | r16_1(int) = Constant[-7] | test.c:171:7:171:8 | - ... |
-| test.c:176:7:176:8 | r1_1(int) = Constant[-7] | test.c:176:7:176:8 | - ... |
-| test.c:181:7:181:8 | r4_1(int) = Constant[-7] | test.c:181:7:181:8 | - ... |
-| test.c:186:7:186:8 | r7_1(int) = Constant[-7] | test.c:186:7:186:8 | - ... |
-| test.c:186:23:186:24 | r9_2(int) = Constant[-2] | test.c:186:23:186:24 | - ... |
-| test.c:208:28:208:30 | r25_0(int) = Constant[-13] | test.c:208:28:208:30 | - ... |
-| test.c:212:28:212:30 | r5_0(int) = Constant[-13] | test.c:212:28:212:30 | - ... |
-| test.c:216:28:216:30 | r10_0(int) = Constant[-13] | test.c:216:28:216:30 | - ... |
-| test.c:216:45:216:46 | r11_2(int) = Constant[-7] | test.c:216:45:216:46 | - ... |
-| test.c:236:28:236:30 | r25_0(int) = Constant[-13] | test.c:236:28:236:30 | - ... |
-| test.c:240:28:240:30 | r5_0(int) = Constant[-13] | test.c:240:28:240:30 | - ... |
-| test.c:244:28:244:30 | r10_0(int) = Constant[-13] | test.c:244:28:244:30 | - ... |
-| test.c:244:45:244:46 | r11_2(int) = Constant[-7] | test.c:244:45:244:46 | - ... |
-| test.c:256:7:256:9 | r0_9(int) = Constant[-17] | test.c:256:7:256:9 | - ... |
-| test.c:260:7:260:9 | r18_1(int) = Constant[-17] | test.c:260:7:260:9 | - ... |
-| test.c:264:7:264:9 | r23_1(int) = Constant[-17] | test.c:264:7:264:9 | - ... |
-| test.c:264:30:264:32 | r25_0(int) = Constant[-13] | test.c:264:30:264:32 | - ... |
-| test.c:268:7:268:9 | r3_1(int) = Constant[-17] | test.c:268:7:268:9 | - ... |
-| test.c:268:30:268:32 | r5_0(int) = Constant[-13] | test.c:268:30:268:32 | - ... |
-| test.c:272:7:272:9 | r8_1(int) = Constant[-17] | test.c:272:7:272:9 | - ... |
-| test.c:272:30:272:32 | r10_0(int) = Constant[-13] | test.c:272:30:272:32 | - ... |
-| test.c:272:47:272:48 | r11_2(int) = Constant[-7] | test.c:272:47:272:48 | - ... |
-| test.c:284:7:284:9 | r0_9(int) = Constant[-17] | test.c:284:7:284:9 | - ... |
-| test.c:288:7:288:9 | r18_1(int) = Constant[-17] | test.c:288:7:288:9 | - ... |
-| test.c:292:7:292:9 | r23_1(int) = Constant[-17] | test.c:292:7:292:9 | - ... |
-| test.c:292:29:292:31 | r25_0(int) = Constant[-13] | test.c:292:29:292:31 | - ... |
-| test.c:296:7:296:9 | r3_1(int) = Constant[-17] | test.c:296:7:296:9 | - ... |
-| test.c:296:29:296:31 | r5_0(int) = Constant[-13] | test.c:296:29:296:31 | - ... |
-| test.c:300:7:300:9 | r8_1(int) = Constant[-17] | test.c:300:7:300:9 | - ... |
-| test.c:300:29:300:31 | r10_0(int) = Constant[-13] | test.c:300:29:300:31 | - ... |
-| test.c:300:46:300:47 | r11_2(int) = Constant[-7] | test.c:300:46:300:47 | - ... |
-| test.c:312:7:312:9 | r0_9(int) = Constant[-17] | test.c:312:7:312:9 | - ... |
-| test.c:312:24:312:25 | r14_2(int) = Constant[-2] | test.c:312:24:312:25 | - ... |
-| test.c:316:7:316:9 | r18_1(int) = Constant[-17] | test.c:316:7:316:9 | - ... |
-| test.c:316:24:316:25 | r19_2(int) = Constant[-2] | test.c:316:24:316:25 | - ... |
-| test.c:320:7:320:9 | r23_1(int) = Constant[-17] | test.c:320:7:320:9 | - ... |
-| test.c:320:24:320:25 | r24_2(int) = Constant[-2] | test.c:320:24:320:25 | - ... |
-| test.c:320:30:320:32 | r25_0(int) = Constant[-13] | test.c:320:30:320:32 | - ... |
-| test.c:324:7:324:9 | r3_1(int) = Constant[-17] | test.c:324:7:324:9 | - ... |
-| test.c:324:24:324:25 | r4_2(int) = Constant[-2] | test.c:324:24:324:25 | - ... |
-| test.c:324:30:324:32 | r5_0(int) = Constant[-13] | test.c:324:30:324:32 | - ... |
-| test.c:328:7:328:9 | r8_1(int) = Constant[-17] | test.c:328:7:328:9 | - ... |
-| test.c:328:24:328:25 | r9_2(int) = Constant[-2] | test.c:328:24:328:25 | - ... |
-| test.c:328:30:328:32 | r10_0(int) = Constant[-13] | test.c:328:30:328:32 | - ... |
-| test.c:328:47:328:48 | r11_2(int) = Constant[-7] | test.c:328:47:328:48 | - ... |
-| test.c:339:12:339:13 | m2_2(int) = Store r2_0, r2_1 | test.c:339:12:339:13 | - ... |
-| test.c:339:12:339:13 | r2_1(int) = Constant[-1] | test.c:339:12:339:13 | - ... |
-| test.cpp:9:11:9:12 | m0_8(int) = Store r0_6, r0_7 | test.cpp:9:11:9:12 | - ... |
-| test.cpp:9:11:9:12 | r0_7(int) = Constant[-1] | test.cpp:9:11:9:12 | - ... |
-| test.cpp:30:12:30:13 | r11_3(int) = Constant[-1] | test.cpp:30:12:30:13 | - ... |
-| test.cpp:31:5:31:10 | m12_2(int) = Store r12_1, r12_0 | test.cpp:31:5:31:10 | ... = ... |
-| test.cpp:31:9:31:10 | r12_0(int) = Constant[-1] | test.cpp:31:9:31:10 | - ... |
-| test.cpp:36:12:36:15 | r15_3(int) = Constant[-128] | test.cpp:36:12:36:15 | - ... |
-| test.cpp:37:5:37:12 | m16_2(int) = Store r16_1, r16_0 | test.cpp:37:5:37:12 | ... = ... |
-| test.cpp:37:9:37:12 | r16_0(int) = Constant[-128] | test.cpp:37:9:37:12 | - ... |
-| test.cpp:42:12:42:16 | r19_3(int) = Constant[-1024] | test.cpp:42:12:42:16 | - ... |
-| test.cpp:43:5:43:13 | m20_2(int) = Store r20_1, r20_0 | test.cpp:43:5:43:13 | ... = ... |
-| test.cpp:43:9:43:13 | r20_0(int) = Constant[-1024] | test.cpp:43:9:43:13 | - ... |
diff --git a/cpp/ql/test/library-tests/rangeanalysis/signanalysis/strictlyNegative.ql b/cpp/ql/test/library-tests/rangeanalysis/signanalysis/strictlyNegative.ql
deleted file mode 100644
index b13fdd5638c..00000000000
--- a/cpp/ql/test/library-tests/rangeanalysis/signanalysis/strictlyNegative.ql
+++ /dev/null
@@ -1,6 +0,0 @@
-import semmle.code.cpp.rangeanalysis.SignAnalysis
-import semmle.code.cpp.ir.IR
-
-from Instruction i
-where strictlyNegative(i)
-select i, i.getAST()
\ No newline at end of file
diff --git a/cpp/ql/test/library-tests/rangeanalysis/signanalysis/strictlyPositive.expected b/cpp/ql/test/library-tests/rangeanalysis/signanalysis/strictlyPositive.expected
deleted file mode 100644
index 64dad2b3ceb..00000000000
--- a/cpp/ql/test/library-tests/rangeanalysis/signanalysis/strictlyPositive.expected
+++ /dev/null
@@ -1,136 +0,0 @@
-| inline_assembly.c:10:7:10:7 | r0_7(unsigned int) = Constant[1] | inline_assembly.c:10:7:10:7 | (unsigned int)... |
-| minmax.c:16:9:16:10 | r0_3(int) = Constant[1] | minmax.c:16:9:16:10 | 1 |
-| minmax.c:16:16:16:17 | r0_6(int) = Constant[2] | minmax.c:16:16:16:17 | 2 |
-| minmax.c:16:23:16:24 | r0_9(int) = Constant[3] | minmax.c:16:23:16:24 | 3 |
-| test.c:8:19:8:19 | r2_2(int) = Constant[1] | test.c:8:19:8:19 | 1 |
-| test.c:16:20:16:20 | r2_2(int) = Constant[1] | test.c:16:20:16:20 | 1 |
-| test.c:16:25:16:26 | r2_4(int) = Constant[10] | test.c:16:25:16:26 | 10 |
-| test.c:24:5:24:11 | r2_2(int) = Constant[1] | test.c:24:5:24:11 | ... ++ |
-| test.c:25:21:25:22 | r2_7(int) = Constant[10] | test.c:25:21:25:22 | 10 |
-| test.c:33:19:33:19 | r1_4(int) = Constant[2] | test.c:33:19:33:19 | 2 |
-| test.c:33:28:33:28 | r2_8(int) = Constant[1] | test.c:33:28:33:28 | 1 |
-| test.c:42:19:42:19 | r1_4(int) = Constant[2] | test.c:42:19:42:19 | 2 |
-| test.c:42:22:42:24 | r2_8(int) = Constant[1] | test.c:42:22:42:24 | ... ++ |
-| test.c:51:17:51:17 | r1_4(int) = Constant[2] | test.c:51:17:51:17 | 2 |
-| test.c:51:21:51:21 | r1_6(int) = Constant[4] | test.c:51:21:51:21 | 4 |
-| test.c:51:30:51:30 | r2_8(int) = Constant[1] | test.c:51:30:51:30 | 1 |
-| test.c:58:11:58:11 | r0_6(int) = Constant[4] | test.c:58:11:58:11 | 4 |
-| test.c:59:13:59:13 | r2_2(int) = Constant[5] | test.c:59:13:59:13 | 5 |
-| test.c:63:10:63:10 | r4_1(int) = Constant[1] | test.c:63:10:63:10 | 1 |
-| test.c:67:24:67:25 | r2_2(int) = Constant[10] | test.c:67:24:67:25 | 10 |
-| test.c:68:15:68:15 | r3_4(int) = Constant[2] | test.c:68:15:68:15 | 2 |
-| test.c:77:13:77:13 | r2_2(int) = Constant[4] | test.c:77:13:77:13 | 4 |
-| test.c:81:13:81:13 | r4_2(int) = Constant[4] | test.c:81:13:81:13 | 4 |
-| test.c:82:14:82:14 | r5_1(int) = Constant[1] | test.c:82:14:82:14 | 1 |
-| test.c:89:11:89:11 | r0_8(int) = Constant[7] | test.c:89:11:89:11 | 7 |
-| test.c:95:10:95:10 | r5_1(int) = Constant[1] | test.c:95:10:95:10 | 1 |
-| test.c:102:6:102:8 | r2_3(int) = Constant[1] | test.c:102:6:102:8 | ... ++ |
-| test.c:104:12:104:14 | r3_4(int) = Constant[58] | test.c:104:12:104:14 | 58 |
-| test.c:107:8:107:10 | r5_3(int) = Constant[1] | test.c:107:8:107:10 | ... ++ |
-| test.c:109:14:109:16 | r6_3(int) = Constant[44] | test.c:109:14:109:16 | 44 |
-| test.c:110:14:110:14 | r7_1(int) = Constant[1] | test.c:110:14:110:14 | 1 |
-| test.c:119:10:119:12 | r0_8(unsigned long long) = Constant[1] | test.c:119:10:119:12 | ... ++ |
-| test.c:124:36:124:36 | r1_5(unsigned long long) = Constant[1] | test.c:124:36:124:36 | (unsigned long long)... |
-| test.c:127:24:127:24 | r2_6(unsigned long long) = Constant[1] | test.c:127:24:127:24 | (unsigned long long)... |
-| test.c:130:11:130:11 | r3_1(int) = Constant[1] | test.c:130:11:130:11 | 1 |
-| test.c:137:22:137:22 | r0_17(unsigned int) = Constant[1] | test.c:137:22:137:22 | (unsigned int)... |
-| test.c:138:13:138:13 | r0_23(int) = Constant[1] | test.c:138:13:138:13 | 1 |
-| test.c:161:7:161:7 | r0_7(int) = Constant[3] | test.c:161:7:161:7 | 3 |
-| test.c:161:22:161:23 | r8_2(int) = Constant[11] | test.c:161:22:161:23 | 11 |
-| test.c:166:22:166:23 | r14_2(int) = Constant[11] | test.c:166:22:166:23 | 11 |
-| test.c:171:23:171:24 | r17_2(int) = Constant[11] | test.c:171:23:171:24 | 11 |
-| test.c:176:23:176:23 | r2_2(int) = Constant[1] | test.c:176:23:176:23 | 1 |
-| test.c:200:7:200:7 | r0_9(int) = Constant[3] | test.c:200:7:200:7 | 3 |
-| test.c:200:22:200:23 | r14_2(int) = Constant[11] | test.c:200:22:200:23 | 11 |
-| test.c:200:28:200:28 | r15_0(int) = Constant[5] | test.c:200:28:200:28 | 5 |
-| test.c:200:43:200:44 | r16_2(int) = Constant[23] | test.c:200:43:200:44 | 23 |
-| test.c:204:7:204:7 | r18_1(int) = Constant[3] | test.c:204:7:204:7 | 3 |
-| test.c:204:22:204:23 | r19_2(int) = Constant[11] | test.c:204:22:204:23 | 11 |
-| test.c:204:43:204:44 | r21_2(int) = Constant[23] | test.c:204:43:204:44 | 23 |
-| test.c:208:7:208:7 | r23_1(int) = Constant[3] | test.c:208:7:208:7 | 3 |
-| test.c:208:22:208:23 | r24_2(int) = Constant[11] | test.c:208:22:208:23 | 11 |
-| test.c:208:45:208:46 | r1_2(int) = Constant[23] | test.c:208:45:208:46 | 23 |
-| test.c:212:7:212:7 | r3_1(int) = Constant[3] | test.c:212:7:212:7 | 3 |
-| test.c:212:22:212:23 | r4_2(int) = Constant[11] | test.c:212:22:212:23 | 11 |
-| test.c:216:7:216:7 | r8_1(int) = Constant[3] | test.c:216:7:216:7 | 3 |
-| test.c:216:22:216:23 | r9_2(int) = Constant[11] | test.c:216:22:216:23 | 11 |
-| test.c:228:22:228:23 | r14_2(int) = Constant[11] | test.c:228:22:228:23 | 11 |
-| test.c:228:28:228:28 | r15_0(int) = Constant[5] | test.c:228:28:228:28 | 5 |
-| test.c:228:43:228:44 | r16_2(int) = Constant[23] | test.c:228:43:228:44 | 23 |
-| test.c:232:22:232:23 | r19_2(int) = Constant[11] | test.c:232:22:232:23 | 11 |
-| test.c:232:43:232:44 | r21_2(int) = Constant[23] | test.c:232:43:232:44 | 23 |
-| test.c:236:22:236:23 | r24_2(int) = Constant[11] | test.c:236:22:236:23 | 11 |
-| test.c:236:45:236:46 | r1_2(int) = Constant[23] | test.c:236:45:236:46 | 23 |
-| test.c:240:22:240:23 | r4_2(int) = Constant[11] | test.c:240:22:240:23 | 11 |
-| test.c:244:22:244:23 | r9_2(int) = Constant[11] | test.c:244:22:244:23 | 11 |
-| test.c:256:24:256:25 | r14_2(int) = Constant[11] | test.c:256:24:256:25 | 11 |
-| test.c:256:30:256:30 | r15_0(int) = Constant[5] | test.c:256:30:256:30 | 5 |
-| test.c:256:45:256:46 | r16_2(int) = Constant[23] | test.c:256:45:256:46 | 23 |
-| test.c:260:24:260:25 | r19_2(int) = Constant[11] | test.c:260:24:260:25 | 11 |
-| test.c:260:45:260:46 | r21_2(int) = Constant[23] | test.c:260:45:260:46 | 23 |
-| test.c:264:24:264:25 | r24_2(int) = Constant[11] | test.c:264:24:264:25 | 11 |
-| test.c:264:47:264:48 | r1_2(int) = Constant[23] | test.c:264:47:264:48 | 23 |
-| test.c:268:24:268:25 | r4_2(int) = Constant[11] | test.c:268:24:268:25 | 11 |
-| test.c:272:24:272:25 | r9_2(int) = Constant[11] | test.c:272:24:272:25 | 11 |
-| test.c:284:29:284:29 | r15_0(int) = Constant[5] | test.c:284:29:284:29 | 5 |
-| test.c:284:44:284:45 | r16_2(int) = Constant[23] | test.c:284:44:284:45 | 23 |
-| test.c:288:44:288:45 | r21_2(int) = Constant[23] | test.c:288:44:288:45 | 23 |
-| test.c:292:46:292:47 | r1_2(int) = Constant[23] | test.c:292:46:292:47 | 23 |
-| test.c:312:30:312:30 | r15_0(int) = Constant[5] | test.c:312:30:312:30 | 5 |
-| test.c:312:45:312:46 | r16_2(int) = Constant[23] | test.c:312:45:312:46 | 23 |
-| test.c:316:45:316:46 | r21_2(int) = Constant[23] | test.c:316:45:316:46 | 23 |
-| test.c:320:47:320:48 | r1_2(int) = Constant[23] | test.c:320:47:320:48 | 23 |
-| test.c:342:14:342:14 | r3_3(int) = Constant[3] | test.c:342:14:342:14 | 3 |
-| test.c:343:5:343:7 | r4_2(int) = Constant[1] | test.c:343:5:343:7 | ... ++ |
-| test.c:348:14:348:14 | r7_1(int) = Constant[1] | test.c:348:14:348:14 | 1 |
-| test.c:357:12:357:14 | r0_22(unsigned int) = Constant[100] | test.c:357:12:357:14 | (unsigned int)... |
-| test.c:357:22:357:23 | r22_0(unsigned int) = Constant[10] | test.c:357:22:357:23 | (unsigned int)... |
-| test.c:358:13:358:15 | r17_7(unsigned int) = Constant[100] | test.c:358:13:358:15 | (unsigned int)... |
-| test.c:358:19:358:20 | r24_0(unsigned int) = Constant[10] | test.c:358:19:358:20 | (unsigned int)... |
-| test.c:365:11:365:13 | r23_25(unsigned int) = Constant[300] | test.c:365:11:365:13 | (unsigned int)... |
-| test.c:366:15:366:15 | r38_0(unsigned int) = Constant[5] | test.c:366:15:366:15 | (unsigned int)... |
-| test.c:366:15:366:15 | r40_0(unsigned int) = Constant[5] | test.c:366:15:366:15 | (unsigned int)... |
-| test.c:367:15:367:17 | r48_0(unsigned int) = Constant[500] | test.c:367:15:367:17 | (unsigned int)... |
-| test.c:367:15:367:17 | r50_0(unsigned int) = Constant[500] | test.c:367:15:367:17 | (unsigned int)... |
-| test.c:368:13:368:13 | r27_0(unsigned int) = Constant[1] | test.c:368:13:368:13 | (unsigned int)... |
-| test.c:368:13:368:13 | r54_0(unsigned int) = Constant[1] | test.c:368:13:368:13 | (unsigned int)... |
-| test.c:368:19:368:21 | r55_0(unsigned int) = Constant[500] | test.c:368:19:368:21 | (unsigned int)... |
-| test.c:369:29:369:29 | r4_0(unsigned int) = Constant[1] | test.c:369:29:369:29 | (unsigned int)... |
-| test.c:369:29:369:29 | r41_0(unsigned int) = Constant[1] | test.c:369:29:369:29 | (unsigned int)... |
-| test.c:369:36:369:36 | r5_0(int) = Constant[5] | test.c:369:36:369:36 | 5 |
-| test.c:370:29:370:29 | r9_0(unsigned int) = Constant[1] | test.c:370:29:370:29 | (unsigned int)... |
-| test.c:370:29:370:29 | r41_0(unsigned int) = Constant[1] | test.c:370:29:370:29 | (unsigned int)... |
-| test.c:370:36:370:38 | r10_0(int) = Constant[500] | test.c:370:36:370:38 | 500 |
-| test.c:371:30:371:30 | r14_0(unsigned int) = Constant[1] | test.c:371:30:371:30 | (unsigned int)... |
-| test.c:371:30:371:30 | r41_0(unsigned int) = Constant[1] | test.c:371:30:371:30 | (unsigned int)... |
-| test.c:371:37:371:39 | r15_0(int) = Constant[500] | test.c:371:37:371:39 | 500 |
-| test.c:379:12:379:14 | r0_16(unsigned int) = Constant[100] | test.c:379:12:379:14 | (unsigned int)... |
-| test.c:379:22:379:24 | r5_0(unsigned int) = Constant[110] | test.c:379:22:379:24 | (unsigned int)... |
-| test.c:380:13:380:15 | r1_7(unsigned int) = Constant[100] | test.c:380:13:380:15 | (unsigned int)... |
-| test.c:380:19:380:21 | r7_0(unsigned int) = Constant[110] | test.c:380:19:380:21 | (unsigned int)... |
-| test.c:381:8:381:11 | r6_5(unsigned int) = Constant[1000] | test.c:381:8:381:11 | (unsigned int)... |
-| test.c:382:8:382:11 | r6_8(unsigned int) = Constant[1000] | test.c:382:8:382:11 | (unsigned int)... |
-| test.c:383:8:383:11 | r6_11(unsigned int) = Constant[1000] | test.c:383:8:383:11 | (unsigned int)... |
-| test.c:384:12:384:14 | r6_16(unsigned int) = Constant[300] | test.c:384:12:384:14 | (unsigned int)... |
-| test.c:385:13:385:15 | r11_0(unsigned int) = Constant[300] | test.c:385:13:385:15 | (unsigned int)... |
-| test.c:385:13:385:15 | r18_0(unsigned int) = Constant[300] | test.c:385:13:385:15 | (unsigned int)... |
-| test.c:385:21:385:21 | r19_0(unsigned int) = Constant[5] | test.c:385:21:385:21 | (unsigned int)... |
-| test.c:386:13:386:15 | r11_0(unsigned int) = Constant[200] | test.c:386:13:386:15 | (unsigned int)... |
-| test.c:386:13:386:15 | r24_0(unsigned int) = Constant[200] | test.c:386:13:386:15 | (unsigned int)... |
-| test.c:386:21:386:21 | r25_0(unsigned int) = Constant[5] | test.c:386:21:386:21 | (unsigned int)... |
-| test.c:387:29:387:31 | r28_0(unsigned int) = Constant[200] | test.c:387:29:387:31 | (unsigned int)... |
-| test.c:387:29:387:31 | r30_0(unsigned int) = Constant[200] | test.c:387:29:387:31 | (unsigned int)... |
-| test.c:387:38:387:38 | r31_0(int) = Constant[5] | test.c:387:38:387:38 | 5 |
-| test.c:394:24:394:26 | r0_7(unsigned int) = Constant[100] | test.c:394:24:394:26 | (unsigned int)... |
-| test.c:394:34:394:36 | r2_0(unsigned int) = Constant[100] | test.c:394:34:394:36 | (unsigned int)... |
-| test.c:397:9:397:11 | r3_10(unsigned int) = Constant[1] | test.c:397:9:397:11 | ++ ... |
-| test.c:398:9:398:11 | r3_19(unsigned int) = Constant[1] | test.c:398:9:398:11 | ... ++ |
-| test.c:398:19:398:19 | r3_22(unsigned int) = Constant[3] | test.c:398:19:398:19 | (unsigned int)... |
-| test.cpp:11:13:11:13 | r1_2(int) = Constant[3] | test.cpp:11:13:11:13 | 3 |
-| test.cpp:33:12:33:12 | r13_3(int) = Constant[1] | test.cpp:33:12:33:12 | 1 |
-| test.cpp:34:9:34:9 | r14_0(int) = Constant[1] | test.cpp:34:9:34:9 | 1 |
-| test.cpp:39:12:39:14 | r17_3(int) = Constant[128] | test.cpp:39:12:39:14 | 128 |
-| test.cpp:40:9:40:11 | r18_0(int) = Constant[128] | test.cpp:40:9:40:11 | 128 |
-| test.cpp:45:12:45:15 | r21_3(int) = Constant[1024] | test.cpp:45:12:45:15 | 1024 |
-| test.cpp:46:9:46:12 | r22_0(int) = Constant[1024] | test.cpp:46:9:46:12 | 1024 |
-| test.cpp:69:10:69:21 | r9_1(bool) = Constant[1] | test.cpp:69:10:69:21 | ... \|\| ... |
diff --git a/cpp/ql/test/library-tests/rangeanalysis/signanalysis/strictlyPositive.ql b/cpp/ql/test/library-tests/rangeanalysis/signanalysis/strictlyPositive.ql
deleted file mode 100644
index 271b17ff9f3..00000000000
--- a/cpp/ql/test/library-tests/rangeanalysis/signanalysis/strictlyPositive.ql
+++ /dev/null
@@ -1,6 +0,0 @@
-import semmle.code.cpp.rangeanalysis.SignAnalysis
-import semmle.code.cpp.ir.IR
-
-from Instruction i
-where strictlyPositive(i)
-select i, i.getAST()
\ No newline at end of file
From 554fea46c7300a0852b0b7b057a140e8ca5022b0 Mon Sep 17 00:00:00 2001
From: Robert Marsh
Date: Wed, 19 Sep 2018 16:10:55 -0700
Subject: [PATCH 06/71] C++: Sign analysis for casts and unsigned integers
---
.../code/cpp/rangeanalysis/SignAnalysis.qll | 91 ++++++++++-
.../signanalysis/SignAnalysis.expected | 149 +++++++++++++++++-
2 files changed, 233 insertions(+), 7 deletions(-)
diff --git a/cpp/ql/src/semmle/code/cpp/rangeanalysis/SignAnalysis.qll b/cpp/ql/src/semmle/code/cpp/rangeanalysis/SignAnalysis.qll
index 16cb2c647a6..e52d33d1e0d 100644
--- a/cpp/ql/src/semmle/code/cpp/rangeanalysis/SignAnalysis.qll
+++ b/cpp/ql/src/semmle/code/cpp/rangeanalysis/SignAnalysis.qll
@@ -119,7 +119,6 @@ private Sign certainInstructionSign(Instruction inst) {
i > 0 and result = TPos()
)
or
- not inst instanceof IntegerConstantInstruction and
exists(float f | f = inst.(FloatConstantInstruction).getValue().toFloat() |
f < 0 and result = TNeg() or
f = 0 and result = TZero() or
@@ -127,6 +126,69 @@ private Sign certainInstructionSign(Instruction inst) {
)
}
+private newtype CastKind = TWiden() or TSame() or TNarrow()
+
+private CastKind getCastKind(ConvertInstruction ci) {
+ exists(int fromSize, int toSize |
+ toSize = ci.getResultSize() and
+ fromSize = ci.getOperand().getResultSize()
+ |
+ fromSize < toSize and
+ result = TWiden()
+ or
+ fromSize = toSize and
+ result = TSame()
+ or
+ fromSize > toSize and
+ result = TNarrow()
+ )
+}
+
+private predicate bindBool(boolean bool) {
+ bool = true or
+ bool = false
+}
+
+private Sign castSign(Sign s, boolean fromSigned, boolean toSigned, CastKind ck) {
+ result = TZero() and
+ (
+ bindBool(fromSigned) and
+ bindBool(toSigned) and
+ s = TZero()
+ or
+ bindBool(fromSigned) and
+ bindBool(toSigned) and
+ ck = TNarrow()
+ )
+ or
+ result = TPos() and
+ (
+ bindBool(fromSigned) and
+ bindBool(toSigned) and
+ s = TPos()
+ or
+ bindBool(fromSigned) and
+ bindBool(toSigned) and
+ s = TNeg() and
+ ck = TNarrow()
+ or
+ fromSigned = true and
+ toSigned = false and
+ s = TNeg()
+ )
+ or
+ result = TNeg() and
+ (
+ fromSigned = true and
+ toSigned = true and
+ s = TNeg()
+ or
+ fromSigned = false and
+ toSigned = true and
+ s = TPos() and
+ ck != TWiden()
+ )
+}
/** Holds if the sign of `e` is too complicated to determine. */
private predicate unknownSign(Instruction i) {
@@ -140,9 +202,6 @@ private predicate unknownSign(Instruction i) {
i instanceof BuiltInInstruction
or
i instanceof CallInstruction
- or
- i instanceof ConvertInstruction and
- i.getResultType().(IntegralType).isSigned()
)
}
@@ -154,6 +213,7 @@ private predicate lowerBound(IRGuardCondition comp, Instruction lowerbound, Inst
exists(int adjustment, Instruction compared |
valueNumber(bounded) = valueNumber(compared) and
bounded = pos.getAnOperand() and
+ not unknownSign(lowerbound) and
/*
* Java library uses guardControlsSsaRead here. I think that the phi node logic doesn't need to
* be duplicated but the implication predicates may need to be ported
@@ -178,6 +238,8 @@ private predicate upperBound(IRGuardCondition comp, Instruction upperbound, Inst
exists(int adjustment, Instruction compared |
valueNumber(bounded) = valueNumber(compared) and
bounded = pos.getAnOperand() and
+ not unknownSign(upperbound) and
+
/*
* Java library uses guardControlsSsaRead here. I think that the phi node logic doesn't need to
* be duplicated but the implication predicates may need to be ported
@@ -202,6 +264,7 @@ private predicate upperBound(IRGuardCondition comp, Instruction upperbound, Inst
*/
private predicate eqBound(IRGuardCondition guard, Instruction eqbound, Instruction bounded, Instruction pos, boolean isEq) {
exists(Instruction compared |
+ not unknownSign(eqbound) and
valueNumber(bounded) = valueNumber(compared) and
bounded = pos.getAnOperand() and
guard.ensuresEq(compared, eqbound, 0, pos.getBlock(), isEq)
@@ -316,9 +379,29 @@ private Sign instructionSign(Instruction i) {
result = certainInstructionSign(i)
or
not exists(certainInstructionSign(i)) and
+ not (
+ result = TNeg() and
+ i.getResultType().(IntegralType).isUnsigned()
+ ) and
(
unknownSign(i)
or
+ exists(ConvertInstruction ci, Instruction prior, boolean fromSigned, boolean toSigned |
+ i = ci and
+ prior = ci.getOperand() and
+ (
+ if ci.getResultType().(IntegralType).isSigned()
+ then toSigned = true
+ else toSigned = false
+ ) and
+ (
+ if prior.getResultType().(IntegralType).isSigned()
+ then fromSigned = true
+ else fromSigned = false
+ ) and
+ result = castSign(operandSign(ci, prior), fromSigned, toSigned, getCastKind(ci))
+ )
+ or
exists(Instruction prior |
prior = i.(CopyInstruction).getSourceValue()
|
diff --git a/cpp/ql/test/library-tests/rangeanalysis/signanalysis/SignAnalysis.expected b/cpp/ql/test/library-tests/rangeanalysis/signanalysis/SignAnalysis.expected
index 7c7d797d245..6c34e0877cb 100644
--- a/cpp/ql/test/library-tests/rangeanalysis/signanalysis/SignAnalysis.expected
+++ b/cpp/ql/test/library-tests/rangeanalysis/signanalysis/SignAnalysis.expected
@@ -1,3 +1,4 @@
+| inline_assembly.c:9:23:9:23 | m0_6(unsigned int) = Uninitialized r0_5 | inline_assembly.c:9:23:9:23 | definition of y | positive |
| inline_assembly.c:10:3:10:7 | m0_9(unsigned int) = Store r0_8, r0_7 | inline_assembly.c:10:3:10:7 | ... = ... | positive strictlyPositive |
| inline_assembly.c:10:7:10:7 | r0_7(unsigned int) = Constant[1] | inline_assembly.c:10:7:10:7 | (unsigned int)... | positive strictlyPositive |
| inline_assembly.c:12:32:12:32 | r0_17(unsigned int) = Load r0_16, m0_9 | inline_assembly.c:12:32:12:32 | y | positive strictlyPositive |
@@ -115,18 +116,48 @@
| test.c:119:10:119:12 | m0_10(unsigned long long) = Store r0_6, r0_9 | test.c:119:10:119:12 | ... ++ | positive strictlyPositive |
| test.c:119:10:119:12 | r0_8(unsigned long long) = Constant[1] | test.c:119:10:119:12 | ... ++ | positive strictlyPositive |
| test.c:119:10:119:12 | r0_9(unsigned long long) = Add r0_7, r0_8 | test.c:119:10:119:12 | ... ++ | positive strictlyPositive |
+| test.c:124:11:124:15 | m1_0(unsigned long long) = Phi from 0:m0_4, from 2:m2_11 | test.c:124:11:124:15 | Start | positive |
+| test.c:124:11:124:15 | r1_2(unsigned long long) = Load r1_1, m1_0 | test.c:124:11:124:15 | Start | positive |
+| test.c:124:20:124:32 | r1_4(unsigned long long) = Call r1_3 | test.c:124:20:124:32 | call to test12_helper | positive |
+| test.c:124:20:124:36 | r1_6(unsigned long long) = Sub r1_4, r1_5 | test.c:124:20:124:36 | ... - ... | positive |
| test.c:124:36:124:36 | r1_5(unsigned long long) = Constant[1] | test.c:124:36:124:36 | (unsigned long long)... | positive strictlyPositive |
+| test.c:126:31:126:43 | m2_3(unsigned long long) = Store r2_0, r2_2 | test.c:126:31:126:43 | call to test12_helper | positive |
+| test.c:126:31:126:43 | r2_2(unsigned long long) = Call r2_1 | test.c:126:31:126:43 | call to test12_helper | positive |
+| test.c:127:6:127:24 | m2_11(unsigned long long) = Store r2_8, r2_10 | test.c:127:6:127:24 | ... += ... | positive strictlyPositive |
+| test.c:127:6:127:24 | r2_9(unsigned long long) = Load r2_8, m1_0 | test.c:127:6:127:24 | ... += ... | positive |
+| test.c:127:6:127:24 | r2_10(unsigned long long) = Add r2_9, r2_7 | test.c:127:6:127:24 | ... += ... | positive strictlyPositive |
+| test.c:127:15:127:20 | r2_5(unsigned long long) = Load r2_4, m2_3 | test.c:127:15:127:20 | Length | positive |
+| test.c:127:15:127:24 | r2_7(unsigned long long) = Add r2_5, r2_6 | test.c:127:15:127:24 | ... + ... | positive strictlyPositive |
| test.c:127:24:127:24 | r2_6(unsigned long long) = Constant[1] | test.c:127:24:127:24 | (unsigned long long)... | positive strictlyPositive |
| test.c:130:11:130:11 | m3_2(int) = Store r3_0, r3_1 | test.c:130:11:130:11 | 1 | positive strictlyPositive |
| test.c:130:11:130:11 | r3_1(int) = Constant[1] | test.c:130:11:130:11 | 1 | positive strictlyPositive |
-| test.c:137:20:137:22 | m0_19(unsigned int) = Store r0_14, r0_18 | test.c:137:20:137:22 | ... - ... | negative strictlyNegative |
-| test.c:137:20:137:22 | r0_18(unsigned int) = Sub r0_16, r0_17 | test.c:137:20:137:22 | ... - ... | negative strictlyNegative |
+| test.c:135:22:135:22 | m0_10(unsigned char) = Store r0_6, r0_9 | test.c:135:22:135:22 | (unsigned char)... | positive |
+| test.c:135:22:135:22 | r0_9(unsigned char) = Convert r0_8 | test.c:135:22:135:22 | (unsigned char)... | positive |
| test.c:137:22:137:22 | r0_17(unsigned int) = Constant[1] | test.c:137:22:137:22 | (unsigned int)... | positive strictlyPositive |
| test.c:138:13:138:13 | r0_23(int) = Constant[1] | test.c:138:13:138:13 | 1 | positive strictlyPositive |
-| test.c:139:36:139:36 | r0_42(unsigned int) = Load r0_41, m0_19 | test.c:139:36:139:36 | y | negative strictlyNegative |
+| test.c:139:19:139:28 | r0_37(unsigned int) = Convert r0_36 | test.c:139:19:139:28 | (unsigned int)... | positive |
+| test.c:139:19:139:32 | r0_40(unsigned int) = Add r0_37, r0_39 | test.c:139:19:139:32 | ... + ... | positive |
+| test.c:139:27:139:28 | r0_34(unsigned char) = Load r0_33, m0_10 | test.c:139:27:139:28 | uc | positive |
+| test.c:139:27:139:28 | r0_35(int) = Convert r0_34 | test.c:139:27:139:28 | (int)... | positive |
+| test.c:139:40:139:40 | r0_46(unsigned int) = Convert r0_45 | test.c:139:40:139:40 | (unsigned int)... | positive |
+| test.c:145:12:145:32 | m0_15(int) = Store r0_10, r0_14 | test.c:145:12:145:32 | (int)... | positive |
+| test.c:145:12:145:32 | r0_14(int) = Convert r0_13 | test.c:145:12:145:32 | (int)... | positive |
+| test.c:145:17:145:32 | r0_13(unsigned char) = Convert r0_12 | test.c:145:17:145:32 | (unsigned char)... | positive |
+| test.c:146:12:146:33 | m0_21(int) = Store r0_16, r0_20 | test.c:146:12:146:33 | (int)... | positive |
+| test.c:146:12:146:33 | r0_20(int) = Convert r0_19 | test.c:146:12:146:33 | (int)... | positive |
+| test.c:146:17:146:33 | r0_19(unsigned short) = Convert r0_18 | test.c:146:17:146:33 | (unsigned short)... | positive |
+| test.c:147:17:147:31 | r0_25(unsigned int) = Convert r0_24 | test.c:147:17:147:31 | (unsigned int)... | positive |
+| test.c:149:23:149:23 | m0_37(unsigned short) = Store r0_33, r0_36 | test.c:149:23:149:23 | (unsigned short)... | positive |
+| test.c:149:23:149:23 | r0_36(unsigned short) = Convert r0_35 | test.c:149:23:149:23 | (unsigned short)... | positive |
+| test.c:150:15:150:16 | r0_42(int) = Load r0_41, m0_15 | test.c:150:15:150:16 | x1 | positive |
+| test.c:150:20:150:21 | r0_45(int) = Load r0_44, m0_21 | test.c:150:20:150:21 | x2 | positive |
+| test.c:150:35:150:36 | r0_55(unsigned short) = Load r0_54, m0_37 | test.c:150:35:150:36 | s0 | positive |
+| test.c:150:35:150:36 | r0_56(int) = Convert r0_55 | test.c:150:35:150:36 | (int)... | positive |
| test.c:154:10:154:40 | m2_3(long long) = Store r2_2, r2_1 | test.c:154:10:154:40 | ... ? ... : ... | positive strictlyPositive |
| test.c:154:10:154:40 | m3_2(long long) = Store r3_1, r3_0 | test.c:154:10:154:40 | ... ? ... : ... | negative strictlyNegative |
| test.c:154:20:154:20 | r1_1(long long) = Load r1_0, m0_3 | test.c:154:20:154:20 | x | positive strictlyPositive |
+| test.c:154:25:154:30 | r1_4(int) = Convert r1_3 | test.c:154:25:154:30 | (int)... | positive |
+| test.c:154:25:154:30 | r1_5(long long) = Convert r1_4 | test.c:154:25:154:30 | (long long)... | positive |
| test.c:154:30:154:30 | r1_3(long long) = Load r1_2, m0_3 | test.c:154:30:154:30 | x | positive strictlyPositive |
| test.c:154:35:154:35 | r2_1(long long) = Load r2_0, m0_3 | test.c:154:35:154:35 | x | positive strictlyPositive |
| test.c:154:39:154:40 | r3_0(long long) = Constant[-1] | test.c:154:39:154:40 | (long long)... | negative strictlyNegative |
@@ -409,49 +440,127 @@
| test.c:347:9:347:9 | r6_1(int) = Load r6_0, m5_3 | test.c:347:9:347:9 | d | positive |
| test.c:348:14:348:14 | m7_2(int) = Store r7_0, r7_1 | test.c:348:14:348:14 | 1 | positive strictlyPositive |
| test.c:348:14:348:14 | r7_1(int) = Constant[1] | test.c:348:14:348:14 | 1 | positive strictlyPositive |
+| test.c:355:42:355:42 | m0_3(unsigned int) = InitializeParameter[x] r0_2 | test.c:355:42:355:42 | x | positive |
+| test.c:356:16:356:17 | m0_5(unsigned int) = Uninitialized r0_4 | test.c:356:16:356:17 | definition of y1 | positive |
+| test.c:356:20:356:21 | m0_7(unsigned int) = Uninitialized r0_6 | test.c:356:20:356:21 | definition of y2 | positive |
+| test.c:356:24:356:25 | m0_9(unsigned int) = Uninitialized r0_8 | test.c:356:24:356:25 | definition of y3 | positive |
+| test.c:356:28:356:29 | m0_11(unsigned int) = Uninitialized r0_10 | test.c:356:28:356:29 | definition of y4 | positive |
+| test.c:356:32:356:33 | m0_13(unsigned int) = Uninitialized r0_12 | test.c:356:32:356:33 | definition of y5 | positive |
+| test.c:356:36:356:37 | m0_15(unsigned int) = Uninitialized r0_14 | test.c:356:36:356:37 | definition of y6 | positive |
+| test.c:356:40:356:41 | m0_17(unsigned int) = Uninitialized r0_16 | test.c:356:40:356:41 | definition of y7 | positive |
+| test.c:356:44:356:45 | m0_19(unsigned int) = Uninitialized r0_18 | test.c:356:44:356:45 | definition of y8 | positive |
+| test.c:357:3:357:23 | m17_4(unsigned int) = Store r17_3, r17_2 | test.c:357:3:357:23 | ... = ... | positive |
+| test.c:357:8:357:8 | r0_21(unsigned int) = Load r0_20, m0_3 | test.c:357:8:357:8 | x | positive |
+| test.c:357:8:357:23 | m17_0(unsigned int) = Phi from 21:m21_3, from 22:m22_2 | test.c:357:8:357:23 | ... ? ... : ... | positive |
+| test.c:357:8:357:23 | m21_3(unsigned int) = Store r21_2, r21_1 | test.c:357:8:357:23 | ... ? ... : ... | positive |
| test.c:357:8:357:23 | m22_2(unsigned int) = Store r22_1, r22_0 | test.c:357:8:357:23 | ... ? ... : ... | positive strictlyPositive |
+| test.c:357:8:357:23 | r17_2(unsigned int) = Load r17_1, m17_0 | test.c:357:8:357:23 | ... ? ... : ... | positive |
| test.c:357:12:357:14 | r0_22(unsigned int) = Constant[100] | test.c:357:12:357:14 | (unsigned int)... | positive strictlyPositive |
+| test.c:357:18:357:18 | r21_1(unsigned int) = Load r21_0, m0_3 | test.c:357:18:357:18 | x | positive |
| test.c:357:22:357:23 | r22_0(unsigned int) = Constant[10] | test.c:357:22:357:23 | (unsigned int)... | positive strictlyPositive |
+| test.c:358:3:358:24 | m23_4(unsigned int) = Store r23_3, r23_2 | test.c:358:3:358:24 | ... = ... | positive |
+| test.c:358:8:358:8 | r17_6(unsigned int) = Load r17_5, m0_3 | test.c:358:8:358:8 | x | positive |
+| test.c:358:8:358:24 | m23_0(unsigned int) = Phi from 24:m24_2, from 25:m25_3 | test.c:358:8:358:24 | ... ? ... : ... | positive |
| test.c:358:8:358:24 | m24_2(unsigned int) = Store r24_1, r24_0 | test.c:358:8:358:24 | ... ? ... : ... | positive strictlyPositive |
+| test.c:358:8:358:24 | m25_3(unsigned int) = Store r25_2, r25_1 | test.c:358:8:358:24 | ... ? ... : ... | positive |
+| test.c:358:8:358:24 | r23_2(unsigned int) = Load r23_1, m23_0 | test.c:358:8:358:24 | ... ? ... : ... | positive |
| test.c:358:13:358:15 | r17_7(unsigned int) = Constant[100] | test.c:358:13:358:15 | (unsigned int)... | positive strictlyPositive |
| test.c:358:19:358:20 | r24_0(unsigned int) = Constant[10] | test.c:358:19:358:20 | (unsigned int)... | positive strictlyPositive |
+| test.c:358:24:358:24 | r25_1(unsigned int) = Load r25_0, m0_3 | test.c:358:24:358:24 | x | positive |
+| test.c:365:7:365:7 | r23_24(unsigned int) = Load r23_23, m0_3 | test.c:365:7:365:7 | x | positive |
| test.c:365:11:365:13 | r23_25(unsigned int) = Constant[300] | test.c:365:11:365:13 | (unsigned int)... | positive strictlyPositive |
+| test.c:366:5:366:15 | m34_4(unsigned int) = Store r34_3, r34_2 | test.c:366:5:366:15 | ... = ... | positive |
+| test.c:366:10:366:10 | r37_1(unsigned int) = Load r39_0, r37_0, m0_3 | test.c:366:10:366:10 | x | positive |
+| test.c:366:10:366:10 | r39_1(unsigned int) = Load r39_0, r37_0, m0_3 | test.c:366:10:366:10 | x | positive |
+| test.c:366:10:366:15 | m34_0(unsigned int) = Phi from 35:m35_1, from 40:m40_2, from 40:m38_2, from 38:m40_2, from 38:m38_2, from 40:m40_2, from 40:m38_2, from 38:m40_2, from 38:m38_2 | test.c:366:10:366:15 | ... ? ... : ... | positive |
+| test.c:366:10:366:15 | m35_1(unsigned int) = Store r35_0, r39_1, r37_1 | test.c:366:10:366:15 | ... ? ... : ... | positive |
| test.c:366:10:366:15 | m38_2(unsigned int) = Store r40_1, r38_1, r40_0, r38_0 | test.c:366:10:366:15 | ... ? ... : ... | positive strictlyPositive |
| test.c:366:10:366:15 | m40_2(unsigned int) = Store r40_1, r38_1, r40_0, r38_0 | test.c:366:10:366:15 | ... ? ... : ... | positive strictlyPositive |
+| test.c:366:10:366:15 | r34_2(unsigned int) = Load r34_1, m34_0 | test.c:366:10:366:15 | ... ? ... : ... | positive |
| test.c:366:15:366:15 | r38_0(unsigned int) = Constant[5] | test.c:366:15:366:15 | (unsigned int)... | positive strictlyPositive |
| test.c:366:15:366:15 | r40_0(unsigned int) = Constant[5] | test.c:366:15:366:15 | (unsigned int)... | positive strictlyPositive |
+| test.c:367:5:367:17 | m44_4(unsigned int) = Store r44_3, r44_2 | test.c:367:5:367:17 | ... = ... | positive |
+| test.c:367:10:367:10 | r47_1(unsigned int) = Load r49_0, r47_0, m0_3 | test.c:367:10:367:10 | x | positive |
+| test.c:367:10:367:10 | r49_1(unsigned int) = Load r49_0, r47_0, m0_3 | test.c:367:10:367:10 | x | positive |
+| test.c:367:10:367:17 | m44_0(unsigned int) = Phi from 45:m45_1, from 50:m50_2, from 50:m48_2, from 48:m50_2, from 48:m48_2, from 50:m50_2, from 50:m48_2, from 48:m50_2, from 48:m48_2 | test.c:367:10:367:17 | ... ? ... : ... | positive |
+| test.c:367:10:367:17 | m45_1(unsigned int) = Store r45_0, r49_1, r47_1 | test.c:367:10:367:17 | ... ? ... : ... | positive |
| test.c:367:10:367:17 | m48_2(unsigned int) = Store r50_1, r48_1, r50_0, r48_0 | test.c:367:10:367:17 | ... ? ... : ... | positive strictlyPositive |
| test.c:367:10:367:17 | m50_2(unsigned int) = Store r50_1, r48_1, r50_0, r48_0 | test.c:367:10:367:17 | ... ? ... : ... | positive strictlyPositive |
+| test.c:367:10:367:17 | r44_2(unsigned int) = Load r44_1, m44_0 | test.c:367:10:367:17 | ... ? ... : ... | positive |
| test.c:367:15:367:17 | r48_0(unsigned int) = Constant[500] | test.c:367:15:367:17 | (unsigned int)... | positive strictlyPositive |
| test.c:367:15:367:17 | r50_0(unsigned int) = Constant[500] | test.c:367:15:367:17 | (unsigned int)... | positive strictlyPositive |
| test.c:368:5:368:21 | m51_4(unsigned int) = Store r51_3, r51_2 | test.c:368:5:368:21 | ... = ... | positive strictlyPositive |
| test.c:368:10:368:21 | m51_0(unsigned int) = Phi from 52:m52_1, from 55:m55_2 | test.c:368:10:368:21 | ... ? ... : ... | positive strictlyPositive |
| test.c:368:10:368:21 | m55_2(unsigned int) = Store r55_1, r55_0 | test.c:368:10:368:21 | ... ? ... : ... | positive strictlyPositive |
| test.c:368:10:368:21 | r51_2(unsigned int) = Load r51_1, m51_0 | test.c:368:10:368:21 | ... ? ... : ... | positive strictlyPositive |
+| test.c:368:11:368:11 | r44_6(unsigned int) = Load r44_5, m0_3 | test.c:368:11:368:11 | x | positive |
+| test.c:368:11:368:13 | r53_0(unsigned int) = Add r44_6, r54_0, r27_0 | test.c:368:11:368:13 | ... + ... | positive strictlyPositive |
| test.c:368:13:368:13 | r27_0(unsigned int) = Constant[1] | test.c:368:13:368:13 | (unsigned int)... | positive strictlyPositive |
| test.c:368:13:368:13 | r54_0(unsigned int) = Constant[1] | test.c:368:13:368:13 | (unsigned int)... | positive strictlyPositive |
| test.c:368:19:368:21 | r55_0(unsigned int) = Constant[500] | test.c:368:19:368:21 | (unsigned int)... | positive strictlyPositive |
+| test.c:369:5:369:36 | m1_5(unsigned int) = Store r1_4, r1_3 | test.c:369:5:369:36 | ... = ... | positive strictlyPositive |
| test.c:369:10:369:36 | m1_0(int) = Phi from 2:m2_1, from 5:m5_2 | test.c:369:10:369:36 | ... ? ... : ... | positive strictlyPositive |
| test.c:369:10:369:36 | m5_2(int) = Store r5_1, r5_0 | test.c:369:10:369:36 | ... ? ... : ... | positive strictlyPositive |
| test.c:369:10:369:36 | r1_2(int) = Load r1_1, m1_0 | test.c:369:10:369:36 | ... ? ... : ... | positive strictlyPositive |
+| test.c:369:10:369:36 | r1_3(unsigned int) = Convert r1_2 | test.c:369:10:369:36 | (unsigned int)... | positive strictlyPositive |
+| test.c:369:11:369:30 | r3_1(unsigned char) = Convert r3_0 | test.c:369:11:369:30 | (unsigned char)... | positive |
+| test.c:369:27:369:27 | r51_6(unsigned int) = Load r51_5, m0_3 | test.c:369:27:369:27 | x | positive |
+| test.c:369:27:369:29 | r3_0(unsigned int) = Add r51_6, r4_0, r41_0 | test.c:369:27:369:29 | ... + ... | positive strictlyPositive |
| test.c:369:29:369:29 | r4_0(unsigned int) = Constant[1] | test.c:369:29:369:29 | (unsigned int)... | positive strictlyPositive |
| test.c:369:29:369:29 | r41_0(unsigned int) = Constant[1] | test.c:369:29:369:29 | (unsigned int)... | positive strictlyPositive |
| test.c:369:36:369:36 | r5_0(int) = Constant[5] | test.c:369:36:369:36 | 5 | positive strictlyPositive |
+| test.c:370:5:370:38 | m6_5(unsigned int) = Store r6_4, r6_3 | test.c:370:5:370:38 | ... = ... | positive strictlyPositive |
| test.c:370:10:370:38 | m6_0(int) = Phi from 7:m7_1, from 10:m10_2 | test.c:370:10:370:38 | ... ? ... : ... | positive strictlyPositive |
| test.c:370:10:370:38 | m10_2(int) = Store r10_1, r10_0 | test.c:370:10:370:38 | ... ? ... : ... | positive strictlyPositive |
| test.c:370:10:370:38 | r6_2(int) = Load r6_1, m6_0 | test.c:370:10:370:38 | ... ? ... : ... | positive strictlyPositive |
+| test.c:370:10:370:38 | r6_3(unsigned int) = Convert r6_2 | test.c:370:10:370:38 | (unsigned int)... | positive strictlyPositive |
+| test.c:370:11:370:30 | r8_1(unsigned char) = Convert r8_0 | test.c:370:11:370:30 | (unsigned char)... | positive |
+| test.c:370:27:370:27 | r1_7(unsigned int) = Load r1_6, m0_3 | test.c:370:27:370:27 | x | positive |
+| test.c:370:27:370:29 | r8_0(unsigned int) = Add r1_7, r9_0, r41_0 | test.c:370:27:370:29 | ... + ... | positive strictlyPositive |
| test.c:370:29:370:29 | r9_0(unsigned int) = Constant[1] | test.c:370:29:370:29 | (unsigned int)... | positive strictlyPositive |
| test.c:370:29:370:29 | r41_0(unsigned int) = Constant[1] | test.c:370:29:370:29 | (unsigned int)... | positive strictlyPositive |
| test.c:370:36:370:38 | r10_0(int) = Constant[500] | test.c:370:36:370:38 | 500 | positive strictlyPositive |
+| test.c:371:5:371:39 | m11_5(unsigned int) = Store r11_4, r11_3 | test.c:371:5:371:39 | ... = ... | positive strictlyPositive |
| test.c:371:10:371:39 | m11_0(int) = Phi from 12:m12_1, from 15:m15_2 | test.c:371:10:371:39 | ... ? ... : ... | positive strictlyPositive |
| test.c:371:10:371:39 | m15_2(int) = Store r15_1, r15_0 | test.c:371:10:371:39 | ... ? ... : ... | positive strictlyPositive |
| test.c:371:10:371:39 | r11_2(int) = Load r11_1, m11_0 | test.c:371:10:371:39 | ... ? ... : ... | positive strictlyPositive |
+| test.c:371:10:371:39 | r11_3(unsigned int) = Convert r11_2 | test.c:371:10:371:39 | (unsigned int)... | positive strictlyPositive |
+| test.c:371:11:371:31 | r13_1(unsigned short) = Convert r13_0 | test.c:371:11:371:31 | (unsigned short)... | positive |
+| test.c:371:28:371:28 | r6_7(unsigned int) = Load r6_6, m0_3 | test.c:371:28:371:28 | x | positive |
+| test.c:371:28:371:30 | r13_0(unsigned int) = Add r6_7, r41_0, r14_0 | test.c:371:28:371:30 | ... + ... | positive strictlyPositive |
| test.c:371:30:371:30 | r14_0(unsigned int) = Constant[1] | test.c:371:30:371:30 | (unsigned int)... | positive strictlyPositive |
| test.c:371:30:371:30 | r41_0(unsigned int) = Constant[1] | test.c:371:30:371:30 | (unsigned int)... | positive strictlyPositive |
| test.c:371:37:371:39 | r15_0(int) = Constant[500] | test.c:371:37:371:39 | 500 | positive strictlyPositive |
+| test.c:373:3:373:47 | m16_0(unsigned int) = Phi from 11:m34_4, from 23:m23_7 | test.c:373:3:373:47 | return ... | positive |
+| test.c:373:3:373:47 | m16_1(unsigned int) = Phi from 11:m44_4, from 23:m23_10 | test.c:373:3:373:47 | return ... | positive |
| test.c:373:3:373:47 | m16_2(unsigned int) = Phi from 11:m51_4, from 23:m23_13 | test.c:373:3:373:47 | return ... | positive |
+| test.c:373:3:373:47 | m16_3(unsigned int) = Phi from 11:m1_5, from 23:m23_16 | test.c:373:3:373:47 | return ... | positive |
+| test.c:373:3:373:47 | m16_4(unsigned int) = Phi from 11:m6_5, from 23:m23_19 | test.c:373:3:373:47 | return ... | positive |
+| test.c:373:3:373:47 | m16_5(unsigned int) = Phi from 11:m11_5, from 23:m23_22 | test.c:373:3:373:47 | return ... | positive |
+| test.c:373:10:373:11 | r16_8(unsigned int) = Load r16_7, m17_4 | test.c:373:10:373:11 | y1 | positive |
+| test.c:373:10:373:16 | r16_11(unsigned int) = Add r16_8, r16_10 | test.c:373:10:373:16 | ... + ... | positive |
+| test.c:373:10:373:21 | r16_14(unsigned int) = Add r16_11, r16_13 | test.c:373:10:373:21 | ... + ... | positive |
+| test.c:373:10:373:26 | r16_17(unsigned int) = Add r16_14, r16_16 | test.c:373:10:373:26 | ... + ... | positive |
+| test.c:373:10:373:31 | r16_20(unsigned int) = Add r16_17, r16_19 | test.c:373:10:373:31 | ... + ... | positive |
+| test.c:373:10:373:36 | r16_23(unsigned int) = Add r16_20, r16_22 | test.c:373:10:373:36 | ... + ... | positive |
+| test.c:373:10:373:41 | r16_26(unsigned int) = Add r16_23, r16_25 | test.c:373:10:373:41 | ... + ... | positive |
+| test.c:373:10:373:46 | m16_30(unsigned int) = Store r16_6, r16_29 | test.c:373:10:373:46 | ... + ... | positive |
+| test.c:373:10:373:46 | r16_29(unsigned int) = Add r16_26, r16_28 | test.c:373:10:373:46 | ... + ... | positive |
+| test.c:373:15:373:16 | r16_10(unsigned int) = Load r16_9, m23_4 | test.c:373:15:373:16 | y2 | positive |
+| test.c:373:20:373:21 | r16_13(unsigned int) = Load r16_12, m16_0 | test.c:373:20:373:21 | y3 | positive |
+| test.c:373:25:373:26 | r16_16(unsigned int) = Load r16_15, m16_1 | test.c:373:25:373:26 | y4 | positive |
| test.c:373:30:373:31 | r16_19(unsigned int) = Load r16_18, m16_2 | test.c:373:30:373:31 | y5 | positive |
+| test.c:373:35:373:36 | r16_22(unsigned int) = Load r16_21, m16_3 | test.c:373:35:373:36 | y6 | positive |
+| test.c:373:40:373:41 | r16_25(unsigned int) = Load r16_24, m16_4 | test.c:373:40:373:41 | y7 | positive |
+| test.c:373:45:373:46 | r16_28(unsigned int) = Load r16_27, m16_5 | test.c:373:45:373:46 | y8 | positive |
+| test.c:377:42:377:42 | m0_3(unsigned int) = InitializeParameter[x] r0_2 | test.c:377:42:377:42 | x | positive |
+| test.c:378:16:378:17 | m0_5(unsigned int) = Uninitialized r0_4 | test.c:378:16:378:17 | definition of y1 | positive |
+| test.c:378:20:378:21 | m0_7(unsigned int) = Uninitialized r0_6 | test.c:378:20:378:21 | definition of y2 | positive |
+| test.c:378:24:378:25 | m0_9(unsigned int) = Uninitialized r0_8 | test.c:378:24:378:25 | definition of y3 | positive |
+| test.c:378:28:378:29 | m0_11(unsigned int) = Uninitialized r0_10 | test.c:378:28:378:29 | definition of y4 | positive |
+| test.c:378:32:378:33 | m0_13(unsigned int) = Uninitialized r0_12 | test.c:378:32:378:33 | definition of y5 | positive |
| test.c:379:3:379:24 | m1_4(unsigned int) = Store r1_3, r1_2 | test.c:379:3:379:24 | ... = ... | positive strictlyPositive |
+| test.c:379:8:379:8 | r0_15(unsigned int) = Load r0_14, m0_3 | test.c:379:8:379:8 | x | positive |
| test.c:379:8:379:24 | m1_0(unsigned int) = Phi from 2:m2_3, from 5:m5_2 | test.c:379:8:379:24 | ... ? ... : ... | positive strictlyPositive |
| test.c:379:8:379:24 | m2_3(unsigned int) = Store r2_2, r2_1 | test.c:379:8:379:24 | ... ? ... : ... | positive strictlyPositive |
| test.c:379:8:379:24 | m5_2(unsigned int) = Store r5_1, r5_0 | test.c:379:8:379:24 | ... ? ... : ... | positive strictlyPositive |
@@ -460,6 +569,7 @@
| test.c:379:18:379:18 | r2_1(unsigned int) = Load r2_0, m0_3 | test.c:379:18:379:18 | x | positive strictlyPositive |
| test.c:379:22:379:24 | r5_0(unsigned int) = Constant[110] | test.c:379:22:379:24 | (unsigned int)... | positive strictlyPositive |
| test.c:380:3:380:25 | m6_4(unsigned int) = Store r6_3, r6_2 | test.c:380:3:380:25 | ... = ... | positive strictlyPositive |
+| test.c:380:8:380:8 | r1_6(unsigned int) = Load r1_5, m0_3 | test.c:380:8:380:8 | x | positive |
| test.c:380:8:380:25 | m6_0(unsigned int) = Phi from 7:m7_2, from 8:m8_3 | test.c:380:8:380:25 | ... ? ... : ... | positive strictlyPositive |
| test.c:380:8:380:25 | m7_2(unsigned int) = Store r7_1, r7_0 | test.c:380:8:380:25 | ... ? ... : ... | positive strictlyPositive |
| test.c:380:8:380:25 | m8_3(unsigned int) = Store r8_2, r8_1 | test.c:380:8:380:25 | ... ? ... : ... | positive strictlyPositive |
@@ -473,12 +583,14 @@
| test.c:382:8:382:11 | r6_8(unsigned int) = Constant[1000] | test.c:382:8:382:11 | (unsigned int)... | positive strictlyPositive |
| test.c:383:3:383:11 | m6_13(unsigned int) = Store r6_12, r6_11 | test.c:383:3:383:11 | ... = ... | positive strictlyPositive |
| test.c:383:8:383:11 | r6_11(unsigned int) = Constant[1000] | test.c:383:8:383:11 | (unsigned int)... | positive strictlyPositive |
+| test.c:384:7:384:7 | r6_15(unsigned int) = Load r6_14, m0_3 | test.c:384:7:384:7 | x | positive |
| test.c:384:12:384:14 | r6_16(unsigned int) = Constant[300] | test.c:384:12:384:14 | (unsigned int)... | positive strictlyPositive |
| test.c:385:5:385:21 | m14_4(unsigned int) = Store r14_3, r14_2 | test.c:385:5:385:21 | ... = ... | positive strictlyPositive |
| test.c:385:10:385:21 | m14_0(unsigned int) = Phi from 15:m15_1, from 19:m19_2 | test.c:385:10:385:21 | ... ? ... : ... | positive strictlyPositive |
| test.c:385:10:385:21 | m19_2(unsigned int) = Store r19_1, r19_0 | test.c:385:10:385:21 | ... ? ... : ... | positive strictlyPositive |
| test.c:385:10:385:21 | r14_2(unsigned int) = Load r14_1, m14_0 | test.c:385:10:385:21 | ... ? ... : ... | positive strictlyPositive |
| test.c:385:11:385:11 | r17_1(unsigned int) = Load r17_0, m0_3 | test.c:385:11:385:11 | x | positive strictlyPositive |
+| test.c:385:11:385:15 | r16_0(unsigned int) = Sub r17_1, r18_0, r11_0 | test.c:385:11:385:15 | ... - ... | positive |
| test.c:385:13:385:15 | r11_0(unsigned int) = Constant[300] | test.c:385:13:385:15 | (unsigned int)... | positive strictlyPositive |
| test.c:385:13:385:15 | r18_0(unsigned int) = Constant[300] | test.c:385:13:385:15 | (unsigned int)... | positive strictlyPositive |
| test.c:385:21:385:21 | r19_0(unsigned int) = Constant[5] | test.c:385:21:385:21 | (unsigned int)... | positive strictlyPositive |
@@ -487,13 +599,18 @@
| test.c:386:10:386:21 | m25_2(unsigned int) = Store r25_1, r25_0 | test.c:386:10:386:21 | ... ? ... : ... | positive strictlyPositive |
| test.c:386:10:386:21 | r20_2(unsigned int) = Load r20_1, m20_0 | test.c:386:10:386:21 | ... ? ... : ... | positive strictlyPositive |
| test.c:386:11:386:11 | r14_6(unsigned int) = Load r14_5, m0_3 | test.c:386:11:386:11 | x | positive strictlyPositive |
+| test.c:386:11:386:15 | r22_0(unsigned int) = Sub r14_6, r24_0, r11_0 | test.c:386:11:386:15 | ... - ... | positive |
| test.c:386:13:386:15 | r11_0(unsigned int) = Constant[200] | test.c:386:13:386:15 | (unsigned int)... | positive strictlyPositive |
| test.c:386:13:386:15 | r24_0(unsigned int) = Constant[200] | test.c:386:13:386:15 | (unsigned int)... | positive strictlyPositive |
| test.c:386:21:386:21 | r25_0(unsigned int) = Constant[5] | test.c:386:21:386:21 | (unsigned int)... | positive strictlyPositive |
+| test.c:387:5:387:38 | m26_5(unsigned int) = Store r26_4, r26_3 | test.c:387:5:387:38 | ... = ... | positive strictlyPositive |
| test.c:387:10:387:38 | m26_0(int) = Phi from 27:m27_1, from 31:m31_2 | test.c:387:10:387:38 | ... ? ... : ... | positive strictlyPositive |
| test.c:387:10:387:38 | m31_2(int) = Store r31_1, r31_0 | test.c:387:10:387:38 | ... ? ... : ... | positive strictlyPositive |
| test.c:387:10:387:38 | r26_2(int) = Load r26_1, m26_0 | test.c:387:10:387:38 | ... ? ... : ... | positive strictlyPositive |
+| test.c:387:10:387:38 | r26_3(unsigned int) = Convert r26_2 | test.c:387:10:387:38 | (unsigned int)... | positive strictlyPositive |
+| test.c:387:11:387:32 | r29_1(unsigned char) = Convert r29_0 | test.c:387:11:387:32 | (unsigned char)... | positive |
| test.c:387:27:387:27 | r20_6(unsigned int) = Load r20_5, m0_3 | test.c:387:27:387:27 | x | positive strictlyPositive |
+| test.c:387:27:387:31 | r29_0(unsigned int) = Sub r20_6, r30_0, r28_0 | test.c:387:27:387:31 | ... - ... | positive |
| test.c:387:29:387:31 | r28_0(unsigned int) = Constant[200] | test.c:387:29:387:31 | (unsigned int)... | positive strictlyPositive |
| test.c:387:29:387:31 | r30_0(unsigned int) = Constant[200] | test.c:387:29:387:31 | (unsigned int)... | positive strictlyPositive |
| test.c:387:38:387:38 | r31_0(int) = Constant[5] | test.c:387:38:387:38 | 5 | positive strictlyPositive |
@@ -510,12 +627,38 @@
| test.c:389:20:389:21 | r32_10(unsigned int) = Load r32_9, m32_0 | test.c:389:20:389:21 | y3 | positive strictlyPositive |
| test.c:389:25:389:26 | r32_13(unsigned int) = Load r32_12, m32_1 | test.c:389:25:389:26 | y4 | positive strictlyPositive |
| test.c:389:30:389:31 | r32_16(unsigned int) = Load r32_15, m32_2 | test.c:389:30:389:31 | y5 | positive strictlyPositive |
+| test.c:393:40:393:40 | m0_3(unsigned int) = InitializeParameter[x] r0_2 | test.c:393:40:393:40 | x | positive |
+| test.c:394:20:394:20 | r0_6(unsigned int) = Load r0_5, m0_3 | test.c:394:20:394:20 | x | positive |
+| test.c:394:20:394:36 | m1_3(unsigned int) = Store r1_2, r1_1 | test.c:394:20:394:36 | ... ? ... : ... | positive |
| test.c:394:20:394:36 | m2_2(unsigned int) = Store r2_1, r2_0 | test.c:394:20:394:36 | ... ? ... : ... | positive strictlyPositive |
+| test.c:394:20:394:36 | m3_0(unsigned int) = Phi from 1:m1_3, from 2:m2_2 | test.c:394:20:394:36 | ... ? ... : ... | positive |
+| test.c:394:20:394:36 | m3_3(unsigned int) = Store r0_4, r3_2 | test.c:394:20:394:36 | ... ? ... : ... | positive |
+| test.c:394:20:394:36 | r3_2(unsigned int) = Load r3_1, m3_0 | test.c:394:20:394:36 | ... ? ... : ... | positive |
| test.c:394:24:394:26 | r0_7(unsigned int) = Constant[100] | test.c:394:24:394:26 | (unsigned int)... | positive strictlyPositive |
+| test.c:394:30:394:30 | r1_1(unsigned int) = Load r1_0, m0_3 | test.c:394:30:394:30 | x | positive |
| test.c:394:34:394:36 | r2_0(unsigned int) = Constant[100] | test.c:394:34:394:36 | (unsigned int)... | positive strictlyPositive |
+| test.c:395:16:395:17 | m3_5(unsigned int) = Uninitialized r3_4 | test.c:395:16:395:17 | definition of y1 | positive |
+| test.c:396:16:396:17 | m3_7(unsigned int) = Uninitialized r3_6 | test.c:396:16:396:17 | definition of y2 | positive |
+| test.c:397:3:397:15 | m3_16(unsigned int) = Store r3_15, r3_14 | test.c:397:3:397:15 | ... = ... | positive strictlyPositive |
+| test.c:397:9:397:11 | m3_12(unsigned int) = Store r3_8, r3_11 | test.c:397:9:397:11 | ++ ... | positive strictlyPositive |
+| test.c:397:9:397:11 | r3_9(unsigned int) = Load r3_8, m3_3 | test.c:397:9:397:11 | ++ ... | positive |
| test.c:397:9:397:11 | r3_10(unsigned int) = Constant[1] | test.c:397:9:397:11 | ++ ... | positive strictlyPositive |
+| test.c:397:9:397:11 | r3_11(unsigned int) = Add r3_9, r3_10 | test.c:397:9:397:11 | ++ ... | positive strictlyPositive |
+| test.c:397:14:397:14 | r3_14(unsigned int) = Load r3_13, m3_12 | test.c:397:14:397:14 | y | positive strictlyPositive |
+| test.c:398:3:398:23 | m3_30(unsigned int) = Store r3_29, r3_28 | test.c:398:3:398:23 | ... = ... | positive strictlyPositive |
+| test.c:398:9:398:11 | m3_21(unsigned int) = Store r3_17, r3_20 | test.c:398:9:398:11 | ... ++ | positive strictlyPositive |
+| test.c:398:9:398:11 | r3_18(unsigned int) = Load r3_17, m3_12 | test.c:398:9:398:11 | ... ++ | positive strictlyPositive |
| test.c:398:9:398:11 | r3_19(unsigned int) = Constant[1] | test.c:398:9:398:11 | ... ++ | positive strictlyPositive |
+| test.c:398:9:398:11 | r3_20(unsigned int) = Add r3_18, r3_19 | test.c:398:9:398:11 | ... ++ | positive strictlyPositive |
+| test.c:398:14:398:19 | m3_26(unsigned int) = Store r3_23, r3_25 | test.c:398:14:398:19 | ... += ... | positive strictlyPositive |
+| test.c:398:14:398:19 | r3_24(unsigned int) = Load r3_23, m3_21 | test.c:398:14:398:19 | ... += ... | positive strictlyPositive |
+| test.c:398:14:398:19 | r3_25(unsigned int) = Add r3_24, r3_22 | test.c:398:14:398:19 | ... += ... | positive strictlyPositive |
| test.c:398:19:398:19 | r3_22(unsigned int) = Constant[3] | test.c:398:19:398:19 | (unsigned int)... | positive strictlyPositive |
+| test.c:398:22:398:22 | r3_28(unsigned int) = Load r3_27, m3_26 | test.c:398:22:398:22 | y | positive strictlyPositive |
+| test.c:399:10:399:11 | r3_33(unsigned int) = Load r3_32, m3_16 | test.c:399:10:399:11 | y1 | positive strictlyPositive |
+| test.c:399:10:399:16 | m3_37(unsigned int) = Store r3_31, r3_36 | test.c:399:10:399:16 | ... + ... | positive strictlyPositive |
+| test.c:399:10:399:16 | r3_36(unsigned int) = Add r3_33, r3_35 | test.c:399:10:399:16 | ... + ... | positive strictlyPositive |
+| test.c:399:15:399:16 | r3_35(unsigned int) = Load r3_34, m3_30 | test.c:399:15:399:16 | y2 | positive strictlyPositive |
| test.cpp:9:11:9:12 | m0_8(int) = Store r0_6, r0_7 | test.cpp:9:11:9:12 | - ... | negative strictlyNegative |
| test.cpp:9:11:9:12 | r0_7(int) = Constant[-1] | test.cpp:9:11:9:12 | - ... | negative strictlyNegative |
| test.cpp:11:13:11:13 | r1_2(int) = Constant[3] | test.cpp:11:13:11:13 | 3 | positive strictlyPositive |
From bf946c3ec3bca17d2673ff44487994bb81f2e7f3 Mon Sep 17 00:00:00 2001
From: Robert Marsh
Date: Thu, 20 Sep 2018 11:35:50 -0700
Subject: [PATCH 07/71] C++: remove comments about Java implies predicates
The Java guards library includes a set of "implies" predicates to handle
short-circuiting conditionals. C++ handles those in IR generation, so
dominance on the IR produces correct results for controlling blocks.
---
.../src/semmle/code/cpp/rangeanalysis/SignAnalysis.qll | 9 ---------
1 file changed, 9 deletions(-)
diff --git a/cpp/ql/src/semmle/code/cpp/rangeanalysis/SignAnalysis.qll b/cpp/ql/src/semmle/code/cpp/rangeanalysis/SignAnalysis.qll
index e52d33d1e0d..32c8c32422f 100644
--- a/cpp/ql/src/semmle/code/cpp/rangeanalysis/SignAnalysis.qll
+++ b/cpp/ql/src/semmle/code/cpp/rangeanalysis/SignAnalysis.qll
@@ -214,10 +214,6 @@ private predicate lowerBound(IRGuardCondition comp, Instruction lowerbound, Inst
valueNumber(bounded) = valueNumber(compared) and
bounded = pos.getAnOperand() and
not unknownSign(lowerbound) and
- /*
- * Java library uses guardControlsSsaRead here. I think that the phi node logic doesn't need to
- * be duplicated but the implication predicates may need to be ported
- */
(
isStrict = true and
adjustment = 0
@@ -239,11 +235,6 @@ private predicate upperBound(IRGuardCondition comp, Instruction upperbound, Inst
valueNumber(bounded) = valueNumber(compared) and
bounded = pos.getAnOperand() and
not unknownSign(upperbound) and
-
- /*
- * Java library uses guardControlsSsaRead here. I think that the phi node logic doesn't need to
- * be duplicated but the implication predicates may need to be ported
- */
(
isStrict = true and
adjustment = 0
From d9e6a6ea24dcc855a27a49040aea273b0590fa54 Mon Sep 17 00:00:00 2001
From: Robert Marsh
Date: Wed, 3 Oct 2018 14:04:20 -0700
Subject: [PATCH 08/71] Move cached predicates to cached module
---
.../code/cpp/rangeanalysis/SignAnalysis.qll | 163 +++++++++---------
1 file changed, 83 insertions(+), 80 deletions(-)
diff --git a/cpp/ql/src/semmle/code/cpp/rangeanalysis/SignAnalysis.qll b/cpp/ql/src/semmle/code/cpp/rangeanalysis/SignAnalysis.qll
index 32c8c32422f..7ea43a1f72c 100644
--- a/cpp/ql/src/semmle/code/cpp/rangeanalysis/SignAnalysis.qll
+++ b/cpp/ql/src/semmle/code/cpp/rangeanalysis/SignAnalysis.qll
@@ -9,6 +9,7 @@ import cpp
private import semmle.code.cpp.ir.IR
private import semmle.code.cpp.controlflow.IRGuards
private import semmle.code.cpp.ir.ValueNumbering
+private import SignAnalysisCached
private newtype TSign = TNeg() or TZero() or TPos()
private class Sign extends TSign {
@@ -354,88 +355,90 @@ private predicate hasGuard(Instruction v, Instruction pos, Sign s) {
s = TZero() and zeroBound(_, _, v, pos)
}
-/**
- * Gets a sign that `operand` may have at `pos`, taking guards into account.
- */
-cached
-private Sign operandSign(Instruction pos, Instruction operand) {
- result = unguardedOperandSign(pos, operand)
- or
- result = guardedOperandSign(pos, operand) and
- result = guardedOperandSignOk(pos, operand)
-}
-
-cached
-private Sign instructionSign(Instruction i) {
- result = certainInstructionSign(i)
- or
- not exists(certainInstructionSign(i)) and
- not (
- result = TNeg() and
- i.getResultType().(IntegralType).isUnsigned()
- ) and
- (
- unknownSign(i)
+cached private module SignAnalysisCached {
+ /**
+ * Gets a sign that `operand` may have at `pos`, taking guards into account.
+ */
+ cached
+ Sign operandSign(Instruction pos, Instruction operand) {
+ result = unguardedOperandSign(pos, operand)
or
- exists(ConvertInstruction ci, Instruction prior, boolean fromSigned, boolean toSigned |
- i = ci and
- prior = ci.getOperand() and
- (
- if ci.getResultType().(IntegralType).isSigned()
- then toSigned = true
- else toSigned = false
- ) and
- (
- if prior.getResultType().(IntegralType).isSigned()
- then fromSigned = true
- else fromSigned = false
- ) and
- result = castSign(operandSign(ci, prior), fromSigned, toSigned, getCastKind(ci))
+ result = guardedOperandSign(pos, operand) and
+ result = guardedOperandSignOk(pos, operand)
+ }
+
+ cached
+ Sign instructionSign(Instruction i) {
+ result = certainInstructionSign(i)
+ or
+ not exists(certainInstructionSign(i)) and
+ not (
+ result = TNeg() and
+ i.getResultType().(IntegralType).isUnsigned()
+ ) and
+ (
+ unknownSign(i)
+ or
+ exists(ConvertInstruction ci, Instruction prior, boolean fromSigned, boolean toSigned |
+ i = ci and
+ prior = ci.getOperand() and
+ (
+ if ci.getResultType().(IntegralType).isSigned()
+ then toSigned = true
+ else toSigned = false
+ ) and
+ (
+ if prior.getResultType().(IntegralType).isSigned()
+ then fromSigned = true
+ else fromSigned = false
+ ) and
+ result = castSign(operandSign(ci, prior), fromSigned, toSigned, getCastKind(ci))
+ )
+ or
+ exists(Instruction prior |
+ prior = i.(CopyInstruction).getSourceValue()
+ |
+ result = operandSign(i, prior)
+ )
+ or
+ result = operandSign(i, i.(BitComplementInstruction).getOperand()).bitnot()
+ or
+ result = operandSign(i, i.(NegateInstruction).getOperand()).neg()
+ or
+ exists(Sign s1, Sign s2 |
+ binaryOpSigns(i, s1, s2)
+ |
+ i instanceof AddInstruction and result = s1.add(s2)
+ or
+ i instanceof SubInstruction and result = s1.add(s2.neg())
+ or
+ i instanceof MulInstruction and result = s1.mul(s2)
+ or
+ i instanceof DivInstruction and result = s1.div(s2)
+ or
+ i instanceof RemInstruction and result = s1.rem(s2)
+ or
+ i instanceof BitAndInstruction and result = s1.bitand(s2)
+ or
+ i instanceof BitOrInstruction and result = s1.bitor(s2)
+ or
+ i instanceof BitXorInstruction and result = s1.bitxor(s2)
+ or
+ i instanceof ShiftLeftInstruction and result = s1.lshift(s2)
+ or
+ i instanceof ShiftRightInstruction and
+ i.getResultType().(IntegralType).isSigned() and
+ result = s1.rshift(s2)
+ or
+ i instanceof ShiftRightInstruction and
+ not i.getResultType().(IntegralType).isSigned() and
+ result = s1.urshift(s2)
+ )
+ or
+ // use hasGuard here?
+ result = operandSign(i, i.(PhiInstruction).getAnOperand())
)
- or
- exists(Instruction prior |
- prior = i.(CopyInstruction).getSourceValue()
- |
- result = operandSign(i, prior)
- )
- or
- result = operandSign(i, i.(BitComplementInstruction).getOperand()).bitnot()
- or
- result = operandSign(i, i.(NegateInstruction).getOperand()).neg()
- or
- exists(Sign s1, Sign s2 |
- binaryOpSigns(i, s1, s2)
- |
- i instanceof AddInstruction and result = s1.add(s2)
- or
- i instanceof SubInstruction and result = s1.add(s2.neg())
- or
- i instanceof MulInstruction and result = s1.mul(s2)
- or
- i instanceof DivInstruction and result = s1.div(s2)
- or
- i instanceof RemInstruction and result = s1.rem(s2)
- or
- i instanceof BitAndInstruction and result = s1.bitand(s2)
- or
- i instanceof BitOrInstruction and result = s1.bitor(s2)
- or
- i instanceof BitXorInstruction and result = s1.bitxor(s2)
- or
- i instanceof ShiftLeftInstruction and result = s1.lshift(s2)
- or
- i instanceof ShiftRightInstruction and
- i.getResultType().(IntegralType).isSigned() and
- result = s1.rshift(s2)
- or
- i instanceof ShiftRightInstruction and
- not i.getResultType().(IntegralType).isSigned() and
- result = s1.urshift(s2)
- )
- or
- // use hasGuard here?
- result = operandSign(i, i.(PhiInstruction).getAnOperand())
- )
+ }
}
/** Holds if `e` can be positive and cannot be negative. */
From 6d06db7989cf2f22eb581a29e6844f2c5d7a630f Mon Sep 17 00:00:00 2001
From: Robert Marsh
Date: Wed, 3 Oct 2018 14:07:03 -0700
Subject: [PATCH 09/71] C++: fix comments
---
.../code/cpp/rangeanalysis/SignAnalysis.qll | 16 ++++++++--------
1 file changed, 8 insertions(+), 8 deletions(-)
diff --git a/cpp/ql/src/semmle/code/cpp/rangeanalysis/SignAnalysis.qll b/cpp/ql/src/semmle/code/cpp/rangeanalysis/SignAnalysis.qll
index 7ea43a1f72c..01a02bf0b26 100644
--- a/cpp/ql/src/semmle/code/cpp/rangeanalysis/SignAnalysis.qll
+++ b/cpp/ql/src/semmle/code/cpp/rangeanalysis/SignAnalysis.qll
@@ -441,51 +441,51 @@ cached private module SignAnalysisCached {
}
}
-/** Holds if `e` can be positive and cannot be negative. */
+/** Holds if `i` can be positive and cannot be negative. */
predicate positive(Instruction i) {
instructionSign(i) = TPos() and
not instructionSign(i) = TNeg()
}
+/** Holds if `i` at `pos` can be positive at and cannot be negative. */
predicate positive(Instruction i, Instruction pos) {
operandSign(pos, i) = TPos() and
not operandSign(pos, i) = TNeg()
}
-/** Holds if `e` can be negative and cannot be positive. */
+/** Holds if `i` can be negative and cannot be positive. */
predicate negative(Instruction i) {
instructionSign(i) = TNeg() and
not instructionSign(i) = TPos()
}
-/** Holds if `e` can be negative and cannot be positive. */
+/** Holds if `i` at `pos` can be negative and cannot be positive. */
predicate negative(Instruction i, Instruction pos) {
operandSign(pos, i) = TNeg() and
not operandSign(pos, i) = TPos()
}
-/** Holds if `e` is strictly positive. */
+/** Holds if `i` is strictly positive. */
predicate strictlyPositive(Instruction i) {
instructionSign(i) = TPos() and
not instructionSign(i) = TNeg() and
not instructionSign(i) = TZero()
}
-/** Holds if `e` is strictly positive. */
+/** Holds if `i` is strictly positive at `pos`. */
predicate strictlyPositive(Instruction i, Instruction pos) {
operandSign(pos, i) = TPos() and
not operandSign(pos, i) = TNeg() and
not operandSign(pos, i) = TZero()
}
-/** Holds if `e` is strictly negative. */
+/** Holds if `i` is strictly negative. */
predicate strictlyNegative(Instruction i) {
instructionSign(i) = TNeg() and
not instructionSign(i) = TPos() and
not instructionSign(i) = TZero()
}
-
-/** Holds if `e` can be negative and cannot be positive. */
+/** Holds if `i` is strictly negative at `pos`. */
predicate strictlyNegative(Instruction i, Instruction pos) {
operandSign(pos, i) = TNeg() and
not operandSign(pos, i) = TPos() and
From 2d04d9ea0424b9b43350665bc45e0c9d26fc7ae6 Mon Sep 17 00:00:00 2001
From: Robert Marsh
Date: Wed, 3 Oct 2018 14:11:32 -0700
Subject: [PATCH 10/71] C++: sync NegateInstruction between IR passes
---
.../semmle/code/cpp/ir/implementation/raw/Instruction.qll | 6 ++++++
.../cpp/ir/implementation/unaliased_ssa/Instruction.qll | 6 ++++++
2 files changed, 12 insertions(+)
diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/Instruction.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/Instruction.qll
index c95cb23814e..99255b8ffa5 100644
--- a/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/Instruction.qll
+++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/Instruction.qll
@@ -761,6 +761,12 @@ class RemInstruction extends BinaryInstruction {
}
}
+class NegateInstruction extends UnaryInstruction {
+ NegateInstruction() {
+ opcode instanceof Opcode::Negate
+ }
+}
+
class BitAndInstruction extends BinaryInstruction {
BitAndInstruction() {
opcode instanceof Opcode::BitAnd
diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/Instruction.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/Instruction.qll
index c95cb23814e..99255b8ffa5 100644
--- a/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/Instruction.qll
+++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/Instruction.qll
@@ -761,6 +761,12 @@ class RemInstruction extends BinaryInstruction {
}
}
+class NegateInstruction extends UnaryInstruction {
+ NegateInstruction() {
+ opcode instanceof Opcode::Negate
+ }
+}
+
class BitAndInstruction extends BinaryInstruction {
BitAndInstruction() {
opcode instanceof Opcode::BitAnd
From 9d2d381e68a95db5b56ff43b833fff8093ea7ea8 Mon Sep 17 00:00:00 2001
From: Robert Marsh
Date: Mon, 15 Oct 2018 14:35:40 -0700
Subject: [PATCH 11/71] C++: test fixes for sign analysis
---
.../signanalysis/SignAnalysis.expected | 1368 ++++++++---------
.../signanalysis/SignAnalysis.ql | 2 +-
.../signanalysis/binary_logical_operator.c | 8 +
3 files changed, 690 insertions(+), 688 deletions(-)
create mode 100644 cpp/ql/test/library-tests/rangeanalysis/signanalysis/binary_logical_operator.c
diff --git a/cpp/ql/test/library-tests/rangeanalysis/signanalysis/SignAnalysis.expected b/cpp/ql/test/library-tests/rangeanalysis/signanalysis/SignAnalysis.expected
index 6c34e0877cb..cea2920afef 100644
--- a/cpp/ql/test/library-tests/rangeanalysis/signanalysis/SignAnalysis.expected
+++ b/cpp/ql/test/library-tests/rangeanalysis/signanalysis/SignAnalysis.expected
@@ -1,687 +1,681 @@
-| inline_assembly.c:9:23:9:23 | m0_6(unsigned int) = Uninitialized r0_5 | inline_assembly.c:9:23:9:23 | definition of y | positive |
-| inline_assembly.c:10:3:10:7 | m0_9(unsigned int) = Store r0_8, r0_7 | inline_assembly.c:10:3:10:7 | ... = ... | positive strictlyPositive |
-| inline_assembly.c:10:7:10:7 | r0_7(unsigned int) = Constant[1] | inline_assembly.c:10:7:10:7 | (unsigned int)... | positive strictlyPositive |
-| inline_assembly.c:12:32:12:32 | r0_17(unsigned int) = Load r0_16, m0_9 | inline_assembly.c:12:32:12:32 | y | positive strictlyPositive |
-| minmax.c:16:9:16:10 | m0_4(int) = Store r0_2, r0_3 | minmax.c:16:9:16:10 | 1 | positive strictlyPositive |
-| minmax.c:16:9:16:10 | r0_3(int) = Constant[1] | minmax.c:16:9:16:10 | 1 | positive strictlyPositive |
-| minmax.c:16:16:16:17 | m0_7(int) = Store r0_5, r0_6 | minmax.c:16:16:16:17 | 2 | positive strictlyPositive |
-| minmax.c:16:16:16:17 | r0_6(int) = Constant[2] | minmax.c:16:16:16:17 | 2 | positive strictlyPositive |
-| minmax.c:16:23:16:24 | m0_10(int) = Store r0_8, r0_9 | minmax.c:16:23:16:24 | 3 | positive strictlyPositive |
-| minmax.c:16:23:16:24 | r0_9(int) = Constant[3] | minmax.c:16:23:16:24 | 3 | positive strictlyPositive |
-| minmax.c:18:37:18:37 | r0_16(int) = Load r0_15, m0_4 | minmax.c:18:37:18:37 | x | positive strictlyPositive |
-| minmax.c:18:40:18:40 | r0_18(int) = Load r0_17, m0_7 | minmax.c:18:40:18:40 | y | positive strictlyPositive |
-| minmax.c:18:43:18:43 | r0_20(int) = Load r0_19, m0_10 | minmax.c:18:43:18:43 | z | positive strictlyPositive |
-| test.c:7:10:7:10 | m1_0(int) = Phi from 0:m0_6, from 2:m2_5 | test.c:7:10:7:10 | p | positive |
-| test.c:8:5:8:19 | m2_5(int) = Store r2_4, r2_3 | test.c:8:5:8:19 | ... = ... | positive strictlyPositive |
-| test.c:8:13:8:17 | r2_1(int) = Load r2_0, m1_0 | test.c:8:13:8:17 | count | positive |
-| test.c:8:13:8:19 | r2_3(int) = Add r2_1, r2_2 | test.c:8:13:8:19 | ... + ... | positive strictlyPositive |
-| test.c:8:19:8:19 | r2_2(int) = Constant[1] | test.c:8:19:8:19 | 1 | positive strictlyPositive |
-| test.c:10:10:10:14 | m3_3(int) = Store r3_0, r3_2 | test.c:10:10:10:14 | count | positive |
-| test.c:10:10:10:14 | r3_2(int) = Load r3_1, m1_0 | test.c:10:10:10:14 | count | positive |
-| test.c:15:10:15:10 | m1_0(int) = Phi from 0:m0_6, from 2:m2_7 | test.c:15:10:15:10 | p | positive |
-| test.c:16:5:16:26 | m2_7(int) = Store r2_6, r2_5 | test.c:16:5:16:26 | ... = ... | positive |
-| test.c:16:13:16:26 | r2_5(int) = Rem r2_3, r2_4 | test.c:16:13:16:26 | ... % ... | positive |
-| test.c:16:14:16:18 | r2_1(int) = Load r2_0, m1_0 | test.c:16:14:16:18 | count | positive |
-| test.c:16:14:16:20 | r2_3(int) = Add r2_1, r2_2 | test.c:16:14:16:20 | ... + ... | positive strictlyPositive |
-| test.c:16:20:16:20 | r2_2(int) = Constant[1] | test.c:16:20:16:20 | 1 | positive strictlyPositive |
-| test.c:16:25:16:26 | r2_4(int) = Constant[10] | test.c:16:25:16:26 | 10 | positive strictlyPositive |
-| test.c:18:10:18:14 | m3_3(int) = Store r3_0, r3_2 | test.c:18:10:18:14 | count | positive |
-| test.c:18:10:18:14 | r3_2(int) = Load r3_1, m1_0 | test.c:18:10:18:14 | count | positive |
-| test.c:23:10:23:10 | m1_0(int) = Phi from 0:m0_6, from 2:m2_10 | test.c:23:10:23:10 | p | positive |
-| test.c:24:5:24:11 | m2_4(int) = Store r2_0, r2_3 | test.c:24:5:24:11 | ... ++ | positive strictlyPositive |
-| test.c:24:5:24:11 | r2_1(int) = Load r2_0, m1_0 | test.c:24:5:24:11 | ... ++ | positive |
-| test.c:24:5:24:11 | r2_2(int) = Constant[1] | test.c:24:5:24:11 | ... ++ | positive strictlyPositive |
-| test.c:24:5:24:11 | r2_3(int) = Add r2_1, r2_2 | test.c:24:5:24:11 | ... ++ | positive strictlyPositive |
-| test.c:25:5:25:22 | m2_10(int) = Store r2_9, r2_8 | test.c:25:5:25:22 | ... = ... | positive |
-| test.c:25:13:25:17 | r2_6(int) = Load r2_5, m2_4 | test.c:25:13:25:17 | count | positive strictlyPositive |
-| test.c:25:13:25:22 | r2_8(int) = Rem r2_6, r2_7 | test.c:25:13:25:22 | ... % ... | positive |
-| test.c:25:21:25:22 | r2_7(int) = Constant[10] | test.c:25:21:25:22 | 10 | positive strictlyPositive |
-| test.c:27:10:27:14 | m3_3(int) = Store r3_0, r3_2 | test.c:27:10:27:14 | count | positive |
-| test.c:27:10:27:14 | r3_2(int) = Load r3_1, m1_0 | test.c:27:10:27:14 | count | positive |
-| test.c:33:15:33:15 | m1_0(int) = Phi from 0:m0_10, from 2:m2_11 | test.c:33:15:33:15 | i | positive |
-| test.c:33:15:33:15 | m1_1(int) = Phi from 0:m0_7, from 2:m2_5 | test.c:33:15:33:15 | i | positive |
-| test.c:33:15:33:15 | r1_3(int) = Load r1_2, m1_0 | test.c:33:15:33:15 | i | positive |
-| test.c:33:19:33:19 | r1_4(int) = Constant[2] | test.c:33:19:33:19 | 2 | positive strictlyPositive |
-| test.c:33:22:33:28 | m2_11(int) = Store r2_10, r2_9 | test.c:33:22:33:28 | ... = ... | positive strictlyPositive |
-| test.c:33:26:33:26 | r2_7(int) = Load r2_6, m1_0 | test.c:33:26:33:26 | i | positive |
-| test.c:33:26:33:28 | r2_9(int) = Add r2_7, r2_8 | test.c:33:26:33:28 | ... + ... | positive strictlyPositive |
-| test.c:33:28:33:28 | r2_8(int) = Constant[1] | test.c:33:28:33:28 | 1 | positive strictlyPositive |
-| test.c:34:5:34:14 | m2_5(int) = Store r2_2, r2_4 | test.c:34:5:34:14 | ... += ... | positive |
-| test.c:34:5:34:14 | r2_3(int) = Load r2_2, m1_1 | test.c:34:5:34:14 | ... += ... | positive |
-| test.c:34:5:34:14 | r2_4(int) = Add r2_3, r2_1 | test.c:34:5:34:14 | ... += ... | positive |
-| test.c:34:14:34:14 | r2_1(int) = Load r2_0, m1_0 | test.c:34:14:34:14 | i | positive |
-| test.c:36:10:36:14 | r3_2(int) = Load r3_1, m1_1 | test.c:36:10:36:14 | total | positive |
-| test.c:36:10:36:18 | m3_6(int) = Store r3_0, r3_5 | test.c:36:10:36:18 | ... + ... | positive |
-| test.c:36:10:36:18 | r3_5(int) = Add r3_2, r3_4 | test.c:36:10:36:18 | ... + ... | positive |
-| test.c:36:18:36:18 | r3_4(int) = Load r3_3, m1_0 | test.c:36:18:36:18 | i | positive |
-| test.c:42:15:42:15 | m1_0(int) = Phi from 0:m0_10, from 2:m2_10 | test.c:42:15:42:15 | i | positive |
-| test.c:42:15:42:15 | m1_1(int) = Phi from 0:m0_7, from 2:m2_5 | test.c:42:15:42:15 | i | positive |
-| test.c:42:15:42:15 | r1_3(int) = Load r1_2, m1_0 | test.c:42:15:42:15 | i | positive |
-| test.c:42:19:42:19 | r1_4(int) = Constant[2] | test.c:42:19:42:19 | 2 | positive strictlyPositive |
-| test.c:42:22:42:24 | m2_10(int) = Store r2_6, r2_9 | test.c:42:22:42:24 | ... ++ | positive strictlyPositive |
-| test.c:42:22:42:24 | r2_7(int) = Load r2_6, m1_0 | test.c:42:22:42:24 | ... ++ | positive |
-| test.c:42:22:42:24 | r2_8(int) = Constant[1] | test.c:42:22:42:24 | ... ++ | positive strictlyPositive |
-| test.c:42:22:42:24 | r2_9(int) = Add r2_7, r2_8 | test.c:42:22:42:24 | ... ++ | positive strictlyPositive |
-| test.c:43:5:43:14 | m2_5(int) = Store r2_2, r2_4 | test.c:43:5:43:14 | ... += ... | positive |
-| test.c:43:5:43:14 | r2_3(int) = Load r2_2, m1_1 | test.c:43:5:43:14 | ... += ... | positive |
-| test.c:43:5:43:14 | r2_4(int) = Add r2_3, r2_1 | test.c:43:5:43:14 | ... += ... | positive |
-| test.c:43:14:43:14 | r2_1(int) = Load r2_0, m1_0 | test.c:43:14:43:14 | i | positive |
-| test.c:45:10:45:14 | r3_2(int) = Load r3_1, m1_1 | test.c:45:10:45:14 | total | positive |
-| test.c:45:10:45:18 | m3_6(int) = Store r3_0, r3_5 | test.c:45:10:45:18 | ... + ... | positive |
-| test.c:45:10:45:18 | r3_5(int) = Add r3_2, r3_4 | test.c:45:10:45:18 | ... + ... | positive |
-| test.c:45:18:45:18 | r3_4(int) = Load r3_3, m1_0 | test.c:45:18:45:18 | i | positive |
-| test.c:51:15:51:15 | m1_0(int) = Phi from 0:m0_10, from 2:m2_11 | test.c:51:15:51:15 | i | positive |
-| test.c:51:15:51:15 | m1_1(int) = Phi from 0:m0_7, from 2:m2_5 | test.c:51:15:51:15 | i | positive |
-| test.c:51:15:51:15 | r1_3(int) = Load r1_2, m1_0 | test.c:51:15:51:15 | i | positive |
-| test.c:51:15:51:17 | r1_5(int) = Add r1_3, r1_4 | test.c:51:15:51:17 | ... + ... | positive strictlyPositive |
-| test.c:51:17:51:17 | r1_4(int) = Constant[2] | test.c:51:17:51:17 | 2 | positive strictlyPositive |
-| test.c:51:21:51:21 | r1_6(int) = Constant[4] | test.c:51:21:51:21 | 4 | positive strictlyPositive |
-| test.c:51:24:51:30 | m2_11(int) = Store r2_10, r2_9 | test.c:51:24:51:30 | ... = ... | positive strictlyPositive |
-| test.c:51:28:51:28 | r2_7(int) = Load r2_6, m1_0 | test.c:51:28:51:28 | i | positive |
-| test.c:51:28:51:30 | r2_9(int) = Add r2_7, r2_8 | test.c:51:28:51:30 | ... + ... | positive strictlyPositive |
-| test.c:51:30:51:30 | r2_8(int) = Constant[1] | test.c:51:30:51:30 | 1 | positive strictlyPositive |
-| test.c:52:5:52:14 | m2_5(int) = Store r2_2, r2_4 | test.c:52:5:52:14 | ... += ... | positive |
-| test.c:52:5:52:14 | r2_3(int) = Load r2_2, m1_1 | test.c:52:5:52:14 | ... += ... | positive |
-| test.c:52:5:52:14 | r2_4(int) = Add r2_3, r2_1 | test.c:52:5:52:14 | ... += ... | positive |
-| test.c:52:14:52:14 | r2_1(int) = Load r2_0, m1_0 | test.c:52:14:52:14 | i | positive |
-| test.c:54:10:54:14 | r3_2(int) = Load r3_1, m1_1 | test.c:54:10:54:14 | total | positive |
-| test.c:54:10:54:18 | m3_6(int) = Store r3_0, r3_5 | test.c:54:10:54:18 | ... + ... | positive |
-| test.c:54:10:54:18 | r3_5(int) = Add r3_2, r3_4 | test.c:54:10:54:18 | ... + ... | positive |
-| test.c:54:18:54:18 | r3_4(int) = Load r3_3, m1_0 | test.c:54:18:54:18 | i | positive |
-| test.c:58:11:58:11 | r0_6(int) = Constant[4] | test.c:58:11:58:11 | 4 | positive strictlyPositive |
-| test.c:59:13:59:13 | r2_2(int) = Constant[5] | test.c:59:13:59:13 | 5 | positive strictlyPositive |
-| test.c:63:10:63:10 | m4_2(int) = Store r4_0, r4_1 | test.c:63:10:63:10 | 1 | positive strictlyPositive |
-| test.c:63:10:63:10 | r4_1(int) = Constant[1] | test.c:63:10:63:10 | 1 | positive strictlyPositive |
-| test.c:67:7:67:11 | r0_6(int) = Constant[-1000] | test.c:67:7:67:11 | - ... | negative strictlyNegative |
-| test.c:67:24:67:25 | r2_2(int) = Constant[10] | test.c:67:24:67:25 | 10 | positive strictlyPositive |
-| test.c:68:15:68:15 | r3_4(int) = Constant[2] | test.c:68:15:68:15 | 2 | positive strictlyPositive |
-| test.c:77:13:77:13 | r2_2(int) = Constant[4] | test.c:77:13:77:13 | 4 | positive strictlyPositive |
-| test.c:81:13:81:13 | r4_2(int) = Constant[4] | test.c:81:13:81:13 | 4 | positive strictlyPositive |
-| test.c:82:14:82:14 | m5_2(int) = Store r5_0, r5_1 | test.c:82:14:82:14 | 1 | positive strictlyPositive |
-| test.c:82:14:82:14 | r5_1(int) = Constant[1] | test.c:82:14:82:14 | 1 | positive strictlyPositive |
-| test.c:88:5:88:10 | m1_0(int) = Phi from 3:m3_2, from 4:m4_3, from 5:m5_2 | test.c:88:5:88:10 | test10 | positive |
-| test.c:89:11:89:11 | r0_8(int) = Constant[7] | test.c:89:11:89:11 | 7 | positive strictlyPositive |
-| test.c:90:13:90:13 | r2_3(int) = Load r2_2, m0_5 | test.c:90:13:90:13 | y | positive strictlyPositive |
-| test.c:93:12:93:12 | m4_3(int) = Store r4_0, r4_2 | test.c:93:12:93:12 | x | positive strictlyPositive |
-| test.c:93:12:93:12 | r4_2(int) = Load r4_1, m0_3 | test.c:93:12:93:12 | x | positive strictlyPositive |
-| test.c:95:10:95:10 | m5_2(int) = Store r5_0, r5_1 | test.c:95:10:95:10 | 1 | positive strictlyPositive |
-| test.c:95:10:95:10 | r5_1(int) = Constant[1] | test.c:95:10:95:10 | 1 | positive strictlyPositive |
-| test.c:98:5:98:10 | m1_0(int) = Phi from 7:m7_2, from 8:m8_2 | test.c:98:5:98:10 | test11 | positive |
-| test.c:102:6:102:8 | r2_3(int) = Constant[1] | test.c:102:6:102:8 | ... ++ | positive strictlyPositive |
-| test.c:104:12:104:14 | r3_4(int) = Constant[58] | test.c:104:12:104:14 | 58 | positive strictlyPositive |
-| test.c:107:8:107:10 | r5_3(int) = Constant[1] | test.c:107:8:107:10 | ... ++ | positive strictlyPositive |
-| test.c:109:14:109:16 | r6_3(int) = Constant[44] | test.c:109:14:109:16 | 44 | positive strictlyPositive |
-| test.c:110:14:110:14 | m7_2(int) = Store r7_0, r7_1 | test.c:110:14:110:14 | 1 | positive strictlyPositive |
-| test.c:110:14:110:14 | r7_1(int) = Constant[1] | test.c:110:14:110:14 | 1 | positive strictlyPositive |
-| test.c:119:10:119:12 | m0_10(unsigned long long) = Store r0_6, r0_9 | test.c:119:10:119:12 | ... ++ | positive strictlyPositive |
-| test.c:119:10:119:12 | r0_8(unsigned long long) = Constant[1] | test.c:119:10:119:12 | ... ++ | positive strictlyPositive |
-| test.c:119:10:119:12 | r0_9(unsigned long long) = Add r0_7, r0_8 | test.c:119:10:119:12 | ... ++ | positive strictlyPositive |
-| test.c:124:11:124:15 | m1_0(unsigned long long) = Phi from 0:m0_4, from 2:m2_11 | test.c:124:11:124:15 | Start | positive |
-| test.c:124:11:124:15 | r1_2(unsigned long long) = Load r1_1, m1_0 | test.c:124:11:124:15 | Start | positive |
-| test.c:124:20:124:32 | r1_4(unsigned long long) = Call r1_3 | test.c:124:20:124:32 | call to test12_helper | positive |
-| test.c:124:20:124:36 | r1_6(unsigned long long) = Sub r1_4, r1_5 | test.c:124:20:124:36 | ... - ... | positive |
-| test.c:124:36:124:36 | r1_5(unsigned long long) = Constant[1] | test.c:124:36:124:36 | (unsigned long long)... | positive strictlyPositive |
-| test.c:126:31:126:43 | m2_3(unsigned long long) = Store r2_0, r2_2 | test.c:126:31:126:43 | call to test12_helper | positive |
-| test.c:126:31:126:43 | r2_2(unsigned long long) = Call r2_1 | test.c:126:31:126:43 | call to test12_helper | positive |
-| test.c:127:6:127:24 | m2_11(unsigned long long) = Store r2_8, r2_10 | test.c:127:6:127:24 | ... += ... | positive strictlyPositive |
-| test.c:127:6:127:24 | r2_9(unsigned long long) = Load r2_8, m1_0 | test.c:127:6:127:24 | ... += ... | positive |
-| test.c:127:6:127:24 | r2_10(unsigned long long) = Add r2_9, r2_7 | test.c:127:6:127:24 | ... += ... | positive strictlyPositive |
-| test.c:127:15:127:20 | r2_5(unsigned long long) = Load r2_4, m2_3 | test.c:127:15:127:20 | Length | positive |
-| test.c:127:15:127:24 | r2_7(unsigned long long) = Add r2_5, r2_6 | test.c:127:15:127:24 | ... + ... | positive strictlyPositive |
-| test.c:127:24:127:24 | r2_6(unsigned long long) = Constant[1] | test.c:127:24:127:24 | (unsigned long long)... | positive strictlyPositive |
-| test.c:130:11:130:11 | m3_2(int) = Store r3_0, r3_1 | test.c:130:11:130:11 | 1 | positive strictlyPositive |
-| test.c:130:11:130:11 | r3_1(int) = Constant[1] | test.c:130:11:130:11 | 1 | positive strictlyPositive |
-| test.c:135:22:135:22 | m0_10(unsigned char) = Store r0_6, r0_9 | test.c:135:22:135:22 | (unsigned char)... | positive |
-| test.c:135:22:135:22 | r0_9(unsigned char) = Convert r0_8 | test.c:135:22:135:22 | (unsigned char)... | positive |
-| test.c:137:22:137:22 | r0_17(unsigned int) = Constant[1] | test.c:137:22:137:22 | (unsigned int)... | positive strictlyPositive |
-| test.c:138:13:138:13 | r0_23(int) = Constant[1] | test.c:138:13:138:13 | 1 | positive strictlyPositive |
-| test.c:139:19:139:28 | r0_37(unsigned int) = Convert r0_36 | test.c:139:19:139:28 | (unsigned int)... | positive |
-| test.c:139:19:139:32 | r0_40(unsigned int) = Add r0_37, r0_39 | test.c:139:19:139:32 | ... + ... | positive |
-| test.c:139:27:139:28 | r0_34(unsigned char) = Load r0_33, m0_10 | test.c:139:27:139:28 | uc | positive |
-| test.c:139:27:139:28 | r0_35(int) = Convert r0_34 | test.c:139:27:139:28 | (int)... | positive |
-| test.c:139:40:139:40 | r0_46(unsigned int) = Convert r0_45 | test.c:139:40:139:40 | (unsigned int)... | positive |
-| test.c:145:12:145:32 | m0_15(int) = Store r0_10, r0_14 | test.c:145:12:145:32 | (int)... | positive |
-| test.c:145:12:145:32 | r0_14(int) = Convert r0_13 | test.c:145:12:145:32 | (int)... | positive |
-| test.c:145:17:145:32 | r0_13(unsigned char) = Convert r0_12 | test.c:145:17:145:32 | (unsigned char)... | positive |
-| test.c:146:12:146:33 | m0_21(int) = Store r0_16, r0_20 | test.c:146:12:146:33 | (int)... | positive |
-| test.c:146:12:146:33 | r0_20(int) = Convert r0_19 | test.c:146:12:146:33 | (int)... | positive |
-| test.c:146:17:146:33 | r0_19(unsigned short) = Convert r0_18 | test.c:146:17:146:33 | (unsigned short)... | positive |
-| test.c:147:17:147:31 | r0_25(unsigned int) = Convert r0_24 | test.c:147:17:147:31 | (unsigned int)... | positive |
-| test.c:149:23:149:23 | m0_37(unsigned short) = Store r0_33, r0_36 | test.c:149:23:149:23 | (unsigned short)... | positive |
-| test.c:149:23:149:23 | r0_36(unsigned short) = Convert r0_35 | test.c:149:23:149:23 | (unsigned short)... | positive |
-| test.c:150:15:150:16 | r0_42(int) = Load r0_41, m0_15 | test.c:150:15:150:16 | x1 | positive |
-| test.c:150:20:150:21 | r0_45(int) = Load r0_44, m0_21 | test.c:150:20:150:21 | x2 | positive |
-| test.c:150:35:150:36 | r0_55(unsigned short) = Load r0_54, m0_37 | test.c:150:35:150:36 | s0 | positive |
-| test.c:150:35:150:36 | r0_56(int) = Convert r0_55 | test.c:150:35:150:36 | (int)... | positive |
-| test.c:154:10:154:40 | m2_3(long long) = Store r2_2, r2_1 | test.c:154:10:154:40 | ... ? ... : ... | positive strictlyPositive |
-| test.c:154:10:154:40 | m3_2(long long) = Store r3_1, r3_0 | test.c:154:10:154:40 | ... ? ... : ... | negative strictlyNegative |
-| test.c:154:20:154:20 | r1_1(long long) = Load r1_0, m0_3 | test.c:154:20:154:20 | x | positive strictlyPositive |
-| test.c:154:25:154:30 | r1_4(int) = Convert r1_3 | test.c:154:25:154:30 | (int)... | positive |
-| test.c:154:25:154:30 | r1_5(long long) = Convert r1_4 | test.c:154:25:154:30 | (long long)... | positive |
-| test.c:154:30:154:30 | r1_3(long long) = Load r1_2, m0_3 | test.c:154:30:154:30 | x | positive strictlyPositive |
-| test.c:154:35:154:35 | r2_1(long long) = Load r2_0, m0_3 | test.c:154:35:154:35 | x | positive strictlyPositive |
-| test.c:154:39:154:40 | r3_0(long long) = Constant[-1] | test.c:154:39:154:40 | (long long)... | negative strictlyNegative |
-| test.c:161:7:161:7 | r0_7(int) = Constant[3] | test.c:161:7:161:7 | 3 | positive strictlyPositive |
-| test.c:161:17:161:17 | r8_1(int) = Load r8_0, m0_3 | test.c:161:17:161:17 | a | positive strictlyPositive |
-| test.c:161:22:161:23 | r8_2(int) = Constant[11] | test.c:161:22:161:23 | 11 | positive strictlyPositive |
-| test.c:162:13:162:14 | m12_4(int) = Store r12_0, r12_3 | test.c:162:13:162:14 | + ... | positive strictlyPositive |
-| test.c:162:13:162:14 | r12_3(int) = CopyValue r12_2 | test.c:162:13:162:14 | + ... | positive strictlyPositive |
-| test.c:162:14:162:14 | r12_2(int) = Load r12_1, m0_3 | test.c:162:14:162:14 | a | positive strictlyPositive |
-| test.c:163:13:163:14 | m12_9(int) = Store r12_5, r12_8 | test.c:163:13:163:14 | - ... | negative strictlyNegative |
-| test.c:163:13:163:14 | r12_8(int) = Negate r12_7 | test.c:163:13:163:14 | - ... | negative strictlyNegative |
-| test.c:163:14:163:14 | r12_7(int) = Load r12_6, m0_3 | test.c:163:14:163:14 | a | positive strictlyPositive |
-| test.c:164:14:164:14 | r12_11(int) = Load r12_10, m12_4 | test.c:164:14:164:14 | b | positive strictlyPositive |
-| test.c:164:16:164:16 | r12_13(int) = Load r12_12, m12_9 | test.c:164:16:164:16 | c | negative strictlyNegative |
-| test.c:166:17:166:17 | r14_1(int) = Load r14_0, m0_3 | test.c:166:17:166:17 | a | positive |
-| test.c:166:22:166:23 | r14_2(int) = Constant[11] | test.c:166:22:166:23 | 11 | positive strictlyPositive |
-| test.c:167:13:167:14 | m15_4(int) = Store r15_0, r15_3 | test.c:167:13:167:14 | + ... | positive |
-| test.c:167:13:167:14 | r15_3(int) = CopyValue r15_2 | test.c:167:13:167:14 | + ... | positive |
-| test.c:167:14:167:14 | r15_2(int) = Load r15_1, m0_3 | test.c:167:14:167:14 | a | positive |
-| test.c:168:13:168:14 | m15_9(int) = Store r15_5, r15_8 | test.c:168:13:168:14 | - ... | negative |
-| test.c:168:13:168:14 | r15_8(int) = Negate r15_7 | test.c:168:13:168:14 | - ... | negative |
-| test.c:168:14:168:14 | r15_7(int) = Load r15_6, m0_3 | test.c:168:14:168:14 | a | positive |
-| test.c:169:14:169:14 | r15_11(int) = Load r15_10, m15_4 | test.c:169:14:169:14 | b | positive |
-| test.c:169:16:169:16 | r15_13(int) = Load r15_12, m15_9 | test.c:169:16:169:16 | c | negative |
-| test.c:171:7:171:8 | r16_1(int) = Constant[-7] | test.c:171:7:171:8 | - ... | negative strictlyNegative |
-| test.c:171:23:171:24 | r17_2(int) = Constant[11] | test.c:171:23:171:24 | 11 | positive strictlyPositive |
-| test.c:176:7:176:8 | r1_1(int) = Constant[-7] | test.c:176:7:176:8 | - ... | negative strictlyNegative |
-| test.c:176:23:176:23 | r2_2(int) = Constant[1] | test.c:176:23:176:23 | 1 | positive strictlyPositive |
-| test.c:181:7:181:8 | r4_1(int) = Constant[-7] | test.c:181:7:181:8 | - ... | negative strictlyNegative |
-| test.c:182:13:182:14 | m6_4(int) = Store r6_0, r6_3 | test.c:182:13:182:14 | + ... | negative |
-| test.c:182:13:182:14 | r6_3(int) = CopyValue r6_2 | test.c:182:13:182:14 | + ... | negative |
-| test.c:182:14:182:14 | r6_2(int) = Load r6_1, m0_3 | test.c:182:14:182:14 | a | negative |
-| test.c:183:13:183:14 | m6_9(int) = Store r6_5, r6_8 | test.c:183:13:183:14 | - ... | positive |
-| test.c:183:13:183:14 | r6_8(int) = Negate r6_7 | test.c:183:13:183:14 | - ... | positive |
-| test.c:183:14:183:14 | r6_7(int) = Load r6_6, m0_3 | test.c:183:14:183:14 | a | negative |
-| test.c:184:14:184:14 | r6_11(int) = Load r6_10, m6_4 | test.c:184:14:184:14 | b | negative |
-| test.c:184:16:184:16 | r6_13(int) = Load r6_12, m6_9 | test.c:184:16:184:16 | c | positive |
-| test.c:186:7:186:8 | r7_1(int) = Constant[-7] | test.c:186:7:186:8 | - ... | negative strictlyNegative |
-| test.c:186:23:186:24 | r9_2(int) = Constant[-2] | test.c:186:23:186:24 | - ... | negative strictlyNegative |
-| test.c:187:13:187:14 | m10_4(int) = Store r10_0, r10_3 | test.c:187:13:187:14 | + ... | negative strictlyNegative |
-| test.c:187:13:187:14 | r10_3(int) = CopyValue r10_2 | test.c:187:13:187:14 | + ... | negative strictlyNegative |
-| test.c:187:14:187:14 | r10_2(int) = Load r10_1, m0_3 | test.c:187:14:187:14 | a | negative strictlyNegative |
-| test.c:188:13:188:14 | m10_9(int) = Store r10_5, r10_8 | test.c:188:13:188:14 | - ... | positive strictlyPositive |
-| test.c:188:13:188:14 | r10_8(int) = Negate r10_7 | test.c:188:13:188:14 | - ... | positive strictlyPositive |
-| test.c:188:14:188:14 | r10_7(int) = Load r10_6, m0_3 | test.c:188:14:188:14 | a | negative strictlyNegative |
-| test.c:189:14:189:14 | r10_11(int) = Load r10_10, m10_4 | test.c:189:14:189:14 | b | negative strictlyNegative |
-| test.c:189:16:189:16 | r10_13(int) = Load r10_12, m10_9 | test.c:189:16:189:16 | c | positive strictlyPositive |
-| test.c:200:7:200:7 | r0_9(int) = Constant[3] | test.c:200:7:200:7 | 3 | positive strictlyPositive |
-| test.c:200:17:200:17 | r14_1(int) = Load r14_0, m0_3 | test.c:200:17:200:17 | a | positive strictlyPositive |
-| test.c:200:22:200:23 | r14_2(int) = Constant[11] | test.c:200:22:200:23 | 11 | positive strictlyPositive |
-| test.c:200:28:200:28 | r15_0(int) = Constant[5] | test.c:200:28:200:28 | 5 | positive strictlyPositive |
-| test.c:200:38:200:38 | r16_1(int) = Load r16_0, m0_5 | test.c:200:38:200:38 | b | positive strictlyPositive |
-| test.c:200:43:200:44 | r16_2(int) = Constant[23] | test.c:200:43:200:44 | 23 | positive strictlyPositive |
-| test.c:201:13:201:13 | r17_2(int) = Load r17_1, m0_3 | test.c:201:13:201:13 | a | positive strictlyPositive |
-| test.c:201:13:201:15 | m17_6(int) = Store r17_0, r17_5 | test.c:201:13:201:15 | ... * ... | positive strictlyPositive |
-| test.c:201:13:201:15 | r17_5(int) = Mul r17_2, r17_4 | test.c:201:13:201:15 | ... * ... | positive strictlyPositive |
-| test.c:201:15:201:15 | r17_4(int) = Load r17_3, m0_5 | test.c:201:15:201:15 | b | positive strictlyPositive |
-| test.c:202:5:202:14 | m17_12(int) = Store r17_9, r17_11 | test.c:202:5:202:14 | ... += ... | positive strictlyPositive |
-| test.c:202:5:202:14 | r17_11(int) = Add r17_10, r17_8 | test.c:202:5:202:14 | ... += ... | positive strictlyPositive |
-| test.c:202:14:202:14 | r17_8(int) = Load r17_7, m17_6 | test.c:202:14:202:14 | r | positive strictlyPositive |
-| test.c:204:7:204:7 | m18_0(int) = Phi from 0:m0_8, from 14:m0_8, from 15:m0_8, from 16:m0_8, from 17:m17_12 | test.c:204:7:204:7 | 3 | positive |
-| test.c:204:7:204:7 | r18_1(int) = Constant[3] | test.c:204:7:204:7 | 3 | positive strictlyPositive |
-| test.c:204:17:204:17 | r19_1(int) = Load r19_0, m0_3 | test.c:204:17:204:17 | a | positive strictlyPositive |
-| test.c:204:22:204:23 | r19_2(int) = Constant[11] | test.c:204:22:204:23 | 11 | positive strictlyPositive |
-| test.c:204:38:204:38 | r21_1(int) = Load r21_0, m0_5 | test.c:204:38:204:38 | b | positive |
-| test.c:204:43:204:44 | r21_2(int) = Constant[23] | test.c:204:43:204:44 | 23 | positive strictlyPositive |
-| test.c:205:13:205:13 | r22_2(int) = Load r22_1, m0_3 | test.c:205:13:205:13 | a | positive strictlyPositive |
-| test.c:205:13:205:15 | m22_6(int) = Store r22_0, r22_5 | test.c:205:13:205:15 | ... * ... | positive |
-| test.c:205:13:205:15 | r22_5(int) = Mul r22_2, r22_4 | test.c:205:13:205:15 | ... * ... | positive |
-| test.c:205:15:205:15 | r22_4(int) = Load r22_3, m0_5 | test.c:205:15:205:15 | b | positive |
-| test.c:206:5:206:14 | m22_12(int) = Store r22_9, r22_11 | test.c:206:5:206:14 | ... += ... | positive |
-| test.c:206:5:206:14 | r22_10(int) = Load r22_9, m18_0 | test.c:206:5:206:14 | ... += ... | positive |
-| test.c:206:5:206:14 | r22_11(int) = Add r22_10, r22_8 | test.c:206:5:206:14 | ... += ... | positive |
-| test.c:206:14:206:14 | r22_8(int) = Load r22_7, m22_6 | test.c:206:14:206:14 | r | positive |
-| test.c:208:7:208:7 | m23_0(int) = Phi from 18:m18_0, from 19:m18_0, from 20:m18_0, from 21:m18_0, from 22:m22_12 | test.c:208:7:208:7 | 3 | positive |
-| test.c:208:7:208:7 | r23_1(int) = Constant[3] | test.c:208:7:208:7 | 3 | positive strictlyPositive |
-| test.c:208:17:208:17 | r24_1(int) = Load r24_0, m0_3 | test.c:208:17:208:17 | a | positive strictlyPositive |
-| test.c:208:22:208:23 | r24_2(int) = Constant[11] | test.c:208:22:208:23 | 11 | positive strictlyPositive |
-| test.c:208:28:208:30 | r25_0(int) = Constant[-13] | test.c:208:28:208:30 | - ... | negative strictlyNegative |
-| test.c:208:45:208:46 | r1_2(int) = Constant[23] | test.c:208:45:208:46 | 23 | positive strictlyPositive |
-| test.c:209:13:209:13 | r2_2(int) = Load r2_1, m0_3 | test.c:209:13:209:13 | a | positive strictlyPositive |
-| test.c:210:5:210:14 | r2_10(int) = Load r2_9, m23_0 | test.c:210:5:210:14 | ... += ... | positive |
-| test.c:212:7:212:7 | r3_1(int) = Constant[3] | test.c:212:7:212:7 | 3 | positive strictlyPositive |
-| test.c:212:17:212:17 | r4_1(int) = Load r4_0, m0_3 | test.c:212:17:212:17 | a | positive strictlyPositive |
-| test.c:212:22:212:23 | r4_2(int) = Constant[11] | test.c:212:22:212:23 | 11 | positive strictlyPositive |
-| test.c:212:28:212:30 | r5_0(int) = Constant[-13] | test.c:212:28:212:30 | - ... | negative strictlyNegative |
-| test.c:213:13:213:13 | r7_2(int) = Load r7_1, m0_3 | test.c:213:13:213:13 | a | positive strictlyPositive |
-| test.c:213:13:213:15 | m7_6(int) = Store r7_0, r7_5 | test.c:213:13:213:15 | ... * ... | negative |
-| test.c:213:13:213:15 | r7_5(int) = Mul r7_2, r7_4 | test.c:213:13:213:15 | ... * ... | negative |
-| test.c:213:15:213:15 | r7_4(int) = Load r7_3, m0_5 | test.c:213:15:213:15 | b | negative |
-| test.c:214:14:214:14 | r7_8(int) = Load r7_7, m7_6 | test.c:214:14:214:14 | r | negative |
-| test.c:216:7:216:7 | r8_1(int) = Constant[3] | test.c:216:7:216:7 | 3 | positive strictlyPositive |
-| test.c:216:17:216:17 | r9_1(int) = Load r9_0, m0_3 | test.c:216:17:216:17 | a | positive strictlyPositive |
-| test.c:216:22:216:23 | r9_2(int) = Constant[11] | test.c:216:22:216:23 | 11 | positive strictlyPositive |
-| test.c:216:28:216:30 | r10_0(int) = Constant[-13] | test.c:216:28:216:30 | - ... | negative strictlyNegative |
-| test.c:216:45:216:46 | r11_2(int) = Constant[-7] | test.c:216:45:216:46 | - ... | negative strictlyNegative |
-| test.c:217:13:217:13 | r12_2(int) = Load r12_1, m0_3 | test.c:217:13:217:13 | a | positive strictlyPositive |
-| test.c:217:13:217:15 | m12_6(int) = Store r12_0, r12_5 | test.c:217:13:217:15 | ... * ... | negative strictlyNegative |
-| test.c:217:13:217:15 | r12_5(int) = Mul r12_2, r12_4 | test.c:217:13:217:15 | ... * ... | negative strictlyNegative |
-| test.c:217:15:217:15 | r12_4(int) = Load r12_3, m0_5 | test.c:217:15:217:15 | b | negative strictlyNegative |
-| test.c:218:14:218:14 | r12_8(int) = Load r12_7, m12_6 | test.c:218:14:218:14 | r | negative strictlyNegative |
-| test.c:228:17:228:17 | r14_1(int) = Load r14_0, m0_3 | test.c:228:17:228:17 | a | positive |
-| test.c:228:22:228:23 | r14_2(int) = Constant[11] | test.c:228:22:228:23 | 11 | positive strictlyPositive |
-| test.c:228:28:228:28 | r15_0(int) = Constant[5] | test.c:228:28:228:28 | 5 | positive strictlyPositive |
-| test.c:228:38:228:38 | r16_1(int) = Load r16_0, m0_5 | test.c:228:38:228:38 | b | positive strictlyPositive |
-| test.c:228:43:228:44 | r16_2(int) = Constant[23] | test.c:228:43:228:44 | 23 | positive strictlyPositive |
-| test.c:229:13:229:13 | r17_2(int) = Load r17_1, m0_3 | test.c:229:13:229:13 | a | positive |
-| test.c:229:13:229:15 | m17_6(int) = Store r17_0, r17_5 | test.c:229:13:229:15 | ... * ... | positive |
-| test.c:229:13:229:15 | r17_5(int) = Mul r17_2, r17_4 | test.c:229:13:229:15 | ... * ... | positive |
-| test.c:229:15:229:15 | r17_4(int) = Load r17_3, m0_5 | test.c:229:15:229:15 | b | positive strictlyPositive |
-| test.c:230:5:230:14 | m17_12(int) = Store r17_9, r17_11 | test.c:230:5:230:14 | ... += ... | positive |
-| test.c:230:5:230:14 | r17_11(int) = Add r17_10, r17_8 | test.c:230:5:230:14 | ... += ... | positive |
-| test.c:230:14:230:14 | r17_8(int) = Load r17_7, m17_6 | test.c:230:14:230:14 | r | positive |
-| test.c:232:7:232:7 | m18_0(int) = Phi from 0:m0_8, from 14:m0_8, from 15:m0_8, from 16:m0_8, from 17:m17_12 | test.c:232:7:232:7 | 0 | positive |
-| test.c:232:17:232:17 | r19_1(int) = Load r19_0, m0_3 | test.c:232:17:232:17 | a | positive |
-| test.c:232:22:232:23 | r19_2(int) = Constant[11] | test.c:232:22:232:23 | 11 | positive strictlyPositive |
-| test.c:232:38:232:38 | r21_1(int) = Load r21_0, m0_5 | test.c:232:38:232:38 | b | positive |
-| test.c:232:43:232:44 | r21_2(int) = Constant[23] | test.c:232:43:232:44 | 23 | positive strictlyPositive |
-| test.c:233:13:233:13 | r22_2(int) = Load r22_1, m0_3 | test.c:233:13:233:13 | a | positive |
-| test.c:233:13:233:15 | m22_6(int) = Store r22_0, r22_5 | test.c:233:13:233:15 | ... * ... | positive |
-| test.c:233:13:233:15 | r22_5(int) = Mul r22_2, r22_4 | test.c:233:13:233:15 | ... * ... | positive |
-| test.c:233:15:233:15 | r22_4(int) = Load r22_3, m0_5 | test.c:233:15:233:15 | b | positive |
-| test.c:234:5:234:14 | m22_12(int) = Store r22_9, r22_11 | test.c:234:5:234:14 | ... += ... | positive |
-| test.c:234:5:234:14 | r22_10(int) = Load r22_9, m18_0 | test.c:234:5:234:14 | ... += ... | positive |
-| test.c:234:5:234:14 | r22_11(int) = Add r22_10, r22_8 | test.c:234:5:234:14 | ... += ... | positive |
-| test.c:234:14:234:14 | r22_8(int) = Load r22_7, m22_6 | test.c:234:14:234:14 | r | positive |
-| test.c:236:7:236:7 | m23_0(int) = Phi from 18:m18_0, from 19:m18_0, from 20:m18_0, from 21:m18_0, from 22:m22_12 | test.c:236:7:236:7 | 0 | positive |
-| test.c:236:17:236:17 | r24_1(int) = Load r24_0, m0_3 | test.c:236:17:236:17 | a | positive |
-| test.c:236:22:236:23 | r24_2(int) = Constant[11] | test.c:236:22:236:23 | 11 | positive strictlyPositive |
-| test.c:236:28:236:30 | r25_0(int) = Constant[-13] | test.c:236:28:236:30 | - ... | negative strictlyNegative |
-| test.c:236:45:236:46 | r1_2(int) = Constant[23] | test.c:236:45:236:46 | 23 | positive strictlyPositive |
-| test.c:237:13:237:13 | r2_2(int) = Load r2_1, m0_3 | test.c:237:13:237:13 | a | positive |
-| test.c:238:5:238:14 | r2_10(int) = Load r2_9, m23_0 | test.c:238:5:238:14 | ... += ... | positive |
-| test.c:240:17:240:17 | r4_1(int) = Load r4_0, m0_3 | test.c:240:17:240:17 | a | positive |
-| test.c:240:22:240:23 | r4_2(int) = Constant[11] | test.c:240:22:240:23 | 11 | positive strictlyPositive |
-| test.c:240:28:240:30 | r5_0(int) = Constant[-13] | test.c:240:28:240:30 | - ... | negative strictlyNegative |
-| test.c:241:13:241:13 | r7_2(int) = Load r7_1, m0_3 | test.c:241:13:241:13 | a | positive |
-| test.c:241:13:241:15 | m7_6(int) = Store r7_0, r7_5 | test.c:241:13:241:15 | ... * ... | negative |
-| test.c:241:13:241:15 | r7_5(int) = Mul r7_2, r7_4 | test.c:241:13:241:15 | ... * ... | negative |
-| test.c:241:15:241:15 | r7_4(int) = Load r7_3, m0_5 | test.c:241:15:241:15 | b | negative |
-| test.c:242:14:242:14 | r7_8(int) = Load r7_7, m7_6 | test.c:242:14:242:14 | r | negative |
-| test.c:244:17:244:17 | r9_1(int) = Load r9_0, m0_3 | test.c:244:17:244:17 | a | positive |
-| test.c:244:22:244:23 | r9_2(int) = Constant[11] | test.c:244:22:244:23 | 11 | positive strictlyPositive |
-| test.c:244:28:244:30 | r10_0(int) = Constant[-13] | test.c:244:28:244:30 | - ... | negative strictlyNegative |
-| test.c:244:45:244:46 | r11_2(int) = Constant[-7] | test.c:244:45:244:46 | - ... | negative strictlyNegative |
-| test.c:245:13:245:13 | r12_2(int) = Load r12_1, m0_3 | test.c:245:13:245:13 | a | positive |
-| test.c:245:13:245:15 | m12_6(int) = Store r12_0, r12_5 | test.c:245:13:245:15 | ... * ... | negative |
-| test.c:245:13:245:15 | r12_5(int) = Mul r12_2, r12_4 | test.c:245:13:245:15 | ... * ... | negative |
-| test.c:245:15:245:15 | r12_4(int) = Load r12_3, m0_5 | test.c:245:15:245:15 | b | negative strictlyNegative |
-| test.c:246:14:246:14 | r12_8(int) = Load r12_7, m12_6 | test.c:246:14:246:14 | r | negative |
-| test.c:256:7:256:9 | r0_9(int) = Constant[-17] | test.c:256:7:256:9 | - ... | negative strictlyNegative |
-| test.c:256:24:256:25 | r14_2(int) = Constant[11] | test.c:256:24:256:25 | 11 | positive strictlyPositive |
-| test.c:256:30:256:30 | r15_0(int) = Constant[5] | test.c:256:30:256:30 | 5 | positive strictlyPositive |
-| test.c:256:40:256:40 | r16_1(int) = Load r16_0, m0_5 | test.c:256:40:256:40 | b | positive strictlyPositive |
-| test.c:256:45:256:46 | r16_2(int) = Constant[23] | test.c:256:45:256:46 | 23 | positive strictlyPositive |
-| test.c:257:15:257:15 | r17_4(int) = Load r17_3, m0_5 | test.c:257:15:257:15 | b | positive strictlyPositive |
-| test.c:260:7:260:9 | r18_1(int) = Constant[-17] | test.c:260:7:260:9 | - ... | negative strictlyNegative |
-| test.c:260:24:260:25 | r19_2(int) = Constant[11] | test.c:260:24:260:25 | 11 | positive strictlyPositive |
-| test.c:260:40:260:40 | r21_1(int) = Load r21_0, m0_5 | test.c:260:40:260:40 | b | positive |
-| test.c:260:45:260:46 | r21_2(int) = Constant[23] | test.c:260:45:260:46 | 23 | positive strictlyPositive |
-| test.c:261:15:261:15 | r22_4(int) = Load r22_3, m0_5 | test.c:261:15:261:15 | b | positive |
-| test.c:264:7:264:9 | r23_1(int) = Constant[-17] | test.c:264:7:264:9 | - ... | negative strictlyNegative |
-| test.c:264:24:264:25 | r24_2(int) = Constant[11] | test.c:264:24:264:25 | 11 | positive strictlyPositive |
-| test.c:264:30:264:32 | r25_0(int) = Constant[-13] | test.c:264:30:264:32 | - ... | negative strictlyNegative |
-| test.c:264:47:264:48 | r1_2(int) = Constant[23] | test.c:264:47:264:48 | 23 | positive strictlyPositive |
-| test.c:268:7:268:9 | r3_1(int) = Constant[-17] | test.c:268:7:268:9 | - ... | negative strictlyNegative |
-| test.c:268:24:268:25 | r4_2(int) = Constant[11] | test.c:268:24:268:25 | 11 | positive strictlyPositive |
-| test.c:268:30:268:32 | r5_0(int) = Constant[-13] | test.c:268:30:268:32 | - ... | negative strictlyNegative |
-| test.c:269:15:269:15 | r7_4(int) = Load r7_3, m0_5 | test.c:269:15:269:15 | b | negative |
-| test.c:272:7:272:9 | r8_1(int) = Constant[-17] | test.c:272:7:272:9 | - ... | negative strictlyNegative |
-| test.c:272:24:272:25 | r9_2(int) = Constant[11] | test.c:272:24:272:25 | 11 | positive strictlyPositive |
-| test.c:272:30:272:32 | r10_0(int) = Constant[-13] | test.c:272:30:272:32 | - ... | negative strictlyNegative |
-| test.c:272:47:272:48 | r11_2(int) = Constant[-7] | test.c:272:47:272:48 | - ... | negative strictlyNegative |
-| test.c:273:15:273:15 | r12_4(int) = Load r12_3, m0_5 | test.c:273:15:273:15 | b | negative strictlyNegative |
-| test.c:284:7:284:9 | r0_9(int) = Constant[-17] | test.c:284:7:284:9 | - ... | negative strictlyNegative |
-| test.c:284:29:284:29 | r15_0(int) = Constant[5] | test.c:284:29:284:29 | 5 | positive strictlyPositive |
-| test.c:284:39:284:39 | r16_1(int) = Load r16_0, m0_5 | test.c:284:39:284:39 | b | positive strictlyPositive |
-| test.c:284:44:284:45 | r16_2(int) = Constant[23] | test.c:284:44:284:45 | 23 | positive strictlyPositive |
-| test.c:285:13:285:13 | r17_2(int) = Load r17_1, m0_3 | test.c:285:13:285:13 | a | negative |
-| test.c:285:13:285:15 | m17_6(int) = Store r17_0, r17_5 | test.c:285:13:285:15 | ... * ... | negative |
-| test.c:285:13:285:15 | r17_5(int) = Mul r17_2, r17_4 | test.c:285:13:285:15 | ... * ... | negative |
-| test.c:285:15:285:15 | r17_4(int) = Load r17_3, m0_5 | test.c:285:15:285:15 | b | positive strictlyPositive |
-| test.c:286:5:286:14 | m17_12(int) = Store r17_9, r17_11 | test.c:286:5:286:14 | ... += ... | negative |
-| test.c:286:5:286:14 | r17_11(int) = Add r17_10, r17_8 | test.c:286:5:286:14 | ... += ... | negative |
-| test.c:286:14:286:14 | r17_8(int) = Load r17_7, m17_6 | test.c:286:14:286:14 | r | negative |
-| test.c:288:7:288:9 | m18_0(int) = Phi from 0:m0_8, from 14:m0_8, from 15:m0_8, from 16:m0_8, from 17:m17_12 | test.c:288:7:288:9 | - ... | negative |
-| test.c:288:7:288:9 | r18_1(int) = Constant[-17] | test.c:288:7:288:9 | - ... | negative strictlyNegative |
-| test.c:288:39:288:39 | r21_1(int) = Load r21_0, m0_5 | test.c:288:39:288:39 | b | positive |
-| test.c:288:44:288:45 | r21_2(int) = Constant[23] | test.c:288:44:288:45 | 23 | positive strictlyPositive |
-| test.c:289:13:289:13 | r22_2(int) = Load r22_1, m0_3 | test.c:289:13:289:13 | a | negative |
-| test.c:289:13:289:15 | m22_6(int) = Store r22_0, r22_5 | test.c:289:13:289:15 | ... * ... | negative |
-| test.c:289:13:289:15 | r22_5(int) = Mul r22_2, r22_4 | test.c:289:13:289:15 | ... * ... | negative |
-| test.c:289:15:289:15 | r22_4(int) = Load r22_3, m0_5 | test.c:289:15:289:15 | b | positive |
-| test.c:290:5:290:14 | m22_12(int) = Store r22_9, r22_11 | test.c:290:5:290:14 | ... += ... | negative |
-| test.c:290:5:290:14 | r22_10(int) = Load r22_9, m18_0 | test.c:290:5:290:14 | ... += ... | negative |
-| test.c:290:5:290:14 | r22_11(int) = Add r22_10, r22_8 | test.c:290:5:290:14 | ... += ... | negative |
-| test.c:290:14:290:14 | r22_8(int) = Load r22_7, m22_6 | test.c:290:14:290:14 | r | negative |
-| test.c:292:7:292:9 | m23_0(int) = Phi from 18:m18_0, from 19:m18_0, from 20:m18_0, from 21:m18_0, from 22:m22_12 | test.c:292:7:292:9 | - ... | negative |
-| test.c:292:7:292:9 | r23_1(int) = Constant[-17] | test.c:292:7:292:9 | - ... | negative strictlyNegative |
-| test.c:292:29:292:31 | r25_0(int) = Constant[-13] | test.c:292:29:292:31 | - ... | negative strictlyNegative |
-| test.c:292:46:292:47 | r1_2(int) = Constant[23] | test.c:292:46:292:47 | 23 | positive strictlyPositive |
-| test.c:293:13:293:13 | r2_2(int) = Load r2_1, m0_3 | test.c:293:13:293:13 | a | negative |
-| test.c:294:5:294:14 | r2_10(int) = Load r2_9, m23_0 | test.c:294:5:294:14 | ... += ... | negative |
-| test.c:296:7:296:9 | r3_1(int) = Constant[-17] | test.c:296:7:296:9 | - ... | negative strictlyNegative |
-| test.c:296:29:296:31 | r5_0(int) = Constant[-13] | test.c:296:29:296:31 | - ... | negative strictlyNegative |
-| test.c:297:13:297:13 | r7_2(int) = Load r7_1, m0_3 | test.c:297:13:297:13 | a | negative |
-| test.c:297:13:297:15 | m7_6(int) = Store r7_0, r7_5 | test.c:297:13:297:15 | ... * ... | positive |
-| test.c:297:13:297:15 | r7_5(int) = Mul r7_2, r7_4 | test.c:297:13:297:15 | ... * ... | positive |
-| test.c:297:15:297:15 | r7_4(int) = Load r7_3, m0_5 | test.c:297:15:297:15 | b | negative |
-| test.c:298:14:298:14 | r7_8(int) = Load r7_7, m7_6 | test.c:298:14:298:14 | r | positive |
-| test.c:300:7:300:9 | r8_1(int) = Constant[-17] | test.c:300:7:300:9 | - ... | negative strictlyNegative |
-| test.c:300:29:300:31 | r10_0(int) = Constant[-13] | test.c:300:29:300:31 | - ... | negative strictlyNegative |
-| test.c:300:46:300:47 | r11_2(int) = Constant[-7] | test.c:300:46:300:47 | - ... | negative strictlyNegative |
-| test.c:301:13:301:13 | r12_2(int) = Load r12_1, m0_3 | test.c:301:13:301:13 | a | negative |
-| test.c:301:13:301:15 | m12_6(int) = Store r12_0, r12_5 | test.c:301:13:301:15 | ... * ... | positive |
-| test.c:301:13:301:15 | r12_5(int) = Mul r12_2, r12_4 | test.c:301:13:301:15 | ... * ... | positive |
-| test.c:301:15:301:15 | r12_4(int) = Load r12_3, m0_5 | test.c:301:15:301:15 | b | negative strictlyNegative |
-| test.c:302:14:302:14 | r12_8(int) = Load r12_7, m12_6 | test.c:302:14:302:14 | r | positive |
-| test.c:312:7:312:9 | r0_9(int) = Constant[-17] | test.c:312:7:312:9 | - ... | negative strictlyNegative |
-| test.c:312:24:312:25 | r14_2(int) = Constant[-2] | test.c:312:24:312:25 | - ... | negative strictlyNegative |
-| test.c:312:30:312:30 | r15_0(int) = Constant[5] | test.c:312:30:312:30 | 5 | positive strictlyPositive |
-| test.c:312:40:312:40 | r16_1(int) = Load r16_0, m0_5 | test.c:312:40:312:40 | b | positive strictlyPositive |
-| test.c:312:45:312:46 | r16_2(int) = Constant[23] | test.c:312:45:312:46 | 23 | positive strictlyPositive |
-| test.c:313:13:313:13 | r17_2(int) = Load r17_1, m0_3 | test.c:313:13:313:13 | a | negative strictlyNegative |
-| test.c:313:13:313:15 | m17_6(int) = Store r17_0, r17_5 | test.c:313:13:313:15 | ... * ... | negative strictlyNegative |
-| test.c:313:13:313:15 | r17_5(int) = Mul r17_2, r17_4 | test.c:313:13:313:15 | ... * ... | negative strictlyNegative |
-| test.c:313:15:313:15 | r17_4(int) = Load r17_3, m0_5 | test.c:313:15:313:15 | b | positive strictlyPositive |
-| test.c:314:5:314:14 | m17_12(int) = Store r17_9, r17_11 | test.c:314:5:314:14 | ... += ... | negative strictlyNegative |
-| test.c:314:5:314:14 | r17_11(int) = Add r17_10, r17_8 | test.c:314:5:314:14 | ... += ... | negative strictlyNegative |
-| test.c:314:14:314:14 | r17_8(int) = Load r17_7, m17_6 | test.c:314:14:314:14 | r | negative strictlyNegative |
-| test.c:316:7:316:9 | m18_0(int) = Phi from 0:m0_8, from 14:m0_8, from 15:m0_8, from 16:m0_8, from 17:m17_12 | test.c:316:7:316:9 | - ... | negative |
-| test.c:316:7:316:9 | r18_1(int) = Constant[-17] | test.c:316:7:316:9 | - ... | negative strictlyNegative |
-| test.c:316:24:316:25 | r19_2(int) = Constant[-2] | test.c:316:24:316:25 | - ... | negative strictlyNegative |
-| test.c:316:40:316:40 | r21_1(int) = Load r21_0, m0_5 | test.c:316:40:316:40 | b | positive |
-| test.c:316:45:316:46 | r21_2(int) = Constant[23] | test.c:316:45:316:46 | 23 | positive strictlyPositive |
-| test.c:317:13:317:13 | r22_2(int) = Load r22_1, m0_3 | test.c:317:13:317:13 | a | negative strictlyNegative |
-| test.c:317:13:317:15 | m22_6(int) = Store r22_0, r22_5 | test.c:317:13:317:15 | ... * ... | negative |
-| test.c:317:13:317:15 | r22_5(int) = Mul r22_2, r22_4 | test.c:317:13:317:15 | ... * ... | negative |
-| test.c:317:15:317:15 | r22_4(int) = Load r22_3, m0_5 | test.c:317:15:317:15 | b | positive |
-| test.c:318:5:318:14 | m22_12(int) = Store r22_9, r22_11 | test.c:318:5:318:14 | ... += ... | negative |
-| test.c:318:5:318:14 | r22_10(int) = Load r22_9, m18_0 | test.c:318:5:318:14 | ... += ... | negative |
-| test.c:318:5:318:14 | r22_11(int) = Add r22_10, r22_8 | test.c:318:5:318:14 | ... += ... | negative |
-| test.c:318:14:318:14 | r22_8(int) = Load r22_7, m22_6 | test.c:318:14:318:14 | r | negative |
-| test.c:320:7:320:9 | m23_0(int) = Phi from 18:m18_0, from 19:m18_0, from 20:m18_0, from 21:m18_0, from 22:m22_12 | test.c:320:7:320:9 | - ... | negative |
-| test.c:320:7:320:9 | r23_1(int) = Constant[-17] | test.c:320:7:320:9 | - ... | negative strictlyNegative |
-| test.c:320:24:320:25 | r24_2(int) = Constant[-2] | test.c:320:24:320:25 | - ... | negative strictlyNegative |
-| test.c:320:30:320:32 | r25_0(int) = Constant[-13] | test.c:320:30:320:32 | - ... | negative strictlyNegative |
-| test.c:320:47:320:48 | r1_2(int) = Constant[23] | test.c:320:47:320:48 | 23 | positive strictlyPositive |
-| test.c:321:13:321:13 | r2_2(int) = Load r2_1, m0_3 | test.c:321:13:321:13 | a | negative strictlyNegative |
-| test.c:322:5:322:14 | r2_10(int) = Load r2_9, m23_0 | test.c:322:5:322:14 | ... += ... | negative |
-| test.c:324:7:324:9 | r3_1(int) = Constant[-17] | test.c:324:7:324:9 | - ... | negative strictlyNegative |
-| test.c:324:24:324:25 | r4_2(int) = Constant[-2] | test.c:324:24:324:25 | - ... | negative strictlyNegative |
-| test.c:324:30:324:32 | r5_0(int) = Constant[-13] | test.c:324:30:324:32 | - ... | negative strictlyNegative |
-| test.c:325:13:325:13 | r7_2(int) = Load r7_1, m0_3 | test.c:325:13:325:13 | a | negative strictlyNegative |
-| test.c:325:13:325:15 | m7_6(int) = Store r7_0, r7_5 | test.c:325:13:325:15 | ... * ... | positive |
-| test.c:325:13:325:15 | r7_5(int) = Mul r7_2, r7_4 | test.c:325:13:325:15 | ... * ... | positive |
-| test.c:325:15:325:15 | r7_4(int) = Load r7_3, m0_5 | test.c:325:15:325:15 | b | negative |
-| test.c:326:14:326:14 | r7_8(int) = Load r7_7, m7_6 | test.c:326:14:326:14 | r | positive |
-| test.c:328:7:328:9 | r8_1(int) = Constant[-17] | test.c:328:7:328:9 | - ... | negative strictlyNegative |
-| test.c:328:24:328:25 | r9_2(int) = Constant[-2] | test.c:328:24:328:25 | - ... | negative strictlyNegative |
-| test.c:328:30:328:32 | r10_0(int) = Constant[-13] | test.c:328:30:328:32 | - ... | negative strictlyNegative |
-| test.c:328:47:328:48 | r11_2(int) = Constant[-7] | test.c:328:47:328:48 | - ... | negative strictlyNegative |
-| test.c:329:13:329:13 | r12_2(int) = Load r12_1, m0_3 | test.c:329:13:329:13 | a | negative strictlyNegative |
-| test.c:329:13:329:15 | m12_6(int) = Store r12_0, r12_5 | test.c:329:13:329:15 | ... * ... | positive strictlyPositive |
-| test.c:329:13:329:15 | r12_5(int) = Mul r12_2, r12_4 | test.c:329:13:329:15 | ... * ... | positive strictlyPositive |
-| test.c:329:15:329:15 | r12_4(int) = Load r12_3, m0_5 | test.c:329:15:329:15 | b | negative strictlyNegative |
-| test.c:330:14:330:14 | r12_8(int) = Load r12_7, m12_6 | test.c:330:14:330:14 | r | positive strictlyPositive |
-| test.c:339:12:339:13 | m2_2(int) = Store r2_0, r2_1 | test.c:339:12:339:13 | - ... | negative strictlyNegative |
-| test.c:339:12:339:13 | r2_1(int) = Constant[-1] | test.c:339:12:339:13 | - ... | negative strictlyNegative |
-| test.c:342:10:342:10 | m3_0(int) = Phi from 0:m0_8, from 4:m4_4 | test.c:342:10:342:10 | i | positive |
-| test.c:342:10:342:10 | r3_2(int) = Load r3_1, m3_0 | test.c:342:10:342:10 | i | positive |
-| test.c:342:14:342:14 | r3_3(int) = Constant[3] | test.c:342:14:342:14 | 3 | positive strictlyPositive |
-| test.c:343:5:343:7 | m4_4(int) = Store r4_0, r4_3 | test.c:343:5:343:7 | ... ++ | positive strictlyPositive |
-| test.c:343:5:343:7 | r4_1(int) = Load r4_0, m3_0 | test.c:343:5:343:7 | ... ++ | positive |
-| test.c:343:5:343:7 | r4_2(int) = Constant[1] | test.c:343:5:343:7 | ... ++ | positive strictlyPositive |
-| test.c:343:5:343:7 | r4_3(int) = Add r4_1, r4_2 | test.c:343:5:343:7 | ... ++ | positive strictlyPositive |
-| test.c:345:3:345:7 | m5_3(int) = Store r5_2, r5_1 | test.c:345:3:345:7 | ... = ... | positive |
-| test.c:345:7:345:7 | r5_1(int) = Load r5_0, m3_0 | test.c:345:7:345:7 | i | positive |
-| test.c:346:7:346:7 | r5_5(int) = Load r5_4, m0_3 | test.c:346:7:346:7 | x | positive |
-| test.c:347:9:347:9 | r6_1(int) = Load r6_0, m5_3 | test.c:347:9:347:9 | d | positive |
-| test.c:348:14:348:14 | m7_2(int) = Store r7_0, r7_1 | test.c:348:14:348:14 | 1 | positive strictlyPositive |
-| test.c:348:14:348:14 | r7_1(int) = Constant[1] | test.c:348:14:348:14 | 1 | positive strictlyPositive |
-| test.c:355:42:355:42 | m0_3(unsigned int) = InitializeParameter[x] r0_2 | test.c:355:42:355:42 | x | positive |
-| test.c:356:16:356:17 | m0_5(unsigned int) = Uninitialized r0_4 | test.c:356:16:356:17 | definition of y1 | positive |
-| test.c:356:20:356:21 | m0_7(unsigned int) = Uninitialized r0_6 | test.c:356:20:356:21 | definition of y2 | positive |
-| test.c:356:24:356:25 | m0_9(unsigned int) = Uninitialized r0_8 | test.c:356:24:356:25 | definition of y3 | positive |
-| test.c:356:28:356:29 | m0_11(unsigned int) = Uninitialized r0_10 | test.c:356:28:356:29 | definition of y4 | positive |
-| test.c:356:32:356:33 | m0_13(unsigned int) = Uninitialized r0_12 | test.c:356:32:356:33 | definition of y5 | positive |
-| test.c:356:36:356:37 | m0_15(unsigned int) = Uninitialized r0_14 | test.c:356:36:356:37 | definition of y6 | positive |
-| test.c:356:40:356:41 | m0_17(unsigned int) = Uninitialized r0_16 | test.c:356:40:356:41 | definition of y7 | positive |
-| test.c:356:44:356:45 | m0_19(unsigned int) = Uninitialized r0_18 | test.c:356:44:356:45 | definition of y8 | positive |
-| test.c:357:3:357:23 | m17_4(unsigned int) = Store r17_3, r17_2 | test.c:357:3:357:23 | ... = ... | positive |
-| test.c:357:8:357:8 | r0_21(unsigned int) = Load r0_20, m0_3 | test.c:357:8:357:8 | x | positive |
-| test.c:357:8:357:23 | m17_0(unsigned int) = Phi from 21:m21_3, from 22:m22_2 | test.c:357:8:357:23 | ... ? ... : ... | positive |
-| test.c:357:8:357:23 | m21_3(unsigned int) = Store r21_2, r21_1 | test.c:357:8:357:23 | ... ? ... : ... | positive |
-| test.c:357:8:357:23 | m22_2(unsigned int) = Store r22_1, r22_0 | test.c:357:8:357:23 | ... ? ... : ... | positive strictlyPositive |
-| test.c:357:8:357:23 | r17_2(unsigned int) = Load r17_1, m17_0 | test.c:357:8:357:23 | ... ? ... : ... | positive |
-| test.c:357:12:357:14 | r0_22(unsigned int) = Constant[100] | test.c:357:12:357:14 | (unsigned int)... | positive strictlyPositive |
-| test.c:357:18:357:18 | r21_1(unsigned int) = Load r21_0, m0_3 | test.c:357:18:357:18 | x | positive |
-| test.c:357:22:357:23 | r22_0(unsigned int) = Constant[10] | test.c:357:22:357:23 | (unsigned int)... | positive strictlyPositive |
-| test.c:358:3:358:24 | m23_4(unsigned int) = Store r23_3, r23_2 | test.c:358:3:358:24 | ... = ... | positive |
-| test.c:358:8:358:8 | r17_6(unsigned int) = Load r17_5, m0_3 | test.c:358:8:358:8 | x | positive |
-| test.c:358:8:358:24 | m23_0(unsigned int) = Phi from 24:m24_2, from 25:m25_3 | test.c:358:8:358:24 | ... ? ... : ... | positive |
-| test.c:358:8:358:24 | m24_2(unsigned int) = Store r24_1, r24_0 | test.c:358:8:358:24 | ... ? ... : ... | positive strictlyPositive |
-| test.c:358:8:358:24 | m25_3(unsigned int) = Store r25_2, r25_1 | test.c:358:8:358:24 | ... ? ... : ... | positive |
-| test.c:358:8:358:24 | r23_2(unsigned int) = Load r23_1, m23_0 | test.c:358:8:358:24 | ... ? ... : ... | positive |
-| test.c:358:13:358:15 | r17_7(unsigned int) = Constant[100] | test.c:358:13:358:15 | (unsigned int)... | positive strictlyPositive |
-| test.c:358:19:358:20 | r24_0(unsigned int) = Constant[10] | test.c:358:19:358:20 | (unsigned int)... | positive strictlyPositive |
-| test.c:358:24:358:24 | r25_1(unsigned int) = Load r25_0, m0_3 | test.c:358:24:358:24 | x | positive |
-| test.c:365:7:365:7 | r23_24(unsigned int) = Load r23_23, m0_3 | test.c:365:7:365:7 | x | positive |
-| test.c:365:11:365:13 | r23_25(unsigned int) = Constant[300] | test.c:365:11:365:13 | (unsigned int)... | positive strictlyPositive |
-| test.c:366:5:366:15 | m34_4(unsigned int) = Store r34_3, r34_2 | test.c:366:5:366:15 | ... = ... | positive |
-| test.c:366:10:366:10 | r37_1(unsigned int) = Load r39_0, r37_0, m0_3 | test.c:366:10:366:10 | x | positive |
-| test.c:366:10:366:10 | r39_1(unsigned int) = Load r39_0, r37_0, m0_3 | test.c:366:10:366:10 | x | positive |
-| test.c:366:10:366:15 | m34_0(unsigned int) = Phi from 35:m35_1, from 40:m40_2, from 40:m38_2, from 38:m40_2, from 38:m38_2, from 40:m40_2, from 40:m38_2, from 38:m40_2, from 38:m38_2 | test.c:366:10:366:15 | ... ? ... : ... | positive |
-| test.c:366:10:366:15 | m35_1(unsigned int) = Store r35_0, r39_1, r37_1 | test.c:366:10:366:15 | ... ? ... : ... | positive |
-| test.c:366:10:366:15 | m38_2(unsigned int) = Store r40_1, r38_1, r40_0, r38_0 | test.c:366:10:366:15 | ... ? ... : ... | positive strictlyPositive |
-| test.c:366:10:366:15 | m40_2(unsigned int) = Store r40_1, r38_1, r40_0, r38_0 | test.c:366:10:366:15 | ... ? ... : ... | positive strictlyPositive |
-| test.c:366:10:366:15 | r34_2(unsigned int) = Load r34_1, m34_0 | test.c:366:10:366:15 | ... ? ... : ... | positive |
-| test.c:366:15:366:15 | r38_0(unsigned int) = Constant[5] | test.c:366:15:366:15 | (unsigned int)... | positive strictlyPositive |
-| test.c:366:15:366:15 | r40_0(unsigned int) = Constant[5] | test.c:366:15:366:15 | (unsigned int)... | positive strictlyPositive |
-| test.c:367:5:367:17 | m44_4(unsigned int) = Store r44_3, r44_2 | test.c:367:5:367:17 | ... = ... | positive |
-| test.c:367:10:367:10 | r47_1(unsigned int) = Load r49_0, r47_0, m0_3 | test.c:367:10:367:10 | x | positive |
-| test.c:367:10:367:10 | r49_1(unsigned int) = Load r49_0, r47_0, m0_3 | test.c:367:10:367:10 | x | positive |
-| test.c:367:10:367:17 | m44_0(unsigned int) = Phi from 45:m45_1, from 50:m50_2, from 50:m48_2, from 48:m50_2, from 48:m48_2, from 50:m50_2, from 50:m48_2, from 48:m50_2, from 48:m48_2 | test.c:367:10:367:17 | ... ? ... : ... | positive |
-| test.c:367:10:367:17 | m45_1(unsigned int) = Store r45_0, r49_1, r47_1 | test.c:367:10:367:17 | ... ? ... : ... | positive |
-| test.c:367:10:367:17 | m48_2(unsigned int) = Store r50_1, r48_1, r50_0, r48_0 | test.c:367:10:367:17 | ... ? ... : ... | positive strictlyPositive |
-| test.c:367:10:367:17 | m50_2(unsigned int) = Store r50_1, r48_1, r50_0, r48_0 | test.c:367:10:367:17 | ... ? ... : ... | positive strictlyPositive |
-| test.c:367:10:367:17 | r44_2(unsigned int) = Load r44_1, m44_0 | test.c:367:10:367:17 | ... ? ... : ... | positive |
-| test.c:367:15:367:17 | r48_0(unsigned int) = Constant[500] | test.c:367:15:367:17 | (unsigned int)... | positive strictlyPositive |
-| test.c:367:15:367:17 | r50_0(unsigned int) = Constant[500] | test.c:367:15:367:17 | (unsigned int)... | positive strictlyPositive |
-| test.c:368:5:368:21 | m51_4(unsigned int) = Store r51_3, r51_2 | test.c:368:5:368:21 | ... = ... | positive strictlyPositive |
-| test.c:368:10:368:21 | m51_0(unsigned int) = Phi from 52:m52_1, from 55:m55_2 | test.c:368:10:368:21 | ... ? ... : ... | positive strictlyPositive |
-| test.c:368:10:368:21 | m55_2(unsigned int) = Store r55_1, r55_0 | test.c:368:10:368:21 | ... ? ... : ... | positive strictlyPositive |
-| test.c:368:10:368:21 | r51_2(unsigned int) = Load r51_1, m51_0 | test.c:368:10:368:21 | ... ? ... : ... | positive strictlyPositive |
-| test.c:368:11:368:11 | r44_6(unsigned int) = Load r44_5, m0_3 | test.c:368:11:368:11 | x | positive |
-| test.c:368:11:368:13 | r53_0(unsigned int) = Add r44_6, r54_0, r27_0 | test.c:368:11:368:13 | ... + ... | positive strictlyPositive |
-| test.c:368:13:368:13 | r27_0(unsigned int) = Constant[1] | test.c:368:13:368:13 | (unsigned int)... | positive strictlyPositive |
-| test.c:368:13:368:13 | r54_0(unsigned int) = Constant[1] | test.c:368:13:368:13 | (unsigned int)... | positive strictlyPositive |
-| test.c:368:19:368:21 | r55_0(unsigned int) = Constant[500] | test.c:368:19:368:21 | (unsigned int)... | positive strictlyPositive |
-| test.c:369:5:369:36 | m1_5(unsigned int) = Store r1_4, r1_3 | test.c:369:5:369:36 | ... = ... | positive strictlyPositive |
-| test.c:369:10:369:36 | m1_0(int) = Phi from 2:m2_1, from 5:m5_2 | test.c:369:10:369:36 | ... ? ... : ... | positive strictlyPositive |
-| test.c:369:10:369:36 | m5_2(int) = Store r5_1, r5_0 | test.c:369:10:369:36 | ... ? ... : ... | positive strictlyPositive |
-| test.c:369:10:369:36 | r1_2(int) = Load r1_1, m1_0 | test.c:369:10:369:36 | ... ? ... : ... | positive strictlyPositive |
-| test.c:369:10:369:36 | r1_3(unsigned int) = Convert r1_2 | test.c:369:10:369:36 | (unsigned int)... | positive strictlyPositive |
-| test.c:369:11:369:30 | r3_1(unsigned char) = Convert r3_0 | test.c:369:11:369:30 | (unsigned char)... | positive |
-| test.c:369:27:369:27 | r51_6(unsigned int) = Load r51_5, m0_3 | test.c:369:27:369:27 | x | positive |
-| test.c:369:27:369:29 | r3_0(unsigned int) = Add r51_6, r4_0, r41_0 | test.c:369:27:369:29 | ... + ... | positive strictlyPositive |
-| test.c:369:29:369:29 | r4_0(unsigned int) = Constant[1] | test.c:369:29:369:29 | (unsigned int)... | positive strictlyPositive |
-| test.c:369:29:369:29 | r41_0(unsigned int) = Constant[1] | test.c:369:29:369:29 | (unsigned int)... | positive strictlyPositive |
-| test.c:369:36:369:36 | r5_0(int) = Constant[5] | test.c:369:36:369:36 | 5 | positive strictlyPositive |
-| test.c:370:5:370:38 | m6_5(unsigned int) = Store r6_4, r6_3 | test.c:370:5:370:38 | ... = ... | positive strictlyPositive |
-| test.c:370:10:370:38 | m6_0(int) = Phi from 7:m7_1, from 10:m10_2 | test.c:370:10:370:38 | ... ? ... : ... | positive strictlyPositive |
-| test.c:370:10:370:38 | m10_2(int) = Store r10_1, r10_0 | test.c:370:10:370:38 | ... ? ... : ... | positive strictlyPositive |
-| test.c:370:10:370:38 | r6_2(int) = Load r6_1, m6_0 | test.c:370:10:370:38 | ... ? ... : ... | positive strictlyPositive |
-| test.c:370:10:370:38 | r6_3(unsigned int) = Convert r6_2 | test.c:370:10:370:38 | (unsigned int)... | positive strictlyPositive |
-| test.c:370:11:370:30 | r8_1(unsigned char) = Convert r8_0 | test.c:370:11:370:30 | (unsigned char)... | positive |
-| test.c:370:27:370:27 | r1_7(unsigned int) = Load r1_6, m0_3 | test.c:370:27:370:27 | x | positive |
-| test.c:370:27:370:29 | r8_0(unsigned int) = Add r1_7, r9_0, r41_0 | test.c:370:27:370:29 | ... + ... | positive strictlyPositive |
-| test.c:370:29:370:29 | r9_0(unsigned int) = Constant[1] | test.c:370:29:370:29 | (unsigned int)... | positive strictlyPositive |
-| test.c:370:29:370:29 | r41_0(unsigned int) = Constant[1] | test.c:370:29:370:29 | (unsigned int)... | positive strictlyPositive |
-| test.c:370:36:370:38 | r10_0(int) = Constant[500] | test.c:370:36:370:38 | 500 | positive strictlyPositive |
-| test.c:371:5:371:39 | m11_5(unsigned int) = Store r11_4, r11_3 | test.c:371:5:371:39 | ... = ... | positive strictlyPositive |
-| test.c:371:10:371:39 | m11_0(int) = Phi from 12:m12_1, from 15:m15_2 | test.c:371:10:371:39 | ... ? ... : ... | positive strictlyPositive |
-| test.c:371:10:371:39 | m15_2(int) = Store r15_1, r15_0 | test.c:371:10:371:39 | ... ? ... : ... | positive strictlyPositive |
-| test.c:371:10:371:39 | r11_2(int) = Load r11_1, m11_0 | test.c:371:10:371:39 | ... ? ... : ... | positive strictlyPositive |
-| test.c:371:10:371:39 | r11_3(unsigned int) = Convert r11_2 | test.c:371:10:371:39 | (unsigned int)... | positive strictlyPositive |
-| test.c:371:11:371:31 | r13_1(unsigned short) = Convert r13_0 | test.c:371:11:371:31 | (unsigned short)... | positive |
-| test.c:371:28:371:28 | r6_7(unsigned int) = Load r6_6, m0_3 | test.c:371:28:371:28 | x | positive |
-| test.c:371:28:371:30 | r13_0(unsigned int) = Add r6_7, r41_0, r14_0 | test.c:371:28:371:30 | ... + ... | positive strictlyPositive |
-| test.c:371:30:371:30 | r14_0(unsigned int) = Constant[1] | test.c:371:30:371:30 | (unsigned int)... | positive strictlyPositive |
-| test.c:371:30:371:30 | r41_0(unsigned int) = Constant[1] | test.c:371:30:371:30 | (unsigned int)... | positive strictlyPositive |
-| test.c:371:37:371:39 | r15_0(int) = Constant[500] | test.c:371:37:371:39 | 500 | positive strictlyPositive |
-| test.c:373:3:373:47 | m16_0(unsigned int) = Phi from 11:m34_4, from 23:m23_7 | test.c:373:3:373:47 | return ... | positive |
-| test.c:373:3:373:47 | m16_1(unsigned int) = Phi from 11:m44_4, from 23:m23_10 | test.c:373:3:373:47 | return ... | positive |
-| test.c:373:3:373:47 | m16_2(unsigned int) = Phi from 11:m51_4, from 23:m23_13 | test.c:373:3:373:47 | return ... | positive |
-| test.c:373:3:373:47 | m16_3(unsigned int) = Phi from 11:m1_5, from 23:m23_16 | test.c:373:3:373:47 | return ... | positive |
-| test.c:373:3:373:47 | m16_4(unsigned int) = Phi from 11:m6_5, from 23:m23_19 | test.c:373:3:373:47 | return ... | positive |
-| test.c:373:3:373:47 | m16_5(unsigned int) = Phi from 11:m11_5, from 23:m23_22 | test.c:373:3:373:47 | return ... | positive |
-| test.c:373:10:373:11 | r16_8(unsigned int) = Load r16_7, m17_4 | test.c:373:10:373:11 | y1 | positive |
-| test.c:373:10:373:16 | r16_11(unsigned int) = Add r16_8, r16_10 | test.c:373:10:373:16 | ... + ... | positive |
-| test.c:373:10:373:21 | r16_14(unsigned int) = Add r16_11, r16_13 | test.c:373:10:373:21 | ... + ... | positive |
-| test.c:373:10:373:26 | r16_17(unsigned int) = Add r16_14, r16_16 | test.c:373:10:373:26 | ... + ... | positive |
-| test.c:373:10:373:31 | r16_20(unsigned int) = Add r16_17, r16_19 | test.c:373:10:373:31 | ... + ... | positive |
-| test.c:373:10:373:36 | r16_23(unsigned int) = Add r16_20, r16_22 | test.c:373:10:373:36 | ... + ... | positive |
-| test.c:373:10:373:41 | r16_26(unsigned int) = Add r16_23, r16_25 | test.c:373:10:373:41 | ... + ... | positive |
-| test.c:373:10:373:46 | m16_30(unsigned int) = Store r16_6, r16_29 | test.c:373:10:373:46 | ... + ... | positive |
-| test.c:373:10:373:46 | r16_29(unsigned int) = Add r16_26, r16_28 | test.c:373:10:373:46 | ... + ... | positive |
-| test.c:373:15:373:16 | r16_10(unsigned int) = Load r16_9, m23_4 | test.c:373:15:373:16 | y2 | positive |
-| test.c:373:20:373:21 | r16_13(unsigned int) = Load r16_12, m16_0 | test.c:373:20:373:21 | y3 | positive |
-| test.c:373:25:373:26 | r16_16(unsigned int) = Load r16_15, m16_1 | test.c:373:25:373:26 | y4 | positive |
-| test.c:373:30:373:31 | r16_19(unsigned int) = Load r16_18, m16_2 | test.c:373:30:373:31 | y5 | positive |
-| test.c:373:35:373:36 | r16_22(unsigned int) = Load r16_21, m16_3 | test.c:373:35:373:36 | y6 | positive |
-| test.c:373:40:373:41 | r16_25(unsigned int) = Load r16_24, m16_4 | test.c:373:40:373:41 | y7 | positive |
-| test.c:373:45:373:46 | r16_28(unsigned int) = Load r16_27, m16_5 | test.c:373:45:373:46 | y8 | positive |
-| test.c:377:42:377:42 | m0_3(unsigned int) = InitializeParameter[x] r0_2 | test.c:377:42:377:42 | x | positive |
-| test.c:378:16:378:17 | m0_5(unsigned int) = Uninitialized r0_4 | test.c:378:16:378:17 | definition of y1 | positive |
-| test.c:378:20:378:21 | m0_7(unsigned int) = Uninitialized r0_6 | test.c:378:20:378:21 | definition of y2 | positive |
-| test.c:378:24:378:25 | m0_9(unsigned int) = Uninitialized r0_8 | test.c:378:24:378:25 | definition of y3 | positive |
-| test.c:378:28:378:29 | m0_11(unsigned int) = Uninitialized r0_10 | test.c:378:28:378:29 | definition of y4 | positive |
-| test.c:378:32:378:33 | m0_13(unsigned int) = Uninitialized r0_12 | test.c:378:32:378:33 | definition of y5 | positive |
-| test.c:379:3:379:24 | m1_4(unsigned int) = Store r1_3, r1_2 | test.c:379:3:379:24 | ... = ... | positive strictlyPositive |
-| test.c:379:8:379:8 | r0_15(unsigned int) = Load r0_14, m0_3 | test.c:379:8:379:8 | x | positive |
-| test.c:379:8:379:24 | m1_0(unsigned int) = Phi from 2:m2_3, from 5:m5_2 | test.c:379:8:379:24 | ... ? ... : ... | positive strictlyPositive |
-| test.c:379:8:379:24 | m2_3(unsigned int) = Store r2_2, r2_1 | test.c:379:8:379:24 | ... ? ... : ... | positive strictlyPositive |
-| test.c:379:8:379:24 | m5_2(unsigned int) = Store r5_1, r5_0 | test.c:379:8:379:24 | ... ? ... : ... | positive strictlyPositive |
-| test.c:379:8:379:24 | r1_2(unsigned int) = Load r1_1, m1_0 | test.c:379:8:379:24 | ... ? ... : ... | positive strictlyPositive |
-| test.c:379:12:379:14 | r0_16(unsigned int) = Constant[100] | test.c:379:12:379:14 | (unsigned int)... | positive strictlyPositive |
-| test.c:379:18:379:18 | r2_1(unsigned int) = Load r2_0, m0_3 | test.c:379:18:379:18 | x | positive strictlyPositive |
-| test.c:379:22:379:24 | r5_0(unsigned int) = Constant[110] | test.c:379:22:379:24 | (unsigned int)... | positive strictlyPositive |
-| test.c:380:3:380:25 | m6_4(unsigned int) = Store r6_3, r6_2 | test.c:380:3:380:25 | ... = ... | positive strictlyPositive |
-| test.c:380:8:380:8 | r1_6(unsigned int) = Load r1_5, m0_3 | test.c:380:8:380:8 | x | positive |
-| test.c:380:8:380:25 | m6_0(unsigned int) = Phi from 7:m7_2, from 8:m8_3 | test.c:380:8:380:25 | ... ? ... : ... | positive strictlyPositive |
-| test.c:380:8:380:25 | m7_2(unsigned int) = Store r7_1, r7_0 | test.c:380:8:380:25 | ... ? ... : ... | positive strictlyPositive |
-| test.c:380:8:380:25 | m8_3(unsigned int) = Store r8_2, r8_1 | test.c:380:8:380:25 | ... ? ... : ... | positive strictlyPositive |
-| test.c:380:8:380:25 | r6_2(unsigned int) = Load r6_1, m6_0 | test.c:380:8:380:25 | ... ? ... : ... | positive strictlyPositive |
-| test.c:380:13:380:15 | r1_7(unsigned int) = Constant[100] | test.c:380:13:380:15 | (unsigned int)... | positive strictlyPositive |
-| test.c:380:19:380:21 | r7_0(unsigned int) = Constant[110] | test.c:380:19:380:21 | (unsigned int)... | positive strictlyPositive |
-| test.c:380:25:380:25 | r8_1(unsigned int) = Load r8_0, m0_3 | test.c:380:25:380:25 | x | positive strictlyPositive |
-| test.c:381:3:381:11 | m6_7(unsigned int) = Store r6_6, r6_5 | test.c:381:3:381:11 | ... = ... | positive strictlyPositive |
-| test.c:381:8:381:11 | r6_5(unsigned int) = Constant[1000] | test.c:381:8:381:11 | (unsigned int)... | positive strictlyPositive |
-| test.c:382:3:382:11 | m6_10(unsigned int) = Store r6_9, r6_8 | test.c:382:3:382:11 | ... = ... | positive strictlyPositive |
-| test.c:382:8:382:11 | r6_8(unsigned int) = Constant[1000] | test.c:382:8:382:11 | (unsigned int)... | positive strictlyPositive |
-| test.c:383:3:383:11 | m6_13(unsigned int) = Store r6_12, r6_11 | test.c:383:3:383:11 | ... = ... | positive strictlyPositive |
-| test.c:383:8:383:11 | r6_11(unsigned int) = Constant[1000] | test.c:383:8:383:11 | (unsigned int)... | positive strictlyPositive |
-| test.c:384:7:384:7 | r6_15(unsigned int) = Load r6_14, m0_3 | test.c:384:7:384:7 | x | positive |
-| test.c:384:12:384:14 | r6_16(unsigned int) = Constant[300] | test.c:384:12:384:14 | (unsigned int)... | positive strictlyPositive |
-| test.c:385:5:385:21 | m14_4(unsigned int) = Store r14_3, r14_2 | test.c:385:5:385:21 | ... = ... | positive strictlyPositive |
-| test.c:385:10:385:21 | m14_0(unsigned int) = Phi from 15:m15_1, from 19:m19_2 | test.c:385:10:385:21 | ... ? ... : ... | positive strictlyPositive |
-| test.c:385:10:385:21 | m19_2(unsigned int) = Store r19_1, r19_0 | test.c:385:10:385:21 | ... ? ... : ... | positive strictlyPositive |
-| test.c:385:10:385:21 | r14_2(unsigned int) = Load r14_1, m14_0 | test.c:385:10:385:21 | ... ? ... : ... | positive strictlyPositive |
-| test.c:385:11:385:11 | r17_1(unsigned int) = Load r17_0, m0_3 | test.c:385:11:385:11 | x | positive strictlyPositive |
-| test.c:385:11:385:15 | r16_0(unsigned int) = Sub r17_1, r18_0, r11_0 | test.c:385:11:385:15 | ... - ... | positive |
-| test.c:385:13:385:15 | r11_0(unsigned int) = Constant[300] | test.c:385:13:385:15 | (unsigned int)... | positive strictlyPositive |
-| test.c:385:13:385:15 | r18_0(unsigned int) = Constant[300] | test.c:385:13:385:15 | (unsigned int)... | positive strictlyPositive |
-| test.c:385:21:385:21 | r19_0(unsigned int) = Constant[5] | test.c:385:21:385:21 | (unsigned int)... | positive strictlyPositive |
-| test.c:386:5:386:21 | m20_4(unsigned int) = Store r20_3, r20_2 | test.c:386:5:386:21 | ... = ... | positive strictlyPositive |
-| test.c:386:10:386:21 | m20_0(unsigned int) = Phi from 21:m21_1, from 25:m25_2 | test.c:386:10:386:21 | ... ? ... : ... | positive strictlyPositive |
-| test.c:386:10:386:21 | m25_2(unsigned int) = Store r25_1, r25_0 | test.c:386:10:386:21 | ... ? ... : ... | positive strictlyPositive |
-| test.c:386:10:386:21 | r20_2(unsigned int) = Load r20_1, m20_0 | test.c:386:10:386:21 | ... ? ... : ... | positive strictlyPositive |
-| test.c:386:11:386:11 | r14_6(unsigned int) = Load r14_5, m0_3 | test.c:386:11:386:11 | x | positive strictlyPositive |
-| test.c:386:11:386:15 | r22_0(unsigned int) = Sub r14_6, r24_0, r11_0 | test.c:386:11:386:15 | ... - ... | positive |
-| test.c:386:13:386:15 | r11_0(unsigned int) = Constant[200] | test.c:386:13:386:15 | (unsigned int)... | positive strictlyPositive |
-| test.c:386:13:386:15 | r24_0(unsigned int) = Constant[200] | test.c:386:13:386:15 | (unsigned int)... | positive strictlyPositive |
-| test.c:386:21:386:21 | r25_0(unsigned int) = Constant[5] | test.c:386:21:386:21 | (unsigned int)... | positive strictlyPositive |
-| test.c:387:5:387:38 | m26_5(unsigned int) = Store r26_4, r26_3 | test.c:387:5:387:38 | ... = ... | positive strictlyPositive |
-| test.c:387:10:387:38 | m26_0(int) = Phi from 27:m27_1, from 31:m31_2 | test.c:387:10:387:38 | ... ? ... : ... | positive strictlyPositive |
-| test.c:387:10:387:38 | m31_2(int) = Store r31_1, r31_0 | test.c:387:10:387:38 | ... ? ... : ... | positive strictlyPositive |
-| test.c:387:10:387:38 | r26_2(int) = Load r26_1, m26_0 | test.c:387:10:387:38 | ... ? ... : ... | positive strictlyPositive |
-| test.c:387:10:387:38 | r26_3(unsigned int) = Convert r26_2 | test.c:387:10:387:38 | (unsigned int)... | positive strictlyPositive |
-| test.c:387:11:387:32 | r29_1(unsigned char) = Convert r29_0 | test.c:387:11:387:32 | (unsigned char)... | positive |
-| test.c:387:27:387:27 | r20_6(unsigned int) = Load r20_5, m0_3 | test.c:387:27:387:27 | x | positive strictlyPositive |
-| test.c:387:27:387:31 | r29_0(unsigned int) = Sub r20_6, r30_0, r28_0 | test.c:387:27:387:31 | ... - ... | positive |
-| test.c:387:29:387:31 | r28_0(unsigned int) = Constant[200] | test.c:387:29:387:31 | (unsigned int)... | positive strictlyPositive |
-| test.c:387:29:387:31 | r30_0(unsigned int) = Constant[200] | test.c:387:29:387:31 | (unsigned int)... | positive strictlyPositive |
-| test.c:387:38:387:38 | r31_0(int) = Constant[5] | test.c:387:38:387:38 | 5 | positive strictlyPositive |
-| test.c:389:3:389:32 | m32_0(unsigned int) = Phi from 6:m6_7, from 26:m14_4 | test.c:389:3:389:32 | return ... | positive strictlyPositive |
-| test.c:389:3:389:32 | m32_1(unsigned int) = Phi from 6:m6_10, from 26:m20_4 | test.c:389:3:389:32 | return ... | positive strictlyPositive |
-| test.c:389:3:389:32 | m32_2(unsigned int) = Phi from 6:m6_13, from 26:m26_5 | test.c:389:3:389:32 | return ... | positive strictlyPositive |
-| test.c:389:10:389:11 | r32_5(unsigned int) = Load r32_4, m1_4 | test.c:389:10:389:11 | y1 | positive strictlyPositive |
-| test.c:389:10:389:16 | r32_8(unsigned int) = Add r32_5, r32_7 | test.c:389:10:389:16 | ... + ... | positive strictlyPositive |
-| test.c:389:10:389:21 | r32_11(unsigned int) = Add r32_8, r32_10 | test.c:389:10:389:21 | ... + ... | positive strictlyPositive |
-| test.c:389:10:389:26 | r32_14(unsigned int) = Add r32_11, r32_13 | test.c:389:10:389:26 | ... + ... | positive strictlyPositive |
-| test.c:389:10:389:31 | m32_18(unsigned int) = Store r32_3, r32_17 | test.c:389:10:389:31 | ... + ... | positive strictlyPositive |
-| test.c:389:10:389:31 | r32_17(unsigned int) = Add r32_14, r32_16 | test.c:389:10:389:31 | ... + ... | positive strictlyPositive |
-| test.c:389:15:389:16 | r32_7(unsigned int) = Load r32_6, m6_4 | test.c:389:15:389:16 | y2 | positive strictlyPositive |
-| test.c:389:20:389:21 | r32_10(unsigned int) = Load r32_9, m32_0 | test.c:389:20:389:21 | y3 | positive strictlyPositive |
-| test.c:389:25:389:26 | r32_13(unsigned int) = Load r32_12, m32_1 | test.c:389:25:389:26 | y4 | positive strictlyPositive |
-| test.c:389:30:389:31 | r32_16(unsigned int) = Load r32_15, m32_2 | test.c:389:30:389:31 | y5 | positive strictlyPositive |
-| test.c:393:40:393:40 | m0_3(unsigned int) = InitializeParameter[x] r0_2 | test.c:393:40:393:40 | x | positive |
-| test.c:394:20:394:20 | r0_6(unsigned int) = Load r0_5, m0_3 | test.c:394:20:394:20 | x | positive |
-| test.c:394:20:394:36 | m1_3(unsigned int) = Store r1_2, r1_1 | test.c:394:20:394:36 | ... ? ... : ... | positive |
-| test.c:394:20:394:36 | m2_2(unsigned int) = Store r2_1, r2_0 | test.c:394:20:394:36 | ... ? ... : ... | positive strictlyPositive |
-| test.c:394:20:394:36 | m3_0(unsigned int) = Phi from 1:m1_3, from 2:m2_2 | test.c:394:20:394:36 | ... ? ... : ... | positive |
-| test.c:394:20:394:36 | m3_3(unsigned int) = Store r0_4, r3_2 | test.c:394:20:394:36 | ... ? ... : ... | positive |
-| test.c:394:20:394:36 | r3_2(unsigned int) = Load r3_1, m3_0 | test.c:394:20:394:36 | ... ? ... : ... | positive |
-| test.c:394:24:394:26 | r0_7(unsigned int) = Constant[100] | test.c:394:24:394:26 | (unsigned int)... | positive strictlyPositive |
-| test.c:394:30:394:30 | r1_1(unsigned int) = Load r1_0, m0_3 | test.c:394:30:394:30 | x | positive |
-| test.c:394:34:394:36 | r2_0(unsigned int) = Constant[100] | test.c:394:34:394:36 | (unsigned int)... | positive strictlyPositive |
-| test.c:395:16:395:17 | m3_5(unsigned int) = Uninitialized r3_4 | test.c:395:16:395:17 | definition of y1 | positive |
-| test.c:396:16:396:17 | m3_7(unsigned int) = Uninitialized r3_6 | test.c:396:16:396:17 | definition of y2 | positive |
-| test.c:397:3:397:15 | m3_16(unsigned int) = Store r3_15, r3_14 | test.c:397:3:397:15 | ... = ... | positive strictlyPositive |
-| test.c:397:9:397:11 | m3_12(unsigned int) = Store r3_8, r3_11 | test.c:397:9:397:11 | ++ ... | positive strictlyPositive |
-| test.c:397:9:397:11 | r3_9(unsigned int) = Load r3_8, m3_3 | test.c:397:9:397:11 | ++ ... | positive |
-| test.c:397:9:397:11 | r3_10(unsigned int) = Constant[1] | test.c:397:9:397:11 | ++ ... | positive strictlyPositive |
-| test.c:397:9:397:11 | r3_11(unsigned int) = Add r3_9, r3_10 | test.c:397:9:397:11 | ++ ... | positive strictlyPositive |
-| test.c:397:14:397:14 | r3_14(unsigned int) = Load r3_13, m3_12 | test.c:397:14:397:14 | y | positive strictlyPositive |
-| test.c:398:3:398:23 | m3_30(unsigned int) = Store r3_29, r3_28 | test.c:398:3:398:23 | ... = ... | positive strictlyPositive |
-| test.c:398:9:398:11 | m3_21(unsigned int) = Store r3_17, r3_20 | test.c:398:9:398:11 | ... ++ | positive strictlyPositive |
-| test.c:398:9:398:11 | r3_18(unsigned int) = Load r3_17, m3_12 | test.c:398:9:398:11 | ... ++ | positive strictlyPositive |
-| test.c:398:9:398:11 | r3_19(unsigned int) = Constant[1] | test.c:398:9:398:11 | ... ++ | positive strictlyPositive |
-| test.c:398:9:398:11 | r3_20(unsigned int) = Add r3_18, r3_19 | test.c:398:9:398:11 | ... ++ | positive strictlyPositive |
-| test.c:398:14:398:19 | m3_26(unsigned int) = Store r3_23, r3_25 | test.c:398:14:398:19 | ... += ... | positive strictlyPositive |
-| test.c:398:14:398:19 | r3_24(unsigned int) = Load r3_23, m3_21 | test.c:398:14:398:19 | ... += ... | positive strictlyPositive |
-| test.c:398:14:398:19 | r3_25(unsigned int) = Add r3_24, r3_22 | test.c:398:14:398:19 | ... += ... | positive strictlyPositive |
-| test.c:398:19:398:19 | r3_22(unsigned int) = Constant[3] | test.c:398:19:398:19 | (unsigned int)... | positive strictlyPositive |
-| test.c:398:22:398:22 | r3_28(unsigned int) = Load r3_27, m3_26 | test.c:398:22:398:22 | y | positive strictlyPositive |
-| test.c:399:10:399:11 | r3_33(unsigned int) = Load r3_32, m3_16 | test.c:399:10:399:11 | y1 | positive strictlyPositive |
-| test.c:399:10:399:16 | m3_37(unsigned int) = Store r3_31, r3_36 | test.c:399:10:399:16 | ... + ... | positive strictlyPositive |
-| test.c:399:10:399:16 | r3_36(unsigned int) = Add r3_33, r3_35 | test.c:399:10:399:16 | ... + ... | positive strictlyPositive |
-| test.c:399:15:399:16 | r3_35(unsigned int) = Load r3_34, m3_30 | test.c:399:15:399:16 | y2 | positive strictlyPositive |
-| test.cpp:9:11:9:12 | m0_8(int) = Store r0_6, r0_7 | test.cpp:9:11:9:12 | - ... | negative strictlyNegative |
-| test.cpp:9:11:9:12 | r0_7(int) = Constant[-1] | test.cpp:9:11:9:12 | - ... | negative strictlyNegative |
-| test.cpp:11:13:11:13 | r1_2(int) = Constant[3] | test.cpp:11:13:11:13 | 3 | positive strictlyPositive |
-| test.cpp:30:12:30:13 | r11_3(int) = Constant[-1] | test.cpp:30:12:30:13 | - ... | negative strictlyNegative |
-| test.cpp:31:5:31:10 | m12_2(int) = Store r12_1, r12_0 | test.cpp:31:5:31:10 | ... = ... | negative strictlyNegative |
-| test.cpp:31:9:31:10 | r12_0(int) = Constant[-1] | test.cpp:31:9:31:10 | - ... | negative strictlyNegative |
-| test.cpp:33:12:33:12 | r13_3(int) = Constant[1] | test.cpp:33:12:33:12 | 1 | positive strictlyPositive |
-| test.cpp:34:5:34:9 | m14_2(int) = Store r14_1, r14_0 | test.cpp:34:5:34:9 | ... = ... | positive strictlyPositive |
-| test.cpp:34:9:34:9 | r14_0(int) = Constant[1] | test.cpp:34:9:34:9 | 1 | positive strictlyPositive |
-| test.cpp:36:12:36:15 | r15_3(int) = Constant[-128] | test.cpp:36:12:36:15 | - ... | negative strictlyNegative |
-| test.cpp:37:5:37:12 | m16_2(int) = Store r16_1, r16_0 | test.cpp:37:5:37:12 | ... = ... | negative strictlyNegative |
-| test.cpp:37:9:37:12 | r16_0(int) = Constant[-128] | test.cpp:37:9:37:12 | - ... | negative strictlyNegative |
-| test.cpp:39:12:39:14 | r17_3(int) = Constant[128] | test.cpp:39:12:39:14 | 128 | positive strictlyPositive |
-| test.cpp:40:5:40:11 | m18_2(int) = Store r18_1, r18_0 | test.cpp:40:5:40:11 | ... = ... | positive strictlyPositive |
-| test.cpp:40:9:40:11 | r18_0(int) = Constant[128] | test.cpp:40:9:40:11 | 128 | positive strictlyPositive |
-| test.cpp:42:12:42:16 | r19_3(int) = Constant[-1024] | test.cpp:42:12:42:16 | - ... | negative strictlyNegative |
-| test.cpp:43:5:43:13 | m20_2(int) = Store r20_1, r20_0 | test.cpp:43:5:43:13 | ... = ... | negative strictlyNegative |
-| test.cpp:43:9:43:13 | r20_0(int) = Constant[-1024] | test.cpp:43:9:43:13 | - ... | negative strictlyNegative |
-| test.cpp:45:12:45:15 | r21_3(int) = Constant[1024] | test.cpp:45:12:45:15 | 1024 | positive strictlyPositive |
-| test.cpp:46:5:46:12 | m22_2(int) = Store r22_1, r22_0 | test.cpp:46:5:46:12 | ... = ... | positive strictlyPositive |
-| test.cpp:46:9:46:12 | r22_0(int) = Constant[1024] | test.cpp:46:9:46:12 | 1024 | positive strictlyPositive |
-| test.cpp:69:10:69:21 | m8_0(bool) = Phi from 7:m7_2, from 9:m9_2 | test.cpp:69:10:69:21 | ... \|\| ... | positive |
-| test.cpp:69:10:69:21 | m8_3(bool) = Store r6_14, r8_2 | test.cpp:69:10:69:21 | ... \|\| ... | positive |
-| test.cpp:69:10:69:21 | m9_2(bool) = Store r9_0, r9_1 | test.cpp:69:10:69:21 | ... \|\| ... | positive strictlyPositive |
-| test.cpp:69:10:69:21 | r8_2(bool) = Load r8_1, m8_0 | test.cpp:69:10:69:21 | ... \|\| ... | positive |
-| test.cpp:69:10:69:21 | r9_1(bool) = Constant[1] | test.cpp:69:10:69:21 | ... \|\| ... | positive strictlyPositive |
+| binary_logical_operator.c:2:11:2:25 | Constant: ... && ... | positive strictlyPositive |
+| binary_logical_operator.c:2:11:2:25 | Load: ... && ... | positive |
+| binary_logical_operator.c:2:11:2:25 | Phi: ... && ... | positive |
+| binary_logical_operator.c:2:11:2:25 | Store: ... && ... | positive |
+| binary_logical_operator.c:2:11:2:25 | Store: ... && ... | positive strictlyPositive |
+| binary_logical_operator.c:2:15:2:16 | Constant: 10 | positive strictlyPositive |
+| binary_logical_operator.c:3:7:3:7 | Load: b | positive |
+| inline_assembly.c:9:23:9:23 | Uninitialized: definition of y | positive |
+| inline_assembly.c:10:3:10:7 | Store: ... = ... | positive strictlyPositive |
+| inline_assembly.c:10:7:10:7 | Constant: (unsigned int)... | positive strictlyPositive |
+| inline_assembly.c:12:32:12:32 | Load: y | positive strictlyPositive |
+| minmax.c:16:9:16:10 | Constant: 1 | positive strictlyPositive |
+| minmax.c:16:9:16:10 | Store: 1 | positive strictlyPositive |
+| minmax.c:16:16:16:17 | Constant: 2 | positive strictlyPositive |
+| minmax.c:16:16:16:17 | Store: 2 | positive strictlyPositive |
+| minmax.c:16:23:16:24 | Constant: 3 | positive strictlyPositive |
+| minmax.c:16:23:16:24 | Store: 3 | positive strictlyPositive |
+| minmax.c:18:37:18:37 | Load: x | positive strictlyPositive |
+| minmax.c:18:40:18:40 | Load: y | positive strictlyPositive |
+| minmax.c:18:43:18:43 | Load: z | positive strictlyPositive |
+| test.c:7:10:7:10 | Phi: p | positive |
+| test.c:8:5:8:19 | Store: ... = ... | positive strictlyPositive |
+| test.c:8:13:8:17 | Load: count | positive |
+| test.c:8:13:8:19 | Add: ... + ... | positive strictlyPositive |
+| test.c:8:19:8:19 | Constant: 1 | positive strictlyPositive |
+| test.c:10:10:10:14 | Load: count | positive |
+| test.c:10:10:10:14 | Store: count | positive |
+| test.c:15:10:15:10 | Phi: p | positive |
+| test.c:16:5:16:26 | Store: ... = ... | positive |
+| test.c:16:13:16:26 | Rem: ... % ... | positive |
+| test.c:16:14:16:18 | Load: count | positive |
+| test.c:16:14:16:20 | Add: ... + ... | positive strictlyPositive |
+| test.c:16:20:16:20 | Constant: 1 | positive strictlyPositive |
+| test.c:16:25:16:26 | Constant: 10 | positive strictlyPositive |
+| test.c:18:10:18:14 | Load: count | positive |
+| test.c:18:10:18:14 | Store: count | positive |
+| test.c:23:10:23:10 | Phi: p | positive |
+| test.c:24:5:24:11 | Add: ... ++ | positive strictlyPositive |
+| test.c:24:5:24:11 | Constant: ... ++ | positive strictlyPositive |
+| test.c:24:5:24:11 | Load: ... ++ | positive |
+| test.c:24:5:24:11 | Store: ... ++ | positive strictlyPositive |
+| test.c:25:5:25:22 | Store: ... = ... | positive |
+| test.c:25:13:25:17 | Load: count | positive strictlyPositive |
+| test.c:25:13:25:22 | Rem: ... % ... | positive |
+| test.c:25:21:25:22 | Constant: 10 | positive strictlyPositive |
+| test.c:27:10:27:14 | Load: count | positive |
+| test.c:27:10:27:14 | Store: count | positive |
+| test.c:33:15:33:15 | Load: i | positive |
+| test.c:33:15:33:15 | Phi: i | positive |
+| test.c:33:15:33:15 | Phi: i | positive |
+| test.c:33:19:33:19 | Constant: 2 | positive strictlyPositive |
+| test.c:33:22:33:28 | Store: ... = ... | positive strictlyPositive |
+| test.c:33:26:33:26 | Load: i | positive |
+| test.c:33:26:33:28 | Add: ... + ... | positive strictlyPositive |
+| test.c:33:28:33:28 | Constant: 1 | positive strictlyPositive |
+| test.c:34:5:34:14 | Add: ... += ... | positive |
+| test.c:34:5:34:14 | Load: ... += ... | positive |
+| test.c:34:5:34:14 | Store: ... += ... | positive |
+| test.c:34:14:34:14 | Load: i | positive |
+| test.c:36:10:36:14 | Load: total | positive |
+| test.c:36:10:36:18 | Add: ... + ... | positive |
+| test.c:36:10:36:18 | Store: ... + ... | positive |
+| test.c:36:18:36:18 | Load: i | positive |
+| test.c:42:15:42:15 | Load: i | positive |
+| test.c:42:15:42:15 | Phi: i | positive |
+| test.c:42:15:42:15 | Phi: i | positive |
+| test.c:42:19:42:19 | Constant: 2 | positive strictlyPositive |
+| test.c:42:22:42:24 | Add: ... ++ | positive strictlyPositive |
+| test.c:42:22:42:24 | Constant: ... ++ | positive strictlyPositive |
+| test.c:42:22:42:24 | Load: ... ++ | positive |
+| test.c:42:22:42:24 | Store: ... ++ | positive strictlyPositive |
+| test.c:43:5:43:14 | Add: ... += ... | positive |
+| test.c:43:5:43:14 | Load: ... += ... | positive |
+| test.c:43:5:43:14 | Store: ... += ... | positive |
+| test.c:43:14:43:14 | Load: i | positive |
+| test.c:45:10:45:14 | Load: total | positive |
+| test.c:45:10:45:18 | Add: ... + ... | positive |
+| test.c:45:10:45:18 | Store: ... + ... | positive |
+| test.c:45:18:45:18 | Load: i | positive |
+| test.c:51:15:51:15 | Load: i | positive |
+| test.c:51:15:51:15 | Phi: i | positive |
+| test.c:51:15:51:15 | Phi: i | positive |
+| test.c:51:15:51:17 | Add: ... + ... | positive strictlyPositive |
+| test.c:51:17:51:17 | Constant: 2 | positive strictlyPositive |
+| test.c:51:21:51:21 | Constant: 4 | positive strictlyPositive |
+| test.c:51:24:51:30 | Store: ... = ... | positive strictlyPositive |
+| test.c:51:28:51:28 | Load: i | positive |
+| test.c:51:28:51:30 | Add: ... + ... | positive strictlyPositive |
+| test.c:51:30:51:30 | Constant: 1 | positive strictlyPositive |
+| test.c:52:5:52:14 | Add: ... += ... | positive |
+| test.c:52:5:52:14 | Load: ... += ... | positive |
+| test.c:52:5:52:14 | Store: ... += ... | positive |
+| test.c:52:14:52:14 | Load: i | positive |
+| test.c:54:10:54:14 | Load: total | positive |
+| test.c:54:10:54:18 | Add: ... + ... | positive |
+| test.c:54:10:54:18 | Store: ... + ... | positive |
+| test.c:54:18:54:18 | Load: i | positive |
+| test.c:58:11:58:11 | Constant: 4 | positive strictlyPositive |
+| test.c:59:13:59:13 | Constant: 5 | positive strictlyPositive |
+| test.c:63:10:63:10 | Constant: 1 | positive strictlyPositive |
+| test.c:63:10:63:10 | Store: 1 | positive strictlyPositive |
+| test.c:67:7:67:11 | Constant: - ... | negative strictlyNegative |
+| test.c:67:24:67:25 | Constant: 10 | positive strictlyPositive |
+| test.c:68:15:68:15 | Constant: 2 | positive strictlyPositive |
+| test.c:77:13:77:13 | Constant: 4 | positive strictlyPositive |
+| test.c:81:13:81:13 | Constant: 4 | positive strictlyPositive |
+| test.c:82:14:82:14 | Constant: 1 | positive strictlyPositive |
+| test.c:82:14:82:14 | Store: 1 | positive strictlyPositive |
+| test.c:88:5:88:10 | Phi: test10 | positive |
+| test.c:89:11:89:11 | Constant: 7 | positive strictlyPositive |
+| test.c:90:13:90:13 | Load: y | positive strictlyPositive |
+| test.c:93:12:93:12 | Load: x | positive strictlyPositive |
+| test.c:93:12:93:12 | Store: x | positive strictlyPositive |
+| test.c:95:10:95:10 | Constant: 1 | positive strictlyPositive |
+| test.c:95:10:95:10 | Store: 1 | positive strictlyPositive |
+| test.c:98:5:98:10 | Phi: test11 | positive |
+| test.c:102:6:102:8 | Constant: ... ++ | positive strictlyPositive |
+| test.c:104:12:104:14 | Constant: 58 | positive strictlyPositive |
+| test.c:107:8:107:10 | Constant: ... ++ | positive strictlyPositive |
+| test.c:109:14:109:16 | Constant: 44 | positive strictlyPositive |
+| test.c:110:14:110:14 | Constant: 1 | positive strictlyPositive |
+| test.c:110:14:110:14 | Store: 1 | positive strictlyPositive |
+| test.c:119:10:119:12 | Add: ... ++ | positive strictlyPositive |
+| test.c:119:10:119:12 | Constant: ... ++ | positive strictlyPositive |
+| test.c:119:10:119:12 | Store: ... ++ | positive strictlyPositive |
+| test.c:124:11:124:15 | Load: Start | positive |
+| test.c:124:11:124:15 | Phi: Start | positive |
+| test.c:124:20:124:32 | Call: call to test12_helper | positive |
+| test.c:124:20:124:36 | Sub: ... - ... | positive |
+| test.c:124:36:124:36 | Constant: (unsigned long long)... | positive strictlyPositive |
+| test.c:126:31:126:43 | Call: call to test12_helper | positive |
+| test.c:126:31:126:43 | Store: call to test12_helper | positive |
+| test.c:127:6:127:24 | Add: ... += ... | positive strictlyPositive |
+| test.c:127:6:127:24 | Load: ... += ... | positive |
+| test.c:127:6:127:24 | Store: ... += ... | positive strictlyPositive |
+| test.c:127:15:127:20 | Load: Length | positive |
+| test.c:127:15:127:24 | Add: ... + ... | positive strictlyPositive |
+| test.c:127:24:127:24 | Constant: (unsigned long long)... | positive strictlyPositive |
+| test.c:130:11:130:11 | Constant: 1 | positive strictlyPositive |
+| test.c:130:11:130:11 | Store: 1 | positive strictlyPositive |
+| test.c:135:22:135:22 | Convert: (unsigned char)... | positive |
+| test.c:135:22:135:22 | Store: (unsigned char)... | positive |
+| test.c:137:22:137:22 | Constant: (unsigned int)... | positive strictlyPositive |
+| test.c:138:13:138:13 | Constant: 1 | positive strictlyPositive |
+| test.c:139:19:139:28 | Convert: (unsigned int)... | positive |
+| test.c:139:19:139:32 | Add: ... + ... | positive |
+| test.c:139:27:139:28 | Convert: (int)... | positive |
+| test.c:139:27:139:28 | Load: uc | positive |
+| test.c:139:40:139:40 | Convert: (unsigned int)... | positive |
+| test.c:145:12:145:32 | Convert: (int)... | positive |
+| test.c:145:12:145:32 | Store: (int)... | positive |
+| test.c:145:17:145:32 | Convert: (unsigned char)... | positive |
+| test.c:146:12:146:33 | Convert: (int)... | positive |
+| test.c:146:12:146:33 | Store: (int)... | positive |
+| test.c:146:17:146:33 | Convert: (unsigned short)... | positive |
+| test.c:147:17:147:31 | Convert: (unsigned int)... | positive |
+| test.c:149:23:149:23 | Convert: (unsigned short)... | positive |
+| test.c:149:23:149:23 | Store: (unsigned short)... | positive |
+| test.c:150:15:150:16 | Load: x1 | positive |
+| test.c:150:20:150:21 | Load: x2 | positive |
+| test.c:150:35:150:36 | Convert: (int)... | positive |
+| test.c:150:35:150:36 | Load: s0 | positive |
+| test.c:154:10:154:40 | Store: ... ? ... : ... | negative strictlyNegative |
+| test.c:154:10:154:40 | Store: ... ? ... : ... | positive strictlyPositive |
+| test.c:154:20:154:20 | Load: x | positive strictlyPositive |
+| test.c:154:25:154:30 | Convert: (int)... | positive |
+| test.c:154:25:154:30 | Convert: (long long)... | positive |
+| test.c:154:30:154:30 | Load: x | positive strictlyPositive |
+| test.c:154:35:154:35 | Load: x | positive strictlyPositive |
+| test.c:154:39:154:40 | Constant: (long long)... | negative strictlyNegative |
+| test.c:161:7:161:7 | Constant: 3 | positive strictlyPositive |
+| test.c:161:17:161:17 | Load: a | positive strictlyPositive |
+| test.c:161:22:161:23 | Constant: 11 | positive strictlyPositive |
+| test.c:162:13:162:14 | CopyValue: + ... | positive strictlyPositive |
+| test.c:162:13:162:14 | Store: + ... | positive strictlyPositive |
+| test.c:162:14:162:14 | Load: a | positive strictlyPositive |
+| test.c:163:13:163:14 | Negate: - ... | negative strictlyNegative |
+| test.c:163:13:163:14 | Store: - ... | negative strictlyNegative |
+| test.c:163:14:163:14 | Load: a | positive strictlyPositive |
+| test.c:164:14:164:14 | Load: b | positive strictlyPositive |
+| test.c:164:16:164:16 | Load: c | negative strictlyNegative |
+| test.c:166:17:166:17 | Load: a | positive |
+| test.c:166:22:166:23 | Constant: 11 | positive strictlyPositive |
+| test.c:167:13:167:14 | CopyValue: + ... | positive |
+| test.c:167:13:167:14 | Store: + ... | positive |
+| test.c:167:14:167:14 | Load: a | positive |
+| test.c:168:13:168:14 | Negate: - ... | negative |
+| test.c:168:13:168:14 | Store: - ... | negative |
+| test.c:168:14:168:14 | Load: a | positive |
+| test.c:169:14:169:14 | Load: b | positive |
+| test.c:169:16:169:16 | Load: c | negative |
+| test.c:171:7:171:8 | Constant: - ... | negative strictlyNegative |
+| test.c:171:23:171:24 | Constant: 11 | positive strictlyPositive |
+| test.c:176:7:176:8 | Constant: - ... | negative strictlyNegative |
+| test.c:176:23:176:23 | Constant: 1 | positive strictlyPositive |
+| test.c:181:7:181:8 | Constant: - ... | negative strictlyNegative |
+| test.c:182:13:182:14 | CopyValue: + ... | negative |
+| test.c:182:13:182:14 | Store: + ... | negative |
+| test.c:182:14:182:14 | Load: a | negative |
+| test.c:183:13:183:14 | Negate: - ... | positive |
+| test.c:183:13:183:14 | Store: - ... | positive |
+| test.c:183:14:183:14 | Load: a | negative |
+| test.c:184:14:184:14 | Load: b | negative |
+| test.c:184:16:184:16 | Load: c | positive |
+| test.c:186:7:186:8 | Constant: - ... | negative strictlyNegative |
+| test.c:186:23:186:24 | Constant: - ... | negative strictlyNegative |
+| test.c:187:13:187:14 | CopyValue: + ... | negative strictlyNegative |
+| test.c:187:13:187:14 | Store: + ... | negative strictlyNegative |
+| test.c:187:14:187:14 | Load: a | negative strictlyNegative |
+| test.c:188:13:188:14 | Negate: - ... | positive strictlyPositive |
+| test.c:188:13:188:14 | Store: - ... | positive strictlyPositive |
+| test.c:188:14:188:14 | Load: a | negative strictlyNegative |
+| test.c:189:14:189:14 | Load: b | negative strictlyNegative |
+| test.c:189:16:189:16 | Load: c | positive strictlyPositive |
+| test.c:200:7:200:7 | Constant: 3 | positive strictlyPositive |
+| test.c:200:17:200:17 | Load: a | positive strictlyPositive |
+| test.c:200:22:200:23 | Constant: 11 | positive strictlyPositive |
+| test.c:200:28:200:28 | Constant: 5 | positive strictlyPositive |
+| test.c:200:38:200:38 | Load: b | positive strictlyPositive |
+| test.c:200:43:200:44 | Constant: 23 | positive strictlyPositive |
+| test.c:201:13:201:13 | Load: a | positive strictlyPositive |
+| test.c:201:13:201:15 | Mul: ... * ... | positive strictlyPositive |
+| test.c:201:13:201:15 | Store: ... * ... | positive strictlyPositive |
+| test.c:201:15:201:15 | Load: b | positive strictlyPositive |
+| test.c:202:5:202:14 | Add: ... += ... | positive strictlyPositive |
+| test.c:202:5:202:14 | Store: ... += ... | positive strictlyPositive |
+| test.c:202:14:202:14 | Load: r | positive strictlyPositive |
+| test.c:204:7:204:7 | Constant: 3 | positive strictlyPositive |
+| test.c:204:7:204:7 | Phi: 3 | positive |
+| test.c:204:17:204:17 | Load: a | positive strictlyPositive |
+| test.c:204:22:204:23 | Constant: 11 | positive strictlyPositive |
+| test.c:204:38:204:38 | Load: b | positive |
+| test.c:204:43:204:44 | Constant: 23 | positive strictlyPositive |
+| test.c:205:13:205:13 | Load: a | positive strictlyPositive |
+| test.c:205:13:205:15 | Mul: ... * ... | positive |
+| test.c:205:13:205:15 | Store: ... * ... | positive |
+| test.c:205:15:205:15 | Load: b | positive |
+| test.c:206:5:206:14 | Add: ... += ... | positive |
+| test.c:206:5:206:14 | Load: ... += ... | positive |
+| test.c:206:5:206:14 | Store: ... += ... | positive |
+| test.c:206:14:206:14 | Load: r | positive |
+| test.c:208:7:208:7 | Constant: 3 | positive strictlyPositive |
+| test.c:208:7:208:7 | Phi: 3 | positive |
+| test.c:208:17:208:17 | Load: a | positive strictlyPositive |
+| test.c:208:22:208:23 | Constant: 11 | positive strictlyPositive |
+| test.c:208:28:208:30 | Constant: - ... | negative strictlyNegative |
+| test.c:208:45:208:46 | Constant: 23 | positive strictlyPositive |
+| test.c:209:13:209:13 | Load: a | positive strictlyPositive |
+| test.c:210:5:210:14 | Load: ... += ... | positive |
+| test.c:212:7:212:7 | Constant: 3 | positive strictlyPositive |
+| test.c:212:17:212:17 | Load: a | positive strictlyPositive |
+| test.c:212:22:212:23 | Constant: 11 | positive strictlyPositive |
+| test.c:212:28:212:30 | Constant: - ... | negative strictlyNegative |
+| test.c:213:13:213:13 | Load: a | positive strictlyPositive |
+| test.c:213:13:213:15 | Mul: ... * ... | negative |
+| test.c:213:13:213:15 | Store: ... * ... | negative |
+| test.c:213:15:213:15 | Load: b | negative |
+| test.c:214:14:214:14 | Load: r | negative |
+| test.c:216:7:216:7 | Constant: 3 | positive strictlyPositive |
+| test.c:216:17:216:17 | Load: a | positive strictlyPositive |
+| test.c:216:22:216:23 | Constant: 11 | positive strictlyPositive |
+| test.c:216:28:216:30 | Constant: - ... | negative strictlyNegative |
+| test.c:216:45:216:46 | Constant: - ... | negative strictlyNegative |
+| test.c:217:13:217:13 | Load: a | positive strictlyPositive |
+| test.c:217:13:217:15 | Mul: ... * ... | negative strictlyNegative |
+| test.c:217:13:217:15 | Store: ... * ... | negative strictlyNegative |
+| test.c:217:15:217:15 | Load: b | negative strictlyNegative |
+| test.c:218:14:218:14 | Load: r | negative strictlyNegative |
+| test.c:228:17:228:17 | Load: a | positive |
+| test.c:228:22:228:23 | Constant: 11 | positive strictlyPositive |
+| test.c:228:28:228:28 | Constant: 5 | positive strictlyPositive |
+| test.c:228:38:228:38 | Load: b | positive strictlyPositive |
+| test.c:228:43:228:44 | Constant: 23 | positive strictlyPositive |
+| test.c:229:13:229:13 | Load: a | positive |
+| test.c:229:13:229:15 | Mul: ... * ... | positive |
+| test.c:229:13:229:15 | Store: ... * ... | positive |
+| test.c:229:15:229:15 | Load: b | positive strictlyPositive |
+| test.c:230:5:230:14 | Add: ... += ... | positive |
+| test.c:230:5:230:14 | Store: ... += ... | positive |
+| test.c:230:14:230:14 | Load: r | positive |
+| test.c:232:7:232:7 | Phi: 0 | positive |
+| test.c:232:17:232:17 | Load: a | positive |
+| test.c:232:22:232:23 | Constant: 11 | positive strictlyPositive |
+| test.c:232:38:232:38 | Load: b | positive |
+| test.c:232:43:232:44 | Constant: 23 | positive strictlyPositive |
+| test.c:233:13:233:13 | Load: a | positive |
+| test.c:233:13:233:15 | Mul: ... * ... | positive |
+| test.c:233:13:233:15 | Store: ... * ... | positive |
+| test.c:233:15:233:15 | Load: b | positive |
+| test.c:234:5:234:14 | Add: ... += ... | positive |
+| test.c:234:5:234:14 | Load: ... += ... | positive |
+| test.c:234:5:234:14 | Store: ... += ... | positive |
+| test.c:234:14:234:14 | Load: r | positive |
+| test.c:236:7:236:7 | Phi: 0 | positive |
+| test.c:236:17:236:17 | Load: a | positive |
+| test.c:236:22:236:23 | Constant: 11 | positive strictlyPositive |
+| test.c:236:28:236:30 | Constant: - ... | negative strictlyNegative |
+| test.c:236:45:236:46 | Constant: 23 | positive strictlyPositive |
+| test.c:237:13:237:13 | Load: a | positive |
+| test.c:238:5:238:14 | Load: ... += ... | positive |
+| test.c:240:17:240:17 | Load: a | positive |
+| test.c:240:22:240:23 | Constant: 11 | positive strictlyPositive |
+| test.c:240:28:240:30 | Constant: - ... | negative strictlyNegative |
+| test.c:241:13:241:13 | Load: a | positive |
+| test.c:241:13:241:15 | Mul: ... * ... | negative |
+| test.c:241:13:241:15 | Store: ... * ... | negative |
+| test.c:241:15:241:15 | Load: b | negative |
+| test.c:242:14:242:14 | Load: r | negative |
+| test.c:244:17:244:17 | Load: a | positive |
+| test.c:244:22:244:23 | Constant: 11 | positive strictlyPositive |
+| test.c:244:28:244:30 | Constant: - ... | negative strictlyNegative |
+| test.c:244:45:244:46 | Constant: - ... | negative strictlyNegative |
+| test.c:245:13:245:13 | Load: a | positive |
+| test.c:245:13:245:15 | Mul: ... * ... | negative |
+| test.c:245:13:245:15 | Store: ... * ... | negative |
+| test.c:245:15:245:15 | Load: b | negative strictlyNegative |
+| test.c:246:14:246:14 | Load: r | negative |
+| test.c:256:7:256:9 | Constant: - ... | negative strictlyNegative |
+| test.c:256:24:256:25 | Constant: 11 | positive strictlyPositive |
+| test.c:256:30:256:30 | Constant: 5 | positive strictlyPositive |
+| test.c:256:40:256:40 | Load: b | positive strictlyPositive |
+| test.c:256:45:256:46 | Constant: 23 | positive strictlyPositive |
+| test.c:257:15:257:15 | Load: b | positive strictlyPositive |
+| test.c:260:7:260:9 | Constant: - ... | negative strictlyNegative |
+| test.c:260:24:260:25 | Constant: 11 | positive strictlyPositive |
+| test.c:260:40:260:40 | Load: b | positive |
+| test.c:260:45:260:46 | Constant: 23 | positive strictlyPositive |
+| test.c:261:15:261:15 | Load: b | positive |
+| test.c:264:7:264:9 | Constant: - ... | negative strictlyNegative |
+| test.c:264:24:264:25 | Constant: 11 | positive strictlyPositive |
+| test.c:264:30:264:32 | Constant: - ... | negative strictlyNegative |
+| test.c:264:47:264:48 | Constant: 23 | positive strictlyPositive |
+| test.c:268:7:268:9 | Constant: - ... | negative strictlyNegative |
+| test.c:268:24:268:25 | Constant: 11 | positive strictlyPositive |
+| test.c:268:30:268:32 | Constant: - ... | negative strictlyNegative |
+| test.c:269:15:269:15 | Load: b | negative |
+| test.c:272:7:272:9 | Constant: - ... | negative strictlyNegative |
+| test.c:272:24:272:25 | Constant: 11 | positive strictlyPositive |
+| test.c:272:30:272:32 | Constant: - ... | negative strictlyNegative |
+| test.c:272:47:272:48 | Constant: - ... | negative strictlyNegative |
+| test.c:273:15:273:15 | Load: b | negative strictlyNegative |
+| test.c:284:7:284:9 | Constant: - ... | negative strictlyNegative |
+| test.c:284:29:284:29 | Constant: 5 | positive strictlyPositive |
+| test.c:284:39:284:39 | Load: b | positive strictlyPositive |
+| test.c:284:44:284:45 | Constant: 23 | positive strictlyPositive |
+| test.c:285:13:285:13 | Load: a | negative |
+| test.c:285:13:285:15 | Mul: ... * ... | negative |
+| test.c:285:13:285:15 | Store: ... * ... | negative |
+| test.c:285:15:285:15 | Load: b | positive strictlyPositive |
+| test.c:286:5:286:14 | Add: ... += ... | negative |
+| test.c:286:5:286:14 | Store: ... += ... | negative |
+| test.c:286:14:286:14 | Load: r | negative |
+| test.c:288:7:288:9 | Constant: - ... | negative strictlyNegative |
+| test.c:288:7:288:9 | Phi: - ... | negative |
+| test.c:288:39:288:39 | Load: b | positive |
+| test.c:288:44:288:45 | Constant: 23 | positive strictlyPositive |
+| test.c:289:13:289:13 | Load: a | negative |
+| test.c:289:13:289:15 | Mul: ... * ... | negative |
+| test.c:289:13:289:15 | Store: ... * ... | negative |
+| test.c:289:15:289:15 | Load: b | positive |
+| test.c:290:5:290:14 | Add: ... += ... | negative |
+| test.c:290:5:290:14 | Load: ... += ... | negative |
+| test.c:290:5:290:14 | Store: ... += ... | negative |
+| test.c:290:14:290:14 | Load: r | negative |
+| test.c:292:7:292:9 | Constant: - ... | negative strictlyNegative |
+| test.c:292:7:292:9 | Phi: - ... | negative |
+| test.c:292:29:292:31 | Constant: - ... | negative strictlyNegative |
+| test.c:292:46:292:47 | Constant: 23 | positive strictlyPositive |
+| test.c:293:13:293:13 | Load: a | negative |
+| test.c:294:5:294:14 | Load: ... += ... | negative |
+| test.c:296:7:296:9 | Constant: - ... | negative strictlyNegative |
+| test.c:296:29:296:31 | Constant: - ... | negative strictlyNegative |
+| test.c:297:13:297:13 | Load: a | negative |
+| test.c:297:13:297:15 | Mul: ... * ... | positive |
+| test.c:297:13:297:15 | Store: ... * ... | positive |
+| test.c:297:15:297:15 | Load: b | negative |
+| test.c:298:14:298:14 | Load: r | positive |
+| test.c:300:7:300:9 | Constant: - ... | negative strictlyNegative |
+| test.c:300:29:300:31 | Constant: - ... | negative strictlyNegative |
+| test.c:300:46:300:47 | Constant: - ... | negative strictlyNegative |
+| test.c:301:13:301:13 | Load: a | negative |
+| test.c:301:13:301:15 | Mul: ... * ... | positive |
+| test.c:301:13:301:15 | Store: ... * ... | positive |
+| test.c:301:15:301:15 | Load: b | negative strictlyNegative |
+| test.c:302:14:302:14 | Load: r | positive |
+| test.c:312:7:312:9 | Constant: - ... | negative strictlyNegative |
+| test.c:312:24:312:25 | Constant: - ... | negative strictlyNegative |
+| test.c:312:30:312:30 | Constant: 5 | positive strictlyPositive |
+| test.c:312:40:312:40 | Load: b | positive strictlyPositive |
+| test.c:312:45:312:46 | Constant: 23 | positive strictlyPositive |
+| test.c:313:13:313:13 | Load: a | negative strictlyNegative |
+| test.c:313:13:313:15 | Mul: ... * ... | negative strictlyNegative |
+| test.c:313:13:313:15 | Store: ... * ... | negative strictlyNegative |
+| test.c:313:15:313:15 | Load: b | positive strictlyPositive |
+| test.c:314:5:314:14 | Add: ... += ... | negative strictlyNegative |
+| test.c:314:5:314:14 | Store: ... += ... | negative strictlyNegative |
+| test.c:314:14:314:14 | Load: r | negative strictlyNegative |
+| test.c:316:7:316:9 | Constant: - ... | negative strictlyNegative |
+| test.c:316:7:316:9 | Phi: - ... | negative |
+| test.c:316:24:316:25 | Constant: - ... | negative strictlyNegative |
+| test.c:316:40:316:40 | Load: b | positive |
+| test.c:316:45:316:46 | Constant: 23 | positive strictlyPositive |
+| test.c:317:13:317:13 | Load: a | negative strictlyNegative |
+| test.c:317:13:317:15 | Mul: ... * ... | negative |
+| test.c:317:13:317:15 | Store: ... * ... | negative |
+| test.c:317:15:317:15 | Load: b | positive |
+| test.c:318:5:318:14 | Add: ... += ... | negative |
+| test.c:318:5:318:14 | Load: ... += ... | negative |
+| test.c:318:5:318:14 | Store: ... += ... | negative |
+| test.c:318:14:318:14 | Load: r | negative |
+| test.c:320:7:320:9 | Constant: - ... | negative strictlyNegative |
+| test.c:320:7:320:9 | Phi: - ... | negative |
+| test.c:320:24:320:25 | Constant: - ... | negative strictlyNegative |
+| test.c:320:30:320:32 | Constant: - ... | negative strictlyNegative |
+| test.c:320:47:320:48 | Constant: 23 | positive strictlyPositive |
+| test.c:321:13:321:13 | Load: a | negative strictlyNegative |
+| test.c:322:5:322:14 | Load: ... += ... | negative |
+| test.c:324:7:324:9 | Constant: - ... | negative strictlyNegative |
+| test.c:324:24:324:25 | Constant: - ... | negative strictlyNegative |
+| test.c:324:30:324:32 | Constant: - ... | negative strictlyNegative |
+| test.c:325:13:325:13 | Load: a | negative strictlyNegative |
+| test.c:325:13:325:15 | Mul: ... * ... | positive |
+| test.c:325:13:325:15 | Store: ... * ... | positive |
+| test.c:325:15:325:15 | Load: b | negative |
+| test.c:326:14:326:14 | Load: r | positive |
+| test.c:328:7:328:9 | Constant: - ... | negative strictlyNegative |
+| test.c:328:24:328:25 | Constant: - ... | negative strictlyNegative |
+| test.c:328:30:328:32 | Constant: - ... | negative strictlyNegative |
+| test.c:328:47:328:48 | Constant: - ... | negative strictlyNegative |
+| test.c:329:13:329:13 | Load: a | negative strictlyNegative |
+| test.c:329:13:329:15 | Mul: ... * ... | positive strictlyPositive |
+| test.c:329:13:329:15 | Store: ... * ... | positive strictlyPositive |
+| test.c:329:15:329:15 | Load: b | negative strictlyNegative |
+| test.c:330:14:330:14 | Load: r | positive strictlyPositive |
+| test.c:339:12:339:13 | Constant: - ... | negative strictlyNegative |
+| test.c:339:12:339:13 | Store: - ... | negative strictlyNegative |
+| test.c:342:10:342:10 | Load: i | positive |
+| test.c:342:10:342:10 | Phi: i | positive |
+| test.c:342:14:342:14 | Constant: 3 | positive strictlyPositive |
+| test.c:343:5:343:7 | Add: ... ++ | positive strictlyPositive |
+| test.c:343:5:343:7 | Constant: ... ++ | positive strictlyPositive |
+| test.c:343:5:343:7 | Load: ... ++ | positive |
+| test.c:343:5:343:7 | Store: ... ++ | positive strictlyPositive |
+| test.c:345:3:345:7 | Store: ... = ... | positive |
+| test.c:345:7:345:7 | Load: i | positive |
+| test.c:346:7:346:7 | Load: x | positive |
+| test.c:347:9:347:9 | Load: d | positive |
+| test.c:348:14:348:14 | Constant: 1 | positive strictlyPositive |
+| test.c:348:14:348:14 | Store: 1 | positive strictlyPositive |
+| test.c:355:42:355:42 | InitializeParameter: x | positive |
+| test.c:356:16:356:17 | Uninitialized: definition of y1 | positive |
+| test.c:356:20:356:21 | Uninitialized: definition of y2 | positive |
+| test.c:356:24:356:25 | Uninitialized: definition of y3 | positive |
+| test.c:356:28:356:29 | Uninitialized: definition of y4 | positive |
+| test.c:356:32:356:33 | Uninitialized: definition of y5 | positive |
+| test.c:356:36:356:37 | Uninitialized: definition of y6 | positive |
+| test.c:356:40:356:41 | Uninitialized: definition of y7 | positive |
+| test.c:356:44:356:45 | Uninitialized: definition of y8 | positive |
+| test.c:357:3:357:23 | Store: ... = ... | positive |
+| test.c:357:8:357:8 | Load: x | positive |
+| test.c:357:8:357:23 | Load: ... ? ... : ... | positive |
+| test.c:357:8:357:23 | Phi: ... ? ... : ... | positive |
+| test.c:357:8:357:23 | Store: ... ? ... : ... | positive |
+| test.c:357:8:357:23 | Store: ... ? ... : ... | positive strictlyPositive |
+| test.c:357:12:357:14 | Constant: (unsigned int)... | positive strictlyPositive |
+| test.c:357:18:357:18 | Load: x | positive |
+| test.c:357:22:357:23 | Constant: (unsigned int)... | positive strictlyPositive |
+| test.c:358:3:358:24 | Store: ... = ... | positive |
+| test.c:358:8:358:8 | Load: x | positive |
+| test.c:358:8:358:24 | Load: ... ? ... : ... | positive |
+| test.c:358:8:358:24 | Phi: ... ? ... : ... | positive |
+| test.c:358:8:358:24 | Store: ... ? ... : ... | positive |
+| test.c:358:8:358:24 | Store: ... ? ... : ... | positive strictlyPositive |
+| test.c:358:13:358:15 | Constant: (unsigned int)... | positive strictlyPositive |
+| test.c:358:19:358:20 | Constant: (unsigned int)... | positive strictlyPositive |
+| test.c:358:24:358:24 | Load: x | positive |
+| test.c:365:7:365:7 | Load: x | positive |
+| test.c:365:11:365:13 | Constant: (unsigned int)... | positive strictlyPositive |
+| test.c:366:5:366:15 | Store: ... = ... | positive |
+| test.c:366:10:366:10 | Load: x | positive |
+| test.c:366:10:366:15 | Load: ... ? ... : ... | positive |
+| test.c:366:10:366:15 | Phi: ... ? ... : ... | positive |
+| test.c:366:10:366:15 | Store: ... ? ... : ... | positive |
+| test.c:366:10:366:15 | Store: ... ? ... : ... | positive strictlyPositive |
+| test.c:366:15:366:15 | Constant: (unsigned int)... | positive strictlyPositive |
+| test.c:367:5:367:17 | Store: ... = ... | positive |
+| test.c:367:10:367:10 | Load: x | positive |
+| test.c:367:10:367:17 | Load: ... ? ... : ... | positive |
+| test.c:367:10:367:17 | Phi: ... ? ... : ... | positive |
+| test.c:367:10:367:17 | Store: ... ? ... : ... | positive |
+| test.c:367:10:367:17 | Store: ... ? ... : ... | positive strictlyPositive |
+| test.c:367:15:367:17 | Constant: (unsigned int)... | positive strictlyPositive |
+| test.c:368:5:368:21 | Store: ... = ... | positive strictlyPositive |
+| test.c:368:10:368:21 | Load: ... ? ... : ... | positive strictlyPositive |
+| test.c:368:10:368:21 | Phi: ... ? ... : ... | positive strictlyPositive |
+| test.c:368:10:368:21 | Store: ... ? ... : ... | positive strictlyPositive |
+| test.c:368:11:368:11 | Load: x | positive |
+| test.c:368:11:368:13 | Add: ... + ... | positive strictlyPositive |
+| test.c:368:13:368:13 | Constant: (unsigned int)... | positive strictlyPositive |
+| test.c:368:19:368:21 | Constant: (unsigned int)... | positive strictlyPositive |
+| test.c:369:5:369:36 | Store: ... = ... | positive strictlyPositive |
+| test.c:369:10:369:36 | Convert: (unsigned int)... | positive strictlyPositive |
+| test.c:369:10:369:36 | Load: ... ? ... : ... | positive strictlyPositive |
+| test.c:369:10:369:36 | Phi: ... ? ... : ... | positive strictlyPositive |
+| test.c:369:10:369:36 | Store: ... ? ... : ... | positive strictlyPositive |
+| test.c:369:11:369:30 | Convert: (unsigned char)... | positive |
+| test.c:369:27:369:27 | Load: x | positive |
+| test.c:369:27:369:29 | Add: ... + ... | positive strictlyPositive |
+| test.c:369:29:369:29 | Constant: (unsigned int)... | positive strictlyPositive |
+| test.c:369:36:369:36 | Constant: 5 | positive strictlyPositive |
+| test.c:370:5:370:38 | Store: ... = ... | positive strictlyPositive |
+| test.c:370:10:370:38 | Convert: (unsigned int)... | positive strictlyPositive |
+| test.c:370:10:370:38 | Load: ... ? ... : ... | positive strictlyPositive |
+| test.c:370:10:370:38 | Phi: ... ? ... : ... | positive strictlyPositive |
+| test.c:370:10:370:38 | Store: ... ? ... : ... | positive strictlyPositive |
+| test.c:370:11:370:30 | Convert: (unsigned char)... | positive |
+| test.c:370:27:370:27 | Load: x | positive |
+| test.c:370:27:370:29 | Add: ... + ... | positive strictlyPositive |
+| test.c:370:29:370:29 | Constant: (unsigned int)... | positive strictlyPositive |
+| test.c:370:36:370:38 | Constant: 500 | positive strictlyPositive |
+| test.c:371:5:371:39 | Store: ... = ... | positive strictlyPositive |
+| test.c:371:10:371:39 | Convert: (unsigned int)... | positive strictlyPositive |
+| test.c:371:10:371:39 | Load: ... ? ... : ... | positive strictlyPositive |
+| test.c:371:10:371:39 | Phi: ... ? ... : ... | positive strictlyPositive |
+| test.c:371:10:371:39 | Store: ... ? ... : ... | positive strictlyPositive |
+| test.c:371:11:371:31 | Convert: (unsigned short)... | positive |
+| test.c:371:28:371:28 | Load: x | positive |
+| test.c:371:28:371:30 | Add: ... + ... | positive strictlyPositive |
+| test.c:371:30:371:30 | Constant: (unsigned int)... | positive strictlyPositive |
+| test.c:371:37:371:39 | Constant: 500 | positive strictlyPositive |
+| test.c:373:3:373:47 | Phi: return ... | positive |
+| test.c:373:3:373:47 | Phi: return ... | positive |
+| test.c:373:3:373:47 | Phi: return ... | positive |
+| test.c:373:3:373:47 | Phi: return ... | positive |
+| test.c:373:3:373:47 | Phi: return ... | positive |
+| test.c:373:3:373:47 | Phi: return ... | positive |
+| test.c:373:10:373:11 | Load: y1 | positive |
+| test.c:373:10:373:16 | Add: ... + ... | positive |
+| test.c:373:10:373:21 | Add: ... + ... | positive |
+| test.c:373:10:373:26 | Add: ... + ... | positive |
+| test.c:373:10:373:31 | Add: ... + ... | positive |
+| test.c:373:10:373:36 | Add: ... + ... | positive |
+| test.c:373:10:373:41 | Add: ... + ... | positive |
+| test.c:373:10:373:46 | Add: ... + ... | positive |
+| test.c:373:10:373:46 | Store: ... + ... | positive |
+| test.c:373:15:373:16 | Load: y2 | positive |
+| test.c:373:20:373:21 | Load: y3 | positive |
+| test.c:373:25:373:26 | Load: y4 | positive |
+| test.c:373:30:373:31 | Load: y5 | positive |
+| test.c:373:35:373:36 | Load: y6 | positive |
+| test.c:373:40:373:41 | Load: y7 | positive |
+| test.c:373:45:373:46 | Load: y8 | positive |
+| test.c:377:42:377:42 | InitializeParameter: x | positive |
+| test.c:378:16:378:17 | Uninitialized: definition of y1 | positive |
+| test.c:378:20:378:21 | Uninitialized: definition of y2 | positive |
+| test.c:378:24:378:25 | Uninitialized: definition of y3 | positive |
+| test.c:378:28:378:29 | Uninitialized: definition of y4 | positive |
+| test.c:378:32:378:33 | Uninitialized: definition of y5 | positive |
+| test.c:379:3:379:24 | Store: ... = ... | positive strictlyPositive |
+| test.c:379:8:379:8 | Load: x | positive |
+| test.c:379:8:379:24 | Load: ... ? ... : ... | positive strictlyPositive |
+| test.c:379:8:379:24 | Phi: ... ? ... : ... | positive strictlyPositive |
+| test.c:379:8:379:24 | Store: ... ? ... : ... | positive strictlyPositive |
+| test.c:379:8:379:24 | Store: ... ? ... : ... | positive strictlyPositive |
+| test.c:379:12:379:14 | Constant: (unsigned int)... | positive strictlyPositive |
+| test.c:379:18:379:18 | Load: x | positive strictlyPositive |
+| test.c:379:22:379:24 | Constant: (unsigned int)... | positive strictlyPositive |
+| test.c:380:3:380:25 | Store: ... = ... | positive strictlyPositive |
+| test.c:380:8:380:8 | Load: x | positive |
+| test.c:380:8:380:25 | Load: ... ? ... : ... | positive strictlyPositive |
+| test.c:380:8:380:25 | Phi: ... ? ... : ... | positive strictlyPositive |
+| test.c:380:8:380:25 | Store: ... ? ... : ... | positive strictlyPositive |
+| test.c:380:8:380:25 | Store: ... ? ... : ... | positive strictlyPositive |
+| test.c:380:13:380:15 | Constant: (unsigned int)... | positive strictlyPositive |
+| test.c:380:19:380:21 | Constant: (unsigned int)... | positive strictlyPositive |
+| test.c:380:25:380:25 | Load: x | positive strictlyPositive |
+| test.c:381:3:381:11 | Store: ... = ... | positive strictlyPositive |
+| test.c:381:8:381:11 | Constant: (unsigned int)... | positive strictlyPositive |
+| test.c:382:3:382:11 | Store: ... = ... | positive strictlyPositive |
+| test.c:382:8:382:11 | Constant: (unsigned int)... | positive strictlyPositive |
+| test.c:383:3:383:11 | Store: ... = ... | positive strictlyPositive |
+| test.c:383:8:383:11 | Constant: (unsigned int)... | positive strictlyPositive |
+| test.c:384:7:384:7 | Load: x | positive |
+| test.c:384:12:384:14 | Constant: (unsigned int)... | positive strictlyPositive |
+| test.c:385:5:385:21 | Store: ... = ... | positive strictlyPositive |
+| test.c:385:10:385:21 | Load: ... ? ... : ... | positive strictlyPositive |
+| test.c:385:10:385:21 | Phi: ... ? ... : ... | positive strictlyPositive |
+| test.c:385:10:385:21 | Store: ... ? ... : ... | positive strictlyPositive |
+| test.c:385:11:385:11 | Load: x | positive strictlyPositive |
+| test.c:385:11:385:15 | Sub: ... - ... | positive |
+| test.c:385:13:385:15 | Constant: (unsigned int)... | positive strictlyPositive |
+| test.c:385:21:385:21 | Constant: (unsigned int)... | positive strictlyPositive |
+| test.c:386:5:386:21 | Store: ... = ... | positive strictlyPositive |
+| test.c:386:10:386:21 | Load: ... ? ... : ... | positive strictlyPositive |
+| test.c:386:10:386:21 | Phi: ... ? ... : ... | positive strictlyPositive |
+| test.c:386:10:386:21 | Store: ... ? ... : ... | positive strictlyPositive |
+| test.c:386:11:386:11 | Load: x | positive strictlyPositive |
+| test.c:386:11:386:15 | Sub: ... - ... | positive |
+| test.c:386:13:386:15 | Constant: (unsigned int)... | positive strictlyPositive |
+| test.c:386:21:386:21 | Constant: (unsigned int)... | positive strictlyPositive |
+| test.c:387:5:387:38 | Store: ... = ... | positive strictlyPositive |
+| test.c:387:10:387:38 | Convert: (unsigned int)... | positive strictlyPositive |
+| test.c:387:10:387:38 | Load: ... ? ... : ... | positive strictlyPositive |
+| test.c:387:10:387:38 | Phi: ... ? ... : ... | positive strictlyPositive |
+| test.c:387:10:387:38 | Store: ... ? ... : ... | positive strictlyPositive |
+| test.c:387:11:387:32 | Convert: (unsigned char)... | positive |
+| test.c:387:27:387:27 | Load: x | positive strictlyPositive |
+| test.c:387:27:387:31 | Sub: ... - ... | positive |
+| test.c:387:29:387:31 | Constant: (unsigned int)... | positive strictlyPositive |
+| test.c:387:38:387:38 | Constant: 5 | positive strictlyPositive |
+| test.c:389:3:389:32 | Phi: return ... | positive strictlyPositive |
+| test.c:389:3:389:32 | Phi: return ... | positive strictlyPositive |
+| test.c:389:3:389:32 | Phi: return ... | positive strictlyPositive |
+| test.c:389:10:389:11 | Load: y1 | positive strictlyPositive |
+| test.c:389:10:389:16 | Add: ... + ... | positive strictlyPositive |
+| test.c:389:10:389:21 | Add: ... + ... | positive strictlyPositive |
+| test.c:389:10:389:26 | Add: ... + ... | positive strictlyPositive |
+| test.c:389:10:389:31 | Add: ... + ... | positive strictlyPositive |
+| test.c:389:10:389:31 | Store: ... + ... | positive strictlyPositive |
+| test.c:389:15:389:16 | Load: y2 | positive strictlyPositive |
+| test.c:389:20:389:21 | Load: y3 | positive strictlyPositive |
+| test.c:389:25:389:26 | Load: y4 | positive strictlyPositive |
+| test.c:389:30:389:31 | Load: y5 | positive strictlyPositive |
+| test.c:393:40:393:40 | InitializeParameter: x | positive |
+| test.c:394:20:394:20 | Load: x | positive |
+| test.c:394:20:394:36 | Load: ... ? ... : ... | positive |
+| test.c:394:20:394:36 | Phi: ... ? ... : ... | positive |
+| test.c:394:20:394:36 | Store: ... ? ... : ... | positive |
+| test.c:394:20:394:36 | Store: ... ? ... : ... | positive |
+| test.c:394:20:394:36 | Store: ... ? ... : ... | positive strictlyPositive |
+| test.c:394:24:394:26 | Constant: (unsigned int)... | positive strictlyPositive |
+| test.c:394:30:394:30 | Load: x | positive |
+| test.c:394:34:394:36 | Constant: (unsigned int)... | positive strictlyPositive |
+| test.c:395:16:395:17 | Uninitialized: definition of y1 | positive |
+| test.c:396:16:396:17 | Uninitialized: definition of y2 | positive |
+| test.c:397:3:397:15 | Store: ... = ... | positive strictlyPositive |
+| test.c:397:9:397:11 | Add: ++ ... | positive strictlyPositive |
+| test.c:397:9:397:11 | Constant: ++ ... | positive strictlyPositive |
+| test.c:397:9:397:11 | Load: ++ ... | positive |
+| test.c:397:9:397:11 | Store: ++ ... | positive strictlyPositive |
+| test.c:397:14:397:14 | Load: y | positive strictlyPositive |
+| test.c:398:3:398:23 | Store: ... = ... | positive strictlyPositive |
+| test.c:398:9:398:11 | Add: ... ++ | positive strictlyPositive |
+| test.c:398:9:398:11 | Constant: ... ++ | positive strictlyPositive |
+| test.c:398:9:398:11 | Load: ... ++ | positive strictlyPositive |
+| test.c:398:9:398:11 | Store: ... ++ | positive strictlyPositive |
+| test.c:398:14:398:19 | Add: ... += ... | positive strictlyPositive |
+| test.c:398:14:398:19 | Load: ... += ... | positive strictlyPositive |
+| test.c:398:14:398:19 | Store: ... += ... | positive strictlyPositive |
+| test.c:398:19:398:19 | Constant: (unsigned int)... | positive strictlyPositive |
+| test.c:398:22:398:22 | Load: y | positive strictlyPositive |
+| test.c:399:10:399:11 | Load: y1 | positive strictlyPositive |
+| test.c:399:10:399:16 | Add: ... + ... | positive strictlyPositive |
+| test.c:399:10:399:16 | Store: ... + ... | positive strictlyPositive |
+| test.c:399:15:399:16 | Load: y2 | positive strictlyPositive |
+| test.cpp:9:11:9:12 | Constant: - ... | negative strictlyNegative |
+| test.cpp:9:11:9:12 | Store: - ... | negative strictlyNegative |
+| test.cpp:11:13:11:13 | Constant: 3 | positive strictlyPositive |
+| test.cpp:30:12:30:13 | Constant: - ... | negative strictlyNegative |
+| test.cpp:31:5:31:10 | Store: ... = ... | negative strictlyNegative |
+| test.cpp:31:9:31:10 | Constant: - ... | negative strictlyNegative |
+| test.cpp:33:12:33:12 | Constant: 1 | positive strictlyPositive |
+| test.cpp:34:5:34:9 | Store: ... = ... | positive strictlyPositive |
+| test.cpp:34:9:34:9 | Constant: 1 | positive strictlyPositive |
+| test.cpp:36:12:36:15 | Constant: - ... | negative strictlyNegative |
+| test.cpp:37:5:37:12 | Store: ... = ... | negative strictlyNegative |
+| test.cpp:37:9:37:12 | Constant: - ... | negative strictlyNegative |
+| test.cpp:39:12:39:14 | Constant: 128 | positive strictlyPositive |
+| test.cpp:40:5:40:11 | Store: ... = ... | positive strictlyPositive |
+| test.cpp:40:9:40:11 | Constant: 128 | positive strictlyPositive |
+| test.cpp:42:12:42:16 | Constant: - ... | negative strictlyNegative |
+| test.cpp:43:5:43:13 | Store: ... = ... | negative strictlyNegative |
+| test.cpp:43:9:43:13 | Constant: - ... | negative strictlyNegative |
+| test.cpp:45:12:45:15 | Constant: 1024 | positive strictlyPositive |
+| test.cpp:46:5:46:12 | Store: ... = ... | positive strictlyPositive |
+| test.cpp:46:9:46:12 | Constant: 1024 | positive strictlyPositive |
+| test.cpp:69:10:69:21 | Constant: ... \|\| ... | positive strictlyPositive |
+| test.cpp:69:10:69:21 | Load: ... \|\| ... | positive |
+| test.cpp:69:10:69:21 | Phi: ... \|\| ... | positive |
+| test.cpp:69:10:69:21 | Store: ... \|\| ... | positive |
+| test.cpp:69:10:69:21 | Store: ... \|\| ... | positive strictlyPositive |
diff --git a/cpp/ql/test/library-tests/rangeanalysis/signanalysis/SignAnalysis.ql b/cpp/ql/test/library-tests/rangeanalysis/signanalysis/SignAnalysis.ql
index cab4cea1d84..8ebdc68d170 100644
--- a/cpp/ql/test/library-tests/rangeanalysis/signanalysis/SignAnalysis.ql
+++ b/cpp/ql/test/library-tests/rangeanalysis/signanalysis/SignAnalysis.ql
@@ -16,4 +16,4 @@ string getASignString(Instruction i) {
}
from Instruction i
-select i, i.getAST(), strictconcat(string s | s = getASignString(i) | s, " ")
\ No newline at end of file
+select i, strictconcat(string s | s = getASignString(i) | s, " ")
\ No newline at end of file
diff --git a/cpp/ql/test/library-tests/rangeanalysis/signanalysis/binary_logical_operator.c b/cpp/ql/test/library-tests/rangeanalysis/signanalysis/binary_logical_operator.c
new file mode 100644
index 00000000000..9339241bda1
--- /dev/null
+++ b/cpp/ql/test/library-tests/rangeanalysis/signanalysis/binary_logical_operator.c
@@ -0,0 +1,8 @@
+int test01(int x, int y) {
+ int b = x > 10 && y < 0;
+ if (b) {
+ return x;
+ } else {
+ return y;
+ }
+}
From ed49c623f1d2f51bee1f87626a0357adf50f1bb7 Mon Sep 17 00:00:00 2001
From: Aditya Sharad
Date: Wed, 7 Nov 2018 14:36:40 +0000
Subject: [PATCH 12/71] Version: Bump to 1.18.2 release.
---
cpp/ql/src/META-INF/MANIFEST.MF | 4 ++--
csharp/ql/src/META-INF/MANIFEST.MF | 4 ++--
java/ql/src/META-INF/MANIFEST.MF | 4 ++--
javascript/ql/src/META-INF/MANIFEST.MF | 4 ++--
4 files changed, 8 insertions(+), 8 deletions(-)
diff --git a/cpp/ql/src/META-INF/MANIFEST.MF b/cpp/ql/src/META-INF/MANIFEST.MF
index 1b820007d8f..a6f8f5008d9 100644
--- a/cpp/ql/src/META-INF/MANIFEST.MF
+++ b/cpp/ql/src/META-INF/MANIFEST.MF
@@ -2,7 +2,7 @@ Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: Semmle C/C++ Default Queries
Bundle-SymbolicName: com.semmle.plugin.semmlecode.cpp.queries;singleton:=true
-Bundle-Version: 1.18.2.qualifier
+Bundle-Version: 1.18.2
Bundle-Vendor: Semmle Ltd.
Bundle-ActivationPolicy: lazy
-Require-Bundle: com.semmle.plugin.qdt.ui;bundle-version="[1.18.2.qualifier,1.18.2.qualifier]"
+Require-Bundle: com.semmle.plugin.qdt.ui;bundle-version="[1.18.2,1.18.2]"
diff --git a/csharp/ql/src/META-INF/MANIFEST.MF b/csharp/ql/src/META-INF/MANIFEST.MF
index d4035e8144d..ada13a5b7ae 100644
--- a/csharp/ql/src/META-INF/MANIFEST.MF
+++ b/csharp/ql/src/META-INF/MANIFEST.MF
@@ -2,7 +2,7 @@ Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: Semmle C# Default Queries
Bundle-SymbolicName: com.semmle.plugin.semmlecode.csharp.queries;singleton:=true
-Bundle-Version: 1.18.2.qualifier
+Bundle-Version: 1.18.2
Bundle-Vendor: Semmle Ltd.
Bundle-ActivationPolicy: lazy
-Require-Bundle: com.semmle.plugin.qdt.ui;bundle-version="[1.18.2.qualifier,1.18.2.qualifier]"
+Require-Bundle: com.semmle.plugin.qdt.ui;bundle-version="[1.18.2,1.18.2]"
diff --git a/java/ql/src/META-INF/MANIFEST.MF b/java/ql/src/META-INF/MANIFEST.MF
index 7658efa850d..d757adf90a1 100644
--- a/java/ql/src/META-INF/MANIFEST.MF
+++ b/java/ql/src/META-INF/MANIFEST.MF
@@ -2,8 +2,8 @@ Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: Semmle Default Java Queries
Bundle-SymbolicName: com.semmle.plugin.semmlecode.queries;singleton:=true
-Bundle-Version: 1.18.2.qualifier
+Bundle-Version: 1.18.2
Bundle-Vendor: Semmle Ltd.
Bundle-ActivationPolicy: lazy
-Require-Bundle: com.semmle.plugin.qdt.ui;bundle-version="[1.18.2.qualifier,1.18.2.qualifier]"
+Require-Bundle: com.semmle.plugin.qdt.ui;bundle-version="[1.18.2,1.18.2]"
diff --git a/javascript/ql/src/META-INF/MANIFEST.MF b/javascript/ql/src/META-INF/MANIFEST.MF
index be51fbc5595..39e24984897 100644
--- a/javascript/ql/src/META-INF/MANIFEST.MF
+++ b/javascript/ql/src/META-INF/MANIFEST.MF
@@ -2,7 +2,7 @@ Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: Semmle JavaScript Default Queries
Bundle-SymbolicName: com.semmle.plugin.semmlecode.javascript.queries;singleton:=true
-Bundle-Version: 1.18.2.qualifier
+Bundle-Version: 1.18.2
Bundle-Vendor: Semmle Ltd.
Bundle-ActivationPolicy: lazy
-Require-Bundle: com.semmle.plugin.qdt.ui;bundle-version="[1.18.2.qualifier,1.18.2.qualifier]"
+Require-Bundle: com.semmle.plugin.qdt.ui;bundle-version="[1.18.2,1.18.2]"
From b9c727c77211cc675f6846e275c4cfbc8481af5f Mon Sep 17 00:00:00 2001
From: Geoffrey White <40627776+geoffw0@users.noreply.github.com>
Date: Wed, 24 Oct 2018 15:52:29 +0100
Subject: [PATCH 13/71] CPP: Include sizeof(expr) expressions in
isDynamicallyAllocatedWithDifferentSize.
---
cpp/ql/src/semmle/code/cpp/commons/Buffer.qll | 7 ++++---
1 file changed, 4 insertions(+), 3 deletions(-)
diff --git a/cpp/ql/src/semmle/code/cpp/commons/Buffer.qll b/cpp/ql/src/semmle/code/cpp/commons/Buffer.qll
index b184832e166..35d34f5e403 100644
--- a/cpp/ql/src/semmle/code/cpp/commons/Buffer.qll
+++ b/cpp/ql/src/semmle/code/cpp/commons/Buffer.qll
@@ -15,11 +15,12 @@ import cpp
* ```
*/
private predicate isDynamicallyAllocatedWithDifferentSize(Class s) {
- exists(SizeofTypeOperator sof |
- sof.getTypeOperand().getUnspecifiedType() = s |
+ exists(SizeofOperator so |
+ so.(SizeofTypeOperator).getTypeOperand().getUnspecifiedType() = s or
+ so.(SizeofExprOperator).getExprOperand().getType().getUnspecifiedType() = s |
// Check all ancestor nodes except the immediate parent for
// allocations.
- isStdLibAllocationExpr(sof.getParent().(Expr).getParent+())
+ isStdLibAllocationExpr(so.getParent().(Expr).getParent+())
)
}
From 3610d35321ea91ee439b628bdba7350e6ff7159b Mon Sep 17 00:00:00 2001
From: Geoffrey White <40627776+geoffw0@users.noreply.github.com>
Date: Wed, 24 Oct 2018 20:07:44 +0100
Subject: [PATCH 14/71] CPP: Include offsetof type calculations in
memberMayBeVarSize.
---
cpp/ql/src/semmle/code/cpp/commons/Buffer.qll | 53 +++++++++----------
1 file changed, 26 insertions(+), 27 deletions(-)
diff --git a/cpp/ql/src/semmle/code/cpp/commons/Buffer.qll b/cpp/ql/src/semmle/code/cpp/commons/Buffer.qll
index 35d34f5e403..ddcc126edea 100644
--- a/cpp/ql/src/semmle/code/cpp/commons/Buffer.qll
+++ b/cpp/ql/src/semmle/code/cpp/commons/Buffer.qll
@@ -1,29 +1,5 @@
import cpp
-/**
- * Holds if `sizeof(s)` occurs as part of the parameter of a dynamic
- * memory allocation (`malloc`, `realloc`, etc.), except if `sizeof(s)`
- * only ever occurs as the immediate parameter to allocations.
- *
- * For example, holds for `s` if it occurs as
- * ```
- * malloc(sizeof(s) + 100 * sizeof(char))
- * ```
- * but not if it only ever occurs as
- * ```
- * malloc(sizeof(s))
- * ```
-*/
-private predicate isDynamicallyAllocatedWithDifferentSize(Class s) {
- exists(SizeofOperator so |
- so.(SizeofTypeOperator).getTypeOperand().getUnspecifiedType() = s or
- so.(SizeofExprOperator).getExprOperand().getType().getUnspecifiedType() = s |
- // Check all ancestor nodes except the immediate parent for
- // allocations.
- isStdLibAllocationExpr(so.getParent().(Expr).getParent+())
- )
-}
-
/**
* Holds if `v` is a member variable of `c` that looks like it might be variable sized in practice. For
* example:
@@ -34,15 +10,38 @@ private predicate isDynamicallyAllocatedWithDifferentSize(Class s) {
* };
* ```
* This requires that `v` is an array of size 0 or 1, and `v` is the last member of `c`. In addition,
- * there must be at least one instance where a `c` pointer is allocated with additional space.
+ * there must be at least one instance where a `c` pointer is allocated with additional space. For
+ * example, holds for `c` if it occurs as
+ * ```
+ * malloc(sizeof(c) + 100 * sizeof(char))
+ * ```
+ * but not if it only ever occurs as
+ * ```
+ * malloc(sizeof(c))
+ * ```
*/
predicate memberMayBeVarSize(Class c, MemberVariable v) {
exists(int i |
+ // `v` is the last field in `c`
i = max(int j | c.getCanonicalMember(j) instanceof Field | j) and
v = c.getCanonicalMember(i) and
+
+ // v is an array of size at most 1
v.getType().getUnspecifiedType().(ArrayType).getSize() <= 1
- ) and
- isDynamicallyAllocatedWithDifferentSize(c)
+ ) and (
+ exists(SizeofOperator so |
+ // `sizeof(c)` is taken
+ so.(SizeofTypeOperator).getTypeOperand().getUnspecifiedType() = c or
+ so.(SizeofExprOperator).getExprOperand().getType().getUnspecifiedType() = c |
+ // Check all ancestor nodes except the immediate parent for
+ // allocations.
+ isStdLibAllocationExpr(so.getParent().(Expr).getParent+())
+ ) or exists(AddressOfExpr aoe |
+ // `&(c.v)` is taken
+ aoe.getAddressable() = v and
+ isStdLibAllocationExpr(aoe.getParent().(Expr).getParent+())
+ )
+ )
}
/**
From 19a53cde79d6357c9e93d6e479124c3a216299e0 Mon Sep 17 00:00:00 2001
From: Geoffrey White <40627776+geoffw0@users.noreply.github.com>
Date: Thu, 25 Oct 2018 14:24:49 +0100
Subject: [PATCH 15/71] CPP: Fix array size bug in memberMayBeVarSize.
---
cpp/ql/src/semmle/code/cpp/commons/Buffer.qll | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/cpp/ql/src/semmle/code/cpp/commons/Buffer.qll b/cpp/ql/src/semmle/code/cpp/commons/Buffer.qll
index ddcc126edea..4e158131156 100644
--- a/cpp/ql/src/semmle/code/cpp/commons/Buffer.qll
+++ b/cpp/ql/src/semmle/code/cpp/commons/Buffer.qll
@@ -27,7 +27,7 @@ predicate memberMayBeVarSize(Class c, MemberVariable v) {
v = c.getCanonicalMember(i) and
// v is an array of size at most 1
- v.getType().getUnspecifiedType().(ArrayType).getSize() <= 1
+ v.getType().getUnspecifiedType().(ArrayType).getArraySize() <= 1
) and (
exists(SizeofOperator so |
// `sizeof(c)` is taken
From 79ff559f7aff162c8fb02f60f0c695b455a483f7 Mon Sep 17 00:00:00 2001
From: Geoffrey White <40627776+geoffw0@users.noreply.github.com>
Date: Thu, 25 Oct 2018 14:54:12 +0100
Subject: [PATCH 16/71] CPP: Don't require alloc in memberMayBeVarSize.
---
cpp/ql/src/semmle/code/cpp/commons/Buffer.qll | 9 ++++-----
1 file changed, 4 insertions(+), 5 deletions(-)
diff --git a/cpp/ql/src/semmle/code/cpp/commons/Buffer.qll b/cpp/ql/src/semmle/code/cpp/commons/Buffer.qll
index 4e158131156..67d69820159 100644
--- a/cpp/ql/src/semmle/code/cpp/commons/Buffer.qll
+++ b/cpp/ql/src/semmle/code/cpp/commons/Buffer.qll
@@ -33,13 +33,12 @@ predicate memberMayBeVarSize(Class c, MemberVariable v) {
// `sizeof(c)` is taken
so.(SizeofTypeOperator).getTypeOperand().getUnspecifiedType() = c or
so.(SizeofExprOperator).getExprOperand().getType().getUnspecifiedType() = c |
- // Check all ancestor nodes except the immediate parent for
- // allocations.
- isStdLibAllocationExpr(so.getParent().(Expr).getParent+())
+
+ // arithmetic is performed on the result
+ so.getParent*() instanceof BinaryArithmeticOperation
) or exists(AddressOfExpr aoe |
// `&(c.v)` is taken
- aoe.getAddressable() = v and
- isStdLibAllocationExpr(aoe.getParent().(Expr).getParent+())
+ aoe.getAddressable() = v
)
)
}
From 313624fd2e3c782197285d6dd414b2788522a1f5 Mon Sep 17 00:00:00 2001
From: Geoffrey White <40627776+geoffw0@users.noreply.github.com>
Date: Thu, 25 Oct 2018 15:16:55 +0100
Subject: [PATCH 17/71] CPP: Support builtin offsetof.
---
cpp/ql/src/semmle/code/cpp/commons/Buffer.qll | 3 +++
1 file changed, 3 insertions(+)
diff --git a/cpp/ql/src/semmle/code/cpp/commons/Buffer.qll b/cpp/ql/src/semmle/code/cpp/commons/Buffer.qll
index 67d69820159..fbd6338925b 100644
--- a/cpp/ql/src/semmle/code/cpp/commons/Buffer.qll
+++ b/cpp/ql/src/semmle/code/cpp/commons/Buffer.qll
@@ -39,6 +39,9 @@ predicate memberMayBeVarSize(Class c, MemberVariable v) {
) or exists(AddressOfExpr aoe |
// `&(c.v)` is taken
aoe.getAddressable() = v
+ ) or exists(BuiltInOperationOffsetOf oo |
+ // `offsetof(c, v)` using a builtin
+ oo.getAChild().(VariableAccess).getTarget() = v
)
)
}
From 57dafe2734f877ed01a5d7eee4edfa1853d7f03d Mon Sep 17 00:00:00 2001
From: Geoffrey White <40627776+geoffw0@users.noreply.github.com>
Date: Fri, 26 Oct 2018 13:40:56 +0100
Subject: [PATCH 18/71] CPP: BinaryArithmeticOperation -> AddExpr.
---
cpp/ql/src/semmle/code/cpp/commons/Buffer.qll | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/cpp/ql/src/semmle/code/cpp/commons/Buffer.qll b/cpp/ql/src/semmle/code/cpp/commons/Buffer.qll
index fbd6338925b..8347dbe354d 100644
--- a/cpp/ql/src/semmle/code/cpp/commons/Buffer.qll
+++ b/cpp/ql/src/semmle/code/cpp/commons/Buffer.qll
@@ -35,7 +35,7 @@ predicate memberMayBeVarSize(Class c, MemberVariable v) {
so.(SizeofExprOperator).getExprOperand().getType().getUnspecifiedType() = c |
// arithmetic is performed on the result
- so.getParent*() instanceof BinaryArithmeticOperation
+ so.getParent*() instanceof AddExpr
) or exists(AddressOfExpr aoe |
// `&(c.v)` is taken
aoe.getAddressable() = v
From 1d7e802157b8906b24e0bcadeea2dda85b7a5c5f Mon Sep 17 00:00:00 2001
From: Robert Marsh
Date: Wed, 7 Nov 2018 16:07:37 -0800
Subject: [PATCH 19/71] C++: move sign analysis to new Operand type
---
.../code/cpp/rangeanalysis/SignAnalysis.qll | 188 +++++++++---------
.../signanalysis/SignAnalysis.ql | 8 +-
2 files changed, 93 insertions(+), 103 deletions(-)
diff --git a/cpp/ql/src/semmle/code/cpp/rangeanalysis/SignAnalysis.qll b/cpp/ql/src/semmle/code/cpp/rangeanalysis/SignAnalysis.qll
index 01a02bf0b26..1981d127bc3 100644
--- a/cpp/ql/src/semmle/code/cpp/rangeanalysis/SignAnalysis.qll
+++ b/cpp/ql/src/semmle/code/cpp/rangeanalysis/SignAnalysis.qll
@@ -207,22 +207,20 @@ private predicate unknownSign(Instruction i) {
}
/**
- * Holds if `lowerbound` is a lower bound for `bounded` at `pos`. This is restricted
+ * Holds if `lowerbound` is a lower bound for `bounded``. This is restricted
* to only include bounds for which we might determine a sign.
*/
-private predicate lowerBound(IRGuardCondition comp, Instruction lowerbound, Instruction bounded, Instruction pos, boolean isStrict) {
+private predicate lowerBound(IRGuardCondition comp, Operand lowerbound, Operand bounded, boolean isStrict) {
exists(int adjustment, Instruction compared |
- valueNumber(bounded) = valueNumber(compared) and
- bounded = pos.getAnOperand() and
- not unknownSign(lowerbound) and
- (
- isStrict = true and
- adjustment = 0
- or
- isStrict = false and
- adjustment = 1
- ) and
- comp.ensuresLt(lowerbound, compared, adjustment, pos.getBlock(), true)
+ valueNumber(bounded.getDefinitionInstruction()) = valueNumber(compared) and
+ (
+ isStrict = true and
+ adjustment = 0
+ or
+ isStrict = false and
+ adjustment = 1
+ ) and
+ comp.ensuresLt(lowerbound.getDefinitionInstruction(), compared, adjustment, bounded.getInstruction().getBlock(), true)
)
}
@@ -231,19 +229,17 @@ private predicate lowerBound(IRGuardCondition comp, Instruction lowerbound, Inst
* Holds if `upperbound` is an upper bound for `bounded` at `pos`. This is restricted
* to only include bounds for which we might determine a sign.
*/
-private predicate upperBound(IRGuardCondition comp, Instruction upperbound, Instruction bounded, Instruction pos, boolean isStrict) {
+private predicate upperBound(IRGuardCondition comp, Operand upperbound, Operand bounded, boolean isStrict) {
exists(int adjustment, Instruction compared |
- valueNumber(bounded) = valueNumber(compared) and
- bounded = pos.getAnOperand() and
- not unknownSign(upperbound) and
- (
- isStrict = true and
- adjustment = 0
- or
- isStrict = false and
- adjustment = 1
- ) and
- comp.ensuresLt(compared, upperbound, adjustment, pos.getBlock(), true)
+ valueNumber(bounded.getDefinitionInstruction()) = valueNumber(compared) and
+ (
+ isStrict = true and
+ adjustment = 0
+ or
+ isStrict = false and
+ adjustment = 1
+ ) and
+ comp.ensuresLt(compared, upperbound.getDefinitionInstruction(), adjustment, bounded.getInstruction().getBlock(), true)
)
}
@@ -254,12 +250,10 @@ private predicate upperBound(IRGuardCondition comp, Instruction upperbound, Inst
* - `isEq = true` : `bounded = eqbound`
* - `isEq = false` : `bounded != eqbound`
*/
-private predicate eqBound(IRGuardCondition guard, Instruction eqbound, Instruction bounded, Instruction pos, boolean isEq) {
+private predicate eqBound(IRGuardCondition guard, Operand eqbound, Operand bounded, boolean isEq) {
exists(Instruction compared |
- not unknownSign(eqbound) and
- valueNumber(bounded) = valueNumber(compared) and
- bounded = pos.getAnOperand() and
- guard.ensuresEq(compared, eqbound, 0, pos.getBlock(), isEq)
+ valueNumber(bounded.getDefinitionInstruction()) = valueNumber(compared) and
+ guard.ensuresEq(compared, eqbound.getDefinitionInstruction(), 0, bounded.getInstruction().getBlock(), isEq)
)
}
@@ -269,56 +263,56 @@ private predicate eqBound(IRGuardCondition guard, Instruction eqbound, Instructi
* Holds if `bound` is a bound for `v` at `pos` that needs to be positive in
* order for `v` to be positive.
*/
-private predicate posBound(IRGuardCondition comp, Instruction bound, Instruction v, Instruction pos) {
- upperBound(comp, bound, v, pos, _) or
- eqBound(comp, bound, v, pos, true)
+private predicate posBound(IRGuardCondition comp, Operand bound, Operand op) {
+ upperBound(comp, bound, op, _) or
+ eqBound(comp, bound, op, true)
}
/**
* Holds if `bound` is a bound for `v` at `pos` that needs to be negative in
* order for `v` to be negative.
*/
-private predicate negBound(IRGuardCondition comp, Instruction bound, Instruction v, Instruction pos) {
- lowerBound(comp, bound, v, pos, _) or
- eqBound(comp, bound, v, pos, true)
+private predicate negBound(IRGuardCondition comp, Operand bound, Operand op) {
+ lowerBound(comp, bound, op, _) or
+ eqBound(comp, bound, op, true)
}
/**
* Holds if `bound` is a bound for `v` at `pos` that can restrict whether `v`
* can be zero.
*/
-private predicate zeroBound(IRGuardCondition comp, Instruction bound, Instruction v, Instruction pos) {
- lowerBound(comp, bound, v, pos, _) or
- upperBound(comp, bound, v, pos, _) or
- eqBound(comp, bound, v, pos, _)
+private predicate zeroBound(IRGuardCondition comp, Operand bound, Operand op) {
+ lowerBound(comp, bound, op, _) or
+ upperBound(comp, bound, op, _) or
+ eqBound(comp, bound, op, _)
}
/** Holds if `bound` allows `v` to be positive at `pos`. */
-private predicate posBoundOk(IRGuardCondition comp, Instruction bound, Instruction v, Instruction pos) {
- posBound(comp, bound, v, pos) and TPos() = operandSign(comp, bound)
+private predicate posBoundOk(IRGuardCondition comp, Operand bound, Operand op) {
+ posBound(comp, bound, op) and TPos() = operandSign(bound)
}
/** Holds if `bound` allows `v` to be negative at `pos`. */
-private predicate negBoundOk(IRGuardCondition comp, Instruction bound, Instruction v, Instruction pos) {
- negBound(comp, bound, v, pos) and TNeg() = operandSign(comp, bound)
+private predicate negBoundOk(IRGuardCondition comp, Operand bound, Operand op) {
+ negBound(comp, bound, op) and TNeg() = operandSign(bound)
}
/** Holds if `bound` allows `v` to be zero at `pos`. */
-private predicate zeroBoundOk(IRGuardCondition comp, Instruction bound, Instruction v, Instruction pos) {
- lowerBound(comp, bound, v, pos, _) and TNeg() = operandSign(comp, bound) or
- lowerBound(comp, bound, v, pos, false) and TZero() = operandSign(comp, bound) or
- upperBound(comp, bound, v, pos, _) and TPos() = operandSign(comp, bound) or
- upperBound(comp, bound, v, pos, false) and TZero() = operandSign(comp, bound) or
- eqBound(comp, bound, v, pos, true) and TZero() = operandSign(comp, bound) or
- eqBound(comp, bound, v, pos, false) and TZero() != operandSign(comp, bound)
+private predicate zeroBoundOk(IRGuardCondition comp, Operand bound, Operand op) {
+ lowerBound(comp, bound, op, _) and TNeg() = operandSign(bound) or
+ lowerBound(comp, bound, op, false) and TZero() = operandSign(bound) or
+ upperBound(comp, bound, op, _) and TPos() = operandSign(bound) or
+ upperBound(comp, bound, op, false) and TZero() = operandSign(bound) or
+ eqBound(comp, bound, op, true) and TZero() = operandSign(bound) or
+ eqBound(comp, bound, op, false) and TZero() != operandSign(bound)
}
private Sign binaryOpLhsSign(Instruction i) {
- result = operandSign(i, i.(BinaryInstruction).getLeftOperand())
+ result = operandSign(i.getAnOperand().(LeftOperand))
}
private Sign binaryOpRhsSign(Instruction i) {
- result = operandSign(i, i.(BinaryInstruction).getRightOperand())
+ result = operandSign(i.getAnOperand().(RightOperand))
}
pragma[noinline]
@@ -327,44 +321,44 @@ private predicate binaryOpSigns(Instruction i, Sign lhs, Sign rhs) {
rhs = binaryOpRhsSign(i)
}
-private Sign unguardedOperandSign(Instruction pos, Instruction operand) {
- result = instructionSign(operand) and
- not hasGuard(operand, pos, result)
+private Sign unguardedOperandSign(Operand operand) {
+ result = instructionSign(operand.getDefinitionInstruction()) and
+ not hasGuard(operand, result)
}
-private Sign guardedOperandSign(Instruction pos, Instruction operand) {
- result = instructionSign(operand) and
- hasGuard(operand, pos, result)
+private Sign guardedOperandSign(Operand operand) {
+ result = instructionSign(operand.getDefinitionInstruction()) and
+ hasGuard(operand, result)
}
-private Sign guardedOperandSignOk(Instruction pos, Instruction operand) {
- result = TPos() and forex(IRGuardCondition guard, Instruction bound | posBound(guard, bound, operand, pos) | posBoundOk(guard, bound, operand, pos)) or
- result = TNeg() and forex(IRGuardCondition guard, Instruction bound | negBound(guard, bound, operand, pos) | negBoundOk(guard, bound, operand, pos)) or
- result = TZero() and forex(IRGuardCondition guard, Instruction bound | zeroBound(guard, bound, operand, pos) | zeroBoundOk(guard, bound, operand, pos))
+private Sign guardedOperandSignOk(Operand operand) {
+ result = TPos() and forex(IRGuardCondition guard, Operand bound | posBound(guard, bound, operand) | posBoundOk(guard, bound, operand)) or
+ result = TNeg() and forex(IRGuardCondition guard, Operand bound | negBound(guard, bound, operand) | negBoundOk(guard, bound, operand)) or
+ result = TZero() and forex(IRGuardCondition guard, Operand bound | zeroBound(guard, bound, operand) | zeroBoundOk(guard, bound, operand))
}
/**
* Holds if there is a bound that might restrict whether `v` has the sign `s`
* at `pos`.
*/
-private predicate hasGuard(Instruction v, Instruction pos, Sign s) {
- s = TPos() and posBound(_, _, v, pos)
+private predicate hasGuard(Operand op, Sign s) {
+ s = TPos() and posBound(_, _, op)
or
- s = TNeg() and negBound(_, _, v, pos)
+ s = TNeg() and negBound(_, _, op)
or
- s = TZero() and zeroBound(_, _, v, pos)
+ s = TZero() and zeroBound(_, _, op)
}
-cached private module SignAnalysisCached {
+cached module SignAnalysisCached {
/**
* Gets a sign that `operand` may have at `pos`, taking guards into account.
*/
cached
- Sign operandSign(Instruction pos, Instruction operand) {
- result = unguardedOperandSign(pos, operand)
+ Sign operandSign(Operand operand) {
+ result = unguardedOperandSign(operand)
or
- result = guardedOperandSign(pos, operand) and
- result = guardedOperandSignOk(pos, operand)
+ result = guardedOperandSign(operand) and
+ result = guardedOperandSignOk(operand)
}
cached
@@ -392,18 +386,14 @@ cached private module SignAnalysisCached {
then fromSigned = true
else fromSigned = false
) and
- result = castSign(operandSign(ci, prior), fromSigned, toSigned, getCastKind(ci))
+ result = castSign(operandSign(ci.getAnOperand()), fromSigned, toSigned, getCastKind(ci))
)
or
- exists(Instruction prior |
- prior = i.(CopyInstruction).getSourceValue()
- |
- result = operandSign(i, prior)
- )
+ result = operandSign(i.getAnOperand().(CopySourceOperand))
or
- result = operandSign(i, i.(BitComplementInstruction).getOperand()).bitnot()
+ result = operandSign(i.(BitComplementInstruction).getAnOperand()).bitnot()
or
- result = operandSign(i, i.(NegateInstruction).getOperand()).neg()
+ result = operandSign(i.(NegateInstruction).getAnOperand()).neg()
or
exists(Sign s1, Sign s2 |
binaryOpSigns(i, s1, s2)
@@ -436,58 +426,58 @@ cached private module SignAnalysisCached {
)
or
// use hasGuard here?
- result = operandSign(i, i.(PhiInstruction).getAnOperand())
+ result = operandSign(i.(PhiInstruction).getAnOperand())
)
}
}
/** Holds if `i` can be positive and cannot be negative. */
-predicate positive(Instruction i) {
+predicate positiveInstruction(Instruction i) {
instructionSign(i) = TPos() and
not instructionSign(i) = TNeg()
}
/** Holds if `i` at `pos` can be positive at and cannot be negative. */
-predicate positive(Instruction i, Instruction pos) {
- operandSign(pos, i) = TPos() and
- not operandSign(pos, i) = TNeg()
+predicate positive(Operand op) {
+ operandSign(op) = TPos() and
+ not operandSign(op) = TNeg()
}
/** Holds if `i` can be negative and cannot be positive. */
-predicate negative(Instruction i) {
+predicate negativeInstruction(Instruction i) {
instructionSign(i) = TNeg() and
not instructionSign(i) = TPos()
}
/** Holds if `i` at `pos` can be negative and cannot be positive. */
-predicate negative(Instruction i, Instruction pos) {
- operandSign(pos, i) = TNeg() and
- not operandSign(pos, i) = TPos()
+predicate negative(Operand op) {
+ operandSign(op) = TNeg() and
+ not operandSign(op) = TPos()
}
/** Holds if `i` is strictly positive. */
-predicate strictlyPositive(Instruction i) {
+predicate strictlyPositiveInstruction(Instruction i) {
instructionSign(i) = TPos() and
not instructionSign(i) = TNeg() and
not instructionSign(i) = TZero()
}
/** Holds if `i` is strictly positive at `pos`. */
-predicate strictlyPositive(Instruction i, Instruction pos) {
- operandSign(pos, i) = TPos() and
- not operandSign(pos, i) = TNeg() and
- not operandSign(pos, i) = TZero()
+predicate strictlyPositive(Operand op) {
+ operandSign(op) = TPos() and
+ not operandSign(op) = TNeg() and
+ not operandSign(op) = TZero()
}
/** Holds if `i` is strictly negative. */
-predicate strictlyNegative(Instruction i) {
+predicate strictlyNegativeInstruction(Instruction i) {
instructionSign(i) = TNeg() and
not instructionSign(i) = TPos() and
not instructionSign(i) = TZero()
}
/** Holds if `i` is strictly negative at `pos`. */
-predicate strictlyNegative(Instruction i, Instruction pos) {
- operandSign(pos, i) = TNeg() and
- not operandSign(pos, i) = TPos() and
- not operandSign(pos, i) = TZero()
+predicate strictlyNegative(Operand op) {
+ operandSign(op) = TNeg() and
+ not operandSign(op) = TPos() and
+ not operandSign(op) = TZero()
}
diff --git a/cpp/ql/test/library-tests/rangeanalysis/signanalysis/SignAnalysis.ql b/cpp/ql/test/library-tests/rangeanalysis/signanalysis/SignAnalysis.ql
index 8ebdc68d170..9875a641627 100644
--- a/cpp/ql/test/library-tests/rangeanalysis/signanalysis/SignAnalysis.ql
+++ b/cpp/ql/test/library-tests/rangeanalysis/signanalysis/SignAnalysis.ql
@@ -2,16 +2,16 @@ import semmle.code.cpp.rangeanalysis.SignAnalysis
import semmle.code.cpp.ir.IR
string getASignString(Instruction i) {
- positive(i) and
+ positiveInstruction(i) and
result = "positive"
or
- negative(i) and
+ negativeInstruction(i) and
result = "negative"
or
- strictlyPositive(i) and
+ strictlyPositiveInstruction(i) and
result = "strictlyPositive"
or
- strictlyNegative(i) and
+ strictlyNegativeInstruction(i) and
result = "strictlyNegative"
}
From cacb8fdee06abb9fb35fe3deb75c0d3e74c335cf Mon Sep 17 00:00:00 2001
From: Esben Sparre Andreasen
Date: Mon, 15 Oct 2018 20:26:29 +0200
Subject: [PATCH 20/71] JS: move DeadStoreOfLocal::isDefaultInit to separate
module
---
javascript/ql/src/Declarations/DeadStore.qll | 22 +++++++++++++++++++
.../ql/src/Declarations/DeadStoreOfLocal.ql | 17 +-------------
2 files changed, 23 insertions(+), 16 deletions(-)
create mode 100644 javascript/ql/src/Declarations/DeadStore.qll
diff --git a/javascript/ql/src/Declarations/DeadStore.qll b/javascript/ql/src/Declarations/DeadStore.qll
new file mode 100644
index 00000000000..1d00423ee8f
--- /dev/null
+++ b/javascript/ql/src/Declarations/DeadStore.qll
@@ -0,0 +1,22 @@
+/**
+ * Provides classes and predicates for reasoning about dead stores.
+ */
+
+import javascript
+
+/**
+ * Holds if `e` is an expression that may be used as a default initial value,
+ * such as `0` or `-1`, or an empty object or array literal.
+ */
+predicate isDefaultInit(Expr e) {
+ // primitive default values: zero, false, empty string, and (integer) -1
+ e.(NumberLiteral).getValue().toFloat() = 0.0 or
+ e.(NegExpr).getOperand().(NumberLiteral).getValue() = "1" or
+ e.(ConstantString).getStringValue() = "" or
+ e.(BooleanLiteral).getValue() = "false" or
+ // initialising to an empty array or object literal, even if unnecessary,
+ // can convey useful type information to the reader
+ e.(ArrayExpr).getSize() = 0 or
+ e.(ObjectExpr).getNumProperty() = 0 or
+ SyntacticConstants::isNullOrUndefined(e)
+}
diff --git a/javascript/ql/src/Declarations/DeadStoreOfLocal.ql b/javascript/ql/src/Declarations/DeadStoreOfLocal.ql
index 4d19d357b25..3299f38e93e 100644
--- a/javascript/ql/src/Declarations/DeadStoreOfLocal.ql
+++ b/javascript/ql/src/Declarations/DeadStoreOfLocal.ql
@@ -11,6 +11,7 @@
*/
import javascript
+import DeadStore
/**
* Holds if `vd` is a definition of variable `v` that is dead, that is,
@@ -25,22 +26,6 @@ predicate deadStoreOfLocal(VarDef vd, PurelyLocalVariable v) {
not exists (SsaExplicitDefinition ssa | ssa.defines(vd, v))
}
-/**
- * Holds if `e` is an expression that may be used as a default initial value,
- * such as `0` or `-1`, or an empty object or array literal.
- */
-predicate isDefaultInit(Expr e) {
- // primitive default values: zero, false, empty string, and (integer) -1
- e.(NumberLiteral).getValue().toFloat() = 0.0 or
- e.(NegExpr).getOperand().(NumberLiteral).getValue() = "1" or
- e.(ConstantString).getStringValue() = "" or
- e.(BooleanLiteral).getValue() = "false" or
- // initialising to an empty array or object literal, even if unnecessary,
- // can convey useful type information to the reader
- e.(ArrayExpr).getSize() = 0 or
- e.(ObjectExpr).getNumProperty() = 0
-}
-
from VarDef dead, PurelyLocalVariable v // captured variables may be read by closures, so don't flag them
where deadStoreOfLocal(dead, v) and
// the variable should be accessed somewhere; otherwise it will be flagged by UnusedVariable
From 6ee47c437e213ce6dd532a036c910e0ae898799a Mon Sep 17 00:00:00 2001
From: Esben Sparre Andreasen
Date: Tue, 16 Oct 2018 11:01:59 +0200
Subject: [PATCH 21/71] JS: generalize and move DeadStoreOfLocal.qhelp to
DeadStore.qhelp
---
.../ql/src/Declarations/DeadStore.qhelp | 49 +++++++++++++++++++
.../src/Declarations/DeadStoreOfLocal.qhelp | 48 ++----------------
2 files changed, 53 insertions(+), 44 deletions(-)
create mode 100644 javascript/ql/src/Declarations/DeadStore.qhelp
diff --git a/javascript/ql/src/Declarations/DeadStore.qhelp b/javascript/ql/src/Declarations/DeadStore.qhelp
new file mode 100644
index 00000000000..58f60fe42a8
--- /dev/null
+++ b/javascript/ql/src/Declarations/DeadStore.qhelp
@@ -0,0 +1,49 @@
+
+
+
+
+A value is assigned to a location, but either that location is never read
+later on, or its value is always overwritten before being read. This means
+that the original assignment has no effect, and could indicate a logic error or
+incomplete code.
+
+
+
+
+
+
+Ensure that you check the control and data flow in the method carefully.
+If a value is really not needed, consider omitting the assignment. Be careful,
+though: if the right-hand side has a side-effect (like performing a method call),
+it is important to keep this to preserve the overall behavior.
+
+
+
+
+
+
+In the following example, the return value of the call to send on line 2
+is assigned to the local variable result, but then never used.
+
+
+
+
+
+Assuming that send returns a status code indicating whether the operation
+succeeded or not, the value of result should be checked, perhaps like this:
+
+
+
+
+
+
+
+
+Wikipedia: Dead store.
+
+
+
+
+
diff --git a/javascript/ql/src/Declarations/DeadStoreOfLocal.qhelp b/javascript/ql/src/Declarations/DeadStoreOfLocal.qhelp
index edba2e60750..fa93ba07198 100644
--- a/javascript/ql/src/Declarations/DeadStoreOfLocal.qhelp
+++ b/javascript/ql/src/Declarations/DeadStoreOfLocal.qhelp
@@ -1,49 +1,9 @@
+"-//Semmle//qhelp//EN"
+"qhelp.dtd">
+
-
-
-A value is assigned to a local variable, but either that variable is never read
-later on, or its value is always overwritten before being read. This means
-that the original assignment has no effect, and could indicate a logic error or
-incomplete code.
-
-
-
+
-
-Ensure that you check the control and data flow in the method carefully.
-If a value is really not needed, consider omitting the assignment. Be careful,
-though: if the right-hand side has a side-effect (like performing a method call),
-it is important to keep this to preserve the overall behavior.
-
-
-
-
-
-
-In the following example, the return value of the call to send on line 2
-is assigned to the local variable result, but then never used.
-
-
-
-
-
-Assuming that send returns a status code indicating whether the operation
-succeeded or not, the value of result should be checked, perhaps like this:
-
-
-
-
-
-
-
-
-Wikipedia: Dead store.
-
-
-
-
From 33a297c829cb8f3801389e201e7ec96669df0c19 Mon Sep 17 00:00:00 2001
From: Esben Sparre Andreasen
Date: Tue, 9 Oct 2018 23:54:10 +0200
Subject: [PATCH 22/71] JS: add query: js/useless-assignment-to-property
---
.../suites/javascript/maintainability-more | 1 +
.../Declarations/DeadStoreOfProperty.qhelp | 9 ++
.../src/Declarations/DeadStoreOfProperty.ql | 138 ++++++++++++++++++
.../DeadStoreOfProperty.expected | 13 ++
.../DeadStoreOfProperty.qlref | 1 +
.../closure-compiler-tricks.js | 12 ++
.../DeadStoreOfProperty/externs.js | 43 ++++++
.../DeadStoreOfProperty/list-manipulation.js | 13 ++
.../real-world-examples.js | 39 +++++
.../Declarations/DeadStoreOfProperty/tst.js | 98 +++++++++++++
10 files changed, 367 insertions(+)
create mode 100644 javascript/ql/src/Declarations/DeadStoreOfProperty.qhelp
create mode 100644 javascript/ql/src/Declarations/DeadStoreOfProperty.ql
create mode 100644 javascript/ql/test/query-tests/Declarations/DeadStoreOfProperty/DeadStoreOfProperty.expected
create mode 100644 javascript/ql/test/query-tests/Declarations/DeadStoreOfProperty/DeadStoreOfProperty.qlref
create mode 100644 javascript/ql/test/query-tests/Declarations/DeadStoreOfProperty/closure-compiler-tricks.js
create mode 100644 javascript/ql/test/query-tests/Declarations/DeadStoreOfProperty/externs.js
create mode 100644 javascript/ql/test/query-tests/Declarations/DeadStoreOfProperty/list-manipulation.js
create mode 100644 javascript/ql/test/query-tests/Declarations/DeadStoreOfProperty/real-world-examples.js
create mode 100644 javascript/ql/test/query-tests/Declarations/DeadStoreOfProperty/tst.js
diff --git a/javascript/config/suites/javascript/maintainability-more b/javascript/config/suites/javascript/maintainability-more
index 353d3e18c04..6cf17736f53 100644
--- a/javascript/config/suites/javascript/maintainability-more
+++ b/javascript/config/suites/javascript/maintainability-more
@@ -2,6 +2,7 @@
+ semmlecode-javascript-queries/Comments/TodoComments.ql: /Maintainability/Comments
+ semmlecode-javascript-queries/Declarations/DeadStoreOfGlobal.ql: /Maintainability/Declarations
+ semmlecode-javascript-queries/Declarations/DeadStoreOfLocal.ql: /Maintainability/Declarations
++ semmlecode-javascript-queries/Declarations/DeadStoreOfProperty.ql: /Maintainability/Declarations
+ semmlecode-javascript-queries/Declarations/DuplicateVarDecl.ql: /Maintainability/Declarations
+ semmlecode-javascript-queries/Declarations/UnusedParameter.ql: /Maintainability/Declarations
+ semmlecode-javascript-queries/Declarations/UnusedVariable.ql: /Maintainability/Declarations
diff --git a/javascript/ql/src/Declarations/DeadStoreOfProperty.qhelp b/javascript/ql/src/Declarations/DeadStoreOfProperty.qhelp
new file mode 100644
index 00000000000..fa93ba07198
--- /dev/null
+++ b/javascript/ql/src/Declarations/DeadStoreOfProperty.qhelp
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
diff --git a/javascript/ql/src/Declarations/DeadStoreOfProperty.ql b/javascript/ql/src/Declarations/DeadStoreOfProperty.ql
new file mode 100644
index 00000000000..863ecb923b5
--- /dev/null
+++ b/javascript/ql/src/Declarations/DeadStoreOfProperty.ql
@@ -0,0 +1,138 @@
+/**
+ * @name Useless assignment to property
+ * @description An assignment to a property whose value is always overwritten, has no effect.
+ * @kind problem
+ * @problem.severity warning
+ * @id js/useless-assignment-to-property
+ * @tags maintainability
+ * @precision high
+ */
+
+import javascript
+import Expressions.DOMProperties
+import DeadStore
+
+/**
+ * Holds if `assign` definitely assigns property `name` of `base`.
+ */
+predicate unambigiousPropWrite(DataFlow::SourceNode base, string name, Assignment assign) {
+ exists(DataFlow::PropWrite lhs |
+ assign.getLhs().flow() = lhs and
+ base.getAPropertyWrite(name) = lhs and
+ not exists (DataFlow::SourceNode otherBase |
+ not otherBase = base and
+ lhs = otherBase.getAPropertyWrite(name)
+ )
+ )
+}
+
+/**
+ * Holds if `assign1` and `assign2` both assign property `name` of the same object, and `assign2` post-dominates `assign1`.
+ */
+predicate postDominatedPropWrite(string name, Assignment assign1, Assignment assign2) {
+ exists (DataFlow::SourceNode base, ReachableBasicBlock block1, ReachableBasicBlock block2 |
+ block1 = assign1.getBasicBlock() and
+ block2 = assign2.getBasicBlock() and
+ unambigiousPropWrite(base, name, assign1) and
+ unambigiousPropWrite(base, name, assign2) and
+ block2.postDominates(block1) and
+ (block1 = block2 implies
+ exists (int i1, int i2 |
+ assign1 = block1.getNode(i1) and
+ assign2 = block2.getNode(i2) and
+ i1 < i2
+ )
+ )
+ )
+}
+
+/**
+ * Holds if `e` may access a property named `name`.
+ */
+bindingset[name]
+predicate maybeAccessesProperty(Expr e, string name) {
+ (e.(PropAccess).getPropertyName() = name and e instanceof RValue) or
+ // conservatively reject all side-effects
+ e.isImpure()
+}
+
+/**
+ * Holds if `assign1` and `assign2` both assign property `name`, but `assign1` is dead because of `assign2`.
+ */
+predicate isDeadAssignment(string name, Assignment assign1, Assignment assign2) {
+ postDominatedPropWrite(name, assign1, assign2) and
+ maybeHasPropAccessBetween(name, assign1, assign2) and
+ not isDOMProperty(name)
+}
+
+/**
+ * Holds if `assign` assigns a property `name` that may be accessed somewhere else in the same block,
+ * `after` indicates if the if the access happens before or after the node for `assign`.
+ */
+bindingset[name]
+predicate maybeAccessesAssignedPropInBlock(string name, Assignment assign, boolean after) {
+ exists (ReachableBasicBlock block, int i, int j, Expr e |
+ block = assign.getBasicBlock() and
+ assign = block.getNode(i) and
+ e = block.getNode(j) and
+ maybeAccessesProperty(e, name) |
+ after = true and i < j
+ or
+ after = false and j < i
+ )
+}
+
+/**
+ * Holds if `assign1` and `assign2` both assign property `name`, and the assigned property may be accessed between the two assignments.
+ */
+bindingset[name]
+predicate maybeHasPropAccessBetween(string name, Assignment assign1, Assignment assign2) {
+ exists (ReachableBasicBlock block1, ReachableBasicBlock block2 |
+ assign1.getBasicBlock() = block1 and
+ assign2.getBasicBlock() = block2 and
+ if block1 = block2 then
+ // same block: check for read between
+ not exists (int i1, int iMid, Expr mid, int i2 |
+ assign1 = block1.getNode(i1) and
+ assign2 = block2.getNode(i2) and
+ i1 < iMid and iMid < i2 and
+ mid = block1.getNode(iMid) and
+ maybeAccessesProperty(mid, name)
+ )
+ else
+ // other block:
+ not (
+ // check for read after in start block
+ maybeAccessesAssignedPropInBlock(name, assign1, true) or
+ // check for read after in other block
+ exists (ReachableBasicBlock mid |
+ block1.getASuccessor+() = mid and
+ mid.getASuccessor+() = block2 |
+ maybeAccessesProperty(mid.getANode(), name)
+ ) or
+ // check for read before in end block
+ maybeAccessesAssignedPropInBlock(name, assign2, false)
+ )
+ )
+}
+
+from string name, Assignment assign1, Assignment assign2
+where isDeadAssignment(name, assign1, assign2) and
+ // whitelist
+ not (
+ // Google Closure Compiler pattern: `o.p = o['p'] = v`
+ exists (PropAccess p1, PropAccess p2 |
+ p1 = assign1.getLhs() and
+ p2 = assign2.getLhs() |
+ p1 instanceof DotExpr and p2 instanceof IndexExpr
+ or
+ p2 instanceof DotExpr and p1 instanceof IndexExpr
+ )
+ or
+ // don't flag overwrites for default values
+ isDefaultInit(assign1.getRhs().getUnderlyingValue())
+ or
+ // don't flag assignments in externs
+ assign1.inExternsFile()
+ )
+select assign1, "This write to property '" + name + "' is useless, since $@ always overrides it.", assign2, "another property write"
diff --git a/javascript/ql/test/query-tests/Declarations/DeadStoreOfProperty/DeadStoreOfProperty.expected b/javascript/ql/test/query-tests/Declarations/DeadStoreOfProperty/DeadStoreOfProperty.expected
new file mode 100644
index 00000000000..75d85508e5c
--- /dev/null
+++ b/javascript/ql/test/query-tests/Declarations/DeadStoreOfProperty/DeadStoreOfProperty.expected
@@ -0,0 +1,13 @@
+| real-world-examples.js:5:4:5:11 | o.p = 42 | This write to property 'p' is useless, since $@ always overrides it. | real-world-examples.js:10:2:10:9 | o.p = 42 | another property write |
+| real-world-examples.js:15:9:15:18 | o.p1 += 42 | This write to property 'p1' is useless, since $@ always overrides it. | real-world-examples.js:15:2:15:18 | o.p1 = o.p1 += 42 | another property write |
+| real-world-examples.js:16:11:16:20 | o.p2 *= 42 | This write to property 'p2' is useless, since $@ always overrides it. | real-world-examples.js:16:2:16:21 | o.p2 -= (o.p2 *= 42) | another property write |
+| real-world-examples.js:29:5:29:12 | o.p = 42 | This write to property 'p' is useless, since $@ always overrides it. | real-world-examples.js:32:3:32:10 | o.p = 42 | another property write |
+| real-world-examples.js:38:15:38:24 | o.p = f3() | This write to property 'p' is useless, since $@ always overrides it. | real-world-examples.js:38:2:38:31 | o.p = f ... : f4() | another property write |
+| tst.js:3:5:3:16 | o.pure1 = 42 | This write to property 'pure1' is useless, since $@ always overrides it. | tst.js:4:5:4:16 | o.pure1 = 42 | another property write |
+| tst.js:6:5:6:16 | o.pure2 = 42 | This write to property 'pure2' is useless, since $@ always overrides it. | tst.js:7:5:7:16 | o.pure2 = 43 | another property write |
+| tst.js:13:5:13:16 | o.pure4 = 42 | This write to property 'pure4' is useless, since $@ always overrides it. | tst.js:15:5:15:16 | o.pure4 = 42 | another property write |
+| tst.js:20:5:20:17 | o.pure6 = f() | This write to property 'pure6' is useless, since $@ always overrides it. | tst.js:21:5:21:16 | o.pure6 = 42 | another property write |
+| tst.js:23:5:23:16 | o.pure7 = 42 | This write to property 'pure7' is useless, since $@ always overrides it. | tst.js:25:5:25:16 | o.pure7 = 42 | another property write |
+| tst.js:76:5:76:34 | o.pure1 ... te = 42 | This write to property 'pure16_simpleAliasWrite' is useless, since $@ always overrides it. | tst.js:77:5:77:36 | o16.pur ... te = 42 | another property write |
+| tst.js:95:5:95:17 | o.pure18 = 42 | This write to property 'pure18' is useless, since $@ always overrides it. | tst.js:96:5:96:17 | o.pure18 = 42 | another property write |
+| tst.js:96:5:96:17 | o.pure18 = 42 | This write to property 'pure18' is useless, since $@ always overrides it. | tst.js:97:5:97:17 | o.pure18 = 42 | another property write |
diff --git a/javascript/ql/test/query-tests/Declarations/DeadStoreOfProperty/DeadStoreOfProperty.qlref b/javascript/ql/test/query-tests/Declarations/DeadStoreOfProperty/DeadStoreOfProperty.qlref
new file mode 100644
index 00000000000..448709b9054
--- /dev/null
+++ b/javascript/ql/test/query-tests/Declarations/DeadStoreOfProperty/DeadStoreOfProperty.qlref
@@ -0,0 +1 @@
+Declarations/DeadStoreOfProperty.ql
\ No newline at end of file
diff --git a/javascript/ql/test/query-tests/Declarations/DeadStoreOfProperty/closure-compiler-tricks.js b/javascript/ql/test/query-tests/Declarations/DeadStoreOfProperty/closure-compiler-tricks.js
new file mode 100644
index 00000000000..8052fe206c3
--- /dev/null
+++ b/javascript/ql/test/query-tests/Declarations/DeadStoreOfProperty/closure-compiler-tricks.js
@@ -0,0 +1,12 @@
+(function(){
+ var o = {};
+ o.prop1 = o['prop1'] = x;
+
+ o['prop2'] = o.prop2 = x;
+
+ o.prop3 = x
+ o['prop3'] = x;
+
+ o['prop4'] = x;
+ o.prop4 = x
+});
diff --git a/javascript/ql/test/query-tests/Declarations/DeadStoreOfProperty/externs.js b/javascript/ql/test/query-tests/Declarations/DeadStoreOfProperty/externs.js
new file mode 100644
index 00000000000..a32e349e56d
--- /dev/null
+++ b/javascript/ql/test/query-tests/Declarations/DeadStoreOfProperty/externs.js
@@ -0,0 +1,43 @@
+// Adapted from the Google Closure externs; original copyright header included below.
+/*
+ * Copyright 2008 The Closure Compiler Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * @interface
+ */
+function EventTarget() {}
+
+/**
+ * @constructor
+ * @implements {EventTarget}
+ * @see http://www.w3.org/TR/1998/REC-DOM-Level-1-19981001/level-one-core.html#ID-1950641247
+ */
+function Node() {}
+
+/**
+ * @constructor
+ * @extends {Node}
+ * @see http://www.w3.org/TR/1998/REC-DOM-Level-1-19981001/level-one-core.html#ID-745549614
+ */
+function Element() {}
+
+/**
+ * @type {number}
+ * @see http://www.w3.org/TR/cssom-view/#dom-element-clienttop
+ */
+Element.prototype.clientTop;
+
+//semmle-extractor-options: --externs
diff --git a/javascript/ql/test/query-tests/Declarations/DeadStoreOfProperty/list-manipulation.js b/javascript/ql/test/query-tests/Declarations/DeadStoreOfProperty/list-manipulation.js
new file mode 100644
index 00000000000..60728af76e5
--- /dev/null
+++ b/javascript/ql/test/query-tests/Declarations/DeadStoreOfProperty/list-manipulation.js
@@ -0,0 +1,13 @@
+(function(){
+ var first = f();
+
+ function flush() {
+ var flushed = first;
+
+ var next = g();
+ first = next;
+ next.prev = 42;
+
+ flushed.prev = 42;
+ }
+});
diff --git a/javascript/ql/test/query-tests/Declarations/DeadStoreOfProperty/real-world-examples.js b/javascript/ql/test/query-tests/Declarations/DeadStoreOfProperty/real-world-examples.js
new file mode 100644
index 00000000000..ff84fa90220
--- /dev/null
+++ b/javascript/ql/test/query-tests/Declarations/DeadStoreOfProperty/real-world-examples.js
@@ -0,0 +1,39 @@
+(function(){
+ var o = f1();
+ while (f2()) {
+ if (f4()) {
+ o.p = 42;
+ break;
+ }
+ f5();
+ }
+ o.p = 42;
+});
+
+(function(){
+ var o = f1();
+ o.p1 = o.p1 += 42;
+ o.p2 -= (o.p2 *= 42);
+});
+
+(function(){
+ var o = f1();
+ o.m(function () {
+ if (f2()) {
+
+ } else {
+ try {
+ f3();
+ } catch (e) {
+ f4();
+ o.p = 42;
+ }
+ }
+ o.p = 42;
+ });
+});
+
+(function(){
+ var o = f1();
+ o.p = f2() ? o.p = f3() : f4();
+});
diff --git a/javascript/ql/test/query-tests/Declarations/DeadStoreOfProperty/tst.js b/javascript/ql/test/query-tests/Declarations/DeadStoreOfProperty/tst.js
new file mode 100644
index 00000000000..9c0bcb19561
--- /dev/null
+++ b/javascript/ql/test/query-tests/Declarations/DeadStoreOfProperty/tst.js
@@ -0,0 +1,98 @@
+(function(){
+ var o = {};
+ o.pure1 = 42;
+ o.pure1 = 42;
+
+ o.pure2 = 42;
+ o.pure2 = 43;
+
+ o.impure3 = 42;
+ f();
+ o.impure3 = 42;
+
+ o.pure4 = 42;
+ 43;
+ o.pure4 = 42;
+
+ o.impure5 = 42;
+ o.impure5 = f();
+
+ o.pure6 = f();
+ o.pure6 = 42;
+
+ o.pure7 = 42;
+ if(x){}
+ o.pure7 = 42;
+
+ o.pure8_cond = 42;
+ if(x){
+ o.pure8_cond = 42;
+ }
+
+ o.impure9 = 42;
+ f();
+ if(x){
+ }
+ o.impure9 = 42;
+
+ o.impure10 = 42;
+ if(x){
+ f();
+ }
+ o.impure10 = 42;
+
+ o.impure11 = 42;
+ if(x){
+
+ }
+ f();
+ o.impure11 = 42;
+
+ o.pure12_read = 42;
+ o.pure12_read;
+ o.pure12_read = 42;
+
+ var o2;
+ o.pure13_otherRead = 42;
+ o2.pure13_otherRead;
+ o.pure13_otherRead = 42;
+
+ function id14(e) {
+ return e;
+ }
+ var o14 = id14(o);
+ o.pure14_aliasRead = 42;
+ o14.pure14_aliasRead;
+ o.pure14_aliasRead = 42;
+
+ function id15(e) {
+ return e;
+ }
+ var o15 = id15(o);
+ o.pure15_aliasWrite = 42;
+ o15.pure15_aliasWrite = 42;
+
+ var o16 = x? o: null;
+ o.pure16_simpleAliasWrite = 42;
+ o16.pure16_simpleAliasWrite = 42;
+
+ var o17 = {
+ duplicate17: 42,
+ duplicate17: 42
+ }
+
+ // DOM
+ o.clientTop = 42;
+ o.clientTop = 42;
+
+ o.defaulted1 = null;
+ o.defaulted1 = 42;
+
+ o.defaulted2 = -1;
+ o.defaulted2 = 42;
+
+ var o = {};
+ o.pure18 = 42;
+ o.pure18 = 42;
+ o.pure18 = 42;
+});
From e82f5157c68676af001ed4903b438588833d7739 Mon Sep 17 00:00:00 2001
From: Esben Sparre Andreasen
Date: Tue, 16 Oct 2018 11:45:25 +0200
Subject: [PATCH 23/71] JS: change note for js/useless-assignment-to-property
---
change-notes/1.19/analysis-javascript.md | 1 +
1 file changed, 1 insertion(+)
diff --git a/change-notes/1.19/analysis-javascript.md b/change-notes/1.19/analysis-javascript.md
index d92f9c7db6f..79b786e55fe 100644
--- a/change-notes/1.19/analysis-javascript.md
+++ b/change-notes/1.19/analysis-javascript.md
@@ -23,6 +23,7 @@
| Replacement of a substring with itself (`js/identity-replacement`) | correctness, security, external/cwe/cwe-116 | Highlights string replacements that replace a string with itself, which usually indicates a mistake. Results shown on LGTM by default. |
| Stored cross-site scripting (`js/stored-xss`) | security, external/cwe/cwe-079, external/cwe/cwe-116 | Highlights uncontrolled stored values flowing into HTML content, indicating a violation of [CWE-079](https://cwe.mitre.org/data/definitions/79.html). Results shown on LGTM by default. |
| Unclear precedence of nested operators (`js/unclear-operator-precedence`) | maintainability, correctness, external/cwe/cwe-783 | Highlights nested binary operators whose relative precedence is easy to misunderstand. Results shown on LGTM by default. |
+| Useless assignment to property | maintainability | Highlights property assignments whose value is always overwritten. Results are shown on LGTM by default. |
| User-controlled data in file | security, external/cwe/cwe-912 | Highlights locations where user-controlled data is written to a file. Results are not shown on LGTM by default. |
## Changes to existing queries
From 1389009388be9db085151de3e22b16dc5bf89285 Mon Sep 17 00:00:00 2001
From: Esben Sparre Andreasen
Date: Tue, 6 Nov 2018 08:22:56 +0100
Subject: [PATCH 24/71] JS: naming and doc cleanups
---
.../ql/src/Declarations/DeadStore.qhelp | 2 +-
.../src/Declarations/DeadStoreOfProperty.ql | 22 +++++++++----------
2 files changed, 12 insertions(+), 12 deletions(-)
diff --git a/javascript/ql/src/Declarations/DeadStore.qhelp b/javascript/ql/src/Declarations/DeadStore.qhelp
index 58f60fe42a8..4f6591a657f 100644
--- a/javascript/ql/src/Declarations/DeadStore.qhelp
+++ b/javascript/ql/src/Declarations/DeadStore.qhelp
@@ -4,7 +4,7 @@
-A value is assigned to a location, but either that location is never read
+A value is assigned to a variable or property, but either that location is never read
later on, or its value is always overwritten before being read. This means
that the original assignment has no effect, and could indicate a logic error or
incomplete code.
diff --git a/javascript/ql/src/Declarations/DeadStoreOfProperty.ql b/javascript/ql/src/Declarations/DeadStoreOfProperty.ql
index 863ecb923b5..fec1e7fb352 100644
--- a/javascript/ql/src/Declarations/DeadStoreOfProperty.ql
+++ b/javascript/ql/src/Declarations/DeadStoreOfProperty.ql
@@ -1,6 +1,6 @@
/**
* @name Useless assignment to property
- * @description An assignment to a property whose value is always overwritten, has no effect.
+ * @description An assignment to a property whose value is always overwritten has no effect.
* @kind problem
* @problem.severity warning
* @id js/useless-assignment-to-property
@@ -15,7 +15,7 @@ import DeadStore
/**
* Holds if `assign` definitely assigns property `name` of `base`.
*/
-predicate unambigiousPropWrite(DataFlow::SourceNode base, string name, Assignment assign) {
+predicate unambiguousPropWrite(DataFlow::SourceNode base, string name, Assignment assign) {
exists(DataFlow::PropWrite lhs |
assign.getLhs().flow() = lhs and
base.getAPropertyWrite(name) = lhs and
@@ -33,8 +33,8 @@ predicate postDominatedPropWrite(string name, Assignment assign1, Assignment ass
exists (DataFlow::SourceNode base, ReachableBasicBlock block1, ReachableBasicBlock block2 |
block1 = assign1.getBasicBlock() and
block2 = assign2.getBasicBlock() and
- unambigiousPropWrite(base, name, assign1) and
- unambigiousPropWrite(base, name, assign2) and
+ unambiguousPropWrite(base, name, assign1) and
+ unambiguousPropWrite(base, name, assign2) and
block2.postDominates(block1) and
(block1 = block2 implies
exists (int i1, int i2 |
@@ -61,13 +61,13 @@ predicate maybeAccessesProperty(Expr e, string name) {
*/
predicate isDeadAssignment(string name, Assignment assign1, Assignment assign2) {
postDominatedPropWrite(name, assign1, assign2) and
- maybeHasPropAccessBetween(name, assign1, assign2) and
+ noPropAccessBetween(name, assign1, assign2) and
not isDOMProperty(name)
}
/**
* Holds if `assign` assigns a property `name` that may be accessed somewhere else in the same block,
- * `after` indicates if the if the access happens before or after the node for `assign`.
+ * `after` indicates if the access happens before or after the node for `assign`.
*/
bindingset[name]
predicate maybeAccessesAssignedPropInBlock(string name, Assignment assign, boolean after) {
@@ -86,12 +86,12 @@ predicate maybeAccessesAssignedPropInBlock(string name, Assignment assign, boole
* Holds if `assign1` and `assign2` both assign property `name`, and the assigned property may be accessed between the two assignments.
*/
bindingset[name]
-predicate maybeHasPropAccessBetween(string name, Assignment assign1, Assignment assign2) {
+predicate noPropAccessBetween(string name, Assignment assign1, Assignment assign2) {
exists (ReachableBasicBlock block1, ReachableBasicBlock block2 |
assign1.getBasicBlock() = block1 and
assign2.getBasicBlock() = block2 and
if block1 = block2 then
- // same block: check for read between
+ // same block: check for access between
not exists (int i1, int iMid, Expr mid, int i2 |
assign1 = block1.getNode(i1) and
assign2 = block2.getNode(i2) and
@@ -102,15 +102,15 @@ predicate maybeHasPropAccessBetween(string name, Assignment assign1, Assignment
else
// other block:
not (
- // check for read after in start block
+ // check for an access after the first write node
maybeAccessesAssignedPropInBlock(name, assign1, true) or
- // check for read after in other block
+ // check for an access between the two write blocks
exists (ReachableBasicBlock mid |
block1.getASuccessor+() = mid and
mid.getASuccessor+() = block2 |
maybeAccessesProperty(mid.getANode(), name)
) or
- // check for read before in end block
+ // check for an access before the second write node
maybeAccessesAssignedPropInBlock(name, assign2, false)
)
)
From 470c241c823a6da43b09203005f6d92eab41e635 Mon Sep 17 00:00:00 2001
From: Esben Sparre Andreasen
Date: Tue, 6 Nov 2018 08:33:27 +0100
Subject: [PATCH 25/71] JS: use range instead of ad hoc LT/GT
---
javascript/ql/src/Declarations/DeadStoreOfProperty.ql | 5 ++---
1 file changed, 2 insertions(+), 3 deletions(-)
diff --git a/javascript/ql/src/Declarations/DeadStoreOfProperty.ql b/javascript/ql/src/Declarations/DeadStoreOfProperty.ql
index fec1e7fb352..7032a42e3af 100644
--- a/javascript/ql/src/Declarations/DeadStoreOfProperty.ql
+++ b/javascript/ql/src/Declarations/DeadStoreOfProperty.ql
@@ -92,11 +92,10 @@ predicate noPropAccessBetween(string name, Assignment assign1, Assignment assign
assign2.getBasicBlock() = block2 and
if block1 = block2 then
// same block: check for access between
- not exists (int i1, int iMid, Expr mid, int i2 |
+ not exists (int i1, Expr mid, int i2 |
assign1 = block1.getNode(i1) and
assign2 = block2.getNode(i2) and
- i1 < iMid and iMid < i2 and
- mid = block1.getNode(iMid) and
+ mid = block1.getNode([i1+1..i2-1]) and
maybeAccessesProperty(mid, name)
)
else
From d813a7cad29c9e1f442d221987cf25e32721682f Mon Sep 17 00:00:00 2001
From: Esben Sparre Andreasen
Date: Tue, 6 Nov 2018 08:34:43 +0100
Subject: [PATCH 26/71] JS: push negation
---
javascript/ql/src/Declarations/DeadStoreOfProperty.ql | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/javascript/ql/src/Declarations/DeadStoreOfProperty.ql b/javascript/ql/src/Declarations/DeadStoreOfProperty.ql
index 7032a42e3af..9f73668d338 100644
--- a/javascript/ql/src/Declarations/DeadStoreOfProperty.ql
+++ b/javascript/ql/src/Declarations/DeadStoreOfProperty.ql
@@ -20,7 +20,7 @@ predicate unambiguousPropWrite(DataFlow::SourceNode base, string name, Assignmen
assign.getLhs().flow() = lhs and
base.getAPropertyWrite(name) = lhs and
not exists (DataFlow::SourceNode otherBase |
- not otherBase = base and
+ otherBase != base and
lhs = otherBase.getAPropertyWrite(name)
)
)
From b7f424df4182f755da664474ea88df28f23b2842 Mon Sep 17 00:00:00 2001
From: Esben Sparre Andreasen
Date: Tue, 6 Nov 2018 15:27:08 +0100
Subject: [PATCH 27/71] JS: introduce DataFlow::PropWrite::getWriteNode
---
.../semmle/javascript/dataflow/DataFlow.qll | 30 +++++++++++++++++++
1 file changed, 30 insertions(+)
diff --git a/javascript/ql/src/semmle/javascript/dataflow/DataFlow.qll b/javascript/ql/src/semmle/javascript/dataflow/DataFlow.qll
index ecf73bccde1..aee1e4e004f 100644
--- a/javascript/ql/src/semmle/javascript/dataflow/DataFlow.qll
+++ b/javascript/ql/src/semmle/javascript/dataflow/DataFlow.qll
@@ -456,6 +456,11 @@ module DataFlow {
prop = getPropertyName() and
rhs = getRhs()
}
+
+ /**
+ * Gets the node where the property write happens in the control flow graph.
+ */
+ abstract ControlFlowNode getWriteNode();
}
/**
@@ -481,6 +486,10 @@ module DataFlow {
override Node getRhs() {
result = valueNode(astNode.(LValue).getRhs())
}
+
+ override ControlFlowNode getWriteNode() {
+ result = astNode.(LValue).getDefNode()
+ }
}
/**
@@ -505,6 +514,10 @@ module DataFlow {
override Node getRhs() {
result = valueNode(prop.(ValueProperty).getInit())
}
+
+ override ControlFlowNode getWriteNode() {
+ result = prop
+ }
}
/**
@@ -534,6 +547,10 @@ module DataFlow {
propdesc.hasPropertyWrite("value", result)
)
}
+
+ override ControlFlowNode getWriteNode() {
+ result = odp.getAstNode()
+ }
}
/**
@@ -560,6 +577,10 @@ module DataFlow {
not prop instanceof AccessorMethodDefinition and
result = valueNode(prop.getInit())
}
+
+ override ControlFlowNode getWriteNode() {
+ result = prop
+ }
}
/**
@@ -584,6 +605,10 @@ module DataFlow {
override Node getRhs() {
result = valueNode(prop.getValue())
}
+
+ override ControlFlowNode getWriteNode() {
+ result = prop
+ }
}
/**
@@ -835,6 +860,11 @@ module DataFlow {
override Node getBase() {
result = valueNode(arr)
}
+
+ override ControlFlowNode getWriteNode() {
+ result = arr
+ }
+
}
/**
From ca215391b4f95673370d3a760fbbaf440209998d Mon Sep 17 00:00:00 2001
From: Esben Sparre Andreasen
Date: Tue, 6 Nov 2018 09:08:06 +0100
Subject: [PATCH 28/71] JS: substitute Assignment for DataFlow::PropWrite
---
.../src/Declarations/DeadStoreOfProperty.ql | 65 ++++++++++---------
1 file changed, 35 insertions(+), 30 deletions(-)
diff --git a/javascript/ql/src/Declarations/DeadStoreOfProperty.ql b/javascript/ql/src/Declarations/DeadStoreOfProperty.ql
index 9f73668d338..c9ebb02a543 100644
--- a/javascript/ql/src/Declarations/DeadStoreOfProperty.ql
+++ b/javascript/ql/src/Declarations/DeadStoreOfProperty.ql
@@ -15,31 +15,30 @@ import DeadStore
/**
* Holds if `assign` definitely assigns property `name` of `base`.
*/
-predicate unambiguousPropWrite(DataFlow::SourceNode base, string name, Assignment assign) {
- exists(DataFlow::PropWrite lhs |
- assign.getLhs().flow() = lhs and
- base.getAPropertyWrite(name) = lhs and
- not exists (DataFlow::SourceNode otherBase |
- otherBase != base and
- lhs = otherBase.getAPropertyWrite(name)
- )
+predicate unambiguousPropWrite(DataFlow::SourceNode base, string name, DataFlow::PropWrite write) {
+ write = base.getAPropertyWrite(name) and
+ not exists (DataFlow::SourceNode otherBase |
+ otherBase != base and
+ write = otherBase.getAPropertyWrite(name)
)
}
/**
* Holds if `assign1` and `assign2` both assign property `name` of the same object, and `assign2` post-dominates `assign1`.
*/
-predicate postDominatedPropWrite(string name, Assignment assign1, Assignment assign2) {
- exists (DataFlow::SourceNode base, ReachableBasicBlock block1, ReachableBasicBlock block2 |
- block1 = assign1.getBasicBlock() and
- block2 = assign2.getBasicBlock() and
+predicate postDominatedPropWrite(string name, DataFlow::PropWrite assign1, DataFlow::PropWrite assign2) {
+ exists (ControlFlowNode write1, ControlFlowNode write2, DataFlow::SourceNode base, ReachableBasicBlock block1, ReachableBasicBlock block2 |
+ write1 = assign1.getWriteNode() and
+ write2 = assign2.getWriteNode() and
+ block1 = write1.getBasicBlock() and
+ block2 = write2.getBasicBlock() and
unambiguousPropWrite(base, name, assign1) and
unambiguousPropWrite(base, name, assign2) and
block2.postDominates(block1) and
(block1 = block2 implies
exists (int i1, int i2 |
- assign1 = block1.getNode(i1) and
- assign2 = block2.getNode(i2) and
+ write1 = block1.getNode(i1) and
+ write2 = block2.getNode(i2) and
i1 < i2
)
)
@@ -59,7 +58,7 @@ predicate maybeAccessesProperty(Expr e, string name) {
/**
* Holds if `assign1` and `assign2` both assign property `name`, but `assign1` is dead because of `assign2`.
*/
-predicate isDeadAssignment(string name, Assignment assign1, Assignment assign2) {
+predicate isDeadAssignment(string name, DataFlow::PropWrite assign1, DataFlow::PropWrite assign2) {
postDominatedPropWrite(name, assign1, assign2) and
noPropAccessBetween(name, assign1, assign2) and
not isDOMProperty(name)
@@ -70,10 +69,11 @@ predicate isDeadAssignment(string name, Assignment assign1, Assignment assign2)
* `after` indicates if the access happens before or after the node for `assign`.
*/
bindingset[name]
-predicate maybeAccessesAssignedPropInBlock(string name, Assignment assign, boolean after) {
- exists (ReachableBasicBlock block, int i, int j, Expr e |
+predicate maybeAccessesAssignedPropInBlock(string name, DataFlow::PropWrite assign, boolean after) {
+ exists (ControlFlowNode write, ReachableBasicBlock block, int i, int j, Expr e |
+ write = assign.getWriteNode() and
block = assign.getBasicBlock() and
- assign = block.getNode(i) and
+ write = block.getNode(i) and
e = block.getNode(j) and
maybeAccessesProperty(e, name) |
after = true and i < j
@@ -86,15 +86,17 @@ predicate maybeAccessesAssignedPropInBlock(string name, Assignment assign, boole
* Holds if `assign1` and `assign2` both assign property `name`, and the assigned property may be accessed between the two assignments.
*/
bindingset[name]
-predicate noPropAccessBetween(string name, Assignment assign1, Assignment assign2) {
- exists (ReachableBasicBlock block1, ReachableBasicBlock block2 |
- assign1.getBasicBlock() = block1 and
- assign2.getBasicBlock() = block2 and
+predicate noPropAccessBetween(string name, DataFlow::PropWrite assign1, DataFlow::PropWrite assign2) {
+ exists (ControlFlowNode write1, ControlFlowNode write2, ReachableBasicBlock block1, ReachableBasicBlock block2 |
+ write1 = assign1.getWriteNode() and
+ write2 = assign2.getWriteNode() and
+ write1.getBasicBlock() = block1 and
+ write2.getBasicBlock() = block2 and
if block1 = block2 then
// same block: check for access between
not exists (int i1, Expr mid, int i2 |
- assign1 = block1.getNode(i1) and
- assign2 = block2.getNode(i2) and
+ assign1.getWriteNode() = block1.getNode(i1) and
+ assign2.getWriteNode() = block2.getNode(i2) and
mid = block1.getNode([i1+1..i2-1]) and
maybeAccessesProperty(mid, name)
)
@@ -115,23 +117,26 @@ predicate noPropAccessBetween(string name, Assignment assign1, Assignment assign
)
}
-from string name, Assignment assign1, Assignment assign2
+from string name, DataFlow::PropWrite assign1, DataFlow::PropWrite assign2
where isDeadAssignment(name, assign1, assign2) and
// whitelist
not (
// Google Closure Compiler pattern: `o.p = o['p'] = v`
exists (PropAccess p1, PropAccess p2 |
- p1 = assign1.getLhs() and
- p2 = assign2.getLhs() |
+ p1 = assign1.getAstNode() and
+ p2 = assign2.getAstNode() |
p1 instanceof DotExpr and p2 instanceof IndexExpr
or
p2 instanceof DotExpr and p1 instanceof IndexExpr
)
or
// don't flag overwrites for default values
- isDefaultInit(assign1.getRhs().getUnderlyingValue())
+ isDefaultInit(assign1.getRhs().asExpr().getUnderlyingValue())
or
// don't flag assignments in externs
- assign1.inExternsFile()
+ assign1.getAstNode().inExternsFile()
+ or
+ // exclude result from js/overwritten-property
+ assign2.getBase() instanceof DataFlow::ObjectLiteralNode
)
-select assign1, "This write to property '" + name + "' is useless, since $@ always overrides it.", assign2, "another property write"
+select assign1.getWriteNode(), "This write to property '" + name + "' is useless, since $@ always overrides it.", assign2.getWriteNode(), "another property write"
From bd2fc33621b8a407d580750916b7d633dba64cb3 Mon Sep 17 00:00:00 2001
From: Esben Sparre Andreasen
Date: Tue, 6 Nov 2018 15:46:33 +0100
Subject: [PATCH 29/71] JS: annotate tests with expectations
---
.../DeadStoreOfProperty/real-world-examples.js | 10 +++++-----
.../Declarations/DeadStoreOfProperty/tst.js | 16 ++++++++--------
2 files changed, 13 insertions(+), 13 deletions(-)
diff --git a/javascript/ql/test/query-tests/Declarations/DeadStoreOfProperty/real-world-examples.js b/javascript/ql/test/query-tests/Declarations/DeadStoreOfProperty/real-world-examples.js
index ff84fa90220..282f6bc7f4a 100644
--- a/javascript/ql/test/query-tests/Declarations/DeadStoreOfProperty/real-world-examples.js
+++ b/javascript/ql/test/query-tests/Declarations/DeadStoreOfProperty/real-world-examples.js
@@ -2,7 +2,7 @@
var o = f1();
while (f2()) {
if (f4()) {
- o.p = 42;
+ o.p = 42; // NOT OK
break;
}
f5();
@@ -12,8 +12,8 @@
(function(){
var o = f1();
- o.p1 = o.p1 += 42;
- o.p2 -= (o.p2 *= 42);
+ o.p1 = o.p1 += 42; // NOT OK
+ o.p2 -= (o.p2 *= 42); // NOT OK
});
(function(){
@@ -26,7 +26,7 @@
f3();
} catch (e) {
f4();
- o.p = 42;
+ o.p = 42; // NOT OK
}
}
o.p = 42;
@@ -35,5 +35,5 @@
(function(){
var o = f1();
- o.p = f2() ? o.p = f3() : f4();
+ o.p = f2() ? o.p = f3() : f4(); // NOT OK
});
diff --git a/javascript/ql/test/query-tests/Declarations/DeadStoreOfProperty/tst.js b/javascript/ql/test/query-tests/Declarations/DeadStoreOfProperty/tst.js
index 9c0bcb19561..81cf4fcd210 100644
--- a/javascript/ql/test/query-tests/Declarations/DeadStoreOfProperty/tst.js
+++ b/javascript/ql/test/query-tests/Declarations/DeadStoreOfProperty/tst.js
@@ -1,26 +1,26 @@
(function(){
var o = {};
- o.pure1 = 42;
+ o.pure1 = 42; // NOT OK
o.pure1 = 42;
- o.pure2 = 42;
+ o.pure2 = 42; // NOT OK
o.pure2 = 43;
o.impure3 = 42;
f();
o.impure3 = 42;
- o.pure4 = 42;
+ o.pure4 = 42; // NOT OK
43;
o.pure4 = 42;
o.impure5 = 42;
o.impure5 = f();
- o.pure6 = f();
+ o.pure6 = f(); // NOT OK
o.pure6 = 42;
- o.pure7 = 42;
+ o.pure7 = 42; // NOT OK
if(x){}
o.pure7 = 42;
@@ -73,7 +73,7 @@
o15.pure15_aliasWrite = 42;
var o16 = x? o: null;
- o.pure16_simpleAliasWrite = 42;
+ o.pure16_simpleAliasWrite = 42; // NOT OK
o16.pure16_simpleAliasWrite = 42;
var o17 = {
@@ -92,7 +92,7 @@
o.defaulted2 = 42;
var o = {};
- o.pure18 = 42;
- o.pure18 = 42;
+ o.pure18 = 42; // NOT OK
+ o.pure18 = 42; // NOT OK
o.pure18 = 42;
});
From 0d9e2098f28be23452f83186fc9030cad898d3ed Mon Sep 17 00:00:00 2001
From: Robert Marsh
Date: Thu, 8 Nov 2018 11:38:34 -0800
Subject: [PATCH 30/71] C++: test for bounded bounds in sign analysis
---
.../rangeanalysis/signanalysis/SignAnalysis.expected | 5 +++++
.../rangeanalysis/signanalysis/bounded_bounds.c | 9 +++++++++
2 files changed, 14 insertions(+)
create mode 100644 cpp/ql/test/library-tests/rangeanalysis/signanalysis/bounded_bounds.c
diff --git a/cpp/ql/test/library-tests/rangeanalysis/signanalysis/SignAnalysis.expected b/cpp/ql/test/library-tests/rangeanalysis/signanalysis/SignAnalysis.expected
index cea2920afef..bde549f3aa6 100644
--- a/cpp/ql/test/library-tests/rangeanalysis/signanalysis/SignAnalysis.expected
+++ b/cpp/ql/test/library-tests/rangeanalysis/signanalysis/SignAnalysis.expected
@@ -5,6 +5,11 @@
| binary_logical_operator.c:2:11:2:25 | Store: ... && ... | positive strictlyPositive |
| binary_logical_operator.c:2:15:2:16 | Constant: 10 | positive strictlyPositive |
| binary_logical_operator.c:3:7:3:7 | Load: b | positive |
+| bounded_bounds.c:3:12:3:12 | Load: x | negative strictlyNegative |
+| bounded_bounds.c:3:12:3:12 | Store: x | negative strictlyNegative |
+| bounded_bounds.c:5:7:5:7 | Load: x | positive |
+| bounded_bounds.c:6:11:6:11 | Load: y | positive strictlyPositive |
+| bounded_bounds.c:6:11:6:11 | Store: y | positive strictlyPositive |
| inline_assembly.c:9:23:9:23 | Uninitialized: definition of y | positive |
| inline_assembly.c:10:3:10:7 | Store: ... = ... | positive strictlyPositive |
| inline_assembly.c:10:7:10:7 | Constant: (unsigned int)... | positive strictlyPositive |
diff --git a/cpp/ql/test/library-tests/rangeanalysis/signanalysis/bounded_bounds.c b/cpp/ql/test/library-tests/rangeanalysis/signanalysis/bounded_bounds.c
new file mode 100644
index 00000000000..7c4f7f70b34
--- /dev/null
+++ b/cpp/ql/test/library-tests/rangeanalysis/signanalysis/bounded_bounds.c
@@ -0,0 +1,9 @@
+int f(int x, int y) {
+ if (x < 0) {
+ return x;
+ }
+ if (x < y) {
+ return y; // y is strictly positive because of the bound on x above
+ }
+ return 0;
+}
From 72bb7c9c42d4335ce3154c7fc1a8d342f30a9633 Mon Sep 17 00:00:00 2001
From: Robert Marsh
Date: Thu, 8 Nov 2018 11:39:47 -0800
Subject: [PATCH 31/71] C++: remove double backtick in qldoc
---
cpp/ql/src/semmle/code/cpp/rangeanalysis/SignAnalysis.qll | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/cpp/ql/src/semmle/code/cpp/rangeanalysis/SignAnalysis.qll b/cpp/ql/src/semmle/code/cpp/rangeanalysis/SignAnalysis.qll
index 1981d127bc3..4e6aa40fcf7 100644
--- a/cpp/ql/src/semmle/code/cpp/rangeanalysis/SignAnalysis.qll
+++ b/cpp/ql/src/semmle/code/cpp/rangeanalysis/SignAnalysis.qll
@@ -207,7 +207,7 @@ private predicate unknownSign(Instruction i) {
}
/**
- * Holds if `lowerbound` is a lower bound for `bounded``. This is restricted
+ * Holds if `lowerbound` is a lower bound for `bounded`. This is restricted
* to only include bounds for which we might determine a sign.
*/
private predicate lowerBound(IRGuardCondition comp, Operand lowerbound, Operand bounded, boolean isStrict) {
From 4fdc992cd931bcb7837cef493ea41b6e8ff17c6f Mon Sep 17 00:00:00 2001
From: Robert Marsh
Date: Thu, 8 Nov 2018 14:43:51 -0800
Subject: [PATCH 32/71] C++: IRGuards uses Operand; fix CP in SignAnalysis
---
.../semmle/code/cpp/controlflow/IRGuards.qll | 92 +++++++++----------
.../code/cpp/rangeanalysis/SignAnalysis.qll | 18 ++--
.../controlflow/guards-ir/tests.ql | 27 +++---
.../signanalysis/bounded_bounds.c | 10 ++
4 files changed, 80 insertions(+), 67 deletions(-)
diff --git a/cpp/ql/src/semmle/code/cpp/controlflow/IRGuards.qll b/cpp/ql/src/semmle/code/cpp/controlflow/IRGuards.qll
index 55d5d4d8a84..fddea8c6d92 100644
--- a/cpp/ql/src/semmle/code/cpp/controlflow/IRGuards.qll
+++ b/cpp/ql/src/semmle/code/cpp/controlflow/IRGuards.qll
@@ -171,7 +171,7 @@ private class GuardConditionFromIR extends GuardCondition {
exists(Instruction li, Instruction ri |
li.getUnconvertedResultExpression() = left and
ri.getUnconvertedResultExpression() = right and
- ir.comparesLt(li, ri, k, isLessThan, testIsTrue)
+ ir.comparesLt(li.getAUse(), ri.getAUse(), k, isLessThan, testIsTrue)
)
}
@@ -181,7 +181,7 @@ private class GuardConditionFromIR extends GuardCondition {
exists(Instruction li, Instruction ri, boolean testIsTrue |
li.getUnconvertedResultExpression() = left and
ri.getUnconvertedResultExpression() = right and
- ir.comparesLt(li, ri, k, isLessThan, testIsTrue) and
+ ir.comparesLt(li.getAUse(), ri.getAUse(), k, isLessThan, testIsTrue) and
this.controls(block, testIsTrue)
)
}
@@ -191,7 +191,7 @@ private class GuardConditionFromIR extends GuardCondition {
exists(Instruction li, Instruction ri |
li.getUnconvertedResultExpression() = left and
ri.getUnconvertedResultExpression() = right and
- ir.comparesEq(li, ri, k, areEqual, testIsTrue)
+ ir.comparesEq(li.getAUse(), ri.getAUse(), k, areEqual, testIsTrue)
)
}
@@ -201,8 +201,8 @@ private class GuardConditionFromIR extends GuardCondition {
exists(Instruction li, Instruction ri, boolean testIsTrue |
li.getUnconvertedResultExpression() = left and
ri.getUnconvertedResultExpression() = right and
- ir.comparesEq(li, ri, k, areEqual, testIsTrue)
- and this.controls(block, testIsTrue)
+ ir.comparesEq(li.getAUse(), ri.getAUse(), k, areEqual, testIsTrue) and
+ this.controls(block, testIsTrue)
)
}
@@ -269,26 +269,26 @@ class IRGuardCondition extends Instruction {
}
/** Holds if (determined by this guard) `left < right + k` evaluates to `isLessThan` if this expression evaluates to `testIsTrue`. */
- cached predicate comparesLt(Instruction left, Instruction right, int k, boolean isLessThan, boolean testIsTrue) {
+ cached predicate comparesLt(Operand left, Operand right, int k, boolean isLessThan, boolean testIsTrue) {
compares_lt(this, left, right, k, isLessThan, testIsTrue)
}
/** Holds if (determined by this guard) `left < right + k` must be `isLessThan` in `block`.
If `isLessThan = false` then this implies `left >= right + k`. */
- cached predicate ensuresLt(Instruction left, Instruction right, int k, IRBlock block, boolean isLessThan) {
+ cached predicate ensuresLt(Operand left, Operand right, int k, IRBlock block, boolean isLessThan) {
exists(boolean testIsTrue |
compares_lt(this, left, right, k, isLessThan, testIsTrue) and this.controls(block, testIsTrue)
)
}
/** Holds if (determined by this guard) `left == right + k` evaluates to `areEqual` if this expression evaluates to `testIsTrue`. */
- cached predicate comparesEq(Instruction left, Instruction right, int k, boolean areEqual, boolean testIsTrue) {
+ cached predicate comparesEq(Operand left, Operand right, int k, boolean areEqual, boolean testIsTrue) {
compares_eq(this, left, right, k, areEqual, testIsTrue)
}
/** Holds if (determined by this guard) `left == right + k` must be `areEqual` in `block`.
If `areEqual = false` then this implies `left != right + k`. */
- cached predicate ensuresEq(Instruction left, Instruction right, int k, IRBlock block, boolean areEqual) {
+ cached predicate ensuresEq(Operand left, Operand right, int k, IRBlock block, boolean areEqual) {
exists(boolean testIsTrue |
compares_eq(this, left, right, k, areEqual, testIsTrue) and this.controls(block, testIsTrue)
)
@@ -328,7 +328,7 @@ private predicate is_condition(Instruction guard) {
*
* Beware making mistaken logical implications here relating `areEqual` and `testIsTrue`.
*/
-private predicate compares_eq(Instruction test, Instruction left, Instruction right, int k, boolean areEqual, boolean testIsTrue) {
+private predicate compares_eq(Instruction test, Operand left, Operand right, int k, boolean areEqual, boolean testIsTrue) {
/* The simple case where the test *is* the comparison so areEqual = testIsTrue xor eq. */
exists(boolean eq | simple_comparison_eq(test, left, right, k, eq) |
areEqual = true and testIsTrue = eq or areEqual = false and testIsTrue = eq.booleanNot()
@@ -349,13 +349,13 @@ private predicate compares_eq(Instruction test, Instruction left, Instruction ri
}
/** Rearrange various simple comparisons into `left == right + k` form. */
-private predicate simple_comparison_eq(CompareInstruction cmp, Instruction left, Instruction right, int k, boolean areEqual) {
- left = cmp.getLeftOperand() and cmp instanceof CompareEQInstruction and right = cmp.getRightOperand() and k = 0 and areEqual = true
+private predicate simple_comparison_eq(CompareInstruction cmp, Operand left, Operand right, int k, boolean areEqual) {
+ left = cmp.getAnOperand().(LeftOperand) and cmp instanceof CompareEQInstruction and right = cmp.getAnOperand().(RightOperand) and k = 0 and areEqual = true
or
- left = cmp.getLeftOperand() and cmp instanceof CompareNEInstruction and right = cmp.getRightOperand() and k = 0 and areEqual = false
+ left = cmp.getAnOperand().(LeftOperand) and cmp instanceof CompareNEInstruction and right = cmp.getAnOperand().(RightOperand) and k = 0 and areEqual = false
}
-private predicate complex_eq(CompareInstruction cmp, Instruction left, Instruction right, int k, boolean areEqual, boolean testIsTrue) {
+private predicate complex_eq(CompareInstruction cmp, Operand left, Operand right, int k, boolean areEqual, boolean testIsTrue) {
sub_eq(cmp, left, right, k, areEqual, testIsTrue)
or
add_eq(cmp, left, right, k, areEqual, testIsTrue)
@@ -367,7 +367,7 @@ private predicate complex_eq(CompareInstruction cmp, Instruction left, Instructi
*/
/** Holds if `left < right + k` evaluates to `isLt` given that test is `testIsTrue`. */
-private predicate compares_lt(Instruction test, Instruction left, Instruction right, int k, boolean isLt, boolean testIsTrue) {
+private predicate compares_lt(Instruction test, Operand left, Operand right, int k, boolean isLt, boolean testIsTrue) {
/* In the simple case, the test is the comparison, so isLt = testIsTrue */
simple_comparison_lt(test, left, right, k) and isLt = true and testIsTrue = true
or
@@ -387,22 +387,22 @@ private predicate compares_lt(Instruction test, Instruction left, Instruction ri
}
/** `(a < b + k) => (b > a - k) => (b >= a + (1-k))` */
-private predicate compares_ge(Instruction test, Instruction left, Instruction right, int k, boolean isGe, boolean testIsTrue) {
+private predicate compares_ge(Instruction test, Operand left, Operand right, int k, boolean isGe, boolean testIsTrue) {
exists(int onemk | k = 1 - onemk | compares_lt(test, right, left, onemk, isGe, testIsTrue))
}
/** Rearrange various simple comparisons into `left < right + k` form. */
-private predicate simple_comparison_lt(CompareInstruction cmp, Instruction left, Instruction right, int k) {
- left = cmp.getLeftOperand() and cmp instanceof CompareLTInstruction and right = cmp.getRightOperand() and k = 0
+private predicate simple_comparison_lt(CompareInstruction cmp, Operand left, Operand right, int k) {
+ left = cmp.getAnOperand().(LeftOperand) and cmp instanceof CompareLTInstruction and right = cmp.getAnOperand().(RightOperand) and k = 0
or
- left = cmp.getLeftOperand() and cmp instanceof CompareLEInstruction and right = cmp.getRightOperand() and k = 1
+ left = cmp.getAnOperand().(LeftOperand) and cmp instanceof CompareLEInstruction and right = cmp.getAnOperand().(RightOperand) and k = 1
or
- right = cmp.getLeftOperand() and cmp instanceof CompareGTInstruction and left = cmp.getRightOperand() and k = 0
+ right = cmp.getAnOperand().(LeftOperand) and cmp instanceof CompareGTInstruction and left = cmp.getAnOperand().(RightOperand) and k = 0
or
- right = cmp.getLeftOperand() and cmp instanceof CompareGEInstruction and left = cmp.getRightOperand() and k = 1
+ right = cmp.getAnOperand().(LeftOperand) and cmp instanceof CompareGEInstruction and left = cmp.getAnOperand().(RightOperand) and k = 1
}
-private predicate complex_lt(CompareInstruction cmp, Instruction left, Instruction right, int k, boolean isLt, boolean testIsTrue) {
+private predicate complex_lt(CompareInstruction cmp, Operand left, Operand right, int k, boolean isLt, boolean testIsTrue) {
sub_lt(cmp, left, right, k, isLt, testIsTrue)
or
add_lt(cmp, left, right, k, isLt, testIsTrue)
@@ -411,33 +411,33 @@ private predicate complex_lt(CompareInstruction cmp, Instruction left, Instructi
/* left - x < right + c => left < right + (c+x)
left < (right - x) + c => left < right + (c-x) */
-private predicate sub_lt(CompareInstruction cmp, Instruction left, Instruction right, int k, boolean isLt, boolean testIsTrue) {
- exists(SubInstruction lhs, int c, int x | compares_lt(cmp, lhs, right, c, isLt, testIsTrue) and
- left = lhs.getLeftOperand() and x = int_value(lhs.getRightOperand())
+private predicate sub_lt(CompareInstruction cmp, Operand left, Operand right, int k, boolean isLt, boolean testIsTrue) {
+ exists(SubInstruction lhs, int c, int x | compares_lt(cmp, lhs.getAUse(), right, c, isLt, testIsTrue) and
+ left = lhs.getAnOperand().(LeftOperand) and x = int_value(lhs.getRightOperand())
and k = c + x
)
or
- exists(SubInstruction rhs, int c, int x | compares_lt(cmp, left, rhs, c, isLt, testIsTrue) and
- right = rhs.getLeftOperand() and x = int_value(rhs.getRightOperand())
+ exists(SubInstruction rhs, int c, int x | compares_lt(cmp, left, rhs.getAUse(), c, isLt, testIsTrue) and
+ right = rhs.getAnOperand().(LeftOperand) and x = int_value(rhs.getRightOperand())
and k = c - x
)
}
/* left + x < right + c => left < right + (c-x)
left < (right + x) + c => left < right + (c+x) */
-private predicate add_lt(CompareInstruction cmp, Instruction left, Instruction right, int k, boolean isLt, boolean testIsTrue) {
- exists(AddInstruction lhs, int c, int x | compares_lt(cmp, lhs, right, c, isLt, testIsTrue) and
- (left = lhs.getLeftOperand() and x = int_value(lhs.getRightOperand())
+private predicate add_lt(CompareInstruction cmp, Operand left, Operand right, int k, boolean isLt, boolean testIsTrue) {
+ exists(AddInstruction lhs, int c, int x | compares_lt(cmp, lhs.getAUse(), right, c, isLt, testIsTrue) and
+ (left = lhs.getAnOperand().(LeftOperand) and x = int_value(lhs.getRightOperand())
or
- left = lhs.getRightOperand() and x = int_value(lhs.getLeftOperand())
+ left = lhs.getAnOperand().(RightOperand) and x = int_value(lhs.getLeftOperand())
)
and k = c - x
)
or
- exists(AddInstruction rhs, int c, int x | compares_lt(cmp, left, rhs, c, isLt, testIsTrue) and
- (right = rhs.getLeftOperand() and x = int_value(rhs.getRightOperand())
+ exists(AddInstruction rhs, int c, int x | compares_lt(cmp, left, rhs.getAUse(), c, isLt, testIsTrue) and
+ (right = rhs.getAnOperand().(LeftOperand) and x = int_value(rhs.getRightOperand())
or
- right = rhs.getRightOperand() and x = int_value(rhs.getLeftOperand())
+ right = rhs.getAnOperand().(RightOperand) and x = int_value(rhs.getLeftOperand())
)
and k = c + x
)
@@ -446,14 +446,14 @@ private predicate add_lt(CompareInstruction cmp, Instruction left, Instruction r
/* left - x == right + c => left == right + (c+x)
left == (right - x) + c => left == right + (c-x) */
-private predicate sub_eq(CompareInstruction cmp, Instruction left, Instruction right, int k, boolean areEqual, boolean testIsTrue) {
- exists(SubInstruction lhs, int c, int x | compares_eq(cmp, lhs, right, c, areEqual, testIsTrue) and
- left = lhs.getLeftOperand() and x = int_value(lhs.getRightOperand())
+private predicate sub_eq(CompareInstruction cmp, Operand left, Operand right, int k, boolean areEqual, boolean testIsTrue) {
+ exists(SubInstruction lhs, int c, int x | compares_eq(cmp, lhs.getAUse(), right, c, areEqual, testIsTrue) and
+ left = lhs.getAnOperand().(LeftOperand) and x = int_value(lhs.getRightOperand())
and k = c + x
)
or
- exists(SubInstruction rhs, int c, int x | compares_eq(cmp, left, rhs, c, areEqual, testIsTrue) and
- right = rhs.getLeftOperand() and x = int_value(rhs.getRightOperand())
+ exists(SubInstruction rhs, int c, int x | compares_eq(cmp, left, rhs.getAUse(), c, areEqual, testIsTrue) and
+ right = rhs.getAnOperand().(LeftOperand) and x = int_value(rhs.getRightOperand())
and k = c - x
)
}
@@ -461,19 +461,19 @@ private predicate sub_eq(CompareInstruction cmp, Instruction left, Instruction r
/* left + x == right + c => left == right + (c-x)
left == (right + x) + c => left == right + (c+x) */
-private predicate add_eq(CompareInstruction cmp, Instruction left, Instruction right, int k, boolean areEqual, boolean testIsTrue) {
- exists(AddInstruction lhs, int c, int x | compares_eq(cmp, lhs, right, c, areEqual, testIsTrue) and
- (left = lhs.getLeftOperand() and x = int_value(lhs.getRightOperand())
+private predicate add_eq(CompareInstruction cmp, Operand left, Operand right, int k, boolean areEqual, boolean testIsTrue) {
+ exists(AddInstruction lhs, int c, int x | compares_eq(cmp, lhs.getAUse(), right, c, areEqual, testIsTrue) and
+ (left = lhs.getAnOperand().(LeftOperand) and x = int_value(lhs.getRightOperand())
or
- left = lhs.getRightOperand() and x = int_value(lhs.getLeftOperand())
+ left = lhs.getAnOperand().(RightOperand) and x = int_value(lhs.getLeftOperand())
)
and k = c - x
)
or
- exists(AddInstruction rhs, int c, int x | compares_eq(cmp, left, rhs, c, areEqual, testIsTrue) and
- (right = rhs.getLeftOperand() and x = int_value(rhs.getRightOperand())
+ exists(AddInstruction rhs, int c, int x | compares_eq(cmp, left, rhs.getAUse(), c, areEqual, testIsTrue) and
+ (right = rhs.getAnOperand().(LeftOperand) and x = int_value(rhs.getRightOperand())
or
- right = rhs.getRightOperand() and x = int_value(rhs.getLeftOperand())
+ right = rhs.getAnOperand().(RightOperand) and x = int_value(rhs.getLeftOperand())
)
and k = c + x
)
diff --git a/cpp/ql/src/semmle/code/cpp/rangeanalysis/SignAnalysis.qll b/cpp/ql/src/semmle/code/cpp/rangeanalysis/SignAnalysis.qll
index 4e6aa40fcf7..5e38b45602c 100644
--- a/cpp/ql/src/semmle/code/cpp/rangeanalysis/SignAnalysis.qll
+++ b/cpp/ql/src/semmle/code/cpp/rangeanalysis/SignAnalysis.qll
@@ -211,8 +211,8 @@ private predicate unknownSign(Instruction i) {
* to only include bounds for which we might determine a sign.
*/
private predicate lowerBound(IRGuardCondition comp, Operand lowerbound, Operand bounded, boolean isStrict) {
- exists(int adjustment, Instruction compared |
- valueNumber(bounded.getDefinitionInstruction()) = valueNumber(compared) and
+ exists(int adjustment, Operand compared |
+ valueNumber(bounded.getDefinitionInstruction()) = valueNumber(compared.getDefinitionInstruction()) and
(
isStrict = true and
adjustment = 0
@@ -220,7 +220,7 @@ private predicate lowerBound(IRGuardCondition comp, Operand lowerbound, Operand
isStrict = false and
adjustment = 1
) and
- comp.ensuresLt(lowerbound.getDefinitionInstruction(), compared, adjustment, bounded.getInstruction().getBlock(), true)
+ comp.ensuresLt(lowerbound, compared, adjustment, bounded.getInstruction().getBlock(), true)
)
}
@@ -230,8 +230,8 @@ private predicate lowerBound(IRGuardCondition comp, Operand lowerbound, Operand
* to only include bounds for which we might determine a sign.
*/
private predicate upperBound(IRGuardCondition comp, Operand upperbound, Operand bounded, boolean isStrict) {
- exists(int adjustment, Instruction compared |
- valueNumber(bounded.getDefinitionInstruction()) = valueNumber(compared) and
+ exists(int adjustment, Operand compared |
+ valueNumber(bounded.getDefinitionInstruction()) = valueNumber(compared.getDefinitionInstruction()) and
(
isStrict = true and
adjustment = 0
@@ -239,7 +239,7 @@ private predicate upperBound(IRGuardCondition comp, Operand upperbound, Operand
isStrict = false and
adjustment = 1
) and
- comp.ensuresLt(compared, upperbound.getDefinitionInstruction(), adjustment, bounded.getInstruction().getBlock(), true)
+ comp.ensuresLt(compared, upperbound, adjustment, bounded.getInstruction().getBlock(), true)
)
}
@@ -251,9 +251,9 @@ private predicate upperBound(IRGuardCondition comp, Operand upperbound, Operand
* - `isEq = false` : `bounded != eqbound`
*/
private predicate eqBound(IRGuardCondition guard, Operand eqbound, Operand bounded, boolean isEq) {
- exists(Instruction compared |
- valueNumber(bounded.getDefinitionInstruction()) = valueNumber(compared) and
- guard.ensuresEq(compared, eqbound.getDefinitionInstruction(), 0, bounded.getInstruction().getBlock(), isEq)
+ exists(Operand compared |
+ valueNumber(bounded.getDefinitionInstruction()) = valueNumber(compared.getDefinitionInstruction()) and
+ guard.ensuresEq(compared, eqbound, 0, bounded.getInstruction().getBlock(), isEq)
)
}
diff --git a/cpp/ql/test/library-tests/controlflow/guards-ir/tests.ql b/cpp/ql/test/library-tests/controlflow/guards-ir/tests.ql
index 2bb8b2f9fa9..173ce6c5d89 100644
--- a/cpp/ql/test/library-tests/controlflow/guards-ir/tests.ql
+++ b/cpp/ql/test/library-tests/controlflow/guards-ir/tests.ql
@@ -51,7 +51,7 @@ query predicate irGuards(IRGuardCondition guard) {
}
query predicate irGuardsCompare(int startLine, string msg) {
- exists(IRGuardCondition guard, Instruction left, Instruction right, int k, string which, string op |
+ exists(IRGuardCondition guard, Operand left, Operand right, int k, string which, string op |
exists(boolean sense |
sense = true and which = "true"
or sense = false and which = "false"
@@ -65,7 +65,7 @@ query predicate irGuardsCompare(int startLine, string msg) {
guard.comparesEq(left, right, k, false, sense) and op = " != "
)
and startLine = guard.getLocation().getStartLine()
- and msg = left.getUnconvertedResultExpression() + op + right.getUnconvertedResultExpression() + "+" + k + " when " + guard + " is " + which
+ and msg = left.getDefinitionInstruction().getUnconvertedResultExpression() + op + right.getDefinitionInstruction().getUnconvertedResultExpression() + "+" + k + " when " + guard + " is " + which
)
}
query predicate irGuardsControl(IRGuardCondition guard, boolean sense, int start, int end) {
@@ -77,15 +77,18 @@ query predicate irGuardsControl(IRGuardCondition guard, boolean sense, int start
query predicate irGuardsEnsure(IRGuardCondition guard, Instruction left, string op, Instruction right, int k, int start, int end)
{
- exists(IRBlock block |
- guard.ensuresLt(left, right, k, block, true) and op = "<"
- or
- guard.ensuresLt(left, right, k, block, false) and op = ">="
- or
- guard.ensuresEq(left, right, k, block, true) and op = "=="
- or
- guard.ensuresEq(left, right, k, block, false) and op = "!="
- |
- block.getLocation().hasLocationInfo(_, start, _, end, _)
+
+ exists(IRBlock block, Operand leftOp, Operand rightOp |
+ guard.ensuresLt(leftOp, rightOp, k, block, true) and op = "<"
+ or
+ guard.ensuresLt(leftOp, rightOp, k, block, false) and op = ">="
+ or
+ guard.ensuresEq(leftOp, rightOp, k, block, true) and op = "=="
+ or
+ guard.ensuresEq(leftOp, rightOp, k, block, false) and op = "!="
+ |
+ leftOp = left.getAUse() and
+ rightOp = right.getAUse() and
+ block.getLocation().hasLocationInfo(_, start, _, end, _)
)
}
diff --git a/cpp/ql/test/library-tests/rangeanalysis/signanalysis/bounded_bounds.c b/cpp/ql/test/library-tests/rangeanalysis/signanalysis/bounded_bounds.c
index 7c4f7f70b34..22c5732f83c 100644
--- a/cpp/ql/test/library-tests/rangeanalysis/signanalysis/bounded_bounds.c
+++ b/cpp/ql/test/library-tests/rangeanalysis/signanalysis/bounded_bounds.c
@@ -7,3 +7,13 @@ int f(int x, int y) {
}
return 0;
}
+
+int g(int x, int y) {
+ if (x < y) {
+ return y
+ }
+ if (x < 0) {
+ return x;
+ }
+ return 0;
+}
From f7d693d06fc0519ceb34e782215c83f4d76d6cec Mon Sep 17 00:00:00 2001
From: Max Schaefer
Date: Fri, 9 Nov 2018 15:53:28 +0000
Subject: [PATCH 33/71] JavaScript: Make default extractor options more
sensible.
We now use module auto-detection and no TypeScript mode.
This only affects extern extraction in `AutoBuild`, everything else sets these options explicitly.
We currently do not have any ES2015 modules or TypeScript code in our externs, so in practice this is behaviour-preserving.
---
.../extractor/src/com/semmle/js/extractor/ExtractorConfig.java | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/javascript/extractor/src/com/semmle/js/extractor/ExtractorConfig.java b/javascript/extractor/src/com/semmle/js/extractor/ExtractorConfig.java
index 9eb384db63a..dfb031021f3 100644
--- a/javascript/extractor/src/com/semmle/js/extractor/ExtractorConfig.java
+++ b/javascript/extractor/src/com/semmle/js/extractor/ExtractorConfig.java
@@ -162,7 +162,7 @@ public class ExtractorConfig {
this.ecmaVersion = experimental ? ECMAVersion.ECMA2019 : ECMAVersion.ECMA2018;
this.platform = Platform.AUTO;
this.jsx = true;
- this.sourceType = SourceType.SCRIPT;
+ this.sourceType = SourceType.AUTO;
this.htmlHandling = HTMLHandling.ELEMENTS;
this.tolerateParseErrors = true;
if (experimental) {
@@ -171,6 +171,7 @@ public class ExtractorConfig {
this.esnext = true;
this.v8Extensions = true;
}
+ this.typescriptMode = TypeScriptMode.NONE;
this.defaultEncoding = StandardCharsets.UTF_8.name();
}
From 63933cdecd201a50a223081e5efd2544905a622c Mon Sep 17 00:00:00 2001
From: Max Schaefer
Date: Fri, 9 Nov 2018 15:55:48 +0000
Subject: [PATCH 34/71] JavaScript: Don't extract extens with `--experimental`
turned on.
There isn't any particularly compelling reason for doing so.
---
javascript/extractor/src/com/semmle/js/extractor/AutoBuild.java | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/javascript/extractor/src/com/semmle/js/extractor/AutoBuild.java b/javascript/extractor/src/com/semmle/js/extractor/AutoBuild.java
index 05a00770c2f..1b4b57812a5 100644
--- a/javascript/extractor/src/com/semmle/js/extractor/AutoBuild.java
+++ b/javascript/extractor/src/com/semmle/js/extractor/AutoBuild.java
@@ -373,7 +373,7 @@ public class AutoBuild {
* externs.
*/
private void extractExterns() throws IOException {
- ExtractorConfig config = new ExtractorConfig(true).withExterns(true);
+ ExtractorConfig config = new ExtractorConfig(false).withExterns(true);
FileExtractor extractor = new FileExtractor(config, outputConfig, trapCache, extractorState);
FileVisitor super Path> visitor = new SimpleFileVisitor() {
@Override
From d9495da2252bc23bdabf7ba5be3dafbf6c5d52fe Mon Sep 17 00:00:00 2001
From: Robert Marsh
Date: Fri, 9 Nov 2018 10:15:28 -0800
Subject: [PATCH 35/71] C++: fix test
---
.../rangeanalysis/signanalysis/SignAnalysis.expected | 2 ++
.../library-tests/rangeanalysis/signanalysis/bounded_bounds.c | 2 +-
2 files changed, 3 insertions(+), 1 deletion(-)
diff --git a/cpp/ql/test/library-tests/rangeanalysis/signanalysis/SignAnalysis.expected b/cpp/ql/test/library-tests/rangeanalysis/signanalysis/SignAnalysis.expected
index bde549f3aa6..a1ebaf0f7bc 100644
--- a/cpp/ql/test/library-tests/rangeanalysis/signanalysis/SignAnalysis.expected
+++ b/cpp/ql/test/library-tests/rangeanalysis/signanalysis/SignAnalysis.expected
@@ -10,6 +10,8 @@
| bounded_bounds.c:5:7:5:7 | Load: x | positive |
| bounded_bounds.c:6:11:6:11 | Load: y | positive strictlyPositive |
| bounded_bounds.c:6:11:6:11 | Store: y | positive strictlyPositive |
+| bounded_bounds.c:16:12:16:12 | Load: x | negative strictlyNegative |
+| bounded_bounds.c:16:12:16:12 | Store: x | negative strictlyNegative |
| inline_assembly.c:9:23:9:23 | Uninitialized: definition of y | positive |
| inline_assembly.c:10:3:10:7 | Store: ... = ... | positive strictlyPositive |
| inline_assembly.c:10:7:10:7 | Constant: (unsigned int)... | positive strictlyPositive |
diff --git a/cpp/ql/test/library-tests/rangeanalysis/signanalysis/bounded_bounds.c b/cpp/ql/test/library-tests/rangeanalysis/signanalysis/bounded_bounds.c
index 22c5732f83c..7519fe00190 100644
--- a/cpp/ql/test/library-tests/rangeanalysis/signanalysis/bounded_bounds.c
+++ b/cpp/ql/test/library-tests/rangeanalysis/signanalysis/bounded_bounds.c
@@ -10,7 +10,7 @@ int f(int x, int y) {
int g(int x, int y) {
if (x < y) {
- return y
+ return y;
}
if (x < 0) {
return x;
From 2033bf81cc194e61c478e54dc6b9e0de168325e8 Mon Sep 17 00:00:00 2001
From: Esben Sparre Andreasen
Date: Mon, 12 Nov 2018 10:03:08 +0100
Subject: [PATCH 36/71] JS: address docstring review comments
---
javascript/ql/src/Declarations/DeadStoreOfProperty.ql | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/javascript/ql/src/Declarations/DeadStoreOfProperty.ql b/javascript/ql/src/Declarations/DeadStoreOfProperty.ql
index c9ebb02a543..393dfd7068e 100644
--- a/javascript/ql/src/Declarations/DeadStoreOfProperty.ql
+++ b/javascript/ql/src/Declarations/DeadStoreOfProperty.ql
@@ -13,7 +13,7 @@ import Expressions.DOMProperties
import DeadStore
/**
- * Holds if `assign` definitely assigns property `name` of `base`.
+ * Holds if `write` writes to property `name` of `base`, and `base` is the only base object of `write`.
*/
predicate unambiguousPropWrite(DataFlow::SourceNode base, string name, DataFlow::PropWrite write) {
write = base.getAPropertyWrite(name) and
@@ -83,7 +83,7 @@ predicate maybeAccessesAssignedPropInBlock(string name, DataFlow::PropWrite assi
}
/**
- * Holds if `assign1` and `assign2` both assign property `name`, and the assigned property may be accessed between the two assignments.
+ * Holds if `assign1` and `assign2` both assign property `name`, and the assigned property is not accessed between the two assignments.
*/
bindingset[name]
predicate noPropAccessBetween(string name, DataFlow::PropWrite assign1, DataFlow::PropWrite assign2) {
From 6d0c93b6a80349d385884b7ec912897694dc999a Mon Sep 17 00:00:00 2001
From: Esben Sparre Andreasen
Date: Wed, 7 Nov 2018 21:32:16 +0100
Subject: [PATCH 37/71] JS: introduce TaintTracking::AdditionalSanitizingCall
---
.../javascript/dataflow/TaintTracking.qll | 63 ++++++++++
.../TaintBarriers/SanitizingGuard.expected | 19 +++
.../TaintBarriers/TaintedSink.expected | 23 ++++
.../TaintBarriers/isBarrier.expected | 3 +
.../test/library-tests/TaintBarriers/tst.js | 119 ++++++++++++++++++
5 files changed, 227 insertions(+)
diff --git a/javascript/ql/src/semmle/javascript/dataflow/TaintTracking.qll b/javascript/ql/src/semmle/javascript/dataflow/TaintTracking.qll
index 53cf8767f6d..7cc46303ff2 100644
--- a/javascript/ql/src/semmle/javascript/dataflow/TaintTracking.qll
+++ b/javascript/ql/src/semmle/javascript/dataflow/TaintTracking.qll
@@ -15,6 +15,7 @@
import javascript
import semmle.javascript.dataflow.CallGraph
+private import semmle.javascript.dataflow.internal.FlowSteps as FlowSteps
private import semmle.javascript.dataflow.InferredTypes
/**
@@ -809,6 +810,68 @@ module TaintTracking {
}
+ /**
+ * A function that returns the result of a sanitizer check.
+ */
+ private class SanitizingFunction extends Function {
+ Parameter sanitizedParameter;
+
+ SanitizerGuardNode sanitizer;
+
+ boolean sanitizerOutcome;
+
+ SanitizingFunction() {
+ exists(Expr e |
+ exists(Expr returnExpr |
+ returnExpr = sanitizer.asExpr()
+ |
+ exists(SsaExplicitDefinition ssa |
+ ssa.getDef().getSource() = returnExpr and
+ ssa.getVariable().getAUse() = getAReturnedExpr()
+ )
+ or
+ returnExpr = getAReturnedExpr()
+ ) and
+ DataFlow::parameterNode(sanitizedParameter).flowsToExpr(e) and
+ sanitizer.sanitizes(sanitizerOutcome, e)
+ ) and
+ getNumParameter() = 1 and
+ sanitizedParameter = getParameter(0)
+ }
+
+ /**
+ * Holds if this function sanitizes argument `e` of call `call`, provided the call evaluates to `outcome`.
+ */
+ predicate isSanitizingCall(DataFlow::CallNode call, Expr e, boolean outcome) {
+ exists(DataFlow::Node arg |
+ arg.asExpr() = e and
+ arg = call.getArgument(0) and
+ call.getNumArgument() = 1 and
+ FlowSteps::argumentPassing(call, arg, this, sanitizedParameter) and
+ outcome = sanitizerOutcome
+ )
+ }
+
+ /**
+ * Holds if this function applies to the flow in `cfg`.
+ */
+ predicate appliesTo(Configuration cfg) {
+ cfg.isBarrierGuard(sanitizer)
+ }
+ }
+
+ /**
+ * A call that sanitizes an argument.
+ */
+ private class AdditionalSanitizingCall extends AdditionalSanitizerGuardNode, DataFlow::CallNode {
+ SanitizingFunction f;
+
+ AdditionalSanitizingCall() { f.isSanitizingCall(this, _, _) }
+
+ override predicate sanitizes(boolean outcome, Expr e) { f.isSanitizingCall(this, e, outcome) }
+
+ override predicate appliesTo(Configuration cfg) { f.appliesTo(cfg) }
+ }
/**
* An equality test on `e.origin` or `e.source` where `e` is a `postMessage` event object,
diff --git a/javascript/ql/test/library-tests/TaintBarriers/SanitizingGuard.expected b/javascript/ql/test/library-tests/TaintBarriers/SanitizingGuard.expected
index ac750a13e3e..faab0c306f5 100644
--- a/javascript/ql/test/library-tests/TaintBarriers/SanitizingGuard.expected
+++ b/javascript/ql/test/library-tests/TaintBarriers/SanitizingGuard.expected
@@ -38,3 +38,22 @@
| tst.js:226:9:226:26 | -1 >= o.indexOf(v) | ExampleConfiguration | false | tst.js:226:25:226:25 | v |
| tst.js:236:9:236:24 | isWhitelisted(v) | ExampleConfiguration | true | tst.js:236:23:236:23 | v |
| tst.js:240:9:240:28 | config.allowValue(v) | ExampleConfiguration | true | tst.js:240:27:240:27 | v |
+| tst.js:252:16:252:36 | whiteli ... ains(x) | ExampleConfiguration | true | tst.js:252:35:252:35 | x |
+| tst.js:254:9:254:12 | f(v) | ExampleConfiguration | true | tst.js:254:11:254:11 | v |
+| tst.js:261:25:261:45 | whiteli ... ains(y) | ExampleConfiguration | true | tst.js:261:44:261:44 | y |
+| tst.js:264:9:264:12 | g(v) | ExampleConfiguration | true | tst.js:264:11:264:11 | v |
+| tst.js:271:25:271:45 | whiteli ... ains(z) | ExampleConfiguration | true | tst.js:271:44:271:44 | z |
+| tst.js:281:16:281:25 | x2 != null | ExampleConfiguration | false | tst.js:281:16:281:17 | x2 |
+| tst.js:281:30:281:51 | whiteli ... ins(x2) | ExampleConfiguration | true | tst.js:281:49:281:50 | x2 |
+| tst.js:290:16:290:25 | x3 == null | ExampleConfiguration | true | tst.js:290:16:290:17 | x3 |
+| tst.js:290:30:290:51 | whiteli ... ins(x3) | ExampleConfiguration | true | tst.js:290:49:290:50 | x3 |
+| tst.js:299:17:299:38 | whiteli ... ins(x4) | ExampleConfiguration | true | tst.js:299:36:299:37 | x4 |
+| tst.js:308:18:308:39 | whiteli ... ins(x5) | ExampleConfiguration | true | tst.js:308:37:308:38 | x5 |
+| tst.js:317:26:317:47 | whiteli ... ins(x6) | ExampleConfiguration | true | tst.js:317:45:317:46 | x6 |
+| tst.js:327:25:327:34 | x7 != null | ExampleConfiguration | false | tst.js:327:25:327:26 | x7 |
+| tst.js:327:39:327:60 | whiteli ... ins(x7) | ExampleConfiguration | true | tst.js:327:58:327:59 | x7 |
+| tst.js:337:25:337:46 | whiteli ... ins(x8) | ExampleConfiguration | true | tst.js:337:44:337:45 | x8 |
+| tst.js:338:16:338:25 | x8 != null | ExampleConfiguration | false | tst.js:338:16:338:17 | x8 |
+| tst.js:347:29:347:50 | whiteli ... ins(x9) | ExampleConfiguration | true | tst.js:347:48:347:49 | x9 |
+| tst.js:356:16:356:27 | x10 !== null | ExampleConfiguration | false | tst.js:356:16:356:18 | x10 |
+| tst.js:356:32:356:48 | x10 !== undefined | ExampleConfiguration | false | tst.js:356:32:356:34 | x10 |
diff --git a/javascript/ql/test/library-tests/TaintBarriers/TaintedSink.expected b/javascript/ql/test/library-tests/TaintBarriers/TaintedSink.expected
index 81935683df3..34a4dd11c6f 100644
--- a/javascript/ql/test/library-tests/TaintBarriers/TaintedSink.expected
+++ b/javascript/ql/test/library-tests/TaintBarriers/TaintedSink.expected
@@ -36,3 +36,26 @@
| tst.js:227:14:227:14 | v | tst.js:199:13:199:20 | SOURCE() |
| tst.js:239:14:239:14 | v | tst.js:235:13:235:20 | SOURCE() |
| tst.js:243:14:243:14 | v | tst.js:235:13:235:20 | SOURCE() |
+| tst.js:249:10:249:10 | v | tst.js:248:13:248:20 | SOURCE() |
+| tst.js:257:14:257:14 | v | tst.js:248:13:248:20 | SOURCE() |
+| tst.js:267:14:267:14 | v | tst.js:248:13:248:20 | SOURCE() |
+| tst.js:275:14:275:14 | v | tst.js:248:13:248:20 | SOURCE() |
+| tst.js:277:14:277:14 | v | tst.js:248:13:248:20 | SOURCE() |
+| tst.js:284:14:284:14 | v | tst.js:248:13:248:20 | SOURCE() |
+| tst.js:286:14:286:14 | v | tst.js:248:13:248:20 | SOURCE() |
+| tst.js:293:14:293:14 | v | tst.js:248:13:248:20 | SOURCE() |
+| tst.js:295:14:295:14 | v | tst.js:248:13:248:20 | SOURCE() |
+| tst.js:302:14:302:14 | v | tst.js:248:13:248:20 | SOURCE() |
+| tst.js:304:14:304:14 | v | tst.js:248:13:248:20 | SOURCE() |
+| tst.js:311:14:311:14 | v | tst.js:248:13:248:20 | SOURCE() |
+| tst.js:313:14:313:14 | v | tst.js:248:13:248:20 | SOURCE() |
+| tst.js:321:14:321:14 | v | tst.js:248:13:248:20 | SOURCE() |
+| tst.js:323:14:323:14 | v | tst.js:248:13:248:20 | SOURCE() |
+| tst.js:331:14:331:14 | v | tst.js:248:13:248:20 | SOURCE() |
+| tst.js:333:14:333:14 | v | tst.js:248:13:248:20 | SOURCE() |
+| tst.js:341:14:341:14 | v | tst.js:248:13:248:20 | SOURCE() |
+| tst.js:343:14:343:14 | v | tst.js:248:13:248:20 | SOURCE() |
+| tst.js:350:14:350:14 | v | tst.js:248:13:248:20 | SOURCE() |
+| tst.js:352:14:352:14 | v | tst.js:248:13:248:20 | SOURCE() |
+| tst.js:359:14:359:14 | v | tst.js:248:13:248:20 | SOURCE() |
+| tst.js:361:14:361:14 | v | tst.js:248:13:248:20 | SOURCE() |
diff --git a/javascript/ql/test/library-tests/TaintBarriers/isBarrier.expected b/javascript/ql/test/library-tests/TaintBarriers/isBarrier.expected
index 315e118a083..7578663ece8 100644
--- a/javascript/ql/test/library-tests/TaintBarriers/isBarrier.expected
+++ b/javascript/ql/test/library-tests/TaintBarriers/isBarrier.expected
@@ -31,3 +31,6 @@
| tst.js:229:14:229:14 | v | ExampleConfiguration |
| tst.js:237:14:237:14 | v | ExampleConfiguration |
| tst.js:241:14:241:14 | v | ExampleConfiguration |
+| tst.js:255:14:255:14 | v | ExampleConfiguration |
+| tst.js:265:14:265:14 | v | ExampleConfiguration |
+| tst.js:356:16:356:27 | x10 | ExampleConfiguration |
diff --git a/javascript/ql/test/library-tests/TaintBarriers/tst.js b/javascript/ql/test/library-tests/TaintBarriers/tst.js
index ea0cc095175..da7fe8f5de5 100644
--- a/javascript/ql/test/library-tests/TaintBarriers/tst.js
+++ b/javascript/ql/test/library-tests/TaintBarriers/tst.js
@@ -243,3 +243,122 @@ function adhocWhitelisting() {
SINK(v);
}
+
+function IndirectSanitizer () {
+ var v = SOURCE();
+ SINK(v);
+
+ function f(x) {
+ return whitelist.contains(x);
+ }
+ if (f(v)) {
+ SINK(v);
+ } else {
+ SINK(v);
+ }
+
+ function g(y) {
+ var sanitized = whitelist.contains(y);
+ return sanitized;
+ }
+ if (g(v)) {
+ SINK(v);
+ } else {
+ SINK(v);
+ }
+
+ function h(z) {
+ var sanitized = whitelist.contains(z);
+ return somethingElse();
+ }
+ if (h(v)) {
+ SINK(v);
+ } else {
+ SINK(v);
+ }
+
+ function f2(x2) {
+ return x2 != null && whitelist.contains(x2);
+ }
+ if (f2(v)) {
+ SINK(v);
+ } else {
+ SINK(v);
+ }
+
+ function f3(x3) {
+ return x3 == null || whitelist.contains(x3);
+ }
+ if (f3(v)) {
+ SINK(v); // SANITIZATION OF THIS IS NOT YET SUPPORTED
+ } else {
+ SINK(v);
+ }
+
+ function f4(x4) {
+ return !whitelist.contains(x4);
+ }
+ if (f4(v)) {
+ SINK(v);
+ } else {
+ SINK(v); // SANITIZATION OF THIS IS NOT YET SUPPORTED
+ }
+
+ function f5(x5) {
+ return !!whitelist.contains(x5);
+ }
+ if (f5(v)) {
+ SINK(v); // SANITIZATION OF THIS IS NOT YET SUPPORTED
+ } else {
+ SINK(v);
+ }
+
+ function f6(x6) {
+ var sanitized = !whitelist.contains(x6);
+ return !sanitized;
+ }
+ if (f6(v)) {
+ SINK(v);
+ } else {
+ SINK(v); // SANITIZATION OF THIS IS NOT YET SUPPORTED
+ }
+
+ function f7(x7) {
+ var sanitized = x7 != null && whitelist.contains(x7);
+ return sanitized;
+ }
+ if (f7(v)) {
+ SINK(v);
+ } else {
+ SINK(v);
+ }
+
+ function f8(x8) {
+ var sanitized = whitelist.contains(x8);
+ return x8 != null && sanitized;
+ }
+ if (f8(v)) {
+ SINK(v); // SANITIZATION OF THIS IS NOT YET SUPPORTED
+ } else {
+ SINK(v);
+ }
+
+ function f9(x9) {
+ return unknown() && whitelist.contains(x9) && unknown();
+ }
+ if (f9(v)) {
+ SINK(v); // SANITIZATION OF THIS IS NOT YET SUPPORTED
+ } else {
+ SINK(v);
+ }
+
+ function f10(x10) {
+ return x10 !== null || x10 !== undefined;
+ }
+ if (f10(v)) {
+ SINK(v);
+ } else {
+ SINK(v);
+ }
+
+}
From ffc3d6ba498ad10434ebd21db3233a77c3430743 Mon Sep 17 00:00:00 2001
From: Esben Sparre Andreasen
Date: Fri, 9 Nov 2018 21:27:29 +0100
Subject: [PATCH 38/71] JS: simplify test (move alerts four lines up)
---
.../ServerSideUrlRedirect.expected | 12 ++++++------
.../CWE-601/ServerSideUrlRedirect/express.js | 4 ----
2 files changed, 6 insertions(+), 10 deletions(-)
diff --git a/javascript/ql/test/query-tests/Security/CWE-601/ServerSideUrlRedirect/ServerSideUrlRedirect.expected b/javascript/ql/test/query-tests/Security/CWE-601/ServerSideUrlRedirect/ServerSideUrlRedirect.expected
index 56e5c781d63..012bb85379f 100644
--- a/javascript/ql/test/query-tests/Security/CWE-601/ServerSideUrlRedirect/ServerSideUrlRedirect.expected
+++ b/javascript/ql/test/query-tests/Security/CWE-601/ServerSideUrlRedirect/ServerSideUrlRedirect.expected
@@ -2,12 +2,12 @@
| express.js:12:26:12:44 | req.param("target") | Untrusted URL redirection due to $@. | express.js:12:26:12:44 | req.param("target") | user-provided value |
| express.js:33:18:33:23 | target | Untrusted URL redirection due to $@. | express.js:27:16:27:34 | req.param("target") | user-provided value |
| express.js:35:16:35:21 | target | Untrusted URL redirection due to $@. | express.js:27:16:27:34 | req.param("target") | user-provided value |
-| express.js:44:16:44:108 | (req.pa ... ntacts" | Untrusted URL redirection due to $@. | express.js:44:69:44:87 | req.param('action') | user-provided value |
-| express.js:53:26:53:28 | url | Untrusted URL redirection due to $@. | express.js:48:16:48:28 | req.params[0] | user-provided value |
-| express.js:78:16:78:43 | `${req. ... )}/foo` | Untrusted URL redirection due to $@. | express.js:78:19:78:37 | req.param("target") | user-provided value |
-| express.js:94:18:94:23 | target | Untrusted URL redirection due to $@. | express.js:87:16:87:34 | req.param("target") | user-provided value |
-| express.js:101:16:101:21 | target | Untrusted URL redirection due to $@. | express.js:87:16:87:34 | req.param("target") | user-provided value |
-| express.js:122:16:122:72 | [req.qu ... oin('') | Untrusted URL redirection due to $@. | express.js:122:17:122:30 | req.query.page | user-provided value |
+| express.js:40:16:40:108 | (req.pa ... ntacts" | Untrusted URL redirection due to $@. | express.js:40:69:40:87 | req.param('action') | user-provided value |
+| express.js:49:26:49:28 | url | Untrusted URL redirection due to $@. | express.js:44:16:44:28 | req.params[0] | user-provided value |
+| express.js:74:16:74:43 | `${req. ... )}/foo` | Untrusted URL redirection due to $@. | express.js:74:19:74:37 | req.param("target") | user-provided value |
+| express.js:90:18:90:23 | target | Untrusted URL redirection due to $@. | express.js:83:16:83:34 | req.param("target") | user-provided value |
+| express.js:97:16:97:21 | target | Untrusted URL redirection due to $@. | express.js:83:16:83:34 | req.param("target") | user-provided value |
+| express.js:118:16:118:72 | [req.qu ... oin('') | Untrusted URL redirection due to $@. | express.js:118:17:118:30 | req.query.page | user-provided value |
| node.js:7:34:7:39 | target | Untrusted URL redirection due to $@. | node.js:6:26:6:32 | req.url | user-provided value |
| node.js:15:34:15:45 | '/' + target | Untrusted URL redirection due to $@. | node.js:11:26:11:32 | req.url | user-provided value |
| node.js:32:34:32:55 | target ... =" + me | Untrusted URL redirection due to $@. | node.js:29:26:29:32 | req.url | user-provided value |
diff --git a/javascript/ql/test/query-tests/Security/CWE-601/ServerSideUrlRedirect/express.js b/javascript/ql/test/query-tests/Security/CWE-601/ServerSideUrlRedirect/express.js
index 1d61fd5f92b..37a1370698c 100644
--- a/javascript/ql/test/query-tests/Security/CWE-601/ServerSideUrlRedirect/express.js
+++ b/javascript/ql/test/query-tests/Security/CWE-601/ServerSideUrlRedirect/express.js
@@ -35,10 +35,6 @@ app.get('/some/path', function(req, res) {
res.redirect(target);
});
-function isLocalURL(target) {
- return new RegExp("^/(?![/\\])|^~/").exec(target);
-}
-
app.get('/foo', function(req, res) {
// BAD: may be a global redirection
res.redirect((req.param('action') && req.param('action') != "") ? req.param('action') : "/google_contacts")
From eaad84bb4fc2637bdb432c7d925121c3638a3c64 Mon Sep 17 00:00:00 2001
From: Esben Sparre Andreasen
Date: Mon, 12 Nov 2018 10:23:52 +0100
Subject: [PATCH 39/71] JS: add support for dis- and conjunctions in
SanitizingFunction
---
.../ql/src/semmle/javascript/dataflow/TaintTracking.qll | 6 ++++++
.../library-tests/TaintBarriers/SanitizingGuard.expected | 3 +++
.../test/library-tests/TaintBarriers/TaintedSink.expected | 3 ---
.../ql/test/library-tests/TaintBarriers/isBarrier.expected | 3 +++
4 files changed, 12 insertions(+), 3 deletions(-)
diff --git a/javascript/ql/src/semmle/javascript/dataflow/TaintTracking.qll b/javascript/ql/src/semmle/javascript/dataflow/TaintTracking.qll
index 7cc46303ff2..4fff201ff8f 100644
--- a/javascript/ql/src/semmle/javascript/dataflow/TaintTracking.qll
+++ b/javascript/ql/src/semmle/javascript/dataflow/TaintTracking.qll
@@ -824,6 +824,12 @@ module TaintTracking {
exists(Expr e |
exists(Expr returnExpr |
returnExpr = sanitizer.asExpr()
+ or
+ // ad hoc support for conjunctions:
+ returnExpr.(LogAndExpr).getAnOperand() = sanitizer.asExpr() and sanitizerOutcome = true
+ or
+ // ad hoc support for disjunctions:
+ returnExpr.(LogOrExpr).getAnOperand() = sanitizer.asExpr() and sanitizerOutcome = false
|
exists(SsaExplicitDefinition ssa |
ssa.getDef().getSource() = returnExpr and
diff --git a/javascript/ql/test/library-tests/TaintBarriers/SanitizingGuard.expected b/javascript/ql/test/library-tests/TaintBarriers/SanitizingGuard.expected
index faab0c306f5..096e3dc6e43 100644
--- a/javascript/ql/test/library-tests/TaintBarriers/SanitizingGuard.expected
+++ b/javascript/ql/test/library-tests/TaintBarriers/SanitizingGuard.expected
@@ -45,6 +45,7 @@
| tst.js:271:25:271:45 | whiteli ... ains(z) | ExampleConfiguration | true | tst.js:271:44:271:44 | z |
| tst.js:281:16:281:25 | x2 != null | ExampleConfiguration | false | tst.js:281:16:281:17 | x2 |
| tst.js:281:30:281:51 | whiteli ... ins(x2) | ExampleConfiguration | true | tst.js:281:49:281:50 | x2 |
+| tst.js:283:9:283:13 | f2(v) | ExampleConfiguration | true | tst.js:283:12:283:12 | v |
| tst.js:290:16:290:25 | x3 == null | ExampleConfiguration | true | tst.js:290:16:290:17 | x3 |
| tst.js:290:30:290:51 | whiteli ... ins(x3) | ExampleConfiguration | true | tst.js:290:49:290:50 | x3 |
| tst.js:299:17:299:38 | whiteli ... ins(x4) | ExampleConfiguration | true | tst.js:299:36:299:37 | x4 |
@@ -52,8 +53,10 @@
| tst.js:317:26:317:47 | whiteli ... ins(x6) | ExampleConfiguration | true | tst.js:317:45:317:46 | x6 |
| tst.js:327:25:327:34 | x7 != null | ExampleConfiguration | false | tst.js:327:25:327:26 | x7 |
| tst.js:327:39:327:60 | whiteli ... ins(x7) | ExampleConfiguration | true | tst.js:327:58:327:59 | x7 |
+| tst.js:330:9:330:13 | f7(v) | ExampleConfiguration | true | tst.js:330:12:330:12 | v |
| tst.js:337:25:337:46 | whiteli ... ins(x8) | ExampleConfiguration | true | tst.js:337:44:337:45 | x8 |
| tst.js:338:16:338:25 | x8 != null | ExampleConfiguration | false | tst.js:338:16:338:17 | x8 |
| tst.js:347:29:347:50 | whiteli ... ins(x9) | ExampleConfiguration | true | tst.js:347:48:347:49 | x9 |
| tst.js:356:16:356:27 | x10 !== null | ExampleConfiguration | false | tst.js:356:16:356:18 | x10 |
| tst.js:356:32:356:48 | x10 !== undefined | ExampleConfiguration | false | tst.js:356:32:356:34 | x10 |
+| tst.js:358:9:358:14 | f10(v) | ExampleConfiguration | false | tst.js:358:13:358:13 | v |
diff --git a/javascript/ql/test/library-tests/TaintBarriers/TaintedSink.expected b/javascript/ql/test/library-tests/TaintBarriers/TaintedSink.expected
index 34a4dd11c6f..905c34b1c1b 100644
--- a/javascript/ql/test/library-tests/TaintBarriers/TaintedSink.expected
+++ b/javascript/ql/test/library-tests/TaintBarriers/TaintedSink.expected
@@ -41,7 +41,6 @@
| tst.js:267:14:267:14 | v | tst.js:248:13:248:20 | SOURCE() |
| tst.js:275:14:275:14 | v | tst.js:248:13:248:20 | SOURCE() |
| tst.js:277:14:277:14 | v | tst.js:248:13:248:20 | SOURCE() |
-| tst.js:284:14:284:14 | v | tst.js:248:13:248:20 | SOURCE() |
| tst.js:286:14:286:14 | v | tst.js:248:13:248:20 | SOURCE() |
| tst.js:293:14:293:14 | v | tst.js:248:13:248:20 | SOURCE() |
| tst.js:295:14:295:14 | v | tst.js:248:13:248:20 | SOURCE() |
@@ -51,11 +50,9 @@
| tst.js:313:14:313:14 | v | tst.js:248:13:248:20 | SOURCE() |
| tst.js:321:14:321:14 | v | tst.js:248:13:248:20 | SOURCE() |
| tst.js:323:14:323:14 | v | tst.js:248:13:248:20 | SOURCE() |
-| tst.js:331:14:331:14 | v | tst.js:248:13:248:20 | SOURCE() |
| tst.js:333:14:333:14 | v | tst.js:248:13:248:20 | SOURCE() |
| tst.js:341:14:341:14 | v | tst.js:248:13:248:20 | SOURCE() |
| tst.js:343:14:343:14 | v | tst.js:248:13:248:20 | SOURCE() |
| tst.js:350:14:350:14 | v | tst.js:248:13:248:20 | SOURCE() |
| tst.js:352:14:352:14 | v | tst.js:248:13:248:20 | SOURCE() |
| tst.js:359:14:359:14 | v | tst.js:248:13:248:20 | SOURCE() |
-| tst.js:361:14:361:14 | v | tst.js:248:13:248:20 | SOURCE() |
diff --git a/javascript/ql/test/library-tests/TaintBarriers/isBarrier.expected b/javascript/ql/test/library-tests/TaintBarriers/isBarrier.expected
index 7578663ece8..97ff9d74188 100644
--- a/javascript/ql/test/library-tests/TaintBarriers/isBarrier.expected
+++ b/javascript/ql/test/library-tests/TaintBarriers/isBarrier.expected
@@ -33,4 +33,7 @@
| tst.js:241:14:241:14 | v | ExampleConfiguration |
| tst.js:255:14:255:14 | v | ExampleConfiguration |
| tst.js:265:14:265:14 | v | ExampleConfiguration |
+| tst.js:284:14:284:14 | v | ExampleConfiguration |
+| tst.js:331:14:331:14 | v | ExampleConfiguration |
| tst.js:356:16:356:27 | x10 | ExampleConfiguration |
+| tst.js:361:14:361:14 | v | ExampleConfiguration |
From 2c1a37c652370026a0460ac4c4c8b8af71acb11d Mon Sep 17 00:00:00 2001
From: Max Schaefer
Date: Fri, 9 Nov 2018 12:01:27 +0000
Subject: [PATCH 40/71] JavaScript: Add WebRTC externs.
---
javascript/externs/README.md | 2 +-
javascript/externs/web/w3c_rtc.js | 2252 +++++++++++++++++++++++++++++
2 files changed, 2253 insertions(+), 1 deletion(-)
create mode 100644 javascript/externs/web/w3c_rtc.js
diff --git a/javascript/externs/README.md b/javascript/externs/README.md
index 5046d08cdfe..2830589476b 100644
--- a/javascript/externs/README.md
+++ b/javascript/externs/README.md
@@ -2,7 +2,7 @@ This directory contains externs definitions for improving the precision of some
Externs are organized into five categories, corresponding to the subdirectories of this directory:
- * `es`: Externs definitions for the ECMAScript language standard; imported from the `externs` directory of the Google Closure Compiler source tree (https://github.com/google/closure-compiler), revision 6b81fd0bebe9b2560b55a37b880156465d045247.
+ * `es`: Externs definitions for the ECMAScript language standard; imported from the `externs` directory of the Google Closure Compiler source tree (https://github.com/google/closure-compiler).
* `web`: Externs definitions for various web standards and browser-specific extensions; imported from the same source.
diff --git a/javascript/externs/web/w3c_rtc.js b/javascript/externs/web/w3c_rtc.js
new file mode 100644
index 00000000000..027d3389426
--- /dev/null
+++ b/javascript/externs/web/w3c_rtc.js
@@ -0,0 +1,2252 @@
+/*
+ * Copyright 2012 The Closure Compiler Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * @fileoverview Definitions for components of the WebRTC browser API.
+ * @see https://www.w3.org/TR/webrtc/
+ * @see https://tools.ietf.org/html/draft-ietf-rtcweb-jsep-19
+ * @see https://developer.mozilla.org/en-US/docs/Web/API/WebRTC_API
+ * @see https://www.w3.org/TR/mediacapture-streams/
+ *
+ * @externs
+ * @author bemasc@google.com (Benjamin M. Schwartz)
+ */
+
+/**
+ * @typedef {string}
+ * @see {https://www.w3.org/TR/mediacapture-streams/
+ * #idl-def-MediaStreamTrackState}
+ * In WebIDL this is an enum with values 'live', 'mute', and 'ended',
+ * but there is no mechanism in Closure for describing a specialization of
+ * the string type.
+ */
+var MediaStreamTrackState;
+
+/**
+ * @interface
+ */
+function SourceInfo() {}
+
+/** @const {string} */
+SourceInfo.prototype.kind;
+
+/** @const {string} */
+SourceInfo.prototype.id;
+
+/** @const {?string} */
+SourceInfo.prototype.label;
+
+/** @const {boolean} */
+SourceInfo.prototype.facing;
+
+/**
+ * @interface
+ * @see https://w3c.github.io/mediacapture-image/#mediasettingsrange-section
+ */
+function MediaSettingsRange() {}
+
+/**
+ * @type {number}
+ * @const
+ */
+MediaSettingsRange.prototype.max;
+
+/**
+ * @type {number}
+ * @const
+ */
+MediaSettingsRange.prototype.min;
+
+/**
+ * @type {number}
+ * @const
+ */
+MediaSettingsRange.prototype.step;
+
+/**
+ * @interface
+ * @see https://www.w3.org/TR/mediacapture-streams/#idl-def-MediaTrackCapabilities
+ * @see https://w3c.github.io/mediacapture-image/#mediatrackcapabilities-section
+ */
+function MediaTrackCapabilities() {}
+
+/** @type {number} */
+MediaTrackCapabilities.prototype.width;
+
+/** @type {number} */
+MediaTrackCapabilities.prototype.height;
+
+/** @type {number} */
+MediaTrackCapabilities.prototype.aspectRatio;
+
+/** @type {number} */
+MediaTrackCapabilities.prototype.frameRate;
+
+/** @type {!Array} */
+MediaTrackCapabilities.prototype.facingMode;
+
+/** @type {number} */
+MediaTrackCapabilities.prototype.volume;
+
+/** @type {number} */
+MediaTrackCapabilities.prototype.sampleRate;
+
+/** @type {number} */
+MediaTrackCapabilities.prototype.sampleSize;
+
+/** @type {!Array} */
+MediaTrackCapabilities.prototype.echoCancellation;
+
+/** @type {number} */
+MediaTrackCapabilities.prototype.latency;
+
+/** @type {number} */
+MediaTrackCapabilities.prototype.channelCount;
+
+/** @type {string} */
+MediaTrackCapabilities.prototype.deviceId;
+
+/** @type {string} */
+MediaTrackCapabilities.prototype.groupId;
+
+/** @type {!Array} */
+MediaTrackCapabilities.prototype.whiteBalanceMode;
+
+/** @type {!Array} */
+MediaTrackCapabilities.prototype.exposureMode;
+
+/** @type {!Array} */
+MediaTrackCapabilities.prototype.focusMode;
+
+/** @type {!MediaSettingsRange} */
+MediaTrackCapabilities.prototype.exposureCompensation;
+
+/** @type {!MediaSettingsRange} */
+MediaTrackCapabilities.prototype.colorTemperature
+
+/** @type {!MediaSettingsRange} */
+MediaTrackCapabilities.prototype.iso
+
+/** @type {!MediaSettingsRange} */
+MediaTrackCapabilities.prototype.brightness
+
+/** @type {!MediaSettingsRange} */
+MediaTrackCapabilities.prototype.contrast
+
+/** @type {!MediaSettingsRange} */
+MediaTrackCapabilities.prototype.saturation
+
+/** @type {!MediaSettingsRange} */
+MediaTrackCapabilities.prototype.sharpness
+
+/** @type {!MediaSettingsRange} */
+MediaTrackCapabilities.prototype.zoom
+
+/** @type {boolean} */
+MediaTrackCapabilities.prototype.torch
+
+/**
+ * @interface
+ * @see https://www.w3.org/TR/mediacapture-streams/#media-track-settings
+ * @see https://w3c.github.io/mediacapture-image/#mediatracksettings-section
+ */
+function MediaTrackSettings() {}
+
+/** @type {number} */
+MediaTrackSettings.prototype.width;
+
+/** @type {number} */
+MediaTrackSettings.prototype.height;
+
+/** @type {number} */
+MediaTrackSettings.prototype.aspectRatio;
+
+/** @type {number} */
+MediaTrackSettings.prototype.frameRate;
+
+/** @type {string} */
+MediaTrackSettings.prototype.facingMode;
+
+/** @type {number} */
+MediaTrackSettings.prototype.volume;
+
+/** @type {number} */
+MediaTrackSettings.prototype.sampleRate;
+
+/** @type {number} */
+MediaTrackSettings.prototype.sampleSize;
+
+/** @type {boolean} */
+MediaTrackSettings.prototype.echoCancellation;
+
+/** @type {number} */
+MediaTrackSettings.prototype.latency;
+
+/** @type {number} */
+MediaTrackSettings.prototype.channelCount;
+
+/** @type {string} */
+MediaTrackSettings.prototype.deviceId;
+
+/** @type {string} */
+MediaTrackSettings.prototype.groupId;
+
+/** @type {string} */
+MediaTrackSettings.prototype.whiteBalanceMode;
+
+/** @type {string} */
+MediaTrackSettings.prototype.exposureMode;
+
+/** @type {string} */
+MediaTrackSettings.prototype.focusMode;
+
+/** @type {!Array<{x: number, y: number}>} */
+MediaTrackSettings.prototype.pointsOfInterest;
+
+/** @type {number} */
+MediaTrackSettings.prototype.exposureCompensation;
+
+/** @type {number} */
+MediaTrackSettings.prototype.colorTemperature
+
+/** @type {number} */
+MediaTrackSettings.prototype.iso
+
+/** @type {number} */
+MediaTrackSettings.prototype.brightness
+
+/** @type {number} */
+MediaTrackSettings.prototype.contrast
+
+/** @type {number} */
+MediaTrackSettings.prototype.saturation
+
+/** @type {number} */
+MediaTrackSettings.prototype.sharpness
+
+/** @type {number} */
+MediaTrackSettings.prototype.zoom
+
+/** @type {boolean} */
+MediaTrackSettings.prototype.torch
+
+
+/**
+ * @interface
+ * @see https://w3c.github.io/mediacapture-main/#media-track-supported-constraints
+ */
+function MediaTrackSupportedConstraints() {}
+
+/** @type {boolean|undefined} */
+MediaTrackSupportedConstraints.prototype.width;
+
+/** @type {boolean|undefined} */
+MediaTrackSupportedConstraints.prototype.height;
+
+/** @type {boolean|undefined} */
+MediaTrackSupportedConstraints.prototype.aspectRatio;
+
+/** @type {boolean|undefined} */
+MediaTrackSupportedConstraints.prototype.frameRate;
+
+/** @type {boolean|undefined} */
+MediaTrackSupportedConstraints.prototype.facingMode;
+
+/** @type {boolean|undefined} */
+MediaTrackSupportedConstraints.prototype.volume;
+
+/** @type {boolean|undefined} */
+MediaTrackSupportedConstraints.prototype.sampleRate;
+
+/** @type {boolean|undefined} */
+MediaTrackSupportedConstraints.prototype.sampleSize;
+
+/** @type {boolean|undefined} */
+MediaTrackSupportedConstraints.prototype.echoCancellation;
+
+/** @type {boolean|undefined} */
+MediaTrackSupportedConstraints.prototype.autoGainControl;
+
+/** @type {boolean|undefined} */
+MediaTrackSupportedConstraints.prototype.noiseSuppression;
+
+/** @type {boolean|undefined} */
+MediaTrackSupportedConstraints.prototype.latency;
+
+/** @type {boolean|undefined} */
+MediaTrackSupportedConstraints.prototype.channelCount;
+
+/** @type {boolean|undefined} */
+MediaTrackSupportedConstraints.prototype.deviceId;
+
+/** @type {boolean|undefined} */
+MediaTrackSupportedConstraints.prototype.groupId;
+
+
+/**
+ * @interface
+ * @extends {EventTarget}
+ * @see https://www.w3.org/TR/mediacapture-streams/#mediastreamtrack
+ */
+function MediaStreamTrack() {}
+
+/**
+ * @param {!function(!Array)} callback
+ * @return {undefined}
+ * @deprecated Use MediaDevices.enumerateDevices().
+ */
+MediaStreamTrack.getSources = function(callback) {};
+
+/**
+ * @type {string}
+ * @const
+ */
+MediaStreamTrack.prototype.kind;
+
+/**
+ * @type {string}
+ * @const
+ */
+MediaStreamTrack.prototype.id;
+
+/**
+ * @type {string}
+ * @const
+ */
+MediaStreamTrack.prototype.label;
+
+/**
+ * @type {boolean}
+ */
+MediaStreamTrack.prototype.enabled;
+
+/**
+ * @type {boolean}
+ * @const
+ */
+MediaStreamTrack.prototype.muted;
+
+/**
+ * @type {string}
+ * @see https://crbug.com/653531
+ * @see https://wicg.github.io/mst-content-hint/
+ */
+MediaStreamTrack.prototype.contentHint;
+
+/**
+ * @type {boolean}
+ * @const
+ */
+MediaStreamTrack.prototype.remote;
+
+/**
+ * @type {MediaStreamTrackState}
+ * Read only.
+ */
+MediaStreamTrack.prototype.readyState;
+
+/**
+ * @type {?function(!Event)}
+ */
+MediaStreamTrack.prototype.onmute;
+
+/**
+ * @type {?function(!Event)}
+ */
+MediaStreamTrack.prototype.onunmute;
+
+/**
+ * @type {?function(!Event)}
+ */
+MediaStreamTrack.prototype.onended;
+
+/**
+ * @type {?function(!Event)}
+ */
+MediaStreamTrack.prototype.onoverconstrained;
+
+/**
+ * Applies the specified set of constraints to the track, if any specified; or
+ * if no constraints are specified, removes all constraints from the track.
+ *
+ * @param {MediaTrackConstraints=} constraints Constraints to apply to the
+ * track.
+ * @return {!Promise} A |Promise| that is resolved when the constraints
+ * have been applied, or rejected if there was an error applying the
+ * constraints.
+ */
+MediaStreamTrack.prototype.applyConstraints = function(constraints) {};
+
+/**
+ * @return {!MediaStreamTrack}
+ */
+MediaStreamTrack.prototype.clone = function() {};
+
+/** @return {void} */
+MediaStreamTrack.prototype.stop = function() {};
+
+/** @return {!MediaTrackCapabilities} */
+MediaStreamTrack.prototype.getCapabilities = function() {};
+
+/** @return {!MediaTrackConstraints} */
+MediaStreamTrack.prototype.getConstraints = function() {};
+
+/** @return {!MediaTrackSettings} */
+MediaStreamTrack.prototype.getSettings = function() {};
+
+/**
+ * @typedef {{track: MediaStreamTrack}}
+ */
+var MediaStreamTrackEventInit;
+
+
+/**
+ * @param {string} type
+ * @param {!MediaStreamTrackEventInit} eventInitDict
+ * @constructor
+ * @extends {Event}
+ * @see https://www.w3.org/TR/mediacapture-streams/#mediastreamtrackevent
+ */
+function MediaStreamTrackEvent(type, eventInitDict) {}
+
+/**
+ * @type {!MediaStreamTrack}
+ * @const
+ */
+MediaStreamTrackEvent.prototype.track;
+
+/**
+ * @param {!MediaStream|!Array=} streamOrTracks
+ * @constructor
+ * @implements {EventTarget}
+ * @see https://www.w3.org/TR/mediacapture-streams/#mediastream
+ */
+function MediaStream(streamOrTracks) {}
+
+/**
+ * @override
+ */
+MediaStream.prototype.addEventListener = function(type, listener,
+ opt_useCapture) {};
+
+/**
+ * @override
+ */
+MediaStream.prototype.removeEventListener = function(type, listener,
+ opt_useCapture) {};
+
+/**
+ * @override
+ * @return {boolean}
+ */
+MediaStream.prototype.dispatchEvent = function(evt) {};
+
+/**
+ * TODO(bemasc): Remove this property.
+ * @deprecated
+ * @type {string}
+ * @const
+ */
+MediaStream.prototype.label;
+
+/**
+ * @type {string}
+ * @const
+ */
+MediaStream.prototype.id;
+
+/**
+ * @return {!Array}
+ */
+MediaStream.prototype.getAudioTracks = function() {};
+
+/**
+ * @return {!Array}
+ */
+MediaStream.prototype.getVideoTracks = function() {};
+
+/**
+ * @return {!Array}
+ */
+MediaStream.prototype.getTracks = function() {};
+
+/**
+ * @param {string} trackId
+ * @return {MediaStreamTrack}
+ */
+MediaStream.prototype.getTrackById = function(trackId) {};
+
+/**
+ * @param {!MediaStreamTrack} track
+ * @return {undefined}
+ */
+MediaStream.prototype.addTrack = function(track) {};
+
+/**
+ * @param {!MediaStreamTrack} track
+ * @return {undefined}
+ */
+MediaStream.prototype.removeTrack = function(track) {};
+
+/**
+ * @return {!MediaStream}
+ */
+MediaStream.prototype.clone = function() {};
+
+/**
+ * @deprecated
+ * @type {boolean}
+ */
+MediaStream.prototype.ended;
+
+/**
+ * @deprecated
+ * @type {?function(!Event)}
+ */
+MediaStream.prototype.onended;
+
+/**
+ * @type {boolean}
+ */
+MediaStream.prototype.active;
+
+/**
+ * @type {?function(!Event)}
+ */
+MediaStream.prototype.onactive;
+
+/**
+ * @type {?function(!Event)}
+ */
+MediaStream.prototype.oninactive;
+
+/**
+ * @type {?function(!MediaStreamTrackEvent)}
+ */
+MediaStream.prototype.onaddtrack;
+
+/**
+ * @type {?function(!MediaStreamTrackEvent)}
+ */
+MediaStream.prototype.onremovetrack;
+
+/**
+ * @deprecated
+ * TODO(bemasc): Remove this method once browsers have updated to
+ * MediaStreamTrack.stop().
+ * @return {undefined}
+ */
+MediaStream.prototype.stop = function() {};
+
+/**
+ * @type {function(new: MediaStream,
+ * (!MediaStream|!Array)=)}
+ */
+var webkitMediaStream;
+
+
+/**
+ * @typedef {{tone: string}}
+ * @see https://www.w3.org/TR/webrtc/#dom-rtcdtmftonechangeeventinit
+ */
+var RTCDTMFToneChangeEventInit;
+
+
+/**
+ * @param {string} type
+ * @param {!RTCDTMFToneChangeEventInit} eventInitDict
+ * @constructor
+ * @extends {Event}
+ * @see https://www.w3.org/TR/webrtc/#dom-rtcdtmftonechangeevent
+ */
+function RTCDTMFToneChangeEvent(type, eventInitDict) {}
+
+/**
+ * @const {string}
+ */
+RTCDTMFToneChangeEvent.prototype.tone;
+
+
+/**
+ * @interface
+ * @see https://www.w3.org/TR/webrtc/#rtcdtmfsender
+ */
+function RTCDTMFSender() {}
+
+/**
+ * @param {string} tones
+ * @param {number=} opt_duration
+ * @param {number=} opt_interToneGap
+ */
+RTCDTMFSender.prototype.insertDTMF =
+ function(tones, opt_duration, opt_interToneGap) {};
+
+/**
+ * @type {?function(!RTCDTMFToneChangeEvent)}
+ */
+RTCDTMFSender.prototype.ontonechange;
+
+/**
+ * @const {string}
+ */
+RTCDTMFSender.prototype.toneBuffer;
+
+
+/**
+ * @interface
+ * @see https://www.w3.org/TR/webrtc/#rtcrtpsender-interface
+ */
+function RTCRtpSender(track, transport) {}
+
+/**
+ * @const {!RTCDTMFSender}
+ */
+RTCRtpSender.prototype.dtmf;
+
+/**
+ * @const {!MediaStreamTrack}
+ */
+RTCRtpSender.prototype.track;
+
+/**
+ * @param {!MediaStreamTrack} track
+ */
+RTCRtpSender.prototype.replaceTrack = function(track) {};
+
+
+/**
+ * @return {!Object}
+ */
+RTCRtpSender.prototype.getParameters = function() {};
+
+
+/**
+ * @param {!Object} params
+ * @return {!Promise}
+ */
+RTCRtpSender.prototype.setParameters = function(params) {};
+
+
+/**
+ * @interface
+ * @see https://www.w3.org/TR/webrtc/#dom-rtcrtpcontributingsource
+ */
+function RTCRtpContributingSource() {}
+
+/**
+ * @type {?number}
+ */
+RTCRtpContributingSource.prototype.source;
+
+/**
+ * @type {?Date}
+ */
+RTCRtpContributingSource.prototype.timestamp;
+
+
+/**
+ * @interface
+ * @see https://www.w3.org/TR/webrtc/#rtcrtpreceiver-interface
+ */
+function RTCRtpReceiver(transport, kind) {}
+
+/**
+ * @const {!MediaStreamTrack}
+ */
+RTCRtpReceiver.prototype.track;
+
+/**
+ * @return {!Array}
+ */
+RTCRtpReceiver.prototype.getContributingSources = function() {};
+
+/**
+ * @return {!Array}
+ */
+RTCRtpReceiver.prototype.getSynchronizationSources = function() {};
+
+/**
+ * @see https://www.w3.org/TR/webrtc/#dom-rtcrtptransceiverinit
+ * @record
+ */
+function RTCRtpTransceiverInit() {}
+
+/**
+ * The direction of the `RTCRtpTransceiver`. Defaults to "sendrecv".
+ * @type {?RTCRtpTransceiverDirection|undefined}
+ */
+RTCRtpTransceiverInit.prototype.direction;
+
+/**
+ * The streams to add to the tranceiver's sender.
+ * @type {?Array|undefined}
+ */
+RTCRtpTransceiverInit.prototype.streams;
+
+/**
+ * @type {?Array|undefined}
+ */
+RTCRtpTransceiverInit.prototype.sendEncodings;
+
+/**
+ * @see https://www.w3.org/TR/webrtc/#dom-rtcrtpencodingparameters
+ * @record
+ */
+function RTCRtpEncodingParameters() {}
+
+/**
+ * @type {?number|undefined}
+ */
+RTCRtpEncodingParameters.prototype.codecPayloadType;
+
+/**
+ * Possible values are "disabled" and "enabled".
+ * @type {?string|undefined}
+ */
+RTCRtpEncodingParameters.prototype.dtx;
+
+/**
+ * @type {?boolean|undefined}
+ */
+RTCRtpEncodingParameters.prototype.active;
+
+/**
+ * Possible values are "very-low", "low" (default), "medium", and "high".
+ * @type {?string|undefined}
+ */
+RTCRtpEncodingParameters.prototype.priority;
+
+/**
+ * @type {?number|undefined}
+ */
+RTCRtpEncodingParameters.prototype.ptime;
+
+/**
+ * @type {?number|undefined}
+ */
+RTCRtpEncodingParameters.prototype.maxBitrate;
+
+/**
+ * @type {?number|undefined}
+ */
+RTCRtpEncodingParameters.prototype.maxFramerate;
+
+/**
+ * @type {?string|number}
+ */
+RTCRtpEncodingParameters.prototype.rid;
+
+/**
+ * @type {?number|number}
+ */
+RTCRtpEncodingParameters.prototype.scaleResolutionDownBy;
+
+/**
+ * @interface
+ * @see https://www.w3.org/TR/webrtc/#rtcrtptransceiver-interface
+ */
+function RTCRtpTransceiver() {}
+
+/**
+ * @const {?string}
+ */
+RTCRtpTransceiver.prototype.mid;
+
+/**
+ * @const {boolean}
+ */
+RTCRtpTransceiver.prototype.stopped;
+
+/**
+ * @const {!RTCRtpTransceiverDirection}
+ */
+RTCRtpTransceiver.prototype.direction;
+
+/**
+ * @const {?RTCRtpTransceiverDirection}
+ */
+RTCRtpTransceiver.prototype.currentDirection;
+
+/**
+ * @param {!RTCRtpTransceiverDirection} direction
+ */
+RTCRtpTransceiver.prototype.setDirection = function(direction) {};
+
+/**
+ */
+RTCRtpTransceiver.prototype.stop = function() {};
+
+/**
+ * @const {?RTCRtpSender}
+ */
+RTCRtpTransceiver.prototype.sender;
+
+/**
+ * @const {?RTCRtpReceiver}
+ */
+RTCRtpTransceiver.prototype.receiver;
+
+/**
+ * @see https://w3c.github.io/mediacapture-main/getusermedia.html#dom-longrange
+ * @record
+ */
+function LongRange() {}
+
+/**
+ * @type {number|undefined}
+ */
+LongRange.prototype.max;
+
+/**
+ * @type {number|undefined}
+ */
+LongRange.prototype.min;
+
+/**
+ * @see https://w3c.github.io/mediacapture-main/getusermedia.html#dom-doublerange
+ * @record
+ */
+function DoubleRange() {}
+
+/**
+ * @type {number|undefined}
+ */
+DoubleRange.prototype.max;
+
+/**
+ * @type {number|undefined}
+ */
+DoubleRange.prototype.min;
+
+
+/**
+ * @see https://w3c.github.io/mediacapture-main/getusermedia.html#dom-constrainbooleanparameters
+ * @record
+ */
+function ConstrainBooleanParameters() {}
+
+/**
+ * @type {boolean|undefined}
+ */
+ConstrainBooleanParameters.prototype.exact;
+
+/**
+ * @type {boolean|undefined}
+ */
+ConstrainBooleanParameters.prototype.ideal;
+
+/**
+ * @see https://w3c.github.io/mediacapture-main/getusermedia.html#dom-constraindomstringparameters
+ * @record
+ */
+function ConstrainDOMStringParameters() {}
+
+/**
+ * @type {string|Array|undefined}
+ */
+ConstrainDOMStringParameters.prototype.exact;
+
+/**
+ * @type {string|Array|undefined}
+ */
+ConstrainDOMStringParameters.prototype.ideal;
+
+/**
+ * @see https://w3c.github.io/mediacapture-main/getusermedia.html#dom-constraindoublerange
+ * @record
+ * @extends {DoubleRange}
+ */
+function ConstrainDoubleRange() {}
+
+/**
+ * @type {number|undefined}
+ */
+ConstrainDoubleRange.prototype.exact;
+
+/**
+ * @type {number|undefined}
+ */
+ConstrainDoubleRange.prototype.ideal;
+
+
+/**
+ * @see https://w3c.github.io/mediacapture-main/getusermedia.html#dom-constrainlongrange
+ * @record
+ * @extends {LongRange}
+ */
+function ConstrainLongRange() {}
+
+/**
+ * @type {number|undefined}
+ */
+ConstrainLongRange.prototype.exact;
+
+/**
+ * @type {number|undefined}
+ */
+ConstrainLongRange.prototype.ideal;
+
+/**
+ * @see https://w3c.github.io/mediacapture-main/getusermedia.html#dom-constrainboolean
+ * @typedef {boolean|ConstrainBooleanParameters}
+ */
+var ConstrainBoolean;
+
+/**
+ * @see https://w3c.github.io/mediacapture-main/getusermedia.html#dom-constraindomString
+ * @typedef {string|Array|ConstrainDOMStringParameters}
+ */
+var ConstrainDOMString;
+
+/**
+ * @see https://w3c.github.io/mediacapture-main/getusermedia.html#dom-constraindouble
+ * @typedef {number|ConstrainDoubleRange}
+ */
+var ConstrainDouble;
+
+/**
+ * @see https://w3c.github.io/mediacapture-main/getusermedia.html#dom-constrainlong
+ * @typedef {number|ConstrainLongRange}
+ */
+var ConstrainLong;
+
+
+/**
+ * @see https://w3c.github.io/mediacapture-main/getusermedia.html#dom-mediatrackconstraintset
+ * @record
+ * @private
+ */
+function MediaTrackConstraintSet() {}
+
+/**
+ * @type {ConstrainBoolean|undefined}
+ */
+MediaTrackConstraintSet.prototype.autoGainControl;
+
+/**
+ * @type {ConstrainDouble|undefined}
+ */
+MediaTrackConstraintSet.prototype.aspectRatio;
+
+/**
+ * @type {ConstrainLong|undefined}
+ */
+MediaTrackConstraintSet.prototype.channelCount;
+
+/**
+ * @type {ConstrainDOMString|undefined}
+ */
+MediaTrackConstraintSet.prototype.deviceId;
+
+/**
+ * @type {ConstrainBoolean|undefined}
+ */
+MediaTrackConstraintSet.prototype.echoCancellation;
+
+/**
+ * @type {ConstrainDOMString|undefined}
+ */
+MediaTrackConstraintSet.prototype.facingMode;
+
+/**
+ * @type {ConstrainDouble|undefined}
+ */
+MediaTrackConstraintSet.prototype.frameRate;
+
+/**
+ * @type {ConstrainDOMString|undefined}
+ */
+MediaTrackConstraintSet.prototype.groupId;
+
+/**
+ * @type {ConstrainLong|undefined}
+ */
+MediaTrackConstraintSet.prototype.height;
+
+/**
+ * @type {ConstrainDouble|undefined}
+ */
+MediaTrackConstraintSet.prototype.latency;
+
+/**
+ * @type {ConstrainBoolean|undefined}
+ */
+MediaTrackConstraintSet.prototype.noiseSuppression;
+
+/**
+ * @type {ConstrainLong|undefined}
+ */
+MediaTrackConstraintSet.prototype.sampleRate;
+
+/**
+ * @type {ConstrainLong|undefined}
+ */
+MediaTrackConstraintSet.prototype.sampleSize;
+
+/**
+ * @type {ConstrainDouble|undefined}
+ */
+MediaTrackConstraintSet.prototype.volume;
+
+/**
+ * @type {ConstrainLong|undefined}
+ */
+MediaTrackConstraintSet.prototype.width;
+
+
+/**
+ * @record
+ * @extends {MediaTrackConstraintSet}
+ */
+function MediaTrackConstraints() {}
+
+/**
+ * @type {Array|undefined}
+ */
+MediaTrackConstraints.prototype.advanced;
+
+/**
+ * @see https://w3c.github.io/mediacapture-main/getusermedia.html#media-track-constraints
+ * @record
+ */
+function MediaStreamConstraints() {}
+
+/**
+ * @type {boolean|MediaTrackConstraints|undefined}
+ */
+MediaStreamConstraints.prototype.audio;
+
+/**
+ * @type {boolean|MediaTrackConstraints|undefined}
+ */
+MediaStreamConstraints.prototype.video;
+
+/**
+ * @see {http://dev.w3.org/2011/webrtc/editor/getusermedia.html#
+ * navigatorusermediaerror-and-navigatorusermediaerrorcallback}
+ * @interface
+ */
+function NavigatorUserMediaError() {}
+
+/**
+ * @type {number}
+ * @deprecated Removed from the standard and some browsers.
+ * @const
+ */
+NavigatorUserMediaError.prototype.PERMISSION_DENIED; /** 1 */
+
+/**
+ * @type {number}
+ * @deprecated Removed from the standard and some browsers.
+ * Read only.
+ */
+NavigatorUserMediaError.prototype.code;
+
+/**
+ * @type {string}
+ * Read only.
+ */
+NavigatorUserMediaError.prototype.name;
+
+/**
+ * @type {?string}
+ * Read only.
+ */
+NavigatorUserMediaError.prototype.message;
+
+/**
+ * @type {?string}
+ * Read only.
+ */
+NavigatorUserMediaError.prototype.constraintName;
+
+/**
+ * @param {MediaStreamConstraints} constraints A MediaStreamConstraints object.
+ * @param {function(!MediaStream)} successCallback
+ * A NavigatorUserMediaSuccessCallback function.
+ * @param {function(!NavigatorUserMediaError)=} errorCallback A
+ * NavigatorUserMediaErrorCallback function.
+ * @see http://dev.w3.org/2011/webrtc/editor/getusermedia.html
+ * @see https://www.w3.org/TR/mediacapture-streams/
+ * @return {undefined}
+ */
+Navigator.prototype.webkitGetUserMedia =
+ function(constraints, successCallback, errorCallback) {};
+
+/**
+ * @param {string} type
+ * @param {!Object} eventInitDict
+ * @constructor
+ */
+function MediaStreamEvent(type, eventInitDict) {}
+
+/**
+ * @type {?MediaStream}
+ * @const
+ */
+MediaStreamEvent.prototype.stream;
+
+/**
+ * @record
+ * @see https://www.w3.org/TR/mediastream-recording/#dictdef-mediarecorderoptions
+ */
+function MediaRecorderOptions() {}
+
+/** @type {(string|undefined)} */
+MediaRecorderOptions.prototype.mimeType
+
+/** @type {(number|undefined)} */
+MediaRecorderOptions.prototype.audioBitsPerSecond
+
+/** @type {(number|undefined)} */
+MediaRecorderOptions.prototype.videoBitsPerSecond
+
+/** @type {(number|undefined)} */
+MediaRecorderOptions.prototype.bitsPerSecond
+
+/**
+ * @see https://www.w3.org/TR/mediastream-recording/#mediarecorder-api
+ * @param {!MediaStream} stream
+ * @param {MediaRecorderOptions=} options
+ * @implements {EventTarget}
+ * @constructor
+ */
+function MediaRecorder(stream, options) {}
+
+/**
+ * @override
+ */
+MediaRecorder.prototype.addEventListener = function(type, listener,
+ opt_useCapture) {};
+
+/**
+ * @override
+ */
+MediaRecorder.prototype.removeEventListener = function(type, listener,
+ opt_useCapture) {};
+
+/**
+ * @override
+ * @return {boolean}
+ */
+MediaRecorder.prototype.dispatchEvent = function(evt) {};
+
+/**
+ * @type {!MediaStream}
+ */
+MediaRecorder.prototype.stream;
+
+/**
+ * @type {string}
+ */
+MediaRecorder.prototype.mimeType;
+
+/**
+ * @type {string}
+ */
+MediaRecorder.prototype.state;
+
+/**
+ * @type {(function(!Event)|undefined)}
+ */
+MediaRecorder.prototype.onstart;
+
+/**
+ * @type {(function(!Event)|undefined)}
+ */
+MediaRecorder.prototype.onstop;
+
+/**
+ * @type {(function(!Event)|undefined)}
+ */
+MediaRecorder.prototype.ondataavailable;
+
+/**
+ * @type {(function(!Event)|undefined)}
+ */
+MediaRecorder.prototype.onpause;
+
+/**
+ * @type {(function(!Event)|undefined)}
+ */
+MediaRecorder.prototype.onresume;
+
+/**
+ * @type {(function(!Event)|undefined)}
+ */
+MediaRecorder.prototype.onerror;
+
+/**
+ * @type {number}
+ */
+MediaRecorder.prototype.videoBitsPerSecond;
+
+/**
+ * @type {number}
+ */
+MediaRecorder.prototype.audioBitsPerSecond;
+
+/**
+ * @param {number=} timeslice
+ */
+MediaRecorder.prototype.start = function(timeslice) {};
+
+/** @return {void} */
+MediaRecorder.prototype.stop = function() {};
+
+/** @return {void} */
+MediaRecorder.prototype.pause = function() {};
+
+/** @return {void} */
+MediaRecorder.prototype.resume = function() {};
+
+/** @return {void} */
+MediaRecorder.prototype.requestData = function() {};
+
+/**
+ * @param {string} type
+ * @return {boolean}
+ */
+MediaRecorder.isTypeSupported = function(type) {};
+
+/**
+ * @interface
+ * @see https://w3c.github.io/mediacapture-image/##photosettings-section
+ */
+function PhotoSettings() {}
+
+/**
+ * @type {string}
+ */
+PhotoSettings.prototype.fillLightMode;
+
+/**
+ * @type {number}
+ */
+PhotoSettings.prototype.imageHeight;
+
+/**
+ * @type {number}
+ */
+PhotoSettings.prototype.imageWidth;
+
+/**
+ * @type {boolean}
+ */
+PhotoSettings.prototype.redEyeReduction;
+
+/**
+ * @interface
+ * @see https://w3c.github.io/mediacapture-image/##photocapabilities-section
+ */
+function PhotoCapabilities() {}
+
+/**
+ * @type {string}
+ * @const
+ */
+PhotoCapabilities.prototype.redEyeReduction;
+
+/**
+ * @type {!MediaSettingsRange}
+ * @const
+ */
+PhotoCapabilities.prototype.imageHeight;
+
+/**
+ * @type {!MediaSettingsRange}
+ * @const
+ */
+PhotoCapabilities.prototype.imageWidth;
+
+/**
+ * @type {!Array}
+ * @const
+ */
+PhotoCapabilities.prototype.fillLightMode;
+
+/**
+ * @see https://w3c.github.io/mediacapture-image/
+ * @param {!MediaStreamTrack} videoTrack
+ * @constructor
+ */
+function ImageCapture(videoTrack) {}
+
+/**
+ * @param {!PhotoSettings=} photoSettings
+ * @return {!Promise}
+ */
+ImageCapture.prototype.takePhoto = function(photoSettings) {};
+
+/**
+ * @return {!Promise}
+ */
+ImageCapture.prototype.getPhotoCapabilities = function() {};
+
+/**
+ * @return {!Promise}
+ */
+ImageCapture.prototype.grabFrame = function() {};
+
+/**
+ * @type {!MediaStreamTrack}
+ * @const
+ */
+ImageCapture.prototype.track;
+
+/**
+ * @see https://www.w3.org/TR/webrtc/#rtctrackevent
+ * @param {string} type
+ * @param {!Object} eventInitDict
+ * @constructor
+ */
+function RTCTrackEvent(type, eventInitDict) {}
+
+/**
+ * @type {?RTCRtpReceiver}
+ * @const
+ */
+RTCTrackEvent.prototype.receiver;
+
+/**
+ * @type {?MediaStreamTrack}
+ * @const
+ */
+RTCTrackEvent.prototype.track;
+
+/**
+ * @type {?Array}
+ * @const
+ */
+RTCTrackEvent.prototype.streams;
+
+/**
+ * @type {?RTCRtpTransceiver}
+ * @const
+ */
+RTCTrackEvent.prototype.transceiver;
+
+/**
+ * @typedef {string}
+ * @see https://www.w3.org/TR/mediacapture-streams/#idl-def-MediaDeviceKind
+ * In WebIDL this is an enum with values 'audioinput', 'audiooutput', and
+ * 'videoinput', but there is no mechanism in Closure for describing a
+ * specialization of the string type.
+ */
+var MediaDeviceKind;
+
+/**
+ * Possible values are "sendrecv", "sendonly", "recvonly", and "inactive".
+ * @typedef {string}
+ * @see https://www.w3.org/TR/webrtc/#dom-rtcrtptransceiverdirection
+ */
+var RTCRtpTransceiverDirection;
+
+/**
+ * @interface
+ */
+function MediaDeviceInfo() {}
+
+/** @const {string} */
+MediaDeviceInfo.prototype.deviceId;
+
+/** @const {!MediaDeviceKind} */
+MediaDeviceInfo.prototype.kind;
+
+/** @const {string} */
+MediaDeviceInfo.prototype.label;
+
+/** @const {string} */
+MediaDeviceInfo.prototype.groupId;
+
+/**
+ * @interface
+ * @extends {EventTarget}
+ * @see https://www.w3.org/TR/mediacapture-streams/#mediadevices
+ */
+function MediaDevices() {}
+
+/**
+ * @return {!Promise>}
+ */
+MediaDevices.prototype.enumerateDevices = function() {};
+
+/**
+ * @see https://developer.mozilla.org/en-US/docs/Web/API/MediaDevices/getUserMedia
+ * @param {!MediaStreamConstraints} constraints
+ * @return {!Promise}
+ */
+MediaDevices.prototype.getUserMedia = function(constraints) {}
+
+/**
+ * @see https://w3c.github.io/mediacapture-main/#dom-mediadevices-getsupportedconstraints
+ * @return {!MediaTrackSupportedConstraints}
+ */
+MediaDevices.prototype.getSupportedConstraints = function() {}
+
+/** @const {!MediaDevices} */
+Navigator.prototype.mediaDevices;
+
+/**
+ * @typedef {string}
+ * @see https://www.w3.org/TR/webrtc/#rtcsdptype
+ * In WebIDL this is an enum with values 'offer', 'pranswer', and 'answer',
+ * but there is no mechanism in Closure for describing a specialization of
+ * the string type.
+ */
+var RTCSdpType;
+
+/**
+ * @param {!Object=} descriptionInitDict The RTCSessionDescriptionInit
+ * dictionary. This optional argument may have type
+ * {type:RTCSdpType, sdp:string}, but neither of these keys are required to be
+ * present, and other keys are ignored, so the closest Closure type is Object.
+ * @constructor
+ * @see https://www.w3.org/TR/webrtc/#rtcsessiondescription-class
+ */
+function RTCSessionDescription(descriptionInitDict) {}
+
+/**
+ * @type {?RTCSdpType}
+ * @see https://www.w3.org/TR/webrtc/#dom-rtcsessiondescription-type
+ */
+RTCSessionDescription.prototype.type;
+
+/**
+ * @type {?string}
+ * @see https://www.w3.org/TR/webrtc/#dom-rtcsessiondescription-sdp
+ */
+RTCSessionDescription.prototype.sdp;
+
+/**
+ * TODO(bemasc): Remove this definition once it is removed from the browser.
+ * @param {string} label The label index (audio/video/data -> 0,1,2)
+ * @param {string} sdp The ICE candidate in SDP text form
+ * @constructor
+ */
+function IceCandidate(label, sdp) {}
+
+/**
+ * @return {string}
+ */
+IceCandidate.prototype.toSdp = function() {};
+
+/**
+ * @type {?string}
+ */
+IceCandidate.prototype.label;
+
+/** @record */
+function RTCIceCandidateInit() {};
+
+/** @type {?string|undefined} */
+RTCIceCandidateInit.prototype.candidate;
+
+/** @type {(?string|undefined)} */
+RTCIceCandidateInit.prototype.sdpMid;
+
+/** @type {(?number|undefined)} */
+RTCIceCandidateInit.prototype.sdpMLineIndex;
+
+/** @type {(string|undefined)} */
+RTCIceCandidateInit.prototype.usernameFragment;
+
+/**
+ * @param {!RTCIceCandidateInit=} candidateInitDict The RTCIceCandidateInit dictionary.
+ * @constructor
+ * @see https://www.w3.org/TR/webrtc/#rtcicecandidate-interface
+ */
+function RTCIceCandidate(candidateInitDict) {}
+
+/**
+ * @type {?string}
+ */
+RTCIceCandidate.prototype.candidate;
+
+/**
+ * @type {?string}
+ */
+RTCIceCandidate.prototype.sdpMid;
+
+/**
+ * @type {?number}
+ */
+RTCIceCandidate.prototype.sdpMLineIndex;
+
+/**
+ * @typedef {{urls: string}|{urls: !Array}}
+ * @private
+ * @see https://www.w3.org/TR/webrtc/#rtciceserver-dictionary
+ * This dictionary type also has an optional key {credential: ?string}.
+ */
+var RTCIceServerRecord_;
+
+/**
+ * @interface
+ * @private
+ */
+function RTCIceServerInterface_() {}
+
+/**
+ * @type {string|!Array}
+ */
+RTCIceServerInterface_.prototype.urls;
+
+/**
+ * @type {?string}
+ */
+RTCIceServerInterface_.prototype.username;
+
+/**
+ * @type {?string}
+ */
+RTCIceServerInterface_.prototype.credential;
+
+/**
+ * This type, and several below it, are constructed as unions between records
+ *
+ * @typedef {RTCIceServerRecord_|RTCIceServerInterface_}
+ * @private
+ */
+var RTCIceServer;
+
+/**
+ * @typedef {{
+ * iceServers: !Array,
+ * sdpSemantics: (string|undefined)
+ * }}
+ * @private
+ */
+var RTCConfigurationRecord_;
+
+/**
+ * @interface
+ * @private
+ */
+function RTCConfigurationInterface_() {}
+
+/**
+ * @type {!Array}
+ */
+RTCConfigurationInterface_.prototype.iceServers;
+
+/**
+ * Allows specifying the SDP semantics. Valid values are "plan-b" and
+ * "unified-plan".
+ *
+ * @see {@link https://webrtc.org/web-apis/chrome/unified-plan/}
+ * @type {string|undefined}
+ */
+RTCConfigurationInterface_.prototype.sdpSemantics;
+
+/**
+ * @typedef {RTCConfigurationRecord_|RTCConfigurationInterface_}
+ */
+var RTCConfiguration;
+
+/**
+ * @typedef {function(!RTCSessionDescription)}
+ */
+var RTCSessionDescriptionCallback;
+
+/**
+ * @typedef {function(string)}
+ */
+var RTCPeerConnectionErrorCallback;
+
+/**
+ * @typedef {function()}
+ */
+var RTCVoidCallback;
+
+/**
+ * @typedef {string}
+ */
+var RTCSignalingState;
+
+/**
+ * @typedef {string}
+ */
+var RTCIceConnectionState;
+
+/**
+ * @typedef {string}
+ */
+var RTCIceGatheringState;
+
+/**
+ * @param {string} type
+ * @param {!Object} eventInitDict
+ * @constructor
+ */
+function RTCPeerConnectionIceEvent(type, eventInitDict) {}
+
+/**
+ * @type {RTCIceCandidate}
+ * @const
+ */
+RTCPeerConnectionIceEvent.prototype.candidate;
+
+// Note: The specification of RTCStats types is still under development.
+// Declarations here will be updated and removed to follow the development of
+// modern browsers, breaking compatibility with older versions as they become
+// obsolete.
+/**
+ * @interface
+ */
+function RTCStatsReport() {}
+
+/**
+ * @type {Date}
+ * @const
+ */
+RTCStatsReport.prototype.timestamp;
+
+/**
+ * @return {!Array}
+ */
+RTCStatsReport.prototype.names = function() {};
+
+/**
+ * @param {string} name
+ * @return {string}
+ */
+RTCStatsReport.prototype.stat = function(name) {};
+
+/**
+ * @deprecated
+ * @type {RTCStatsReport}
+ * @const
+ */
+RTCStatsReport.prototype.local;
+
+/**
+ * @deprecated
+ * @type {RTCStatsReport}
+ * @const
+ */
+RTCStatsReport.prototype.remote;
+
+/**
+ * @type {string}
+ * @const
+ */
+RTCStatsReport.prototype.type;
+
+/**
+ * @type {string}
+ * @const
+ */
+RTCStatsReport.prototype.id;
+
+// Note: Below are Map like methods supported by WebRTC statistics
+// specification-compliant RTCStatsReport. Currently only implemented by
+// Mozilla.
+// See https://www.w3.org/TR/webrtc/#rtcstatsreport-object for definition.
+/**
+ * @param {function(this:SCOPE, Object, string, MAP)} callback
+ * @param {SCOPE=} opt_thisObj The value of "this" inside callback function.
+ * @this {MAP}
+ * @template MAP,SCOPE
+ * @readonly
+ */
+RTCStatsReport.prototype.forEach = function(callback, opt_thisObj) {};
+
+/**
+ * @param {string} key
+ * @return {Object}
+ * @readonly
+ */
+RTCStatsReport.prototype.get = function(key) {};
+
+/**
+ * @return {!IteratorIterable}
+ * @readonly
+ */
+RTCStatsReport.prototype.keys = function() {};
+
+/**
+ * TODO(bemasc): Remove this type once it is no longer in use. It has already
+ * been removed from the specification.
+ * @typedef {RTCStatsReport}
+ * @deprecated
+ */
+var RTCStatsElement;
+
+/**
+ * @interface
+ */
+function RTCStatsResponse() {}
+
+/**
+ * @return {!Array}
+ */
+RTCStatsResponse.prototype.result = function() {};
+
+/**
+ * @typedef {function(!RTCStatsResponse, MediaStreamTrack=)}
+ */
+var RTCStatsCallback;
+
+/**
+ * This type is not yet standardized, so the properties here only represent
+ * the current capabilities of libjingle (and hence Chromium).
+ * TODO(bemasc): Add a link to the relevant standard once MediaConstraint has a
+ * standard definition.
+ *
+ * @interface
+ * @private
+ */
+function MediaConstraintSetInterface_() {}
+
+/**
+ * @type {?boolean}
+ */
+MediaConstraintSetInterface_.prototype.OfferToReceiveAudio;
+
+/**
+ * @type {?boolean}
+ */
+MediaConstraintSetInterface_.prototype.OfferToReceiveVideo;
+
+/**
+ * @type {?boolean}
+ */
+MediaConstraintSetInterface_.prototype.DtlsSrtpKeyAgreement;
+
+/**
+ * @type {?boolean}
+ */
+MediaConstraintSetInterface_.prototype.RtpDataChannels;
+
+/**
+ * TODO(bemasc): Make this type public once it is defined in a standard.
+ *
+ * @typedef {Object|MediaConstraintSetInterface_}
+ * @private
+ */
+var MediaConstraintSet_;
+
+/**
+ * @interface
+ * @private
+ */
+function MediaConstraintsInterface_() {}
+
+/**
+ * @type {?MediaConstraintSet_}
+ */
+MediaConstraintsInterface_.prototype.mandatory;
+
+/**
+ * @type {?Array}
+ */
+MediaConstraintsInterface_.prototype.optional;
+
+/**
+ * This type is used extensively in
+ * {@see http://dev.w3.org/2011/webrtc/editor/webrtc.html} but is not yet
+ * defined.
+ *
+ * @typedef {Object|MediaConstraintsInterface_}
+ */
+var MediaConstraints;
+
+/**
+ * @interface
+ * @extends {EventTarget}
+ */
+function RTCDataChannel() {}
+
+/**
+ * @type {string}
+ * @const
+ */
+RTCDataChannel.prototype.label;
+
+/**
+ * @type {boolean}
+ * @const
+ */
+RTCDataChannel.prototype.reliable;
+
+/**
+ * An enumerated string type (RTCDataChannelState) with values:
+ * "connecting", "open", "closing", and "closed".
+ * @type {string}
+ * Read only.
+ */
+RTCDataChannel.prototype.readyState;
+
+/**
+ * @type {number}
+ * Read only.
+ */
+RTCDataChannel.prototype.bufferedAmount;
+
+/**
+ * @type {?function(!Event)}
+ */
+RTCDataChannel.prototype.onopen;
+
+/**
+ * @type {?function(!Event)}
+ */
+RTCDataChannel.prototype.onerror;
+
+/**
+ * @type {?function(!Event)}
+ */
+RTCDataChannel.prototype.onclose;
+
+RTCDataChannel.prototype.close = function() {};
+
+/**
+ * @type {?function(!MessageEvent<*>)}
+ */
+RTCDataChannel.prototype.onmessage;
+
+/**
+ * @type {string}
+ */
+RTCDataChannel.prototype.binaryType;
+
+/**
+ * @param {string|!Blob|!ArrayBuffer|!ArrayBufferView} data
+ * @return {undefined}
+ */
+RTCDataChannel.prototype.send = function(data) {};
+
+/**
+ * @constructor
+ * @extends {Event}
+ * @private
+ */
+function RTCDataChannelEvent() {}
+
+/**
+ * @type {!RTCDataChannel}
+ * Read only.
+ */
+RTCDataChannelEvent.prototype.channel;
+
+/**
+ * @typedef {{reliable: boolean}}
+ */
+var RTCDataChannelInitRecord_;
+
+/**
+ * @interface
+ * @private
+ */
+function RTCDataChannelInitInterface_() {}
+
+/**
+ * @type {boolean}
+ */
+RTCDataChannelInitInterface_.prototype.reliable;
+
+/**
+ * @typedef {Object}
+ * @property {boolean=} [ordered=true]
+ * @property {number=} maxPacketLifeTime
+ * @property {number=} maxRetransmits
+ * @property {string=} [protocol=""]
+ * @property {boolean=} [negotiated=false]
+ * @property {number=} id
+ * @property {string=} [priority='low']
+ * see https://www.w3.org/TR/webrtc/#dom-rtcdatachannelinit for documentation
+ * Type inconsistencies due to Closure limitations:
+ * maxPacketLifeTime should be UnsignedShort
+ * maxRetransmits should be UnsignedShort
+ * protocol should be USVString
+ * id should be UnsignedShort
+ * In WebIDL priority is an enum with values 'very-low', 'low',
+ * 'medium' and 'high', but there is no mechanism in Closure for describing
+ * a specialization of the string type.
+ */
+var RTCDataChannelInitDictionary_;
+
+/**
+ * @typedef {RTCDataChannelInitInterface_|RTCDataChannelInitRecord_|RTCDataChannelInitDictionary_}
+ */
+var RTCDataChannelInit;
+
+/**
+ * @typedef {{expires: number}}
+ */
+var RTCCertificate;
+
+/**
+ * @param {RTCConfiguration} configuration
+ * @param {!MediaConstraints=} constraints
+ * @constructor
+ * @implements {EventTarget}
+ */
+function RTCPeerConnection(configuration, constraints) {}
+
+/**
+ * @param {Object} keygenAlgorithm
+ * @return {Promise}
+ */
+RTCPeerConnection.generateCertificate = function (keygenAlgorithm) {};
+
+/**
+ * @override
+ */
+RTCPeerConnection.prototype.addEventListener = function(
+ type, listener, opt_useCapture) {};
+
+/**
+ * @override
+ */
+RTCPeerConnection.prototype.removeEventListener = function(
+ type, listener, opt_useCapture) {};
+
+/**
+ * @override
+ * @return {boolean}
+ */
+RTCPeerConnection.prototype.dispatchEvent = function(evt) {};
+
+
+// NB: Until closure annotations support overloading, many of the following
+// functions take odd unions of parameter types. This is to support the various
+// api differences between browsers. Generally, returning a promise means you
+// don't take callback function parameters and draw any further parameters
+// forward, and vice versa.
+
+/**
+ * @param {(!RTCSessionDescriptionCallback|!MediaConstraints)=}
+ * successCallbackOrConstraints
+ * @param {!RTCPeerConnectionErrorCallback=} errorCallback
+ * @param {!MediaConstraints=} constraints
+ * @return {!Promise|undefined}
+ */
+RTCPeerConnection.prototype.createOffer = function(successCallbackOrConstraints,
+ errorCallback, constraints) {};
+
+/**
+ * @param {(!RTCSessionDescriptionCallback|!MediaConstraints)=}
+ * successCallbackOrConstraints
+ * @param {!RTCPeerConnectionErrorCallback=} errorCallback
+ * @param {!MediaConstraints=} constraints
+ * @return {!Promise|undefined}
+ */
+RTCPeerConnection.prototype.createAnswer =
+ function(successCallbackOrConstraints, errorCallback, constraints) {};
+
+/**
+ * @param {!RTCSessionDescription} description
+ * @param {!RTCVoidCallback=} successCallback
+ * @param {!RTCPeerConnectionErrorCallback=} errorCallback
+ * @return {!Promise}
+ */
+RTCPeerConnection.prototype.setLocalDescription = function(description,
+ successCallback, errorCallback) {};
+
+/**
+ * @param {!RTCSessionDescription} description
+ * @param {!RTCVoidCallback=} successCallback
+ * @param {!RTCPeerConnectionErrorCallback=} errorCallback
+ * @return {!Promise}
+ */
+RTCPeerConnection.prototype.setRemoteDescription = function(description,
+ successCallback, errorCallback) {};
+
+/**
+ * @type {?RTCSessionDescription}
+ * Read only.
+ */
+RTCPeerConnection.prototype.localDescription;
+
+/**
+ * @type {?RTCSessionDescription}
+ * Read only.
+ */
+RTCPeerConnection.prototype.remoteDescription;
+
+/**
+ * @type {RTCSignalingState}
+ * Read only.
+ */
+RTCPeerConnection.prototype.signalingState;
+
+/**
+ * @param {?RTCConfiguration=} configuration
+ * @param {?MediaConstraints=} constraints
+ * @return {undefined}
+ */
+RTCPeerConnection.prototype.updateIce = function(configuration, constraints) {};
+
+/**
+ * Void in Chrome for now, a promise that you can then/catch in Firefox.
+ * @param {!RTCIceCandidate} candidate
+ * @param {!RTCVoidCallback=} successCallback
+ * @param {!function(DOMException)=} errorCallback
+ * @return {!Promise|undefined}
+ */
+RTCPeerConnection.prototype.addIceCandidate = function(candidate, successCallback, errorCallback) {};
+
+/**
+ * @type {!RTCIceGatheringState}
+ * Read only.
+ */
+RTCPeerConnection.prototype.iceGatheringState;
+
+/**
+ * @type {!RTCIceConnectionState}
+ * Read only.
+ */
+RTCPeerConnection.prototype.iceConnectionState;
+
+/**
+ * @return {!Array}
+ */
+RTCPeerConnection.prototype.getLocalStreams = function() {};
+
+/**
+ * @return {!Array}
+ */
+RTCPeerConnection.prototype.getRemoteStreams = function() {};
+
+/**
+ * @param {string} streamId
+ * @return {MediaStream}
+ */
+RTCPeerConnection.prototype.getStreamById = function(streamId) {};
+
+/**
+ * @return {!Array}
+ */
+RTCPeerConnection.prototype.getSenders = function() {};
+
+/**
+ * @return {!Array}
+ */
+RTCPeerConnection.prototype.getReceivers = function() {};
+
+/**
+ * @param {?string} label
+ * @param {RTCDataChannelInit=} dataChannelDict
+ * @return {!RTCDataChannel}
+ */
+RTCPeerConnection.prototype.createDataChannel =
+ function(label, dataChannelDict) {};
+/**
+ * @param {!MediaStream} stream
+ * @param {!MediaConstraints=} constraints
+ * @return {undefined}
+ */
+RTCPeerConnection.prototype.addStream = function(stream, constraints) {};
+
+/**
+ * @param {!MediaStream} stream
+ * @return {undefined}
+ */
+RTCPeerConnection.prototype.removeStream = function(stream) {};
+
+/**
+ * @param {!MediaStreamTrack} track
+ * @param {!MediaStream} stream
+ * @param {...MediaStream} var_args Additional streams.
+ * @return {!RTCRtpSender}
+ */
+RTCPeerConnection.prototype.addTrack = function(track, stream, var_args) {};
+
+/**
+ * @param {!MediaStreamTrack|string} trackOrKind
+ * @param {?RTCRtpTransceiverInit=} init
+ * @return {!RTCRtpTransceiver}
+ */
+RTCPeerConnection.prototype.addTransceiver = function(trackOrKind, init) {};
+
+/**
+ * Returns the list of transceivers are currently attached to this peer.
+ *
+ * @return {!Array}
+ */
+RTCPeerConnection.prototype.getTransceivers = function() {};
+
+/**
+ * @return {!RTCConfiguration}
+ */
+RTCPeerConnection.prototype.getConfiguration = function() {};
+
+/**
+ * @param {!RTCConfiguration} configuration
+ * @return {undefined}
+ */
+RTCPeerConnection.prototype.setConfiguration = function(configuration) {};
+
+/**
+ * @param {!RTCRtpSender} sender
+ * @return {undefined}
+ */
+RTCPeerConnection.prototype.removeTrack = function(sender) {};
+
+// TODO(bemasc): Add identity provider stuff once implementations exist
+
+// TODO(rjogrady): Per w3c spec, getStats() should always return a Promise.
+// Remove RTCStatsReport from the return value once Firefox supports that.
+/**
+ * Firefox' getstats is synchronous and returns a much simpler
+ * {!RTCStatsReport} Map-like object.
+ * @param {!RTCStatsCallback=} successCallback
+ * @param {MediaStreamTrack=} selector
+ * @return {undefined|!RTCStatsReport|!Promise}
+ */
+RTCPeerConnection.prototype.getStats = function(successCallback, selector) {};
+
+RTCPeerConnection.prototype.close = function() {};
+
+/**
+ * @type {?function(!Event)}
+ */
+RTCPeerConnection.prototype.onnegotiationneeded;
+
+/**
+ * @type {?function(!RTCPeerConnectionIceEvent)}
+ */
+RTCPeerConnection.prototype.onicecandidate;
+
+/**
+ * @type {?function(!Event)}
+ */
+RTCPeerConnection.prototype.onsignalingstatechange;
+
+/**
+ * @type {?function(!MediaStreamEvent)}
+ */
+RTCPeerConnection.prototype.onaddstream;
+
+/**
+ * @type {?function(!RTCTrackEvent)}
+ */
+RTCPeerConnection.prototype.ontrack;
+
+/**
+ * @type {?function(!MediaStreamEvent)}
+ */
+RTCPeerConnection.prototype.onremovestream;
+
+/**
+ * @type {?function(!Event)}
+ */
+RTCPeerConnection.prototype.oniceconnectionstatechange;
+
+/**
+ * @type {?function(!RTCDataChannelEvent)}
+ */
+RTCPeerConnection.prototype.ondatachannel;
+
+/**
+ * @const
+ */
+var webkitRTCPeerConnection = RTCPeerConnection;
+
+/**
+ * @const
+ */
+var mozRTCPeerConnection = RTCPeerConnection;
+
+/**
+ * @interface
+ * @param {RTCIceGatherer} iceGatherer
+ * @see https://www.w3.org/TR/webrtc/#idl-def-rtcicetransport
+ */
+function RTCIceTransport(iceGatherer) {}
+
+/**
+ * @type {!RTCIceGatheringState}
+ * @const
+ */
+RTCIceTransport.prototype.gatheringState;
+
+/**
+ * @return {RTCIceCandidate[]}
+ */
+RTCIceTransport.prototype.getLocalCandidates = function(){};
+
+/**
+ * @return {RTCIceCandidate[]}
+ */
+RTCIceTransport.prototype.getRemoteCandidates = function(){};
+
+/**
+ * @return {RTCIceCandidatePair}
+ */
+RTCIceTransport.prototype.getSelectedCandidatePair = function(){};
+
+/**
+ * @return {RTCIceParameters}
+ */
+RTCIceTransport.prototype.getLocalParameters = function(){};
+
+/**
+ * @return {RTCIceParameters}
+ */
+RTCIceTransport.prototype.getRemoteParameters = function(){};
+
+/**
+ * @param {!Event} e
+ * @return {undefined}
+ */
+RTCIceTransport.prototype.onstatechange = function(e){};
+
+/**
+ * @param {!Event} e
+ * @return {undefined}
+ */
+RTCIceTransport.prototype.ongatheringstatechange = function(e){};
+
+/**
+ * @param {!Event} e
+ * @return {undefined}
+ */
+RTCIceTransport.prototype.onselectedcandidatepairchange = function(e){};
+
+
+/**
+ * @constructor
+ * @param {!RTCIceGatherOptions} options
+ * @see https://msdn.microsoft.com/en-us/library/mt433107(v=vs.85).aspx
+ */
+function RTCIceGatherer(options) {}
+
+/**
+ * @interface
+ * @param {RTCIceTransport} iceTransport
+ * @see https://www.w3.org/TR/webrtc/#idl-def-rtcdtlstransport
+ */
+function RTCDtlsTransport(iceTransport) {}
+
+/**
+ * @type {RTCIceTransport}
+ * @const
+ */
+RTCDtlsTransport.prototype.transport;
+
+/**
+ * @return {ArrayBuffer[]}
+ */
+RTCDtlsTransport.prototype.getRemoteCertificates = function() {};
+
+/**
+ * @param {!Event} e
+ * @return {undefined}
+ */
+RTCDtlsTransport.prototype.onstatechange = function(e){};
From 271628c280a1f460b498392f792dd7c309344bb8 Mon Sep 17 00:00:00 2001
From: Aditya Sharad
Date: Mon, 12 Nov 2018 14:55:26 +0000
Subject: [PATCH 41/71] Version: Bump to 1.18.3 dev.
---
cpp/ql/src/META-INF/MANIFEST.MF | 4 ++--
csharp/ql/src/META-INF/MANIFEST.MF | 4 ++--
java/ql/src/META-INF/MANIFEST.MF | 4 ++--
javascript/ql/src/META-INF/MANIFEST.MF | 4 ++--
4 files changed, 8 insertions(+), 8 deletions(-)
diff --git a/cpp/ql/src/META-INF/MANIFEST.MF b/cpp/ql/src/META-INF/MANIFEST.MF
index a6f8f5008d9..b7387557cc2 100644
--- a/cpp/ql/src/META-INF/MANIFEST.MF
+++ b/cpp/ql/src/META-INF/MANIFEST.MF
@@ -2,7 +2,7 @@ Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: Semmle C/C++ Default Queries
Bundle-SymbolicName: com.semmle.plugin.semmlecode.cpp.queries;singleton:=true
-Bundle-Version: 1.18.2
+Bundle-Version: 1.18.3.qualifier
Bundle-Vendor: Semmle Ltd.
Bundle-ActivationPolicy: lazy
-Require-Bundle: com.semmle.plugin.qdt.ui;bundle-version="[1.18.2,1.18.2]"
+Require-Bundle: com.semmle.plugin.qdt.ui;bundle-version="[1.18.3.qualifier,1.18.3.qualifier]"
diff --git a/csharp/ql/src/META-INF/MANIFEST.MF b/csharp/ql/src/META-INF/MANIFEST.MF
index ada13a5b7ae..9ee778191ae 100644
--- a/csharp/ql/src/META-INF/MANIFEST.MF
+++ b/csharp/ql/src/META-INF/MANIFEST.MF
@@ -2,7 +2,7 @@ Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: Semmle C# Default Queries
Bundle-SymbolicName: com.semmle.plugin.semmlecode.csharp.queries;singleton:=true
-Bundle-Version: 1.18.2
+Bundle-Version: 1.18.3.qualifier
Bundle-Vendor: Semmle Ltd.
Bundle-ActivationPolicy: lazy
-Require-Bundle: com.semmle.plugin.qdt.ui;bundle-version="[1.18.2,1.18.2]"
+Require-Bundle: com.semmle.plugin.qdt.ui;bundle-version="[1.18.3.qualifier,1.18.3.qualifier]"
diff --git a/java/ql/src/META-INF/MANIFEST.MF b/java/ql/src/META-INF/MANIFEST.MF
index d757adf90a1..cb4864fe9d7 100644
--- a/java/ql/src/META-INF/MANIFEST.MF
+++ b/java/ql/src/META-INF/MANIFEST.MF
@@ -2,8 +2,8 @@ Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: Semmle Default Java Queries
Bundle-SymbolicName: com.semmle.plugin.semmlecode.queries;singleton:=true
-Bundle-Version: 1.18.2
+Bundle-Version: 1.18.3.qualifier
Bundle-Vendor: Semmle Ltd.
Bundle-ActivationPolicy: lazy
-Require-Bundle: com.semmle.plugin.qdt.ui;bundle-version="[1.18.2,1.18.2]"
+Require-Bundle: com.semmle.plugin.qdt.ui;bundle-version="[1.18.3.qualifier,1.18.3.qualifier]"
diff --git a/javascript/ql/src/META-INF/MANIFEST.MF b/javascript/ql/src/META-INF/MANIFEST.MF
index 39e24984897..4313cac94f7 100644
--- a/javascript/ql/src/META-INF/MANIFEST.MF
+++ b/javascript/ql/src/META-INF/MANIFEST.MF
@@ -2,7 +2,7 @@ Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: Semmle JavaScript Default Queries
Bundle-SymbolicName: com.semmle.plugin.semmlecode.javascript.queries;singleton:=true
-Bundle-Version: 1.18.2
+Bundle-Version: 1.18.3.qualifier
Bundle-Vendor: Semmle Ltd.
Bundle-ActivationPolicy: lazy
-Require-Bundle: com.semmle.plugin.qdt.ui;bundle-version="[1.18.2,1.18.2]"
+Require-Bundle: com.semmle.plugin.qdt.ui;bundle-version="[1.18.3.qualifier,1.18.3.qualifier]"
From 2d665e51d06798c298328fd980ee60d3dc196d7d Mon Sep 17 00:00:00 2001
From: Geoffrey White <40627776+geoffw0@users.noreply.github.com>
Date: Mon, 12 Nov 2018 15:14:41 +0000
Subject: [PATCH 42/71] CPP: Move the BitwiseSignCheck.ql test.
---
.../Arithmetic/BitwiseSignCheck/BitwiseSignCheck.expected} | 0
.../Arithmetic/BitwiseSignCheck/BitwiseSignCheck.qlref} | 0
.../Likely Bugs/Arithmetic/BitwiseSignCheck}/bsc.cpp | 0
3 files changed, 0 insertions(+), 0 deletions(-)
rename cpp/ql/test/{library-tests/queries/bitwise_sign_check/bsc.expected => query-tests/Likely Bugs/Arithmetic/BitwiseSignCheck/BitwiseSignCheck.expected} (100%)
rename cpp/ql/test/{library-tests/queries/bitwise_sign_check/bsc.qlref => query-tests/Likely Bugs/Arithmetic/BitwiseSignCheck/BitwiseSignCheck.qlref} (100%)
rename cpp/ql/test/{library-tests/queries/bitwise_sign_check => query-tests/Likely Bugs/Arithmetic/BitwiseSignCheck}/bsc.cpp (100%)
diff --git a/cpp/ql/test/library-tests/queries/bitwise_sign_check/bsc.expected b/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/BitwiseSignCheck/BitwiseSignCheck.expected
similarity index 100%
rename from cpp/ql/test/library-tests/queries/bitwise_sign_check/bsc.expected
rename to cpp/ql/test/query-tests/Likely Bugs/Arithmetic/BitwiseSignCheck/BitwiseSignCheck.expected
diff --git a/cpp/ql/test/library-tests/queries/bitwise_sign_check/bsc.qlref b/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/BitwiseSignCheck/BitwiseSignCheck.qlref
similarity index 100%
rename from cpp/ql/test/library-tests/queries/bitwise_sign_check/bsc.qlref
rename to cpp/ql/test/query-tests/Likely Bugs/Arithmetic/BitwiseSignCheck/BitwiseSignCheck.qlref
diff --git a/cpp/ql/test/library-tests/queries/bitwise_sign_check/bsc.cpp b/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/BitwiseSignCheck/bsc.cpp
similarity index 100%
rename from cpp/ql/test/library-tests/queries/bitwise_sign_check/bsc.cpp
rename to cpp/ql/test/query-tests/Likely Bugs/Arithmetic/BitwiseSignCheck/bsc.cpp
From 03cad6c0844562568bb419fa390aa13be364ad51 Mon Sep 17 00:00:00 2001
From: Geoffrey White <40627776+geoffw0@users.noreply.github.com>
Date: Mon, 12 Nov 2018 15:17:26 +0000
Subject: [PATCH 43/71] CPP: Move the AV Rule 97 test.
---
.../jsf/4.10 Classes/AV Rule 97/AV Rule 97.expected} | 0
.../jsf/4.10 Classes/AV Rule 97/AV Rule 97.qlref} | 0
.../jsf97 => query-tests/jsf/4.10 Classes/AV Rule 97}/jsf97.cpp | 0
3 files changed, 0 insertions(+), 0 deletions(-)
rename cpp/ql/test/{library-tests/queries/jsf97/jsf97.expected => query-tests/jsf/4.10 Classes/AV Rule 97/AV Rule 97.expected} (100%)
rename cpp/ql/test/{library-tests/queries/jsf97/jsf97.qlref => query-tests/jsf/4.10 Classes/AV Rule 97/AV Rule 97.qlref} (100%)
rename cpp/ql/test/{library-tests/queries/jsf97 => query-tests/jsf/4.10 Classes/AV Rule 97}/jsf97.cpp (100%)
diff --git a/cpp/ql/test/library-tests/queries/jsf97/jsf97.expected b/cpp/ql/test/query-tests/jsf/4.10 Classes/AV Rule 97/AV Rule 97.expected
similarity index 100%
rename from cpp/ql/test/library-tests/queries/jsf97/jsf97.expected
rename to cpp/ql/test/query-tests/jsf/4.10 Classes/AV Rule 97/AV Rule 97.expected
diff --git a/cpp/ql/test/library-tests/queries/jsf97/jsf97.qlref b/cpp/ql/test/query-tests/jsf/4.10 Classes/AV Rule 97/AV Rule 97.qlref
similarity index 100%
rename from cpp/ql/test/library-tests/queries/jsf97/jsf97.qlref
rename to cpp/ql/test/query-tests/jsf/4.10 Classes/AV Rule 97/AV Rule 97.qlref
diff --git a/cpp/ql/test/library-tests/queries/jsf97/jsf97.cpp b/cpp/ql/test/query-tests/jsf/4.10 Classes/AV Rule 97/jsf97.cpp
similarity index 100%
rename from cpp/ql/test/library-tests/queries/jsf97/jsf97.cpp
rename to cpp/ql/test/query-tests/jsf/4.10 Classes/AV Rule 97/jsf97.cpp
From 1417929cdf628bab7372b6d20d0922f28049da73 Mon Sep 17 00:00:00 2001
From: Geoffrey White <40627776+geoffw0@users.noreply.github.com>
Date: Mon, 12 Nov 2018 15:25:20 +0000
Subject: [PATCH 44/71] CPP: Merge the Todo/FixmeComments tests.
---
cpp/ql/test/library-tests/queries/todo_fixme/.gitattributes | 1 -
cpp/ql/test/library-tests/queries/todo_fixme/todo.expected | 3 ---
cpp/ql/test/library-tests/queries/todo_fixme/todo.qlref | 1 -
.../test/query-tests/Documentation/TodoComments/.gitattributes | 1 +
.../Documentation/TodoComments/FixmeComments.expected} | 0
.../Documentation/TodoComments/FixmeComments.qlref} | 0
.../Documentation/TodoComments/TodoComments.expected | 3 +++
.../Documentation/TodoComments}/todo_fixme.cpp | 0
8 files changed, 4 insertions(+), 5 deletions(-)
delete mode 100644 cpp/ql/test/library-tests/queries/todo_fixme/.gitattributes
delete mode 100644 cpp/ql/test/library-tests/queries/todo_fixme/todo.expected
delete mode 100644 cpp/ql/test/library-tests/queries/todo_fixme/todo.qlref
rename cpp/ql/test/{library-tests/queries/todo_fixme/fixme.expected => query-tests/Documentation/TodoComments/FixmeComments.expected} (100%)
rename cpp/ql/test/{library-tests/queries/todo_fixme/fixme.qlref => query-tests/Documentation/TodoComments/FixmeComments.qlref} (100%)
rename cpp/ql/test/{library-tests/queries/todo_fixme => query-tests/Documentation/TodoComments}/todo_fixme.cpp (100%)
diff --git a/cpp/ql/test/library-tests/queries/todo_fixme/.gitattributes b/cpp/ql/test/library-tests/queries/todo_fixme/.gitattributes
deleted file mode 100644
index 309468b7488..00000000000
--- a/cpp/ql/test/library-tests/queries/todo_fixme/.gitattributes
+++ /dev/null
@@ -1 +0,0 @@
-todo_fixme.cpp text eol=lf
diff --git a/cpp/ql/test/library-tests/queries/todo_fixme/todo.expected b/cpp/ql/test/library-tests/queries/todo_fixme/todo.expected
deleted file mode 100644
index f7dd64f9540..00000000000
--- a/cpp/ql/test/library-tests/queries/todo_fixme/todo.expected
+++ /dev/null
@@ -1,3 +0,0 @@
-| todo_fixme.cpp:1:1:1:17 | // TODO: Thing 1. | TODO comment: Thing 1. |
-| todo_fixme.cpp:2:1:2:20 | /* TODO: Thing 2. */ | TODO comment: Thing 2. |
-| todo_fixme.cpp:3:1:5:3 | /**\n * TODO: Thing 3.\n */ | TODO comment: Thing 3. |
diff --git a/cpp/ql/test/library-tests/queries/todo_fixme/todo.qlref b/cpp/ql/test/library-tests/queries/todo_fixme/todo.qlref
deleted file mode 100644
index bb57dbe50ce..00000000000
--- a/cpp/ql/test/library-tests/queries/todo_fixme/todo.qlref
+++ /dev/null
@@ -1 +0,0 @@
-Documentation/TodoComments.ql
diff --git a/cpp/ql/test/query-tests/Documentation/TodoComments/.gitattributes b/cpp/ql/test/query-tests/Documentation/TodoComments/.gitattributes
index 86b7d112c0f..ccc59c54234 100644
--- a/cpp/ql/test/query-tests/Documentation/TodoComments/.gitattributes
+++ b/cpp/ql/test/query-tests/Documentation/TodoComments/.gitattributes
@@ -1 +1,2 @@
todo.c text eol=lf
+todo_fixme.cpp text eol=lf
diff --git a/cpp/ql/test/library-tests/queries/todo_fixme/fixme.expected b/cpp/ql/test/query-tests/Documentation/TodoComments/FixmeComments.expected
similarity index 100%
rename from cpp/ql/test/library-tests/queries/todo_fixme/fixme.expected
rename to cpp/ql/test/query-tests/Documentation/TodoComments/FixmeComments.expected
diff --git a/cpp/ql/test/library-tests/queries/todo_fixme/fixme.qlref b/cpp/ql/test/query-tests/Documentation/TodoComments/FixmeComments.qlref
similarity index 100%
rename from cpp/ql/test/library-tests/queries/todo_fixme/fixme.qlref
rename to cpp/ql/test/query-tests/Documentation/TodoComments/FixmeComments.qlref
diff --git a/cpp/ql/test/query-tests/Documentation/TodoComments/TodoComments.expected b/cpp/ql/test/query-tests/Documentation/TodoComments/TodoComments.expected
index c6854c2159a..e02c4752128 100644
--- a/cpp/ql/test/query-tests/Documentation/TodoComments/TodoComments.expected
+++ b/cpp/ql/test/query-tests/Documentation/TodoComments/TodoComments.expected
@@ -6,3 +6,6 @@
| todo.c:17:1:21:15 | /* Some comment\n * TODO This is a mid-comment\n * multi-line comment with two\n * TODO comments\n * inside it */ | TODO comment: comments [...] |
| todo.c:23:1:23:53 | /* TODO This comment mentions TODO in its body too */ | TODO comment: This comment mentions TODO in its body too |
| todo.c:25:1:25:40 | // TODO: Can have C++-style comments too | TODO comment: Can have C++-style comments too |
+| todo_fixme.cpp:1:1:1:17 | // TODO: Thing 1. | TODO comment: Thing 1. |
+| todo_fixme.cpp:2:1:2:20 | /* TODO: Thing 2. */ | TODO comment: Thing 2. |
+| todo_fixme.cpp:3:1:5:3 | /**\n * TODO: Thing 3.\n */ | TODO comment: Thing 3. |
diff --git a/cpp/ql/test/library-tests/queries/todo_fixme/todo_fixme.cpp b/cpp/ql/test/query-tests/Documentation/TodoComments/todo_fixme.cpp
similarity index 100%
rename from cpp/ql/test/library-tests/queries/todo_fixme/todo_fixme.cpp
rename to cpp/ql/test/query-tests/Documentation/TodoComments/todo_fixme.cpp
From 1d464ae35dbb285f4536d90d6a4da96547443943 Mon Sep 17 00:00:00 2001
From: Geoffrey White <40627776+geoffw0@users.noreply.github.com>
Date: Mon, 12 Nov 2018 15:28:33 +0000
Subject: [PATCH 45/71] CPP: Merge the ExprHasNoEffect tests.
---
.../queries/expr_has_no_effect/expr_has_no_effect.expected | 7 -------
.../queries/expr_has_no_effect/expr_has_no_effect.qlref | 1 -
.../Likely Typos/ExprHasNoEffect/ExprHasNoEffect.expected | 7 +++++++
.../Likely Bugs/Likely Typos/ExprHasNoEffect}/calls.cpp | 0
.../Likely Typos/ExprHasNoEffect}/templatey.cpp | 0
.../Likely Bugs/Likely Typos/ExprHasNoEffect}/volatile.c | 0
6 files changed, 7 insertions(+), 8 deletions(-)
delete mode 100644 cpp/ql/test/library-tests/queries/expr_has_no_effect/expr_has_no_effect.expected
delete mode 100644 cpp/ql/test/library-tests/queries/expr_has_no_effect/expr_has_no_effect.qlref
rename cpp/ql/test/{library-tests/queries/expr_has_no_effect => query-tests/Likely Bugs/Likely Typos/ExprHasNoEffect}/calls.cpp (100%)
rename cpp/ql/test/{library-tests/queries/expr_has_no_effect => query-tests/Likely Bugs/Likely Typos/ExprHasNoEffect}/templatey.cpp (100%)
rename cpp/ql/test/{library-tests/queries/expr_has_no_effect => query-tests/Likely Bugs/Likely Typos/ExprHasNoEffect}/volatile.c (100%)
diff --git a/cpp/ql/test/library-tests/queries/expr_has_no_effect/expr_has_no_effect.expected b/cpp/ql/test/library-tests/queries/expr_has_no_effect/expr_has_no_effect.expected
deleted file mode 100644
index 5982cfa589e..00000000000
--- a/cpp/ql/test/library-tests/queries/expr_has_no_effect/expr_has_no_effect.expected
+++ /dev/null
@@ -1,7 +0,0 @@
-| calls.cpp:8:5:8:5 | 1 | This expression has no effect. | calls.cpp:8:5:8:5 | 1 | |
-| calls.cpp:12:5:12:16 | call to thingy | This expression has no effect (because $@ has no external side effects). | calls.cpp:7:15:7:20 | thingy | thingy |
-| templatey.cpp:39:3:39:23 | call to pointless_add_numbers | This expression has no effect (because $@ has no external side effects). | templatey.cpp:29:5:29:25 | pointless_add_numbers | pointless_add_numbers |
-| volatile.c:9:5:9:5 | c | This expression has no effect. | volatile.c:9:5:9:5 | c | |
-| volatile.c:12:5:12:9 | access to array | This expression has no effect. | volatile.c:12:5:12:9 | access to array | |
-| volatile.c:16:5:16:7 | * ... | This expression has no effect. | volatile.c:16:5:16:7 | * ... | |
-| volatile.c:20:5:20:13 | * ... | This expression has no effect. | volatile.c:20:5:20:13 | * ... | |
diff --git a/cpp/ql/test/library-tests/queries/expr_has_no_effect/expr_has_no_effect.qlref b/cpp/ql/test/library-tests/queries/expr_has_no_effect/expr_has_no_effect.qlref
deleted file mode 100644
index 6d8e82140d6..00000000000
--- a/cpp/ql/test/library-tests/queries/expr_has_no_effect/expr_has_no_effect.qlref
+++ /dev/null
@@ -1 +0,0 @@
-Likely Bugs/Likely Typos/ExprHasNoEffect.ql
\ No newline at end of file
diff --git a/cpp/ql/test/query-tests/Likely Bugs/Likely Typos/ExprHasNoEffect/ExprHasNoEffect.expected b/cpp/ql/test/query-tests/Likely Bugs/Likely Typos/ExprHasNoEffect/ExprHasNoEffect.expected
index f50c352fe34..32cf4a9608b 100644
--- a/cpp/ql/test/query-tests/Likely Bugs/Likely Typos/ExprHasNoEffect/ExprHasNoEffect.expected
+++ b/cpp/ql/test/query-tests/Likely Bugs/Likely Typos/ExprHasNoEffect/ExprHasNoEffect.expected
@@ -1,6 +1,9 @@
+| calls.cpp:8:5:8:5 | 1 | This expression has no effect. | calls.cpp:8:5:8:5 | 1 | |
+| calls.cpp:12:5:12:16 | call to thingy | This expression has no effect (because $@ has no external side effects). | calls.cpp:7:15:7:20 | thingy | thingy |
| preproc.c:89:2:89:4 | call to fn4 | This expression has no effect (because $@ has no external side effects). | preproc.c:33:5:33:7 | fn4 | fn4 |
| preproc.c:94:2:94:4 | call to fn9 | This expression has no effect (because $@ has no external side effects). | preproc.c:78:5:78:7 | fn9 | fn9 |
| template.cpp:19:3:19:3 | call to operator++ | This expression has no effect (because $@ has no external side effects). | template.cpp:9:10:9:19 | operator++ | operator++ |
+| templatey.cpp:39:3:39:23 | call to pointless_add_numbers | This expression has no effect (because $@ has no external side effects). | templatey.cpp:29:5:29:25 | pointless_add_numbers | pointless_add_numbers |
| test.c:7:5:7:5 | 0 | This expression has no effect. | test.c:7:5:7:5 | 0 | |
| test.c:9:8:9:8 | 1 | This expression has no effect. | test.c:9:8:9:8 | 1 | |
| test.c:9:11:9:11 | 2 | This expression has no effect. | test.c:9:11:9:11 | 2 | |
@@ -23,3 +26,7 @@
| test.cpp:25:3:25:3 | call to operator++ | This expression has no effect (because $@ has no external side effects). | test.cpp:9:14:9:23 | operator++ | operator++ |
| test.cpp:62:5:62:5 | call to operator= | This expression has no effect (because $@ has no external side effects). | test.cpp:47:14:47:22 | operator= | operator= |
| test.cpp:65:5:65:5 | call to operator= | This expression has no effect (because $@ has no external side effects). | test.cpp:55:7:55:7 | operator= | operator= |
+| volatile.c:9:5:9:5 | c | This expression has no effect. | volatile.c:9:5:9:5 | c | |
+| volatile.c:12:5:12:9 | access to array | This expression has no effect. | volatile.c:12:5:12:9 | access to array | |
+| volatile.c:16:5:16:7 | * ... | This expression has no effect. | volatile.c:16:5:16:7 | * ... | |
+| volatile.c:20:5:20:13 | * ... | This expression has no effect. | volatile.c:20:5:20:13 | * ... | |
diff --git a/cpp/ql/test/library-tests/queries/expr_has_no_effect/calls.cpp b/cpp/ql/test/query-tests/Likely Bugs/Likely Typos/ExprHasNoEffect/calls.cpp
similarity index 100%
rename from cpp/ql/test/library-tests/queries/expr_has_no_effect/calls.cpp
rename to cpp/ql/test/query-tests/Likely Bugs/Likely Typos/ExprHasNoEffect/calls.cpp
diff --git a/cpp/ql/test/library-tests/queries/expr_has_no_effect/templatey.cpp b/cpp/ql/test/query-tests/Likely Bugs/Likely Typos/ExprHasNoEffect/templatey.cpp
similarity index 100%
rename from cpp/ql/test/library-tests/queries/expr_has_no_effect/templatey.cpp
rename to cpp/ql/test/query-tests/Likely Bugs/Likely Typos/ExprHasNoEffect/templatey.cpp
diff --git a/cpp/ql/test/library-tests/queries/expr_has_no_effect/volatile.c b/cpp/ql/test/query-tests/Likely Bugs/Likely Typos/ExprHasNoEffect/volatile.c
similarity index 100%
rename from cpp/ql/test/library-tests/queries/expr_has_no_effect/volatile.c
rename to cpp/ql/test/query-tests/Likely Bugs/Likely Typos/ExprHasNoEffect/volatile.c
From fa8fd0513c390130e371dbef609e117bcd0a76e0 Mon Sep 17 00:00:00 2001
From: Felicity Chapman
Date: Mon, 12 Nov 2018 17:54:59 +0000
Subject: [PATCH 46/71] Update qhelp for queries with CWE tags
---
.../Dead Code/DeadStoreOfLocalUnread.qhelp | 7 +++++--
.../Dead Code/DeadStoreOfLocalUnread.ql | 5 +----
.../LocalInitialisedButNotUsed.qhelp | 5 ++++-
.../Dead Code/LocalInitialisedButNotUsed.ql | 2 +-
.../Dead Code/UnusedLocal.qhelp | 19 +++++--------------
.../Dead Code/UnusedLocal.ql | 2 +-
.../legacy/InexactVarArg.java | 2 +-
.../legacy/InexactVarArg.qhelp | 2 +-
8 files changed, 19 insertions(+), 25 deletions(-)
diff --git a/java/ql/src/Violations of Best Practice/Dead Code/DeadStoreOfLocalUnread.qhelp b/java/ql/src/Violations of Best Practice/Dead Code/DeadStoreOfLocalUnread.qhelp
index adfce3b0764..b9bc97d56c9 100644
--- a/java/ql/src/Violations of Best Practice/Dead Code/DeadStoreOfLocalUnread.qhelp
+++ b/java/ql/src/Violations of Best Practice/Dead Code/DeadStoreOfLocalUnread.qhelp
@@ -5,8 +5,9 @@
-A value is assigned to a local variable, but the variable is never read subsequently. This means
-that the original assignment is suspect, because the state of the local variable that
+
A value is assigned to a local variable, but the local variable is only
+read before the assignment, not after it.
+This means that the assignment is suspect, because the state of the local variable that
it creates is never used.
@@ -17,4 +18,6 @@ though: if the right-hand side has a side-effect (like performing a method call)
it is important to keep this to preserve the overall behavior.
+
+
diff --git a/java/ql/src/Violations of Best Practice/Dead Code/DeadStoreOfLocalUnread.ql b/java/ql/src/Violations of Best Practice/Dead Code/DeadStoreOfLocalUnread.ql
index aabf70cda59..ccca6818ad1 100644
--- a/java/ql/src/Violations of Best Practice/Dead Code/DeadStoreOfLocalUnread.ql
+++ b/java/ql/src/Violations of Best Practice/Dead Code/DeadStoreOfLocalUnread.ql
@@ -1,9 +1,6 @@
/**
* @name Useless assignment to local variable
- * @description A value is assigned to a local variable, but the local variable
- * is only read before the assignment, not after it.
- * The assignment has no effect: either it should be removed,
- * or the assigned value should be used.
+ * @description Assigning a value to a local variable that is not later used has no effect.
* @kind problem
* @problem.severity recommendation
* @precision low
diff --git a/java/ql/src/Violations of Best Practice/Dead Code/LocalInitialisedButNotUsed.qhelp b/java/ql/src/Violations of Best Practice/Dead Code/LocalInitialisedButNotUsed.qhelp
index ef1451768f5..f35a9e53a7e 100644
--- a/java/ql/src/Violations of Best Practice/Dead Code/LocalInitialisedButNotUsed.qhelp
+++ b/java/ql/src/Violations of Best Practice/Dead Code/LocalInitialisedButNotUsed.qhelp
@@ -6,7 +6,7 @@
A local variable is initialized, but the variable is never read or written to subsequently. This suggests
-that the local variable is either useless and should be removed, or that the value was intended to be used
+that the local variable is either unnecessary and should be removed, or that the value was intended to be used
somewhere.
@@ -18,4 +18,7 @@ though: if the right-hand side has a side-effect (like performing a method call)
it is important to keep this to preserve the overall behavior.
+
+
+
diff --git a/java/ql/src/Violations of Best Practice/Dead Code/LocalInitialisedButNotUsed.ql b/java/ql/src/Violations of Best Practice/Dead Code/LocalInitialisedButNotUsed.ql
index b0fefa93845..b1ff841c7cd 100644
--- a/java/ql/src/Violations of Best Practice/Dead Code/LocalInitialisedButNotUsed.ql
+++ b/java/ql/src/Violations of Best Practice/Dead Code/LocalInitialisedButNotUsed.ql
@@ -1,6 +1,6 @@
/**
* @name Local variable is initialized but not used
- * @description A local variable is initialized once, but never read or written to. Either the local variable is useless, or its value was intended to be used but is not.
+ * @description Assigning a value to a local variable that is not used may indicate an error in the code.
* @kind problem
* @problem.severity recommendation
* @precision low
diff --git a/java/ql/src/Violations of Best Practice/Dead Code/UnusedLocal.qhelp b/java/ql/src/Violations of Best Practice/Dead Code/UnusedLocal.qhelp
index b870eb8463e..6183e3153ae 100644
--- a/java/ql/src/Violations of Best Practice/Dead Code/UnusedLocal.qhelp
+++ b/java/ql/src/Violations of Best Practice/Dead Code/UnusedLocal.qhelp
@@ -5,26 +5,17 @@
-A local variable that is never accessed nor initialized
-is typically a leftover from old refactorings or a sign of incomplete or pending
-code changes.
+A local variable that is not accessed or initialized
+is typically a sign of incomplete or pending code changes.
-If an unused variable is a leftover from old refactorings, you should just remove it. If it indicates
-incomplete or pending code changes, finish making the changes and remove the variable if it is not
+
If an unused variable is no longer needed following refactoring, you should just remove it. If there are
+incomplete or pending code changes, finish making the changes, and then remove the variable if it is no longer
needed.
-
-
-
-Help - Eclipse Platform:
-Java Compiler Errors/Warnings Preferences.
-
-
-
-
+
diff --git a/java/ql/src/Violations of Best Practice/Dead Code/UnusedLocal.ql b/java/ql/src/Violations of Best Practice/Dead Code/UnusedLocal.ql
index 5f68dba3e02..cb1a18dca7a 100644
--- a/java/ql/src/Violations of Best Practice/Dead Code/UnusedLocal.ql
+++ b/java/ql/src/Violations of Best Practice/Dead Code/UnusedLocal.ql
@@ -1,6 +1,6 @@
/**
* @name Unused local variable
- * @description A local variable is entirely unused: it is not initialized, written to or read. The variable serves no purpose and obscures the code. It should be removed.
+ * @description Assigning a value to a local variable that is not used may indicate incomplete code.
* @kind problem
* @problem.severity recommendation
* @precision low
diff --git a/java/ql/src/Violations of Best Practice/legacy/InexactVarArg.java b/java/ql/src/Violations of Best Practice/legacy/InexactVarArg.java
index 8402008007e..9e534107744 100644
--- a/java/ql/src/Violations of Best Practice/legacy/InexactVarArg.java
+++ b/java/ql/src/Violations of Best Practice/legacy/InexactVarArg.java
@@ -7,7 +7,7 @@ class InexactVarArg
public static void main(String[] args) {
String[] words = { "apple", "banana", "cherry" };
String[][] lists = { words, words };
- length(words); // BAD: Argument does not clarify
+ length(words); // wrong: Argument does not clarify
length(lists); // which parameter type is used.
}
}
diff --git a/java/ql/src/Violations of Best Practice/legacy/InexactVarArg.qhelp b/java/ql/src/Violations of Best Practice/legacy/InexactVarArg.qhelp
index c7c45cb0d4c..c9586c8ca7d 100644
--- a/java/ql/src/Violations of Best Practice/legacy/InexactVarArg.qhelp
+++ b/java/ql/src/Violations of Best Practice/legacy/InexactVarArg.qhelp
@@ -49,7 +49,7 @@ versions of Eclipse, the output may be:
-To fix the code, length(words) should be replaced by either of the following:
+To remove this dependency on the compiler, length(words) should be replaced by either of the following:
length((Object) words)
From ce0dd241f64db6e11217a91b17231704120973fe Mon Sep 17 00:00:00 2001
From: Esben Sparre Andreasen
Date: Wed, 7 Nov 2018 10:46:53 +0100
Subject: [PATCH 47/71] JS: add models of $.ajax, $.getJSON and XMLHttpRequst
---
.../javascript/frameworks/ClientRequests.qll | 11 ++++++++++
.../semmle/javascript/frameworks/jQuery.qll | 21 +++++++++++++++++++
.../ClientRequests/ClientRequest.expected | 5 +++++
.../ClientRequest_getADataNode.expected | 3 +++
.../ClientRequest_getUrl.expected | 7 +++++++
.../frameworks/ClientRequests/tst.js | 12 +++++++++++
6 files changed, 59 insertions(+)
diff --git a/javascript/ql/src/semmle/javascript/frameworks/ClientRequests.qll b/javascript/ql/src/semmle/javascript/frameworks/ClientRequests.qll
index 199e3d24d59..596e5e3bf1a 100644
--- a/javascript/ql/src/semmle/javascript/frameworks/ClientRequests.qll
+++ b/javascript/ql/src/semmle/javascript/frameworks/ClientRequests.qll
@@ -246,3 +246,14 @@ private class SuperAgentUrlRequest extends CustomClientRequest {
}
}
+
+/**
+ * A model of a URL request made using the `XMLHttpRequest` browser class.
+ */
+private class XMLHttpRequest extends CustomClientRequest {
+ XMLHttpRequest() { this = DataFlow::globalVarRef("XMLHttpRequest").getAnInstantiation() }
+
+ override DataFlow::Node getUrl() { result = getAMethodCall("open").getArgument(1) }
+
+ override DataFlow::Node getADataNode() { result = getAMethodCall("send").getArgument(0) }
+}
diff --git a/javascript/ql/src/semmle/javascript/frameworks/jQuery.qll b/javascript/ql/src/semmle/javascript/frameworks/jQuery.qll
index b67a807b16e..ab923574207 100644
--- a/javascript/ql/src/semmle/javascript/frameworks/jQuery.qll
+++ b/javascript/ql/src/semmle/javascript/frameworks/jQuery.qll
@@ -340,3 +340,24 @@ private class JQueryChainedElement extends DOM::Element {
)
}
}
+
+/**
+ * A model of a URL request made using the `jQuery.ajax` or `jQuery.getJSON`.
+ */
+private class JQueryClientRequest extends CustomClientRequest {
+ JQueryClientRequest() {
+ exists(string name |
+ name = "ajax" or
+ name = "getJSON"
+ |
+ this = jquery().getAMemberCall(name)
+ )
+ }
+
+ override DataFlow::Node getUrl() {
+ result = getArgument(0) or
+ result = getOptionArgument([0 .. 1], "url")
+ }
+
+ override DataFlow::Node getADataNode() { result = getOptionArgument([0 .. 1], "data") }
+}
diff --git a/javascript/ql/test/library-tests/frameworks/ClientRequests/ClientRequest.expected b/javascript/ql/test/library-tests/frameworks/ClientRequests/ClientRequest.expected
index 50beddbf5c2..a52f0fa500d 100644
--- a/javascript/ql/test/library-tests/frameworks/ClientRequests/ClientRequest.expected
+++ b/javascript/ql/test/library-tests/frameworks/ClientRequests/ClientRequest.expected
@@ -27,3 +27,8 @@
| tst.js:67:5:67:24 | superagent.post(url) |
| tst.js:68:5:68:23 | superagent.get(url) |
| tst.js:69:5:69:23 | superagent.get(url) |
+| tst.js:74:5:74:29 | $.ajax( ... data}) |
+| tst.js:75:5:75:35 | $.ajax( ... data}) |
+| tst.js:77:5:77:32 | $.getJS ... data}) |
+| tst.js:78:5:78:38 | $.getJS ... data}) |
+| tst.js:80:15:80:34 | new XMLHttpRequest() |
diff --git a/javascript/ql/test/library-tests/frameworks/ClientRequests/ClientRequest_getADataNode.expected b/javascript/ql/test/library-tests/frameworks/ClientRequests/ClientRequest_getADataNode.expected
index c59c8e087d4..a213447b7bd 100644
--- a/javascript/ql/test/library-tests/frameworks/ClientRequests/ClientRequest_getADataNode.expected
+++ b/javascript/ql/test/library-tests/frameworks/ClientRequests/ClientRequest_getADataNode.expected
@@ -15,3 +15,6 @@
| tst.js:68:5:68:23 | superagent.get(url) | tst.js:68:34:68:43 | headerData |
| tst.js:68:5:68:23 | superagent.get(url) | tst.js:68:52:68:60 | queryData |
| tst.js:69:5:69:23 | superagent.get(url) | tst.js:69:48:69:56 | queryData |
+| tst.js:74:5:74:29 | $.ajax( ... data}) | tst.js:74:24:74:27 | data |
+| tst.js:77:5:77:32 | $.getJS ... data}) | tst.js:77:27:77:30 | data |
+| tst.js:80:15:80:34 | new XMLHttpRequest() | tst.js:82:14:82:17 | data |
diff --git a/javascript/ql/test/library-tests/frameworks/ClientRequests/ClientRequest_getUrl.expected b/javascript/ql/test/library-tests/frameworks/ClientRequests/ClientRequest_getUrl.expected
index c1664bdeacc..f9e4de1ee21 100644
--- a/javascript/ql/test/library-tests/frameworks/ClientRequests/ClientRequest_getUrl.expected
+++ b/javascript/ql/test/library-tests/frameworks/ClientRequests/ClientRequest_getUrl.expected
@@ -31,3 +31,10 @@
| tst.js:67:5:67:24 | superagent.post(url) | tst.js:67:21:67:23 | url |
| tst.js:68:5:68:23 | superagent.get(url) | tst.js:68:20:68:22 | url |
| tst.js:69:5:69:23 | superagent.get(url) | tst.js:69:20:69:22 | url |
+| tst.js:74:5:74:29 | $.ajax( ... data}) | tst.js:74:12:74:14 | url |
+| tst.js:75:5:75:35 | $.ajax( ... data}) | tst.js:75:12:75:34 | {url: u ... : data} |
+| tst.js:75:5:75:35 | $.ajax( ... data}) | tst.js:75:18:75:20 | url |
+| tst.js:77:5:77:32 | $.getJS ... data}) | tst.js:77:15:77:17 | url |
+| tst.js:78:5:78:38 | $.getJS ... data}) | tst.js:78:15:78:37 | {url: u ... : data} |
+| tst.js:78:5:78:38 | $.getJS ... data}) | tst.js:78:21:78:23 | url |
+| tst.js:80:15:80:34 | new XMLHttpRequest() | tst.js:81:17:81:19 | url |
diff --git a/javascript/ql/test/library-tests/frameworks/ClientRequests/tst.js b/javascript/ql/test/library-tests/frameworks/ClientRequests/tst.js
index 13782f6fdeb..ee638893a52 100644
--- a/javascript/ql/test/library-tests/frameworks/ClientRequests/tst.js
+++ b/javascript/ql/test/library-tests/frameworks/ClientRequests/tst.js
@@ -69,3 +69,15 @@ import {ClientRequest, net} from 'electron';
superagent.get(url).unknown(nonData).query(queryData);
});
+
+(function() {
+ $.ajax(url, {data: data});
+ $.ajax({url: url, tdata: data});
+
+ $.getJSON(url, {data: data});
+ $.getJSON({url: url, tdata: data});
+
+ var xhr = new XMLHttpRequest();
+ xhr.open(_, url);
+ xhr.send(data);
+});
From 577b22542913b34753e3254449624ddc8af1bff6 Mon Sep 17 00:00:00 2001
From: Esben Sparre Andreasen
Date: Fri, 9 Nov 2018 11:46:16 +0100
Subject: [PATCH 48/71] JS: sort change notes table
---
change-notes/1.19/analysis-javascript.md | 22 +++++++++++-----------
1 file changed, 11 insertions(+), 11 deletions(-)
diff --git a/change-notes/1.19/analysis-javascript.md b/change-notes/1.19/analysis-javascript.md
index 5630452ded3..94d085e8cd2 100644
--- a/change-notes/1.19/analysis-javascript.md
+++ b/change-notes/1.19/analysis-javascript.md
@@ -30,19 +30,19 @@
| **Query** | **Expected impact** | **Change** |
|--------------------------------|----------------------------|----------------------------------------------|
-| Useless assignment to local variable | Fewer false-positive results | This rule now recognizes additional ways default values can be set. |
-| Regular expression injection | Fewer false-positive results | This rule now identifies calls to `String.prototype.search` with more precision. |
-| Unbound event handler receiver | Fewer false-positive results | This rule now recognizes additional ways class methods can be bound. |
-| Remote property injection | Fewer results | The precision of this rule has been revised to "medium". Results are no longer shown on LGTM by default. |
-| Missing CSRF middleware | Fewer false-positive results | This rule now recognizes additional CSRF protection middlewares. |
-| Server-side URL redirect | More results | This rule now recognizes redirection calls in more cases. |
-| Unused variable, import, function or class | Fewer false-positive results | This rule now flags fewer variables that may be used by `eval` calls. |
-| Unused variable, import, function or class | Fewer results | This rule now flags import statements with multiple unused imports once. |
-| Whitespace contradicts operator precedence | Fewer false-positive results | This rule no longer flags operators with asymmetric whitespace. |
-| Unused import | Fewer false-positive results | This rule no longer flags imports used by the `transform-react-jsx` Babel plugin. |
-| Self assignment | Fewer false-positive results | This rule now ignores self-assignments preceded by a JSDoc comment with a `@type` tag. |
| Client side cross-site scripting | More results | This rule now also flags HTML injection in the body of an email. |
| Information exposure through a stack trace | More results | This rule now also flags cases where the entire exception object (including the stack trace) may be exposed. |
+| Missing CSRF middleware | Fewer false-positive results | This rule now recognizes additional CSRF protection middlewares. |
+| Regular expression injection | Fewer false-positive results | This rule now identifies calls to `String.prototype.search` with more precision. |
+| Remote property injection | Fewer results | The precision of this rule has been revised to "medium". Results are no longer shown on LGTM by default. |
+| Self assignment | Fewer false-positive results | This rule now ignores self-assignments preceded by a JSDoc comment with a `@type` tag. |
+| Server-side URL redirect | More results | This rule now recognizes redirection calls in more cases. |
+| Unbound event handler receiver | Fewer false-positive results | This rule now recognizes additional ways class methods can be bound. |
+| Unused import | Fewer false-positive results | This rule no longer flags imports used by the `transform-react-jsx` Babel plugin. |
+| Unused variable, import, function or class | Fewer false-positive results | This rule now flags fewer variables that may be used by `eval` calls. |
+| Unused variable, import, function or class | Fewer results | This rule now flags import statements with multiple unused imports once. |
+| Useless assignment to local variable | Fewer false-positive results | This rule now recognizes additional ways default values can be set. |
+| Whitespace contradicts operator precedence | Fewer false-positive results | This rule no longer flags operators with asymmetric whitespace. |
## Changes to QL libraries
From 37b7b39ec6311e0e8fb2491f197ecfb92787b853 Mon Sep 17 00:00:00 2001
From: Esben Sparre Andreasen
Date: Fri, 9 Nov 2018 11:48:52 +0100
Subject: [PATCH 49/71] JS: change notes for improved js/request-forgery
---
change-notes/1.19/analysis-javascript.md | 1 +
1 file changed, 1 insertion(+)
diff --git a/change-notes/1.19/analysis-javascript.md b/change-notes/1.19/analysis-javascript.md
index 94d085e8cd2..f8bc1593121 100644
--- a/change-notes/1.19/analysis-javascript.md
+++ b/change-notes/1.19/analysis-javascript.md
@@ -38,6 +38,7 @@
| Self assignment | Fewer false-positive results | This rule now ignores self-assignments preceded by a JSDoc comment with a `@type` tag. |
| Server-side URL redirect | More results | This rule now recognizes redirection calls in more cases. |
| Unbound event handler receiver | Fewer false-positive results | This rule now recognizes additional ways class methods can be bound. |
+| Uncontrolled data used in remote request | More results | This rule now recognizes additional kinds of requests. |
| Unused import | Fewer false-positive results | This rule no longer flags imports used by the `transform-react-jsx` Babel plugin. |
| Unused variable, import, function or class | Fewer false-positive results | This rule now flags fewer variables that may be used by `eval` calls. |
| Unused variable, import, function or class | Fewer results | This rule now flags import statements with multiple unused imports once. |
From c2fb14640e66aaf0b97b9a39d424071e5fa92806 Mon Sep 17 00:00:00 2001
From: Esben Sparre Andreasen
Date: Thu, 27 Sep 2018 15:01:46 +0200
Subject: [PATCH 50/71] JS: move isDefensiveInit to DefensiveProgramming.qll
---
.../ql/src/Statements/UselessConditional.ql | 26 ++----------------
.../javascript/DefensiveProgramming.qll | 27 +++++++++++++++++++
2 files changed, 29 insertions(+), 24 deletions(-)
create mode 100644 javascript/ql/src/semmle/javascript/DefensiveProgramming.qll
diff --git a/javascript/ql/src/Statements/UselessConditional.ql b/javascript/ql/src/Statements/UselessConditional.ql
index 6e71d682713..5de56e292ee 100644
--- a/javascript/ql/src/Statements/UselessConditional.ql
+++ b/javascript/ql/src/Statements/UselessConditional.ql
@@ -15,29 +15,7 @@
import javascript
import semmle.javascript.RestrictedLocations
import semmle.javascript.dataflow.Refinements
-
-/**
- * Holds if `va` is a defensive truthiness check that may be worth keeping, even if it
- * is strictly speaking useless.
- *
- * We currently recognize three patterns:
- *
- * - the first `x` in `x || (x = e)`
- * - the second `x` in `x = (x || e)`
- * - the second `x` in `var x = x || e`
- */
-predicate isDefensiveInit(VarAccess va) {
- exists (LogOrExpr o, VarRef va2 |
- va = o.getLeftOperand().getUnderlyingReference() and va2.getVariable() = va.getVariable() |
- exists (AssignExpr assgn | va2 = assgn.getTarget() |
- assgn = o.getRightOperand().stripParens() or
- o = assgn.getRhs().getUnderlyingValue()
- ) or
- exists (VariableDeclarator vd | va2 = vd.getBindingPattern() |
- o = vd.getInit().getUnderlyingValue()
- )
- )
-}
+import semmle.javascript.DefensiveProgramming
/**
* Holds if variable `v` looks like a symbolic constant, that is, it is assigned
@@ -109,7 +87,7 @@ predicate isConstantBooleanReturnValue(Expr e) {
predicate whitelist(Expr e) {
isConstant(e) or
isConstant(e.(LogNotExpr).getOperand()) or
- isDefensiveInit(e) or
+ e.flow() instanceof DefensiveInit or
isInitialParameterUse(e) or
isConstantBooleanReturnValue(e)
}
diff --git a/javascript/ql/src/semmle/javascript/DefensiveProgramming.qll b/javascript/ql/src/semmle/javascript/DefensiveProgramming.qll
new file mode 100644
index 00000000000..2bd4f80bede
--- /dev/null
+++ b/javascript/ql/src/semmle/javascript/DefensiveProgramming.qll
@@ -0,0 +1,27 @@
+import javascript
+
+/**
+ * A defensive truthiness check that may be worth keeping, even if it
+ * is strictly speaking useless.
+ *
+ * We currently recognize three patterns:
+ *
+ * - the first `x` in `x || (x = e)`
+ * - the second `x` in `x = (x || e)`
+ * - the second `x` in `var x = x || e`
+ */
+class DefensiveInit extends DataFlow::ValueNode {
+ DefensiveInit() {
+ exists(VarAccess va, LogOrExpr o, VarRef va2 |
+ va = astNode and
+ va = o.getLeftOperand().stripParens() and va2.getVariable() = va.getVariable() |
+ exists(AssignExpr assgn | va2 = assgn.getTarget() |
+ assgn = o.getRightOperand().stripParens() or
+ o = assgn.getRhs().stripParens()
+ )
+ or
+ exists(VariableDeclarator vd | va2 = vd.getBindingPattern() | o = vd.getInit().stripParens())
+ )
+ }
+
+}
\ No newline at end of file
From a5eeba3c3a4996e9f76b3b008f754685c92948a6 Mon Sep 17 00:00:00 2001
From: Esben Sparre Andreasen
Date: Wed, 10 Oct 2018 14:45:06 +0200
Subject: [PATCH 51/71] JS: prepare DefensiveProgramming.qll for additions
---
.../ql/src/Statements/UselessConditional.ql | 2 +-
.../javascript/DefensiveProgramming.qll | 60 +++++++++++++------
2 files changed, 42 insertions(+), 20 deletions(-)
diff --git a/javascript/ql/src/Statements/UselessConditional.ql b/javascript/ql/src/Statements/UselessConditional.ql
index 5de56e292ee..06e6e8601b9 100644
--- a/javascript/ql/src/Statements/UselessConditional.ql
+++ b/javascript/ql/src/Statements/UselessConditional.ql
@@ -87,7 +87,7 @@ predicate isConstantBooleanReturnValue(Expr e) {
predicate whitelist(Expr e) {
isConstant(e) or
isConstant(e.(LogNotExpr).getOperand()) or
- e.flow() instanceof DefensiveInit or
+ e.flow() instanceof Internal::DefensiveInit or
isInitialParameterUse(e) or
isConstantBooleanReturnValue(e)
}
diff --git a/javascript/ql/src/semmle/javascript/DefensiveProgramming.qll b/javascript/ql/src/semmle/javascript/DefensiveProgramming.qll
index 2bd4f80bede..a1498866108 100644
--- a/javascript/ql/src/semmle/javascript/DefensiveProgramming.qll
+++ b/javascript/ql/src/semmle/javascript/DefensiveProgramming.qll
@@ -1,27 +1,49 @@
+/**
+ * Provides classes for working with defensive programming patterns.
+ */
+
import javascript
+private import semmle.javascript.dataflow.InferredTypes
/**
- * A defensive truthiness check that may be worth keeping, even if it
- * is strictly speaking useless.
- *
- * We currently recognize three patterns:
- *
- * - the first `x` in `x || (x = e)`
- * - the second `x` in `x = (x || e)`
- * - the second `x` in `var x = x || e`
+ * The test in a defensive programming pattern.
*/
-class DefensiveInit extends DataFlow::ValueNode {
- DefensiveInit() {
- exists(VarAccess va, LogOrExpr o, VarRef va2 |
- va = astNode and
- va = o.getLeftOperand().stripParens() and va2.getVariable() = va.getVariable() |
- exists(AssignExpr assgn | va2 = assgn.getTarget() |
- assgn = o.getRightOperand().stripParens() or
- o = assgn.getRhs().stripParens()
+abstract class DefensiveExpression extends DataFlow::ValueNode {
+ /** Gets the unique Boolean value that this test evaluates to, if any. */
+ abstract boolean getTheTestResult();
+}
+
+/**
+ * INTERNAL: Do not use directly; use `DefensiveExpression` instead.
+ */
+module Internal {
+ /**
+ * A defensive truthiness check that may be worth keeping, even if it
+ * is strictly speaking useless.
+ *
+ * We currently recognize three patterns:
+ *
+ * - the first `x` in `x || (x = e)`
+ * - the second `x` in `x = (x || e)`
+ * - the second `x` in `var x = x || e`
+ */
+ class DefensiveInit extends DefensiveExpression {
+ DefensiveInit() {
+ exists(VarAccess va, LogOrExpr o, VarRef va2 |
+ va = astNode and
+ va = o.getLeftOperand().stripParens() and va2.getVariable() = va.getVariable() |
+ exists(AssignExpr assgn | va2 = assgn.getTarget() |
+ assgn = o.getRightOperand().stripParens() or
+ o = assgn.getRhs().stripParens()
+ )
+ or
+ exists(VariableDeclarator vd | va2 = vd.getBindingPattern() | o = vd.getInit().stripParens())
)
- or
- exists(VariableDeclarator vd | va2 = vd.getBindingPattern() | o = vd.getInit().stripParens())
- )
+ }
+
+ override boolean getTheTestResult() {
+ result = analyze().getTheBooleanValue()
+ }
}
}
\ No newline at end of file
From 8086e88587d5b9c333b4f988862c881796f16e85 Mon Sep 17 00:00:00 2001
From: Esben Sparre Andreasen
Date: Wed, 10 Oct 2018 14:53:26 +0200
Subject: [PATCH 52/71] JS: add utilities to DefensiveProgramming.qll
---
javascript/ql/src/semmle/javascript/DefensiveProgramming.qll | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/javascript/ql/src/semmle/javascript/DefensiveProgramming.qll b/javascript/ql/src/semmle/javascript/DefensiveProgramming.qll
index a1498866108..9c4a975dbcc 100644
--- a/javascript/ql/src/semmle/javascript/DefensiveProgramming.qll
+++ b/javascript/ql/src/semmle/javascript/DefensiveProgramming.qll
@@ -6,7 +6,7 @@ import javascript
private import semmle.javascript.dataflow.InferredTypes
/**
- * The test in a defensive programming pattern.
+ * A test in a defensive programming pattern.
*/
abstract class DefensiveExpression extends DataFlow::ValueNode {
/** Gets the unique Boolean value that this test evaluates to, if any. */
From 2b6ef24bc2ce74436ef5fc9eedd80e8642550109 Mon Sep 17 00:00:00 2001
From: Esben Sparre Andreasen
Date: Wed, 10 Oct 2018 14:53:26 +0200
Subject: [PATCH 53/71] JS: add utilities to DefensiveProgramming.qll
---
.../javascript/DefensiveProgramming.qll | 82 +++++++++++++++++++
1 file changed, 82 insertions(+)
diff --git a/javascript/ql/src/semmle/javascript/DefensiveProgramming.qll b/javascript/ql/src/semmle/javascript/DefensiveProgramming.qll
index 9c4a975dbcc..7c6baa87256 100644
--- a/javascript/ql/src/semmle/javascript/DefensiveProgramming.qll
+++ b/javascript/ql/src/semmle/javascript/DefensiveProgramming.qll
@@ -46,4 +46,86 @@ module Internal {
}
}
+ /**
+ * Gets the inner expression of `e`, with any surrounding parentheses and boolean nots removed.
+ * `polarity` is true iff the inner expression is nested in an even number of negations.
+ */
+ private Expr stripNotsAndParens(Expr e, boolean polarity) {
+ exists (Expr inner |
+ inner = e.stripParens() |
+ if inner instanceof LogNotExpr then
+ (result = stripNotsAndParens(inner.(LogNotExpr).getOperand(), polarity.booleanNot()))
+ else
+ (result = inner and polarity = true)
+ )
+ }
+
+ /**
+ * An equality test for `null` and `undefined`.
+ */
+ private abstract class UndefinedNullTest extends EqualityTest {
+ /** Gets the unique Boolean value that this test evaluates to, if any. */
+ abstract boolean getTheTestResult();
+
+ /**
+ * Gets the expression that is tested for being `null` or `undefined`.
+ */
+ abstract Expr getOperand();
+ }
+
+ /**
+ * A dis- or conjunction that tests if an expression is `null` or `undefined` in either branch.
+ */
+ private class CompositeUndefinedNullTestPart extends DefensiveExpression {
+
+ UndefinedNullTest test;
+
+ boolean polarity;
+
+ CompositeUndefinedNullTestPart(){
+ exists (BinaryExpr composite, Variable v, Expr op, Expr opOther, UndefinedNullTest testOther |
+ composite instanceof LogAndExpr or
+ composite instanceof LogOrExpr |
+ composite.hasOperands(op, opOther) and
+ this = op.flow() and
+ test = stripNotsAndParens(op, polarity) and
+ testOther = stripNotsAndParens(opOther, _) and
+ test.getOperand().(VarRef).getVariable() = v and
+ testOther.getOperand().(VarRef).getVariable() = v
+ )
+ }
+
+ override boolean getTheTestResult() {
+ polarity = true and result = test.getTheTestResult()
+ or
+ polarity = false and result = test.getTheTestResult().booleanNot()
+ }
+
+ }
+
+ /**
+ * A test for `undefined` or `null` in an if-statement.
+ */
+ private class SanityCheckingUndefinedNullGuard extends DefensiveExpression {
+
+ UndefinedNullTest test;
+
+ boolean polarity;
+
+ SanityCheckingUndefinedNullGuard() {
+ exists (IfStmt c |
+ this = c.getCondition().flow() and
+ test = stripNotsAndParens(c.getCondition(), polarity) and
+ test.getOperand() instanceof VarRef
+ )
+ }
+
+ override boolean getTheTestResult() {
+ polarity = true and result = test.getTheTestResult()
+ or
+ polarity = false and result = test.getTheTestResult().booleanNot()
+ }
+
+ }
+
}
\ No newline at end of file
From a2ecf408789bbe9e37ae30452c9f766fd479b4ef Mon Sep 17 00:00:00 2001
From: Esben Sparre Andreasen
Date: Wed, 10 Oct 2018 14:58:10 +0200
Subject: [PATCH 54/71] JS: recognize defensive expressions for null/undefined
---
.../javascript/DefensiveProgramming.qll | 56 +++++++++++++++++++
1 file changed, 56 insertions(+)
diff --git a/javascript/ql/src/semmle/javascript/DefensiveProgramming.qll b/javascript/ql/src/semmle/javascript/DefensiveProgramming.qll
index 7c6baa87256..515f03d45b0 100644
--- a/javascript/ql/src/semmle/javascript/DefensiveProgramming.qll
+++ b/javascript/ql/src/semmle/javascript/DefensiveProgramming.qll
@@ -128,4 +128,60 @@ module Internal {
}
+ /**
+ * Holds if `t` is `null` or `undefined`.
+ */
+ private predicate isNullOrUndefined(InferredType t) {
+ t = TTNull() or
+ t = TTUndefined()
+ }
+
+ /**
+ * Holds if `t` is not `null` or `undefined`.
+ */
+ private predicate isNotNullOrUndefined(InferredType t) {
+ not isNullOrUndefined(t)
+ }
+
+ /**
+ * A value comparison for `null` and `undefined`.
+ */
+ private class NullUndefinedComparison extends UndefinedNullTest {
+
+ Expr operand;
+
+ InferredType op2type;
+
+ NullUndefinedComparison() {
+ exists (Expr op2 |
+ hasOperands(operand, op2) |
+ op2type = TTNull() and SyntacticConstants::isNull(op2)
+ or
+ op2type = TTUndefined() and SyntacticConstants::isUndefined(op2)
+ )
+ }
+
+ override boolean getTheTestResult() {
+ result = getPolarity() and
+ (
+ if this instanceof StrictEqualityTest then
+ operand.analyze().getTheType() = op2type
+ else
+ not isNotNullOrUndefined(operand.analyze().getAType())
+ )
+ or
+ result = getPolarity().booleanNot() and
+ (
+ if this instanceof StrictEqualityTest then
+ not operand.analyze().getAType() = op2type
+ else
+ not isNullOrUndefined(operand.analyze().getAType())
+ )
+ }
+
+ override Expr getOperand() {
+ result = operand
+ }
+ }
+
}
\ No newline at end of file
From 6e77489a3b24dc2ae80aa4d7f3daa9646ff1115c Mon Sep 17 00:00:00 2001
From: Esben Sparre Andreasen
Date: Wed, 10 Oct 2018 15:00:21 +0200
Subject: [PATCH 55/71] JS: add utilities for expression guards to
DefensiveProgramming.qll
---
.../javascript/DefensiveProgramming.qll | 66 +++++++++++++++++++
1 file changed, 66 insertions(+)
diff --git a/javascript/ql/src/semmle/javascript/DefensiveProgramming.qll b/javascript/ql/src/semmle/javascript/DefensiveProgramming.qll
index 515f03d45b0..2d07a01f217 100644
--- a/javascript/ql/src/semmle/javascript/DefensiveProgramming.qll
+++ b/javascript/ql/src/semmle/javascript/DefensiveProgramming.qll
@@ -184,4 +184,70 @@ module Internal {
}
}
+ /**
+ * An expression that throws an exception if one of its subexpressions evaluates to `null` or `undefined`.
+ */
+ private class UndefinedNullCrashUse extends Expr {
+
+ Expr target;
+
+ UndefinedNullCrashUse() {
+ this.(InvokeExpr).getCallee().stripParens() = target
+ or
+ this.(PropAccess).getBase().stripParens() = target
+ or
+ this.(MethodCallExpr).getReceiver().stripParens() = target
+ }
+
+ /**
+ * Gets the subexpression that will cause an exception to be thrown if it is `null` or `undefined`.
+ */
+ Expr getVulnerableSubexpression() {
+ result = target
+ }
+
+ }
+
+ /**
+ * An expression that throws an exception if one of its subexpressions is not a `function`.
+ */
+ private class NonFunctionCallCrashUse extends Expr {
+
+ Expr target;
+
+ NonFunctionCallCrashUse() {
+ this.(InvokeExpr).getCallee().stripParens() = target
+ }
+
+ /**
+ * Gets the subexpression that will cause an exception to be thrown if it is not a `function`.
+ */
+ Expr getVulnerableSubexpression() {
+ result = target
+ }
+
+ }
+
+ /**
+ * Gets the first expression that is guarded by `guard`.
+ */
+ private Expr getAGuardedExpr(Expr guard) {
+ exists(BinaryExpr op |
+ op.getLeftOperand() = guard and
+ (op instanceof LogAndExpr or op instanceof LogOrExpr) and
+ op.getRightOperand() = result
+ )
+ or
+ exists(IfStmt c |
+ c.getCondition() = guard |
+ result = c.getAControlledStmt().getChildExpr(0) or
+ result = c.getAControlledStmt().(BlockStmt).getStmt(0).getChildExpr(0)
+ )
+ or
+ exists (ConditionalExpr c |
+ c.getCondition() = guard |
+ result = c.getABranch()
+ )
+ }
+
}
\ No newline at end of file
From c403416fef86ccca0322993d57ac86c20437139d Mon Sep 17 00:00:00 2001
From: Esben Sparre Andreasen
Date: Wed, 10 Oct 2018 15:02:42 +0200
Subject: [PATCH 56/71] JS: recognize defensive expressions that prevents
exceptions
---
.../javascript/DefensiveProgramming.qll | 67 +++++++++++++++++++
1 file changed, 67 insertions(+)
diff --git a/javascript/ql/src/semmle/javascript/DefensiveProgramming.qll b/javascript/ql/src/semmle/javascript/DefensiveProgramming.qll
index 2d07a01f217..e0f659fa186 100644
--- a/javascript/ql/src/semmle/javascript/DefensiveProgramming.qll
+++ b/javascript/ql/src/semmle/javascript/DefensiveProgramming.qll
@@ -250,4 +250,71 @@ module Internal {
)
}
+ /**
+ * Holds if `t` is `string`, `number` or `boolean`.
+ */
+ private predicate isStringOrNumOrBool(InferredType t) {
+ t = TTString() or
+ t = TTNumber() or
+ t = TTBoolean()
+ }
+
+ /**
+ * A defensive expression that tests for `undefined` and `null` using a truthiness test.
+ */
+ private class UndefinedNullTruthinessGuard extends DefensiveExpression {
+
+ VarRef guardVar;
+
+ boolean polarity;
+
+ UndefinedNullTruthinessGuard() {
+ exists (VarRef useVar |
+ guardVar = stripNotsAndParens(this.asExpr(), polarity) and
+ guardVar.getVariable() = useVar.getVariable() |
+ getAGuardedExpr(this.asExpr()).stripParens().(UndefinedNullCrashUse).getVulnerableSubexpression() = useVar and
+ // exclude types whose truthiness depend on the value
+ not isStringOrNumOrBool(guardVar.analyze().getAType())
+ )
+ }
+
+ override boolean getTheTestResult() {
+ exists (boolean testResult |
+ testResult = guardVar.analyze().getTheBooleanValue() |
+ if polarity = true then
+ result = testResult
+ else
+ result = testResult.booleanNot()
+ )
+ }
+
+ }
+
+ /**
+ * A defensive expression that tests for `undefined` and `null`.
+ */
+ private class UndefinedNullTypeGuard extends DefensiveExpression {
+
+ UndefinedNullTest test;
+
+ boolean polarity;
+
+ UndefinedNullTypeGuard() {
+ exists (Expr guard, VarRef guardVar, VarRef useVar |
+ this = guard.flow() and
+ test = stripNotsAndParens(guard, polarity) and
+ test.getOperand() = guardVar and
+ guardVar.getVariable() = useVar.getVariable() |
+ getAGuardedExpr(guard).stripParens().(UndefinedNullCrashUse).getVulnerableSubexpression() = useVar
+ )
+ }
+
+ override boolean getTheTestResult() {
+ polarity = true and result = test.getTheTestResult()
+ or
+ polarity = false and result = test.getTheTestResult().booleanNot()
+ }
+
+ }
+
}
\ No newline at end of file
From 7b215ecb2b621de8499914dd2d5a0787df40fe2a Mon Sep 17 00:00:00 2001
From: Esben Sparre Andreasen
Date: Wed, 10 Oct 2018 15:10:36 +0200
Subject: [PATCH 57/71] JS: recognize defensive programming patterns using
`typeof`
---
.../javascript/DefensiveProgramming.qll | 92 +++++++++++++++++++
1 file changed, 92 insertions(+)
diff --git a/javascript/ql/src/semmle/javascript/DefensiveProgramming.qll b/javascript/ql/src/semmle/javascript/DefensiveProgramming.qll
index e0f659fa186..ffa4246e128 100644
--- a/javascript/ql/src/semmle/javascript/DefensiveProgramming.qll
+++ b/javascript/ql/src/semmle/javascript/DefensiveProgramming.qll
@@ -317,4 +317,96 @@ module Internal {
}
+ /**
+ * A test for the value of a `typeof` expression.
+ */
+ private class TypeofTest extends EqualityTest {
+ Expr operand;
+
+ TypeofTag tag;
+
+ TypeofTest() {
+ exists (Expr op1, Expr op2 |
+ hasOperands(op1, op2) |
+ operand = op1.(TypeofExpr).getOperand() and
+ op2.mayHaveStringValue(tag)
+ )
+ }
+
+ boolean getTheTestResult() {
+ exists (boolean testResult |
+ testResult = true and operand.analyze().getTheType().getTypeofTag() = tag or
+ testResult = false and not operand.analyze().getAType().getTypeofTag() = tag |
+ if getPolarity() = true then
+ result = testResult
+ else
+ result = testResult.booleanNot()
+ )
+ }
+
+ /**
+ * Gets the operand used in the `typeof` expression.
+ */
+ Expr getOperand() {
+ result = operand
+ }
+
+ /**
+ * Gets the `typeof` tag that is tested.
+ */
+ TypeofTag getTag() {
+ result = tag
+ }
+ }
+
+ /**
+ * A defensive expression that tests if an expression has type `function`.
+ */
+ private class FunctionTypeGuard extends DefensiveExpression {
+
+ TypeofTest test;
+
+ boolean polarity;
+
+ FunctionTypeGuard() {
+ exists (Expr guard, VarRef guardVar, VarRef useVar |
+ this = guard.flow() and
+ test = stripNotsAndParens(guard, polarity) and
+ test.getOperand() = guardVar and
+ guardVar.getVariable() = useVar.getVariable() |
+ getAGuardedExpr(guard).stripParens().(NonFunctionCallCrashUse).getVulnerableSubexpression() = useVar
+ ) and
+ test.getTag() = "function"
+ }
+
+ override boolean getTheTestResult() {
+ polarity = true and result = test.getTheTestResult()
+ or
+ polarity = false and result = test.getTheTestResult().booleanNot()
+ }
+
+ }
+
+ /**
+ * A test for `undefined` using a `typeof` expression.
+ */
+ private class TypeofUndefinedTest extends UndefinedNullTest {
+
+ TypeofTest test;
+
+ TypeofUndefinedTest() {
+ this = test and
+ test.getTag() = "undefined"
+ }
+
+ override boolean getTheTestResult() {
+ result = test.getTheTestResult()
+ }
+
+ override Expr getOperand() {
+ result = test.getOperand()
+ }
+
+ }
+
}
\ No newline at end of file
From b073fcfca25ea55c638c90c30dc955fc38509bd8 Mon Sep 17 00:00:00 2001
From: Esben Sparre Andreasen
Date: Wed, 10 Oct 2018 14:34:58 +0200
Subject: [PATCH 58/71] JS: add query: js/useless-defensive-code
---
.../suites/javascript/maintainability-more | 1 +
.../UselessDefensiveProgramming.qhelp | 91 +++++++++
.../UselessDefensiveProgramming.ql | 19 ++
.../UselessDefensiveProgramming1_bad.js | 10 +
.../UselessDefensiveProgramming1_good.js | 9 +
.../UselessDefensiveProgramming2_bad.js | 5 +
.../UselessDefensiveProgramming2_good.js | 5 +
.../UselessDefensiveProgramming.expected | 78 ++++++++
.../UselessDefensiveProgramming.qlref | 1 +
.../global-module-definition.js | 11 ++
.../module-environment-detection.js | 24 +++
.../UselessDefensiveProgramming/tst.js | 174 ++++++++++++++++++
.../UselessDefensiveProgramming/tst2.js | 10 +
13 files changed, 438 insertions(+)
create mode 100644 javascript/ql/src/Expressions/UselessDefensiveProgramming.qhelp
create mode 100644 javascript/ql/src/Expressions/UselessDefensiveProgramming.ql
create mode 100644 javascript/ql/src/Expressions/examples/UselessDefensiveProgramming1_bad.js
create mode 100644 javascript/ql/src/Expressions/examples/UselessDefensiveProgramming1_good.js
create mode 100644 javascript/ql/src/Expressions/examples/UselessDefensiveProgramming2_bad.js
create mode 100644 javascript/ql/src/Expressions/examples/UselessDefensiveProgramming2_good.js
create mode 100644 javascript/ql/test/query-tests/Expressions/UselessDefensiveProgramming/UselessDefensiveProgramming.expected
create mode 100644 javascript/ql/test/query-tests/Expressions/UselessDefensiveProgramming/UselessDefensiveProgramming.qlref
create mode 100644 javascript/ql/test/query-tests/Expressions/UselessDefensiveProgramming/global-module-definition.js
create mode 100644 javascript/ql/test/query-tests/Expressions/UselessDefensiveProgramming/module-environment-detection.js
create mode 100644 javascript/ql/test/query-tests/Expressions/UselessDefensiveProgramming/tst.js
create mode 100644 javascript/ql/test/query-tests/Expressions/UselessDefensiveProgramming/tst2.js
diff --git a/javascript/config/suites/javascript/maintainability-more b/javascript/config/suites/javascript/maintainability-more
index 6cf17736f53..822a055b2e7 100644
--- a/javascript/config/suites/javascript/maintainability-more
+++ b/javascript/config/suites/javascript/maintainability-more
@@ -6,6 +6,7 @@
+ semmlecode-javascript-queries/Declarations/DuplicateVarDecl.ql: /Maintainability/Declarations
+ semmlecode-javascript-queries/Declarations/UnusedParameter.ql: /Maintainability/Declarations
+ semmlecode-javascript-queries/Declarations/UnusedVariable.ql: /Maintainability/Declarations
++ semmlecode-javascript-queries/Expressions/UselessDefensiveProgramming.ql: /Maintainability/Expressions
+ semmlecode-javascript-queries/LanguageFeatures/ArgumentsCallerCallee.ql: /Maintainability/Language Features
+ semmlecode-javascript-queries/LanguageFeatures/ConditionalComments.ql: /Maintainability/Language Features
+ semmlecode-javascript-queries/LanguageFeatures/Eval.ql: /Maintainability/Language Features
diff --git a/javascript/ql/src/Expressions/UselessDefensiveProgramming.qhelp b/javascript/ql/src/Expressions/UselessDefensiveProgramming.qhelp
new file mode 100644
index 00000000000..870bc26da17
--- /dev/null
+++ b/javascript/ql/src/Expressions/UselessDefensiveProgramming.qhelp
@@ -0,0 +1,91 @@
+
+
+
+
+
+ Defensive code can prevent unforeseen circumstances from
+ causing fatal program behaviors.
+
+ A common defensive code pattern is to guard
+ against dereferencing the values null or
+ undefined.
+
+ However, if the situation that some defensive code guards
+ against never can occur, then the defensive code serves no purpose and
+ it can safely be removed.
+
+
+
+
+
+
+
+
+ Examine the surrounding code to determine if the defensive
+ code is worth keeping despite providing no practical use. If it is no
+ longer needed, remove it.
+
+
+
+
+
+
+
+
+ The following example shows a cleanupLater
+ function that asynchronously will perform a cleanup task after some
+ delay. When the cleanup task completes, the function invokes the
+ provided callback parameter cb.
+
+ To prevent a crash by invoking cb when it
+ has the value undefined, defensive code guards
+ the invocation by checking if cb is truthy.
+
+
+
+
+
+
+
+ However, the cleanupLater function is always
+ invoked with a callback argument, so the defensive code condition
+ always holds, and it is therefore not
+ required. The function can therefore be simplified to:
+
+
+
+
+
+
+
+ Guarding against the same situation multiple times is
+ another example of defensive code that provides no practical use. The
+ example below shows a function that assigns a value to a property of
+ an object, where defensive code ensures that the assigned value is not
+ undefined or null.
+
+
+
+
+
+
+
+ However, due to coercion rules, v ==
+ undefined holds for both the situation where v
+ isundefined and the situation where v
+ isnull, so the v == null
+ guard serves no purpose, and it can be removed:
+
+
+
+
+
+
+
+
+ - Wikipedia: Defensive programming.
+
+
+
diff --git a/javascript/ql/src/Expressions/UselessDefensiveProgramming.ql b/javascript/ql/src/Expressions/UselessDefensiveProgramming.ql
new file mode 100644
index 00000000000..9dd76ffec13
--- /dev/null
+++ b/javascript/ql/src/Expressions/UselessDefensiveProgramming.ql
@@ -0,0 +1,19 @@
+/**
+ * @name Useless defensive code
+ * @description If the situation some defensive code guards against never
+ * happens, then the defensive code is not needed.
+ * @kind problem
+ * @problem.severity recommendation
+ * @id js/useless-defensive-code
+ * @tags correctness
+ * external/cwe/cwe-570
+ * external/cwe/cwe-571
+ * @precision very-high
+ */
+
+import javascript
+import semmle.javascript.DefensiveProgramming
+
+from DefensiveExpression e, boolean cv
+where e.getTheTestResult() = cv
+select e, "This guard always evaluates to " + cv + "."
diff --git a/javascript/ql/src/Expressions/examples/UselessDefensiveProgramming1_bad.js b/javascript/ql/src/Expressions/examples/UselessDefensiveProgramming1_bad.js
new file mode 100644
index 00000000000..d4816efdabb
--- /dev/null
+++ b/javascript/ql/src/Expressions/examples/UselessDefensiveProgramming1_bad.js
@@ -0,0 +1,10 @@
+function cleanupLater(delay, cb) {
+ setTimeout(function() {
+ cleanup();
+ if (cb) { // BAD: useless check, `cb` is always truthy
+ cb();
+ }
+ }, delay)
+}
+
+cleanupLater(1000, function(){console.log("Cleanup done")});
diff --git a/javascript/ql/src/Expressions/examples/UselessDefensiveProgramming1_good.js b/javascript/ql/src/Expressions/examples/UselessDefensiveProgramming1_good.js
new file mode 100644
index 00000000000..3a67bd563f8
--- /dev/null
+++ b/javascript/ql/src/Expressions/examples/UselessDefensiveProgramming1_good.js
@@ -0,0 +1,9 @@
+function cleanupLater(delay, cb) {
+ setTimeout(function() {
+ cleanupNow();
+ // GOOD: no need to guard the invocation
+ cb();
+ }, delay)
+}
+
+cleanupLater(function(){console.log("Cleanup done")});
diff --git a/javascript/ql/src/Expressions/examples/UselessDefensiveProgramming2_bad.js b/javascript/ql/src/Expressions/examples/UselessDefensiveProgramming2_bad.js
new file mode 100644
index 00000000000..087a19497c9
--- /dev/null
+++ b/javascript/ql/src/Expressions/examples/UselessDefensiveProgramming2_bad.js
@@ -0,0 +1,5 @@
+function setSafeStringProp(o, prop, v) {
+ // BAD: `v == null` is useless
+ var safe = v == undefined || v == null? '': v;
+ o[prop] = safe;
+}
diff --git a/javascript/ql/src/Expressions/examples/UselessDefensiveProgramming2_good.js b/javascript/ql/src/Expressions/examples/UselessDefensiveProgramming2_good.js
new file mode 100644
index 00000000000..80734c2391f
--- /dev/null
+++ b/javascript/ql/src/Expressions/examples/UselessDefensiveProgramming2_good.js
@@ -0,0 +1,5 @@
+function setSafeStringProp(o, prop, v) {
+ // GOOD: `v == undefined` handles both `undefined` and `null`
+ var safe = v == undefined? '': v;
+ o[prop] = safe;
+}
diff --git a/javascript/ql/test/query-tests/Expressions/UselessDefensiveProgramming/UselessDefensiveProgramming.expected b/javascript/ql/test/query-tests/Expressions/UselessDefensiveProgramming/UselessDefensiveProgramming.expected
new file mode 100644
index 00000000000..65a25659f1a
--- /dev/null
+++ b/javascript/ql/test/query-tests/Expressions/UselessDefensiveProgramming/UselessDefensiveProgramming.expected
@@ -0,0 +1,78 @@
+| global-module-definition.js:10:8:10:11 | Mod2 | This guard always evaluates to false. |
+| module-environment-detection.js:3:13:3:41 | typeof ... efined' | This guard always evaluates to true. |
+| module-environment-detection.js:15:9:15:37 | typeof ... efined' | This guard always evaluates to true. |
+| module-environment-detection.js:23:8:23:36 | typeof ... efined' | This guard always evaluates to true. |
+| tst2.js:4:12:4:35 | typeof ... efined" | This guard always evaluates to true. |
+| tst.js:13:10:13:11 | u_ | This guard always evaluates to false. |
+| tst.js:14:10:14:11 | n_ | This guard always evaluates to false. |
+| tst.js:15:10:15:11 | o_ | This guard always evaluates to true. |
+| tst.js:18:5:18:5 | u | This guard always evaluates to false. |
+| tst.js:19:5:19:5 | n | This guard always evaluates to false. |
+| tst.js:20:5:20:5 | o | This guard always evaluates to true. |
+| tst.js:23:5:23:5 | u | This guard always evaluates to false. |
+| tst.js:24:5:24:5 | n | This guard always evaluates to false. |
+| tst.js:25:5:25:5 | o | This guard always evaluates to true. |
+| tst.js:28:5:28:6 | !u | This guard always evaluates to true. |
+| tst.js:29:5:29:6 | !n | This guard always evaluates to true. |
+| tst.js:30:5:30:6 | !o | This guard always evaluates to false. |
+| tst.js:33:5:33:7 | !!u | This guard always evaluates to false. |
+| tst.js:34:5:34:7 | !!n | This guard always evaluates to false. |
+| tst.js:35:5:35:7 | !!o | This guard always evaluates to true. |
+| tst.js:38:5:38:18 | u != undefined | This guard always evaluates to false. |
+| tst.js:39:5:39:18 | n != undefined | This guard always evaluates to false. |
+| tst.js:40:5:40:18 | o != undefined | This guard always evaluates to true. |
+| tst.js:43:5:43:18 | u == undefined | This guard always evaluates to true. |
+| tst.js:44:5:44:18 | n == undefined | This guard always evaluates to true. |
+| tst.js:45:5:45:18 | o == undefined | This guard always evaluates to false. |
+| tst.js:48:5:48:19 | u === undefined | This guard always evaluates to true. |
+| tst.js:49:5:49:19 | n === undefined | This guard always evaluates to false. |
+| tst.js:50:5:50:19 | o === undefined | This guard always evaluates to false. |
+| tst.js:53:9:53:9 | u | This guard always evaluates to false. |
+| tst.js:56:9:56:9 | n | This guard always evaluates to false. |
+| tst.js:59:9:59:9 | o | This guard always evaluates to true. |
+| tst.js:66:5:66:5 | u | This guard always evaluates to false. |
+| tst.js:67:5:67:5 | n | This guard always evaluates to false. |
+| tst.js:68:5:68:5 | o | This guard always evaluates to true. |
+| tst.js:71:9:71:23 | u !== undefined | This guard always evaluates to false. |
+| tst.js:74:9:74:23 | n !== undefined | This guard always evaluates to true. |
+| tst.js:77:9:77:23 | o !== undefined | This guard always evaluates to true. |
+| tst.js:84:9:84:22 | u == undefined | This guard always evaluates to true. |
+| tst.js:85:9:85:22 | n == undefined | This guard always evaluates to true. |
+| tst.js:86:9:86:22 | o == undefined | This guard always evaluates to false. |
+| tst.js:89:9:89:22 | u != undefined | This guard always evaluates to false. |
+| tst.js:90:9:90:22 | n != undefined | This guard always evaluates to false. |
+| tst.js:91:9:91:22 | o != undefined | This guard always evaluates to true. |
+| tst.js:94:9:94:32 | typeof ... efined" | This guard always evaluates to true. |
+| tst.js:95:9:95:32 | typeof ... efined" | This guard always evaluates to false. |
+| tst.js:96:9:96:32 | typeof ... efined" | This guard always evaluates to false. |
+| tst.js:100:5:100:27 | typeof ... nction" | This guard always evaluates to true. |
+| tst.js:101:5:101:27 | typeof ... nction" | This guard always evaluates to false. |
+| tst.js:114:5:114:15 | empty_array | This guard always evaluates to true. |
+| tst.js:115:5:115:22 | pseudo_empty_array | This guard always evaluates to true. |
+| tst.js:116:5:116:19 | non_empty_array | This guard always evaluates to true. |
+| tst.js:124:6:124:20 | u !== undefined | This guard always evaluates to false. |
+| tst.js:124:25:124:34 | u !== null | This guard always evaluates to true. |
+| tst.js:125:5:125:19 | u !== undefined | This guard always evaluates to false. |
+| tst.js:125:24:125:33 | u !== null | This guard always evaluates to true. |
+| tst.js:127:5:127:18 | u != undefined | This guard always evaluates to false. |
+| tst.js:127:23:127:31 | u != null | This guard always evaluates to false. |
+| tst.js:127:23:127:31 | u != null | This guard always evaluates to true. |
+| tst.js:128:5:128:18 | u == undefined | This guard always evaluates to true. |
+| tst.js:128:23:128:31 | u == null | This guard always evaluates to false. |
+| tst.js:128:23:128:31 | u == null | This guard always evaluates to true. |
+| tst.js:129:5:129:19 | u !== undefined | This guard always evaluates to false. |
+| tst.js:129:24:129:33 | u !== null | This guard always evaluates to true. |
+| tst.js:130:5:130:22 | !(u === undefined) | This guard always evaluates to false. |
+| tst.js:130:27:130:39 | !(u === null) | This guard always evaluates to true. |
+| tst.js:131:5:131:19 | u === undefined | This guard always evaluates to true. |
+| tst.js:131:24:131:33 | u === null | This guard always evaluates to false. |
+| tst.js:132:7:132:21 | u === undefined | This guard always evaluates to true. |
+| tst.js:132:26:132:35 | u === null | This guard always evaluates to false. |
+| tst.js:133:5:133:22 | !(u === undefined) | This guard always evaluates to false. |
+| tst.js:133:27:133:36 | u !== null | This guard always evaluates to true. |
+| tst.js:135:5:135:18 | u == undefined | This guard always evaluates to true. |
+| tst.js:135:23:135:31 | u == null | This guard always evaluates to true. |
+| tst.js:138:24:138:33 | x === null | This guard always evaluates to false. |
+| tst.js:140:13:140:22 | x === null | This guard always evaluates to false. |
+| tst.js:156:23:156:31 | x != null | This guard always evaluates to true. |
+| tst.js:158:13:158:21 | x != null | This guard always evaluates to true. |
diff --git a/javascript/ql/test/query-tests/Expressions/UselessDefensiveProgramming/UselessDefensiveProgramming.qlref b/javascript/ql/test/query-tests/Expressions/UselessDefensiveProgramming/UselessDefensiveProgramming.qlref
new file mode 100644
index 00000000000..9a5222a05d0
--- /dev/null
+++ b/javascript/ql/test/query-tests/Expressions/UselessDefensiveProgramming/UselessDefensiveProgramming.qlref
@@ -0,0 +1 @@
+Expressions/UselessDefensiveProgramming.ql
diff --git a/javascript/ql/test/query-tests/Expressions/UselessDefensiveProgramming/global-module-definition.js b/javascript/ql/test/query-tests/Expressions/UselessDefensiveProgramming/global-module-definition.js
new file mode 100644
index 00000000000..8c61f38d113
--- /dev/null
+++ b/javascript/ql/test/query-tests/Expressions/UselessDefensiveProgramming/global-module-definition.js
@@ -0,0 +1,11 @@
+var Mod1;
+(function (Mod1) {
+ Mod1.p = 42;
+})(Mod1 || (Mod1 = {}));
+
+(function(){
+ var Mod2;
+ (function (Mod2) {
+ Mod2.p = 42;
+ })(Mod2 || (Mod2 = {})); // NOT OK
+});
diff --git a/javascript/ql/test/query-tests/Expressions/UselessDefensiveProgramming/module-environment-detection.js b/javascript/ql/test/query-tests/Expressions/UselessDefensiveProgramming/module-environment-detection.js
new file mode 100644
index 00000000000..913684d6f6a
--- /dev/null
+++ b/javascript/ql/test/query-tests/Expressions/UselessDefensiveProgramming/module-environment-detection.js
@@ -0,0 +1,24 @@
+var _ = (function() {
+ if (typeof exports !== 'undefined') {
+ if (typeof module !== 'undefined' && module.exports) {
+ exports = module.exports = _;
+ }
+ exports._ = _;
+ }
+ return {
+ define: function(name, factory) {
+ }
+ };
+})(this);
+
+if (typeof exports !== 'undefined') {
+ if (typeof module !== 'undefined' && module.exports) {
+ exports = module.exports = emmet;
+ }
+ exports.emmet = emmet;
+}
+
+(function(){
+ var module;
+ if(typeof module === 'undefined'); // NOT OK
+});
diff --git a/javascript/ql/test/query-tests/Expressions/UselessDefensiveProgramming/tst.js b/javascript/ql/test/query-tests/Expressions/UselessDefensiveProgramming/tst.js
new file mode 100644
index 00000000000..4993c1e32c0
--- /dev/null
+++ b/javascript/ql/test/query-tests/Expressions/UselessDefensiveProgramming/tst.js
@@ -0,0 +1,174 @@
+(function(){
+ var v;
+ var u = undefined;
+ var n = null;
+ var o = {};
+ var x = functionWithUnknownReturnValue();
+
+ var u_ = u;
+ var n_ = n;
+ var o_ = o;
+ var x_ = x;
+
+ u_ = u_ || e;
+ n_ = n_ || e;
+ o_ = o_ || e;
+ x_ = x_ || e;
+
+ u && u.p;
+ n && n.p;
+ o && o.p;
+ x && x.p;
+
+ u && u();
+ n && n();
+ o && o();
+ x && x();
+
+ !u || u.p;
+ !n || n.p;
+ !o || o.p;
+ !x || x.p;
+
+ !!u && u.p;
+ !!n && n.p;
+ !!o && o.p;
+ !!x && x.p;
+
+ u != undefined && u.p;
+ n != undefined && n.p;
+ o != undefined && o.p;
+ x != undefined && x.p;
+
+ u == undefined || u.p;
+ n == undefined || n.p;
+ o == undefined || o.p;
+ x == undefined || x.p;
+
+ u === undefined || u.p;
+ n === undefined || n.p;
+ o === undefined || o.p; // T, D
+ x === undefined || x.p;
+
+ if (u) {
+ u.p;
+ }
+ if (n) {
+ n.p;
+ }
+ if (o) {
+ o.p;
+ }
+ if (x) {
+ x.p;
+ }
+
+ u? u():_;
+ n? n(): _;
+ o? o(): _;
+ x? x(): _;
+
+ if (u !== undefined) {
+ u.p;
+ }
+ if (n !== undefined) {
+ n.p;
+ }
+ if (o !== undefined) {
+ o.p;
+ }
+ if (x !== undefined) {
+ x.p;
+ }
+
+ if (u == undefined){}
+ if (n == undefined){}
+ if (o == undefined){}
+ if (x == undefined){}
+
+ if (u != undefined){}
+ if (n != undefined){}
+ if (o != undefined){}
+ if (x != undefined){}
+
+ if (typeof u === "undefined"){}
+ if (typeof n === "undefined"){}
+ if (typeof o === "undefined"){}
+ if (typeof x === "undefined"){}
+
+ function f() { }
+ typeof f === "function" && f();
+ typeof u === "function" && u();
+ typeof x === "function" && x();
+
+ var empty_array = [];
+ var pseudo_empty_array = [''];
+ var non_empty_array = ['foo'];
+ var empty_string = "";
+ var non_empty_string = "foo";
+ var zero = 0;
+ var neg = -1;
+ var _true = true;
+ var _false = false;
+
+ empty_array && empty_array.pop();
+ pseudo_empty_array && pseudo_empty_array.pop();
+ non_empty_array && non_empty_array.pop();
+ empty_string && empty_string.charAt(0);
+ non_empty_string && non_empty_string.charAt(0);
+ zero && zero();
+ neg && neg();
+ _true && _true();
+ _false && _false();D
+
+ (u !== undefined && u !== null) && u.p;
+ u !== undefined && u !== null && u.p;
+
+ u != undefined && u != null;
+ u == undefined || u == null;
+ u !== undefined && u !== null;
+ !(u === undefined) && !(u === null);
+ u === undefined || u === null;
+ !(u === undefined || u === null);
+ !(u === undefined) && u !== null;
+ u !== undefined && n !== null;
+ u == undefined && u == null;
+ x == undefined && x == null;
+
+ x === undefined && x === null;
+ if (x === undefined) {
+ if (x === null) {
+ }
+ }
+
+ x !== undefined && x !== null;
+ if (x !== undefined) {
+ if (x !== null) {
+ }
+ }
+
+ x == undefined && x == null;
+ if (x == undefined) {
+ if (x == null) {
+ }
+ }
+
+ x != undefined && x != null;
+ if (x != undefined) {
+ if (x != null) {
+ }
+ }
+
+ if (typeof x !== undefined);
+ if (typeof window !== undefined);
+ if (typeof x !== x);
+ if (typeof x !== u);
+
+ if (typeof window !== "undefined");
+ if (typeof module !== "undefined");
+ if (typeof global !== "undefined");
+
+ if (typeof window !== "undefined" && window.document);
+ if (typeof module !== "undefined" && module.exports);
+ if (typeof global !== "undefined" && global.process);
+});
diff --git a/javascript/ql/test/query-tests/Expressions/UselessDefensiveProgramming/tst2.js b/javascript/ql/test/query-tests/Expressions/UselessDefensiveProgramming/tst2.js
new file mode 100644
index 00000000000..4c6ad02a6bf
--- /dev/null
+++ b/javascript/ql/test/query-tests/Expressions/UselessDefensiveProgramming/tst2.js
@@ -0,0 +1,10 @@
+(function(){
+ var v;
+ (function(){
+ if(typeof v === "undefined"){ // NOT OK
+ v = 42;
+ }
+ for(var v in x){
+ }
+ });
+});
From e29c57a58ee1387b30ccf04af13122594e9f89a6 Mon Sep 17 00:00:00 2001
From: Esben Sparre Andreasen
Date: Wed, 10 Oct 2018 14:37:36 +0200
Subject: [PATCH 59/71] JS: add whitelist to js/useless-defensive-code
---
.../Expressions/UselessDefensiveProgramming.ql | 15 ++++++++++++++-
.../semmle/javascript/DefensiveProgramming.qll | 2 +-
.../UselessDefensiveProgramming.expected | 6 ------
3 files changed, 15 insertions(+), 8 deletions(-)
diff --git a/javascript/ql/src/Expressions/UselessDefensiveProgramming.ql b/javascript/ql/src/Expressions/UselessDefensiveProgramming.ql
index 9dd76ffec13..3ca0a5fdafb 100644
--- a/javascript/ql/src/Expressions/UselessDefensiveProgramming.ql
+++ b/javascript/ql/src/Expressions/UselessDefensiveProgramming.ql
@@ -15,5 +15,18 @@ import javascript
import semmle.javascript.DefensiveProgramming
from DefensiveExpression e, boolean cv
-where e.getTheTestResult() = cv
+where e.getTheTestResult() = cv and
+ // whitelist
+ not (
+ // module environment detection
+ exists (VarAccess access, string name |
+ name = "exports" or name = "module" |
+ e.asExpr().(Internal::TypeofUndefinedTest).getOperand() = access and
+ access.getName() = name and
+ not exists (access.getVariable().getADeclaration())
+ )
+ or
+ // too benign in practice
+ e instanceof Internal::DefensiveInit
+ )
select e, "This guard always evaluates to " + cv + "."
diff --git a/javascript/ql/src/semmle/javascript/DefensiveProgramming.qll b/javascript/ql/src/semmle/javascript/DefensiveProgramming.qll
index ffa4246e128..3de4f2121ef 100644
--- a/javascript/ql/src/semmle/javascript/DefensiveProgramming.qll
+++ b/javascript/ql/src/semmle/javascript/DefensiveProgramming.qll
@@ -390,7 +390,7 @@ module Internal {
/**
* A test for `undefined` using a `typeof` expression.
*/
- private class TypeofUndefinedTest extends UndefinedNullTest {
+ class TypeofUndefinedTest extends UndefinedNullTest {
TypeofTest test;
diff --git a/javascript/ql/test/query-tests/Expressions/UselessDefensiveProgramming/UselessDefensiveProgramming.expected b/javascript/ql/test/query-tests/Expressions/UselessDefensiveProgramming/UselessDefensiveProgramming.expected
index 65a25659f1a..f726f0a0b5d 100644
--- a/javascript/ql/test/query-tests/Expressions/UselessDefensiveProgramming/UselessDefensiveProgramming.expected
+++ b/javascript/ql/test/query-tests/Expressions/UselessDefensiveProgramming/UselessDefensiveProgramming.expected
@@ -1,11 +1,5 @@
-| global-module-definition.js:10:8:10:11 | Mod2 | This guard always evaluates to false. |
-| module-environment-detection.js:3:13:3:41 | typeof ... efined' | This guard always evaluates to true. |
-| module-environment-detection.js:15:9:15:37 | typeof ... efined' | This guard always evaluates to true. |
| module-environment-detection.js:23:8:23:36 | typeof ... efined' | This guard always evaluates to true. |
| tst2.js:4:12:4:35 | typeof ... efined" | This guard always evaluates to true. |
-| tst.js:13:10:13:11 | u_ | This guard always evaluates to false. |
-| tst.js:14:10:14:11 | n_ | This guard always evaluates to false. |
-| tst.js:15:10:15:11 | o_ | This guard always evaluates to true. |
| tst.js:18:5:18:5 | u | This guard always evaluates to false. |
| tst.js:19:5:19:5 | n | This guard always evaluates to false. |
| tst.js:20:5:20:5 | o | This guard always evaluates to true. |
From 358e6188d98ed43449a29a0c54d3da9c31546b5c Mon Sep 17 00:00:00 2001
From: Esben Sparre Andreasen
Date: Wed, 10 Oct 2018 12:52:52 +0200
Subject: [PATCH 60/71] JS: downgrade other alerts to js/useless-defensive-code
---
javascript/ql/src/Expressions/HeterogeneousComparison.ql | 2 ++
javascript/ql/src/Statements/UselessConditional.ql | 2 +-
.../HeterogeneousComparison.expected | 3 +++
.../UselessDefensiveProgramming/HeterogeneousComparison.qlref | 1 +
.../UselessDefensiveProgramming/UselessConditional.expected | 0
.../UselessDefensiveProgramming/UselessConditional.qlref | 1 +
6 files changed, 8 insertions(+), 1 deletion(-)
create mode 100644 javascript/ql/test/query-tests/Expressions/UselessDefensiveProgramming/HeterogeneousComparison.expected
create mode 100644 javascript/ql/test/query-tests/Expressions/UselessDefensiveProgramming/HeterogeneousComparison.qlref
create mode 100644 javascript/ql/test/query-tests/Expressions/UselessDefensiveProgramming/UselessConditional.expected
create mode 100644 javascript/ql/test/query-tests/Expressions/UselessDefensiveProgramming/UselessConditional.qlref
diff --git a/javascript/ql/src/Expressions/HeterogeneousComparison.ql b/javascript/ql/src/Expressions/HeterogeneousComparison.ql
index fd524466ddf..6e20e3acaa4 100644
--- a/javascript/ql/src/Expressions/HeterogeneousComparison.ql
+++ b/javascript/ql/src/Expressions/HeterogeneousComparison.ql
@@ -15,6 +15,7 @@
import javascript
private import semmle.javascript.dataflow.InferredTypes
+private import semmle.javascript.DefensiveProgramming
/**
* Holds if `left` and `right` are the left and right operands, respectively, of `nd`, which is
@@ -198,6 +199,7 @@ from ASTNode cmp,
int leftTypeCount, int rightTypeCount ,
string leftTypeDescription, string rightTypeDescription
where isHeterogeneousComparison(cmp, left, right, leftTypes, rightTypes) and
+ not exists (cmp.(Expr).flow().(DefensiveExpression).getTheTestResult()) and
not whitelist(left.asExpr()) and
not whitelist(right.asExpr()) and
leftExprDescription = capitalize(getDescription(left.asExpr(), "this expression")) and
diff --git a/javascript/ql/src/Statements/UselessConditional.ql b/javascript/ql/src/Statements/UselessConditional.ql
index 06e6e8601b9..d4dbebbb6f8 100644
--- a/javascript/ql/src/Statements/UselessConditional.ql
+++ b/javascript/ql/src/Statements/UselessConditional.ql
@@ -87,7 +87,7 @@ predicate isConstantBooleanReturnValue(Expr e) {
predicate whitelist(Expr e) {
isConstant(e) or
isConstant(e.(LogNotExpr).getOperand()) or
- e.flow() instanceof Internal::DefensiveInit or
+ exists (e.flow().(DefensiveExpression).getTheTestResult()) or
isInitialParameterUse(e) or
isConstantBooleanReturnValue(e)
}
diff --git a/javascript/ql/test/query-tests/Expressions/UselessDefensiveProgramming/HeterogeneousComparison.expected b/javascript/ql/test/query-tests/Expressions/UselessDefensiveProgramming/HeterogeneousComparison.expected
new file mode 100644
index 00000000000..534048b0d15
--- /dev/null
+++ b/javascript/ql/test/query-tests/Expressions/UselessDefensiveProgramming/HeterogeneousComparison.expected
@@ -0,0 +1,3 @@
+| tst.js:162:9:162:16 | typeof x | This expression is of type string, but it is compared to $@ of type undefined. | tst.js:162:22:162:30 | undefined | 'undefined' |
+| tst.js:163:9:163:21 | typeof window | This expression is of type string, but it is compared to $@ of type undefined. | tst.js:163:27:163:35 | undefined | 'undefined' |
+| tst.js:165:9:165:16 | typeof x | This expression is of type string, but it is compared to $@ of type undefined. | tst.js:165:22:165:22 | u | variable 'u' |
diff --git a/javascript/ql/test/query-tests/Expressions/UselessDefensiveProgramming/HeterogeneousComparison.qlref b/javascript/ql/test/query-tests/Expressions/UselessDefensiveProgramming/HeterogeneousComparison.qlref
new file mode 100644
index 00000000000..13b0e2a181c
--- /dev/null
+++ b/javascript/ql/test/query-tests/Expressions/UselessDefensiveProgramming/HeterogeneousComparison.qlref
@@ -0,0 +1 @@
+Expressions/HeterogeneousComparison.ql
\ No newline at end of file
diff --git a/javascript/ql/test/query-tests/Expressions/UselessDefensiveProgramming/UselessConditional.expected b/javascript/ql/test/query-tests/Expressions/UselessDefensiveProgramming/UselessConditional.expected
new file mode 100644
index 00000000000..e69de29bb2d
diff --git a/javascript/ql/test/query-tests/Expressions/UselessDefensiveProgramming/UselessConditional.qlref b/javascript/ql/test/query-tests/Expressions/UselessDefensiveProgramming/UselessConditional.qlref
new file mode 100644
index 00000000000..d29916245d6
--- /dev/null
+++ b/javascript/ql/test/query-tests/Expressions/UselessDefensiveProgramming/UselessConditional.qlref
@@ -0,0 +1 @@
+Statements/UselessConditional.ql
\ No newline at end of file
From f440c9221ac686b4e3c34de865fe946872a9f54e Mon Sep 17 00:00:00 2001
From: Esben Sparre Andreasen
Date: Tue, 16 Oct 2018 10:40:58 +0200
Subject: [PATCH 61/71] JS: replace some `Expr.stripParens` with
`Expr.getUnderlyingValue`
---
.../semmle/javascript/DefensiveProgramming.qll | 16 ++++++++--------
1 file changed, 8 insertions(+), 8 deletions(-)
diff --git a/javascript/ql/src/semmle/javascript/DefensiveProgramming.qll b/javascript/ql/src/semmle/javascript/DefensiveProgramming.qll
index 3de4f2121ef..def68da6824 100644
--- a/javascript/ql/src/semmle/javascript/DefensiveProgramming.qll
+++ b/javascript/ql/src/semmle/javascript/DefensiveProgramming.qll
@@ -52,7 +52,7 @@ module Internal {
*/
private Expr stripNotsAndParens(Expr e, boolean polarity) {
exists (Expr inner |
- inner = e.stripParens() |
+ inner = e.getUnderlyingValue() |
if inner instanceof LogNotExpr then
(result = stripNotsAndParens(inner.(LogNotExpr).getOperand(), polarity.booleanNot()))
else
@@ -192,11 +192,11 @@ module Internal {
Expr target;
UndefinedNullCrashUse() {
- this.(InvokeExpr).getCallee().stripParens() = target
+ this.(InvokeExpr).getCallee().getUnderlyingValue() = target
or
- this.(PropAccess).getBase().stripParens() = target
+ this.(PropAccess).getBase().getUnderlyingValue() = target
or
- this.(MethodCallExpr).getReceiver().stripParens() = target
+ this.(MethodCallExpr).getReceiver().getUnderlyingValue() = target
}
/**
@@ -216,7 +216,7 @@ module Internal {
Expr target;
NonFunctionCallCrashUse() {
- this.(InvokeExpr).getCallee().stripParens() = target
+ this.(InvokeExpr).getCallee().getUnderlyingValue() = target
}
/**
@@ -272,7 +272,7 @@ module Internal {
exists (VarRef useVar |
guardVar = stripNotsAndParens(this.asExpr(), polarity) and
guardVar.getVariable() = useVar.getVariable() |
- getAGuardedExpr(this.asExpr()).stripParens().(UndefinedNullCrashUse).getVulnerableSubexpression() = useVar and
+ getAGuardedExpr(this.asExpr()).getUnderlyingValue().(UndefinedNullCrashUse).getVulnerableSubexpression() = useVar and
// exclude types whose truthiness depend on the value
not isStringOrNumOrBool(guardVar.analyze().getAType())
)
@@ -305,7 +305,7 @@ module Internal {
test = stripNotsAndParens(guard, polarity) and
test.getOperand() = guardVar and
guardVar.getVariable() = useVar.getVariable() |
- getAGuardedExpr(guard).stripParens().(UndefinedNullCrashUse).getVulnerableSubexpression() = useVar
+ getAGuardedExpr(guard).getUnderlyingValue().(UndefinedNullCrashUse).getVulnerableSubexpression() = useVar
)
}
@@ -374,7 +374,7 @@ module Internal {
test = stripNotsAndParens(guard, polarity) and
test.getOperand() = guardVar and
guardVar.getVariable() = useVar.getVariable() |
- getAGuardedExpr(guard).stripParens().(NonFunctionCallCrashUse).getVulnerableSubexpression() = useVar
+ getAGuardedExpr(guard).getUnderlyingValue().(NonFunctionCallCrashUse).getVulnerableSubexpression() = useVar
) and
test.getTag() = "function"
}
From 7d4cf495451d7138a2bf94f88709a0c9ae044d7c Mon Sep 17 00:00:00 2001
From: Esben Sparre Andreasen
Date: Wed, 31 Oct 2018 09:33:49 +0100
Subject: [PATCH 62/71] JS: fixup double reporting of alerts
---
.../ql/src/Statements/UselessConditional.ql | 15 ++++++++++++++-
1 file changed, 14 insertions(+), 1 deletion(-)
diff --git a/javascript/ql/src/Statements/UselessConditional.ql b/javascript/ql/src/Statements/UselessConditional.ql
index d4dbebbb6f8..e682a56b006 100644
--- a/javascript/ql/src/Statements/UselessConditional.ql
+++ b/javascript/ql/src/Statements/UselessConditional.ql
@@ -73,6 +73,19 @@ predicate isConstantBooleanReturnValue(Expr e) {
isConstantBooleanReturnValue(e.(LogNotExpr).getOperand())
}
+/**
+ * Holds if `e` is a defensive expression with a fixed outcome.
+ */
+predicate isConstantDefensive(Expr e) {
+ exists(Expr defensive |
+ defensive = e or
+ // traverse negations
+ defensive.(LogNotExpr).getOperand+() = e
+ |
+ exists(defensive.flow().(DefensiveExpression).getTheTestResult())
+ )
+}
+
/**
* Holds if `e` is an expression that should not be flagged as a useless condition.
*
@@ -87,7 +100,7 @@ predicate isConstantBooleanReturnValue(Expr e) {
predicate whitelist(Expr e) {
isConstant(e) or
isConstant(e.(LogNotExpr).getOperand()) or
- exists (e.flow().(DefensiveExpression).getTheTestResult()) or
+ isConstantDefensive(e) or // flagged by js/useless-defensive-code
isInitialParameterUse(e) or
isConstantBooleanReturnValue(e)
}
From a636319c97b64264fff32eeede7929d9de5ed4e7 Mon Sep 17 00:00:00 2001
From: Esben Sparre Andreasen
Date: Thu, 1 Nov 2018 08:47:35 +0100
Subject: [PATCH 63/71] JS: change notes for js/useless-defensive-code
---
change-notes/1.19/analysis-javascript.md | 1 +
1 file changed, 1 insertion(+)
diff --git a/change-notes/1.19/analysis-javascript.md b/change-notes/1.19/analysis-javascript.md
index 5630452ded3..e79bae13009 100644
--- a/change-notes/1.19/analysis-javascript.md
+++ b/change-notes/1.19/analysis-javascript.md
@@ -24,6 +24,7 @@
| Stored cross-site scripting (`js/stored-xss`) | security, external/cwe/cwe-079, external/cwe/cwe-116 | Highlights uncontrolled stored values flowing into HTML content, indicating a violation of [CWE-079](https://cwe.mitre.org/data/definitions/79.html). Results shown on LGTM by default. |
| Unclear precedence of nested operators (`js/unclear-operator-precedence`) | maintainability, correctness, external/cwe/cwe-783 | Highlights nested binary operators whose relative precedence is easy to misunderstand. Results shown on LGTM by default. |
| Useless assignment to property | maintainability | Highlights property assignments whose value is always overwritten. Results are shown on LGTM by default. |
+| Useless defensive code | correctness, external/cwe/cwe-570, external/cwe/cwe-571 | Highlights locations where defensive code serves no purpose. Results are shown on LGTM by default. |
| User-controlled data in file | security, external/cwe/cwe-912 | Highlights locations where user-controlled data is written to a file. Results are not shown on LGTM by default. |
## Changes to existing queries
From 8b71b25a2a05c26a1681cb660c9725a47a0e1a12 Mon Sep 17 00:00:00 2001
From: Esben Sparre Andreasen
Date: Thu, 1 Nov 2018 09:48:16 +0100
Subject: [PATCH 64/71] JS: annotate test file with expected results
---
.../UselessDefensiveProgramming/tst.js | 126 +++++++++---------
1 file changed, 63 insertions(+), 63 deletions(-)
diff --git a/javascript/ql/test/query-tests/Expressions/UselessDefensiveProgramming/tst.js b/javascript/ql/test/query-tests/Expressions/UselessDefensiveProgramming/tst.js
index 4993c1e32c0..1e03c4e3ba1 100644
--- a/javascript/ql/test/query-tests/Expressions/UselessDefensiveProgramming/tst.js
+++ b/javascript/ql/test/query-tests/Expressions/UselessDefensiveProgramming/tst.js
@@ -10,95 +10,95 @@
var o_ = o;
var x_ = x;
- u_ = u_ || e;
- n_ = n_ || e;
- o_ = o_ || e;
+ u_ = u_ || e; // NOT OK
+ n_ = n_ || e; // NOT OK
+ o_ = o_ || e; // NOT OK
x_ = x_ || e;
- u && u.p;
- n && n.p;
- o && o.p;
+ u && u.p; // NOT OK
+ n && n.p; // NOT OK
+ o && o.p; // NOT OK
x && x.p;
- u && u();
- n && n();
- o && o();
+ u && u(); // NOT OK
+ n && n(); // NOT OK
+ o && o(); // NOT OK
x && x();
- !u || u.p;
- !n || n.p;
- !o || o.p;
+ !u || u.p; // NOT OK
+ !n || n.p; // NOT OK
+ !o || o.p; // NOT OK
!x || x.p;
- !!u && u.p;
- !!n && n.p;
- !!o && o.p;
+ !!u && u.p; // NOT OK
+ !!n && n.p; // NOT OK
+ !!o && o.p; // NOT OK
!!x && x.p;
- u != undefined && u.p;
- n != undefined && n.p;
- o != undefined && o.p;
+ u != undefined && u.p; // NOT OK
+ n != undefined && n.p; // NOT OK
+ o != undefined && o.p; // NOT OK
x != undefined && x.p;
- u == undefined || u.p;
- n == undefined || n.p;
- o == undefined || o.p;
+ u == undefined || u.p; // NOT OK
+ n == undefined || n.p; // NOT OK
+ o == undefined || o.p; // NOT OK
x == undefined || x.p;
- u === undefined || u.p;
- n === undefined || n.p;
- o === undefined || o.p; // T, D
+ u === undefined || u.p; // NOT OK
+ n === undefined || n.p; // NOT OK
+ o === undefined || o.p; // NOT OK
x === undefined || x.p;
- if (u) {
+ if (u) { // NOT OK
u.p;
}
- if (n) {
+ if (n) { // NOT OK
n.p;
}
- if (o) {
+ if (o) { // NOT OK
o.p;
}
if (x) {
x.p;
}
- u? u():_;
- n? n(): _;
- o? o(): _;
+ u? u():_; // NOT OK
+ n? n(): _; // NOT OK
+ o? o(): _; // NOT OK
x? x(): _;
- if (u !== undefined) {
+ if (u !== undefined) { // NOT OK
u.p;
}
- if (n !== undefined) {
+ if (n !== undefined) { // NOT OK
n.p;
}
- if (o !== undefined) {
+ if (o !== undefined) { // NOT OK
o.p;
}
if (x !== undefined) {
x.p;
}
- if (u == undefined){}
- if (n == undefined){}
- if (o == undefined){}
+ if (u == undefined){} // NOT OK
+ if (n == undefined){} // NOT OK
+ if (o == undefined){} // NOT OK
if (x == undefined){}
- if (u != undefined){}
- if (n != undefined){}
- if (o != undefined){}
+ if (u != undefined){} // NOT OK
+ if (n != undefined){} // NOT OK
+ if (o != undefined){} // NOT OK
if (x != undefined){}
- if (typeof u === "undefined"){}
- if (typeof n === "undefined"){}
- if (typeof o === "undefined"){}
+ if (typeof u === "undefined"){} // NOT OK
+ if (typeof n === "undefined"){} // NOT OK
+ if (typeof o === "undefined"){} // NOT OK
if (typeof x === "undefined"){}
function f() { }
- typeof f === "function" && f();
- typeof u === "function" && u();
+ typeof f === "function" && f(); // NOT OK
+ typeof u === "function" && u(); // NOT OK
typeof x === "function" && x();
var empty_array = [];
@@ -111,33 +111,33 @@
var _true = true;
var _false = false;
- empty_array && empty_array.pop();
- pseudo_empty_array && pseudo_empty_array.pop();
- non_empty_array && non_empty_array.pop();
+ empty_array && empty_array.pop(); // NOT OK
+ pseudo_empty_array && pseudo_empty_array.pop(); // NOT OK
+ non_empty_array && non_empty_array.pop(); // NOT OK
empty_string && empty_string.charAt(0);
non_empty_string && non_empty_string.charAt(0);
zero && zero();
neg && neg();
_true && _true();
- _false && _false();D
+ _false && _false();
- (u !== undefined && u !== null) && u.p;
- u !== undefined && u !== null && u.p;
+ (u !== undefined && u !== null) && u.p; // NOT OK
+ u !== undefined && u !== null && u.p; // NOT OK
- u != undefined && u != null;
- u == undefined || u == null;
- u !== undefined && u !== null;
- !(u === undefined) && !(u === null);
- u === undefined || u === null;
- !(u === undefined || u === null);
- !(u === undefined) && u !== null;
+ u != undefined && u != null; // NOT OK
+ u == undefined || u == null; // NOT OK
+ u !== undefined && u !== null; // NOT OK
+ !(u === undefined) && !(u === null); // NOT OK
+ u === undefined || u === null; // NOT OK
+ !(u === undefined || u === null); // NOT OK
+ !(u === undefined) && u !== null; // NOT OK
u !== undefined && n !== null;
- u == undefined && u == null;
+ u == undefined && u == null; // NOT OK
x == undefined && x == null;
- x === undefined && x === null;
+ x === undefined && x === null; // NOT OK
if (x === undefined) {
- if (x === null) {
+ if (x === null) { // NOT OK
}
}
@@ -153,16 +153,16 @@
}
}
- x != undefined && x != null;
+ x != undefined && x != null; // NOT OK
if (x != undefined) {
- if (x != null) {
+ if (x != null) { // NOT OK
}
}
if (typeof x !== undefined);
if (typeof window !== undefined);
if (typeof x !== x);
- if (typeof x !== u);
+ if (typeof x !== u); // NOT OK
if (typeof window !== "undefined");
if (typeof module !== "undefined");
From 8ea9fd4ccac8415a6ec6d3e4f4a5ad56001008bb Mon Sep 17 00:00:00 2001
From: Esben Sparre Andreasen
Date: Mon, 5 Nov 2018 11:27:09 +0100
Subject: [PATCH 65/71] JS: address review comments
---
.../Expressions/HeterogeneousComparison.ql | 2 +-
.../UselessDefensiveProgramming.ql | 2 +-
.../ql/src/Statements/UselessConditional.ql | 2 +-
.../javascript/DefensiveProgramming.qll | 27 ++++++++++---------
4 files changed, 17 insertions(+), 16 deletions(-)
diff --git a/javascript/ql/src/Expressions/HeterogeneousComparison.ql b/javascript/ql/src/Expressions/HeterogeneousComparison.ql
index 6e20e3acaa4..ae1be5a7a98 100644
--- a/javascript/ql/src/Expressions/HeterogeneousComparison.ql
+++ b/javascript/ql/src/Expressions/HeterogeneousComparison.ql
@@ -199,7 +199,7 @@ from ASTNode cmp,
int leftTypeCount, int rightTypeCount ,
string leftTypeDescription, string rightTypeDescription
where isHeterogeneousComparison(cmp, left, right, leftTypes, rightTypes) and
- not exists (cmp.(Expr).flow().(DefensiveExpression).getTheTestResult()) and
+ not exists (cmp.(Expr).flow().(DefensiveExpressionTest).getTheTestResult()) and
not whitelist(left.asExpr()) and
not whitelist(right.asExpr()) and
leftExprDescription = capitalize(getDescription(left.asExpr(), "this expression")) and
diff --git a/javascript/ql/src/Expressions/UselessDefensiveProgramming.ql b/javascript/ql/src/Expressions/UselessDefensiveProgramming.ql
index 3ca0a5fdafb..ce6dea98ecf 100644
--- a/javascript/ql/src/Expressions/UselessDefensiveProgramming.ql
+++ b/javascript/ql/src/Expressions/UselessDefensiveProgramming.ql
@@ -14,7 +14,7 @@
import javascript
import semmle.javascript.DefensiveProgramming
-from DefensiveExpression e, boolean cv
+from DefensiveExpressionTest e, boolean cv
where e.getTheTestResult() = cv and
// whitelist
not (
diff --git a/javascript/ql/src/Statements/UselessConditional.ql b/javascript/ql/src/Statements/UselessConditional.ql
index e682a56b006..3051ee3448e 100644
--- a/javascript/ql/src/Statements/UselessConditional.ql
+++ b/javascript/ql/src/Statements/UselessConditional.ql
@@ -82,7 +82,7 @@ predicate isConstantDefensive(Expr e) {
// traverse negations
defensive.(LogNotExpr).getOperand+() = e
|
- exists(defensive.flow().(DefensiveExpression).getTheTestResult())
+ exists(defensive.flow().(DefensiveExpressionTest).getTheTestResult())
)
}
diff --git a/javascript/ql/src/semmle/javascript/DefensiveProgramming.qll b/javascript/ql/src/semmle/javascript/DefensiveProgramming.qll
index def68da6824..08bfe6702c5 100644
--- a/javascript/ql/src/semmle/javascript/DefensiveProgramming.qll
+++ b/javascript/ql/src/semmle/javascript/DefensiveProgramming.qll
@@ -8,13 +8,13 @@ private import semmle.javascript.dataflow.InferredTypes
/**
* A test in a defensive programming pattern.
*/
-abstract class DefensiveExpression extends DataFlow::ValueNode {
+abstract class DefensiveExpressionTest extends DataFlow::ValueNode {
/** Gets the unique Boolean value that this test evaluates to, if any. */
abstract boolean getTheTestResult();
}
/**
- * INTERNAL: Do not use directly; use `DefensiveExpression` instead.
+ * INTERNAL: Do not use directly; use `DefensiveExpressionTest` instead.
*/
module Internal {
/**
@@ -27,7 +27,7 @@ module Internal {
* - the second `x` in `x = (x || e)`
* - the second `x` in `var x = x || e`
*/
- class DefensiveInit extends DefensiveExpression {
+ class DefensiveInit extends DefensiveExpressionTest {
DefensiveInit() {
exists(VarAccess va, LogOrExpr o, VarRef va2 |
va = astNode and
@@ -76,16 +76,14 @@ module Internal {
/**
* A dis- or conjunction that tests if an expression is `null` or `undefined` in either branch.
*/
- private class CompositeUndefinedNullTestPart extends DefensiveExpression {
+ private class CompositeUndefinedNullTestPart extends DefensiveExpressionTest {
UndefinedNullTest test;
boolean polarity;
CompositeUndefinedNullTestPart(){
- exists (BinaryExpr composite, Variable v, Expr op, Expr opOther, UndefinedNullTest testOther |
- composite instanceof LogAndExpr or
- composite instanceof LogOrExpr |
+ exists (LogicalBinaryExpr composite, Variable v, Expr op, Expr opOther, UndefinedNullTest testOther |
composite.hasOperands(op, opOther) and
this = op.flow() and
test = stripNotsAndParens(op, polarity) and
@@ -106,7 +104,7 @@ module Internal {
/**
* A test for `undefined` or `null` in an if-statement.
*/
- private class SanityCheckingUndefinedNullGuard extends DefensiveExpression {
+ private class SanityCheckingUndefinedNullGuard extends DefensiveExpressionTest {
UndefinedNullTest test;
@@ -165,16 +163,20 @@ module Internal {
result = getPolarity() and
(
if this instanceof StrictEqualityTest then
+ // case: `operand === null` or `operand === undefined`
operand.analyze().getTheType() = op2type
else
+ // case: `operand == null` or `operand == undefined`
not isNotNullOrUndefined(operand.analyze().getAType())
)
or
result = getPolarity().booleanNot() and
(
if this instanceof StrictEqualityTest then
+ // case: `operand !== null` or `operand !== undefined`
not operand.analyze().getAType() = op2type
else
+ // case: `operand != null` or `operand != undefined`
not isNullOrUndefined(operand.analyze().getAType())
)
}
@@ -232,9 +234,8 @@ module Internal {
* Gets the first expression that is guarded by `guard`.
*/
private Expr getAGuardedExpr(Expr guard) {
- exists(BinaryExpr op |
+ exists(LogicalBinaryExpr op |
op.getLeftOperand() = guard and
- (op instanceof LogAndExpr or op instanceof LogOrExpr) and
op.getRightOperand() = result
)
or
@@ -262,7 +263,7 @@ module Internal {
/**
* A defensive expression that tests for `undefined` and `null` using a truthiness test.
*/
- private class UndefinedNullTruthinessGuard extends DefensiveExpression {
+ private class UndefinedNullTruthinessGuard extends DefensiveExpressionTest {
VarRef guardVar;
@@ -293,7 +294,7 @@ module Internal {
/**
* A defensive expression that tests for `undefined` and `null`.
*/
- private class UndefinedNullTypeGuard extends DefensiveExpression {
+ private class UndefinedNullTypeGuard extends DefensiveExpressionTest {
UndefinedNullTest test;
@@ -362,7 +363,7 @@ module Internal {
/**
* A defensive expression that tests if an expression has type `function`.
*/
- private class FunctionTypeGuard extends DefensiveExpression {
+ private class FunctionTypeGuard extends DefensiveExpressionTest {
TypeofTest test;
From 15123da0b7f728f7ecc327f7d4d809159347ea32 Mon Sep 17 00:00:00 2001
From: Esben Sparre Andreasen
Date: Mon, 5 Nov 2018 11:33:14 +0100
Subject: [PATCH 66/71] JS: minor fixup: only traverse `LogNotExpr`s
---
javascript/ql/src/Statements/UselessConditional.ql | 14 ++++++++------
1 file changed, 8 insertions(+), 6 deletions(-)
diff --git a/javascript/ql/src/Statements/UselessConditional.ql b/javascript/ql/src/Statements/UselessConditional.ql
index 3051ee3448e..27b703f652b 100644
--- a/javascript/ql/src/Statements/UselessConditional.ql
+++ b/javascript/ql/src/Statements/UselessConditional.ql
@@ -73,16 +73,18 @@ predicate isConstantBooleanReturnValue(Expr e) {
isConstantBooleanReturnValue(e.(LogNotExpr).getOperand())
}
+private Expr maybeStripLogNot(Expr e) {
+ result = maybeStripLogNot(e.(LogNotExpr).getOperand()) or
+ result = e
+}
+
/**
* Holds if `e` is a defensive expression with a fixed outcome.
*/
predicate isConstantDefensive(Expr e) {
- exists(Expr defensive |
- defensive = e or
- // traverse negations
- defensive.(LogNotExpr).getOperand+() = e
- |
- exists(defensive.flow().(DefensiveExpressionTest).getTheTestResult())
+ exists(DefensiveExpressionTest defensive |
+ maybeStripLogNot(defensive.asExpr()) = e and
+ exists(defensive.getTheTestResult())
)
}
From 3aae1d17dbcb3d7b8b42806279d331bf39f19894 Mon Sep 17 00:00:00 2001
From: Esben Sparre Andreasen
Date: Mon, 5 Nov 2018 11:34:34 +0100
Subject: [PATCH 67/71] JS: avoid two uses of `getChildExpr(0)`
---
.../ql/src/semmle/javascript/DefensiveProgramming.qll | 9 +++++----
1 file changed, 5 insertions(+), 4 deletions(-)
diff --git a/javascript/ql/src/semmle/javascript/DefensiveProgramming.qll b/javascript/ql/src/semmle/javascript/DefensiveProgramming.qll
index 08bfe6702c5..6b224fe586b 100644
--- a/javascript/ql/src/semmle/javascript/DefensiveProgramming.qll
+++ b/javascript/ql/src/semmle/javascript/DefensiveProgramming.qll
@@ -239,10 +239,11 @@ module Internal {
op.getRightOperand() = result
)
or
- exists(IfStmt c |
- c.getCondition() = guard |
- result = c.getAControlledStmt().getChildExpr(0) or
- result = c.getAControlledStmt().(BlockStmt).getStmt(0).getChildExpr(0)
+ exists(IfStmt c, ExprStmt guardedStmt |
+ c.getCondition() = guard and
+ result = guardedStmt.getExpr() |
+ guardedStmt = c.getAControlledStmt() or
+ guardedStmt = c.getAControlledStmt().(BlockStmt).getStmt(0)
)
or
exists (ConditionalExpr c |
From 1db2e6ca55777501ae048696782b28f321a411e9 Mon Sep 17 00:00:00 2001
From: Esben Sparre Andreasen
Date: Mon, 5 Nov 2018 11:49:54 +0100
Subject: [PATCH 68/71] JS: add source code examples to docstrings
---
.../javascript/DefensiveProgramming.qll | 22 +++++++++++++++++++
1 file changed, 22 insertions(+)
diff --git a/javascript/ql/src/semmle/javascript/DefensiveProgramming.qll b/javascript/ql/src/semmle/javascript/DefensiveProgramming.qll
index 6b224fe586b..6529566495b 100644
--- a/javascript/ql/src/semmle/javascript/DefensiveProgramming.qll
+++ b/javascript/ql/src/semmle/javascript/DefensiveProgramming.qll
@@ -62,6 +62,8 @@ module Internal {
/**
* An equality test for `null` and `undefined`.
+ *
+ * Examples: `e === undefined` or `typeof e !== undefined`.
*/
private abstract class UndefinedNullTest extends EqualityTest {
/** Gets the unique Boolean value that this test evaluates to, if any. */
@@ -75,6 +77,8 @@ module Internal {
/**
* A dis- or conjunction that tests if an expression is `null` or `undefined` in either branch.
+ *
+ * Example: a branch in `x === null || x === undefined`.
*/
private class CompositeUndefinedNullTestPart extends DefensiveExpressionTest {
@@ -103,6 +107,8 @@ module Internal {
/**
* A test for `undefined` or `null` in an if-statement.
+ *
+ * Example: `if (x === null) ...`.
*/
private class SanityCheckingUndefinedNullGuard extends DefensiveExpressionTest {
@@ -143,6 +149,8 @@ module Internal {
/**
* A value comparison for `null` and `undefined`.
+ *
+ * Examples: `x === null` or `x != undefined`.
*/
private class NullUndefinedComparison extends UndefinedNullTest {
@@ -188,6 +196,8 @@ module Internal {
/**
* An expression that throws an exception if one of its subexpressions evaluates to `null` or `undefined`.
+ *
+ * Examples: `sub.p` or `sub()`.
*/
private class UndefinedNullCrashUse extends Expr {
@@ -212,6 +222,8 @@ module Internal {
/**
* An expression that throws an exception if one of its subexpressions is not a `function`.
+ *
+ * Example: `sub()`.
*/
private class NonFunctionCallCrashUse extends Expr {
@@ -263,6 +275,8 @@ module Internal {
/**
* A defensive expression that tests for `undefined` and `null` using a truthiness test.
+ *
+ * Examples: The condition in `if(x) { x.p; }` or `!x || x.m()`.
*/
private class UndefinedNullTruthinessGuard extends DefensiveExpressionTest {
@@ -294,6 +308,8 @@ module Internal {
/**
* A defensive expression that tests for `undefined` and `null`.
+ *
+ * Example: the condition in `if(x !== null) { x.p; }`.
*/
private class UndefinedNullTypeGuard extends DefensiveExpressionTest {
@@ -321,6 +337,8 @@ module Internal {
/**
* A test for the value of a `typeof` expression.
+ *
+ * Example: `typeof x === 'undefined'`.
*/
private class TypeofTest extends EqualityTest {
Expr operand;
@@ -363,6 +381,8 @@ module Internal {
/**
* A defensive expression that tests if an expression has type `function`.
+ *
+ * Example: the condition in `if(typeof x === 'function') x()`.
*/
private class FunctionTypeGuard extends DefensiveExpressionTest {
@@ -391,6 +411,8 @@ module Internal {
/**
* A test for `undefined` using a `typeof` expression.
+ *
+ * Example: `typeof x === undefined'.
*/
class TypeofUndefinedTest extends UndefinedNullTest {
From 5666deac14bee439f529cc238767af74f3851427 Mon Sep 17 00:00:00 2001
From: Esben Sparre Andreasen
Date: Thu, 8 Nov 2018 12:08:32 +0100
Subject: [PATCH 69/71] JS: rename js/useless-defensive-code to
js/unneeded-defensive-code
---
change-notes/1.19/analysis-javascript.md | 2 +-
...ming.qhelp => UnneededDefensiveProgramming.qhelp} | 12 ++++++------
...rogramming.ql => UnneededDefensiveProgramming.ql} | 7 +++----
...1_bad.js => UnneededDefensiveProgramming1_bad.js} | 0
...good.js => UnneededDefensiveProgramming1_good.js} | 0
...2_bad.js => UnneededDefensiveProgramming2_bad.js} | 0
...good.js => UnneededDefensiveProgramming2_good.js} | 0
.../HeterogeneousComparison.expected | 0
.../HeterogeneousComparison.qlref | 0
.../UnneededDefensiveProgramming.expected} | 0
.../UnneededDefensiveProgramming.qlref | 1 +
.../UselessConditional.expected | 0
.../UselessConditional.qlref | 0
.../global-module-definition.js | 0
.../module-environment-detection.js | 0
.../tst.js | 0
.../tst2.js | 0
.../UselessDefensiveProgramming.qlref | 1 -
18 files changed, 11 insertions(+), 12 deletions(-)
rename javascript/ql/src/Expressions/{UselessDefensiveProgramming.qhelp => UnneededDefensiveProgramming.qhelp} (86%)
rename javascript/ql/src/Expressions/{UselessDefensiveProgramming.ql => UnneededDefensiveProgramming.ql} (80%)
rename javascript/ql/src/Expressions/examples/{UselessDefensiveProgramming1_bad.js => UnneededDefensiveProgramming1_bad.js} (100%)
rename javascript/ql/src/Expressions/examples/{UselessDefensiveProgramming1_good.js => UnneededDefensiveProgramming1_good.js} (100%)
rename javascript/ql/src/Expressions/examples/{UselessDefensiveProgramming2_bad.js => UnneededDefensiveProgramming2_bad.js} (100%)
rename javascript/ql/src/Expressions/examples/{UselessDefensiveProgramming2_good.js => UnneededDefensiveProgramming2_good.js} (100%)
rename javascript/ql/test/query-tests/Expressions/{UselessDefensiveProgramming => UnneededDefensiveProgramming}/HeterogeneousComparison.expected (100%)
rename javascript/ql/test/query-tests/Expressions/{UselessDefensiveProgramming => UnneededDefensiveProgramming}/HeterogeneousComparison.qlref (100%)
rename javascript/ql/test/query-tests/Expressions/{UselessDefensiveProgramming/UselessDefensiveProgramming.expected => UnneededDefensiveProgramming/UnneededDefensiveProgramming.expected} (100%)
create mode 100644 javascript/ql/test/query-tests/Expressions/UnneededDefensiveProgramming/UnneededDefensiveProgramming.qlref
rename javascript/ql/test/query-tests/Expressions/{UselessDefensiveProgramming => UnneededDefensiveProgramming}/UselessConditional.expected (100%)
rename javascript/ql/test/query-tests/Expressions/{UselessDefensiveProgramming => UnneededDefensiveProgramming}/UselessConditional.qlref (100%)
rename javascript/ql/test/query-tests/Expressions/{UselessDefensiveProgramming => UnneededDefensiveProgramming}/global-module-definition.js (100%)
rename javascript/ql/test/query-tests/Expressions/{UselessDefensiveProgramming => UnneededDefensiveProgramming}/module-environment-detection.js (100%)
rename javascript/ql/test/query-tests/Expressions/{UselessDefensiveProgramming => UnneededDefensiveProgramming}/tst.js (100%)
rename javascript/ql/test/query-tests/Expressions/{UselessDefensiveProgramming => UnneededDefensiveProgramming}/tst2.js (100%)
delete mode 100644 javascript/ql/test/query-tests/Expressions/UselessDefensiveProgramming/UselessDefensiveProgramming.qlref
diff --git a/change-notes/1.19/analysis-javascript.md b/change-notes/1.19/analysis-javascript.md
index e79bae13009..4071deb9cb9 100644
--- a/change-notes/1.19/analysis-javascript.md
+++ b/change-notes/1.19/analysis-javascript.md
@@ -23,8 +23,8 @@
| Replacement of a substring with itself (`js/identity-replacement`) | correctness, security, external/cwe/cwe-116 | Highlights string replacements that replace a string with itself, which usually indicates a mistake. Results shown on LGTM by default. |
| Stored cross-site scripting (`js/stored-xss`) | security, external/cwe/cwe-079, external/cwe/cwe-116 | Highlights uncontrolled stored values flowing into HTML content, indicating a violation of [CWE-079](https://cwe.mitre.org/data/definitions/79.html). Results shown on LGTM by default. |
| Unclear precedence of nested operators (`js/unclear-operator-precedence`) | maintainability, correctness, external/cwe/cwe-783 | Highlights nested binary operators whose relative precedence is easy to misunderstand. Results shown on LGTM by default. |
+| Unneeded defensive code | correctness, external/cwe/cwe-570, external/cwe/cwe-571 | Highlights locations where defensive code is not needed. Results are shown on LGTM by default. |
| Useless assignment to property | maintainability | Highlights property assignments whose value is always overwritten. Results are shown on LGTM by default. |
-| Useless defensive code | correctness, external/cwe/cwe-570, external/cwe/cwe-571 | Highlights locations where defensive code serves no purpose. Results are shown on LGTM by default. |
| User-controlled data in file | security, external/cwe/cwe-912 | Highlights locations where user-controlled data is written to a file. Results are not shown on LGTM by default. |
## Changes to existing queries
diff --git a/javascript/ql/src/Expressions/UselessDefensiveProgramming.qhelp b/javascript/ql/src/Expressions/UnneededDefensiveProgramming.qhelp
similarity index 86%
rename from javascript/ql/src/Expressions/UselessDefensiveProgramming.qhelp
rename to javascript/ql/src/Expressions/UnneededDefensiveProgramming.qhelp
index 870bc26da17..fd7191dd7fa 100644
--- a/javascript/ql/src/Expressions/UselessDefensiveProgramming.qhelp
+++ b/javascript/ql/src/Expressions/UnneededDefensiveProgramming.qhelp
@@ -14,7 +14,7 @@
However, if the situation that some defensive code guards
against never can occur, then the defensive code serves no purpose and
- it can safely be removed.
+ can safely be removed.
@@ -45,7 +45,7 @@
-
+
@@ -56,7 +56,7 @@
-
+
@@ -68,7 +68,7 @@
-
+
@@ -76,11 +76,11 @@
undefined holds for both the situation where v
isundefined and the situation where v
isnull, so the v == null
- guard serves no purpose, and it can be removed:
+ guard serves no purpose, and can be removed:
-
+
diff --git a/javascript/ql/src/Expressions/UselessDefensiveProgramming.ql b/javascript/ql/src/Expressions/UnneededDefensiveProgramming.ql
similarity index 80%
rename from javascript/ql/src/Expressions/UselessDefensiveProgramming.ql
rename to javascript/ql/src/Expressions/UnneededDefensiveProgramming.ql
index ce6dea98ecf..bb36d94aef3 100644
--- a/javascript/ql/src/Expressions/UselessDefensiveProgramming.ql
+++ b/javascript/ql/src/Expressions/UnneededDefensiveProgramming.ql
@@ -1,10 +1,9 @@
/**
- * @name Useless defensive code
- * @description If the situation some defensive code guards against never
- * happens, then the defensive code is not needed.
+ * @name Unneeded defensive code
+ * @description Defensive code that guards against a situation that never happens is not needed.
* @kind problem
* @problem.severity recommendation
- * @id js/useless-defensive-code
+ * @id js/unneeded-defensive-code
* @tags correctness
* external/cwe/cwe-570
* external/cwe/cwe-571
diff --git a/javascript/ql/src/Expressions/examples/UselessDefensiveProgramming1_bad.js b/javascript/ql/src/Expressions/examples/UnneededDefensiveProgramming1_bad.js
similarity index 100%
rename from javascript/ql/src/Expressions/examples/UselessDefensiveProgramming1_bad.js
rename to javascript/ql/src/Expressions/examples/UnneededDefensiveProgramming1_bad.js
diff --git a/javascript/ql/src/Expressions/examples/UselessDefensiveProgramming1_good.js b/javascript/ql/src/Expressions/examples/UnneededDefensiveProgramming1_good.js
similarity index 100%
rename from javascript/ql/src/Expressions/examples/UselessDefensiveProgramming1_good.js
rename to javascript/ql/src/Expressions/examples/UnneededDefensiveProgramming1_good.js
diff --git a/javascript/ql/src/Expressions/examples/UselessDefensiveProgramming2_bad.js b/javascript/ql/src/Expressions/examples/UnneededDefensiveProgramming2_bad.js
similarity index 100%
rename from javascript/ql/src/Expressions/examples/UselessDefensiveProgramming2_bad.js
rename to javascript/ql/src/Expressions/examples/UnneededDefensiveProgramming2_bad.js
diff --git a/javascript/ql/src/Expressions/examples/UselessDefensiveProgramming2_good.js b/javascript/ql/src/Expressions/examples/UnneededDefensiveProgramming2_good.js
similarity index 100%
rename from javascript/ql/src/Expressions/examples/UselessDefensiveProgramming2_good.js
rename to javascript/ql/src/Expressions/examples/UnneededDefensiveProgramming2_good.js
diff --git a/javascript/ql/test/query-tests/Expressions/UselessDefensiveProgramming/HeterogeneousComparison.expected b/javascript/ql/test/query-tests/Expressions/UnneededDefensiveProgramming/HeterogeneousComparison.expected
similarity index 100%
rename from javascript/ql/test/query-tests/Expressions/UselessDefensiveProgramming/HeterogeneousComparison.expected
rename to javascript/ql/test/query-tests/Expressions/UnneededDefensiveProgramming/HeterogeneousComparison.expected
diff --git a/javascript/ql/test/query-tests/Expressions/UselessDefensiveProgramming/HeterogeneousComparison.qlref b/javascript/ql/test/query-tests/Expressions/UnneededDefensiveProgramming/HeterogeneousComparison.qlref
similarity index 100%
rename from javascript/ql/test/query-tests/Expressions/UselessDefensiveProgramming/HeterogeneousComparison.qlref
rename to javascript/ql/test/query-tests/Expressions/UnneededDefensiveProgramming/HeterogeneousComparison.qlref
diff --git a/javascript/ql/test/query-tests/Expressions/UselessDefensiveProgramming/UselessDefensiveProgramming.expected b/javascript/ql/test/query-tests/Expressions/UnneededDefensiveProgramming/UnneededDefensiveProgramming.expected
similarity index 100%
rename from javascript/ql/test/query-tests/Expressions/UselessDefensiveProgramming/UselessDefensiveProgramming.expected
rename to javascript/ql/test/query-tests/Expressions/UnneededDefensiveProgramming/UnneededDefensiveProgramming.expected
diff --git a/javascript/ql/test/query-tests/Expressions/UnneededDefensiveProgramming/UnneededDefensiveProgramming.qlref b/javascript/ql/test/query-tests/Expressions/UnneededDefensiveProgramming/UnneededDefensiveProgramming.qlref
new file mode 100644
index 00000000000..13c05f1e74b
--- /dev/null
+++ b/javascript/ql/test/query-tests/Expressions/UnneededDefensiveProgramming/UnneededDefensiveProgramming.qlref
@@ -0,0 +1 @@
+Expressions/UnneededDefensiveProgramming.ql
diff --git a/javascript/ql/test/query-tests/Expressions/UselessDefensiveProgramming/UselessConditional.expected b/javascript/ql/test/query-tests/Expressions/UnneededDefensiveProgramming/UselessConditional.expected
similarity index 100%
rename from javascript/ql/test/query-tests/Expressions/UselessDefensiveProgramming/UselessConditional.expected
rename to javascript/ql/test/query-tests/Expressions/UnneededDefensiveProgramming/UselessConditional.expected
diff --git a/javascript/ql/test/query-tests/Expressions/UselessDefensiveProgramming/UselessConditional.qlref b/javascript/ql/test/query-tests/Expressions/UnneededDefensiveProgramming/UselessConditional.qlref
similarity index 100%
rename from javascript/ql/test/query-tests/Expressions/UselessDefensiveProgramming/UselessConditional.qlref
rename to javascript/ql/test/query-tests/Expressions/UnneededDefensiveProgramming/UselessConditional.qlref
diff --git a/javascript/ql/test/query-tests/Expressions/UselessDefensiveProgramming/global-module-definition.js b/javascript/ql/test/query-tests/Expressions/UnneededDefensiveProgramming/global-module-definition.js
similarity index 100%
rename from javascript/ql/test/query-tests/Expressions/UselessDefensiveProgramming/global-module-definition.js
rename to javascript/ql/test/query-tests/Expressions/UnneededDefensiveProgramming/global-module-definition.js
diff --git a/javascript/ql/test/query-tests/Expressions/UselessDefensiveProgramming/module-environment-detection.js b/javascript/ql/test/query-tests/Expressions/UnneededDefensiveProgramming/module-environment-detection.js
similarity index 100%
rename from javascript/ql/test/query-tests/Expressions/UselessDefensiveProgramming/module-environment-detection.js
rename to javascript/ql/test/query-tests/Expressions/UnneededDefensiveProgramming/module-environment-detection.js
diff --git a/javascript/ql/test/query-tests/Expressions/UselessDefensiveProgramming/tst.js b/javascript/ql/test/query-tests/Expressions/UnneededDefensiveProgramming/tst.js
similarity index 100%
rename from javascript/ql/test/query-tests/Expressions/UselessDefensiveProgramming/tst.js
rename to javascript/ql/test/query-tests/Expressions/UnneededDefensiveProgramming/tst.js
diff --git a/javascript/ql/test/query-tests/Expressions/UselessDefensiveProgramming/tst2.js b/javascript/ql/test/query-tests/Expressions/UnneededDefensiveProgramming/tst2.js
similarity index 100%
rename from javascript/ql/test/query-tests/Expressions/UselessDefensiveProgramming/tst2.js
rename to javascript/ql/test/query-tests/Expressions/UnneededDefensiveProgramming/tst2.js
diff --git a/javascript/ql/test/query-tests/Expressions/UselessDefensiveProgramming/UselessDefensiveProgramming.qlref b/javascript/ql/test/query-tests/Expressions/UselessDefensiveProgramming/UselessDefensiveProgramming.qlref
deleted file mode 100644
index 9a5222a05d0..00000000000
--- a/javascript/ql/test/query-tests/Expressions/UselessDefensiveProgramming/UselessDefensiveProgramming.qlref
+++ /dev/null
@@ -1 +0,0 @@
-Expressions/UselessDefensiveProgramming.ql
From 79a6cfdf38dbf939062095d9b5524b295e34c4c8 Mon Sep 17 00:00:00 2001
From: Max Schaefer
Date: Fri, 9 Nov 2018 12:13:33 +0000
Subject: [PATCH 70/71] JavaScript: Add generic externs for BDD/TDD-style
testing frameworks.
---
javascript/externs/lib/bdd.js | 96 +++++++++++++++++++++++++++++++++++
1 file changed, 96 insertions(+)
create mode 100644 javascript/externs/lib/bdd.js
diff --git a/javascript/externs/lib/bdd.js b/javascript/externs/lib/bdd.js
new file mode 100644
index 00000000000..dca2d9008c6
--- /dev/null
+++ b/javascript/externs/lib/bdd.js
@@ -0,0 +1,96 @@
+/*
+ * Copyright 2018 Semmle
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * @fileoverview Simple externs definitions for various BDD and TDD APIs.
+ *
+ * The goal is to declare global functions provided by frameworks like Chai,
+ * Mocha and Jasmine. No type information is included at the moment.
+ *
+ * @externs
+ */
+
+/** @param {...*} args */
+function after(args) {}
+
+/** @param {...*} args */
+function afterAll(args) {}
+
+/** @param {...*} args */
+function afterEach(args) {}
+
+/** @param {...*} args */
+function assert(args) {}
+
+/** @param {...*} args */
+function before(args) {}
+
+/** @param {...*} args */
+function beforeAll(args) {}
+
+/** @param {...*} args */
+function beforeEach(args) {}
+
+/** @param {...*} args */
+function context(args) {}
+
+/** @param {...*} args */
+function describe(args) {}
+
+/** @param {...*} args */
+function expect(args) {}
+
+/** @param {...*} args */
+function fdescribe(args) {}
+
+/** @param {...*} args */
+function fit(args) {}
+
+/** @param {...*} args */
+function it(args) {}
+
+/** @param {...*} args */
+function pending(args) {}
+
+/** @param {...*} args */
+function setup(args) {}
+
+/** @param {...*} args */
+function specify(args) {}
+
+/** @param {...*} args */
+function spyOn(args) {}
+
+/** @param {...*} args */
+function suite(args) {}
+
+/** @param {...*} args */
+function suiteSetup(args) {}
+
+/** @param {...*} args */
+function suiteTeardown(args) {}
+
+/** @param {...*} args */
+function teardown(args) {}
+
+/** @param {...*} args */
+function test(args) {}
+
+/** @param {...*} args */
+function xdescribe(args) {}
+
+/** @param {...*} args */
+function xit(args) {}
From fe151597569a6c698993f798ff0d17221e649fb8 Mon Sep 17 00:00:00 2001
From: Felicity Chapman
Date: Tue, 13 Nov 2018 16:34:06 +0000
Subject: [PATCH 71/71] Update for feedback
---
.../Dead Code/LocalInitialisedButNotUsed.ql | 2 +-
.../ql/src/Violations of Best Practice/Dead Code/UnusedLocal.ql | 2 +-
.../src/Violations of Best Practice/legacy/InexactVarArg.java | 2 +-
.../src/Violations of Best Practice/legacy/InexactVarArg.qhelp | 2 +-
4 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/java/ql/src/Violations of Best Practice/Dead Code/LocalInitialisedButNotUsed.ql b/java/ql/src/Violations of Best Practice/Dead Code/LocalInitialisedButNotUsed.ql
index b1ff841c7cd..00e2b782453 100644
--- a/java/ql/src/Violations of Best Practice/Dead Code/LocalInitialisedButNotUsed.ql
+++ b/java/ql/src/Violations of Best Practice/Dead Code/LocalInitialisedButNotUsed.ql
@@ -1,6 +1,6 @@
/**
* @name Local variable is initialized but not used
- * @description Assigning a value to a local variable that is not used may indicate an error in the code.
+ * @description A local variable that is initialized but not subsequently used may indicate an error in the code.
* @kind problem
* @problem.severity recommendation
* @precision low
diff --git a/java/ql/src/Violations of Best Practice/Dead Code/UnusedLocal.ql b/java/ql/src/Violations of Best Practice/Dead Code/UnusedLocal.ql
index cb1a18dca7a..62bea618610 100644
--- a/java/ql/src/Violations of Best Practice/Dead Code/UnusedLocal.ql
+++ b/java/ql/src/Violations of Best Practice/Dead Code/UnusedLocal.ql
@@ -1,6 +1,6 @@
/**
* @name Unused local variable
- * @description Assigning a value to a local variable that is not used may indicate incomplete code.
+ * @description A local variable that is not initialized, assigned, or read may indicate incomplete code.
* @kind problem
* @problem.severity recommendation
* @precision low
diff --git a/java/ql/src/Violations of Best Practice/legacy/InexactVarArg.java b/java/ql/src/Violations of Best Practice/legacy/InexactVarArg.java
index 9e534107744..e34004cf3b4 100644
--- a/java/ql/src/Violations of Best Practice/legacy/InexactVarArg.java
+++ b/java/ql/src/Violations of Best Practice/legacy/InexactVarArg.java
@@ -7,7 +7,7 @@ class InexactVarArg
public static void main(String[] args) {
String[] words = { "apple", "banana", "cherry" };
String[][] lists = { words, words };
- length(words); // wrong: Argument does not clarify
+ length(words); // avoid: Argument does not clarify
length(lists); // which parameter type is used.
}
}
diff --git a/java/ql/src/Violations of Best Practice/legacy/InexactVarArg.qhelp b/java/ql/src/Violations of Best Practice/legacy/InexactVarArg.qhelp
index c9586c8ca7d..7b2458cccf6 100644
--- a/java/ql/src/Violations of Best Practice/legacy/InexactVarArg.qhelp
+++ b/java/ql/src/Violations of Best Practice/legacy/InexactVarArg.qhelp
@@ -49,7 +49,7 @@ versions of Eclipse, the output may be:
-To remove this dependency on the compiler, length(words) should be replaced by either of the following:
+To avoid this compiler-dependent behavior, length(words) should be replaced by either of the following: