diff --git a/java/ql/src/Likely Bugs/Arithmetic/InformationLoss.ql b/java/ql/src/Likely Bugs/Arithmetic/InformationLoss.ql index d2ff4c24060..7d97af12b71 100644 --- a/java/ql/src/Likely Bugs/Arithmetic/InformationLoss.ql +++ b/java/ql/src/Likely Bugs/Arithmetic/InformationLoss.ql @@ -27,10 +27,23 @@ class DangerousAssignOpExpr extends AssignOp { predicate problematicCasting(Type t, Expr e) { e.getType().(NumType).widerThan(t) } -from DangerousAssignOpExpr a, Expr e +Variable getVariable(Expr dest) { + result = dest.(VarAccess).getVariable() + or + result = dest.(ArrayAccess).getArray().(VarAccess).getVariable() +} + +from DangerousAssignOpExpr a, Expr e, Top v where e = a.getSource() and - problematicCasting(a.getDest().getType(), e) + problematicCasting(a.getDest().getType(), e) and + ( + v = getVariable(a.getDest()) + or + // fallback, in case we can't easily determine the variable + not exists(getVariable(a.getDest())) and + v = a.getDest() + ) select a, - "Implicit cast of source type " + e.getType().getName() + " to narrower destination type " + - a.getDest().getType().getName() + "." + "Implicit cast of source type " + e.getType().getName() + " to narrower destination type $@.", v, + a.getDest().getType().getName() diff --git a/java/ql/test/query-tests/security/CWE-190/semmle/tests/InformationLoss.expected b/java/ql/test/query-tests/security/CWE-190/semmle/tests/InformationLoss.expected index 1c4ed46e136..e317375c199 100644 --- a/java/ql/test/query-tests/security/CWE-190/semmle/tests/InformationLoss.expected +++ b/java/ql/test/query-tests/security/CWE-190/semmle/tests/InformationLoss.expected @@ -1,2 +1,4 @@ -| Test.java:68:5:68:25 | ...+=... | Implicit cast of source type long to narrower destination type int. | -| Test.java:87:4:87:9 | ...+=... | Implicit cast of source type long to narrower destination type int. | +| Test.java:68:5:68:25 | ...+=... | Implicit cast of source type long to narrower destination type $@. | Test.java:64:4:64:13 | int i | int | +| Test.java:87:4:87:9 | ...+=... | Implicit cast of source type long to narrower destination type $@. | Test.java:81:4:81:13 | int i | int | +| Test.java:289:5:289:30 | ...+=... | Implicit cast of source type long to narrower destination type $@. | Test.java:285:4:285:27 | int[] arr | int | +| Test.java:293:7:293:44 | ...+=... | Implicit cast of source type long to narrower destination type $@. | Test.java:293:7:293:24 | ...[...] | int | diff --git a/java/ql/test/query-tests/security/CWE-190/semmle/tests/Test.java b/java/ql/test/query-tests/security/CWE-190/semmle/tests/Test.java index 2935368dccb..f24d16a236c 100644 --- a/java/ql/test/query-tests/security/CWE-190/semmle/tests/Test.java +++ b/java/ql/test/query-tests/security/CWE-190/semmle/tests/Test.java @@ -279,12 +279,29 @@ class Test { // subsequently cast to narrower type int int widenedThenNarrowed = (int) (data2 + 10L); } + + // InformationLoss + { + int[] arr = new int[10]; + while (arr[2] < 1000000) { + // BAD: getLargeNumber is implicitly narrowed to an integer + // which will result in overflows if it is large + arr[2] += getLargeNumber(); + } + + // BAD. + getAnIntArray()[0] += getLargeNumber(); + } } public static long getLargeNumber() { return Long.MAX_VALUE / 2; } + public static int[] getAnIntArray() { + return new int[10]; + } + public static boolean properlyBounded(int i) { return i < Integer.MAX_VALUE; }