diff --git a/cpp/ql/src/Architecture/InappropriateIntimacy.cpp b/cpp/ql/src/Architecture/InappropriateIntimacy.cpp deleted file mode 100644 index e69de29bb2d1..000000000000 diff --git a/cpp/ql/src/Documentation/UncommentedFunction.cpp b/cpp/ql/src/Documentation/UncommentedFunction.cpp deleted file mode 100644 index 8b137891791f..000000000000 --- a/cpp/ql/src/Documentation/UncommentedFunction.cpp +++ /dev/null @@ -1 +0,0 @@ - diff --git a/cpp/ql/src/Likely Bugs/Arithmetic/BadCheckOdd.cpp b/cpp/ql/src/Likely Bugs/Arithmetic/BadCheckOdd.cpp deleted file mode 100644 index 8b137891791f..000000000000 --- a/cpp/ql/src/Likely Bugs/Arithmetic/BadCheckOdd.cpp +++ /dev/null @@ -1 +0,0 @@ - diff --git a/cpp/ql/src/Likely Bugs/Arithmetic/BitwiseSignCheck.cpp b/cpp/ql/src/Likely Bugs/Arithmetic/BitwiseSignCheck.cpp deleted file mode 100644 index 8b137891791f..000000000000 --- a/cpp/ql/src/Likely Bugs/Arithmetic/BitwiseSignCheck.cpp +++ /dev/null @@ -1 +0,0 @@ - diff --git a/cpp/ql/src/Likely Bugs/Memory Management/UnsafeUseOfStrcat.ql b/cpp/ql/src/Likely Bugs/Memory Management/UnsafeUseOfStrcat.ql index b3ab5828094d..51302b710f2c 100644 --- a/cpp/ql/src/Likely Bugs/Memory Management/UnsafeUseOfStrcat.ql +++ b/cpp/ql/src/Likely Bugs/Memory Management/UnsafeUseOfStrcat.ql @@ -29,11 +29,20 @@ predicate isEffectivelyConstAccess(VariableAccess a) ) } -from FunctionCall fc, VariableAccess src -where fc.getTarget().hasName("strcat") and - src = fc.getArgument(1) and - not src.getType() instanceof ArrayType and +class StrcatSource extends VariableAccess { + FunctionCall strcat; + + StrcatSource() { + strcat.getTarget().hasName("strcat") and + this = strcat.getArgument(1) + } + + FunctionCall getStrcatCall() { result = strcat } +} + +from StrcatSource src +where not src.getType() instanceof ArrayType and not exists(BufferSizeExpr bse | bse.getArg().(VariableAccess).getTarget() = src.getTarget()) and not isEffectivelyConstAccess(src) -select fc, "Always check the size of the source buffer when using strcat." +select src.getStrcatCall(), "Always check the size of the source buffer when using strcat." diff --git a/cpp/ql/src/semmle/code/cpp/Declaration.qll b/cpp/ql/src/semmle/code/cpp/Declaration.qll index 0576c6e2c53e..2b42485eda64 100644 --- a/cpp/ql/src/semmle/code/cpp/Declaration.qll +++ b/cpp/ql/src/semmle/code/cpp/Declaration.qll @@ -56,6 +56,7 @@ abstract class Declaration extends Locatable, @declaration { // MemberFunction, MemberVariable, MemberType exists (Declaration m | m = this and + not m instanceof EnumConstant and result = m.getDeclaringType().getQualifiedName() + "::" + m.getName()) or exists (EnumConstant c diff --git a/cpp/ql/src/semmle/code/cpp/Type.qll b/cpp/ql/src/semmle/code/cpp/Type.qll index e3df04abb5aa..060d7a27e976 100644 --- a/cpp/ql/src/semmle/code/cpp/Type.qll +++ b/cpp/ql/src/semmle/code/cpp/Type.qll @@ -904,15 +904,25 @@ class ArrayType extends DerivedType { ArrayType() { derivedtypes(underlyingElement(this),_,4,_) } predicate hasArraySize() { arraysizes(underlyingElement(this),_,_,_) } + + /** + * Gets the number of elements in this array. Only has a result for arrays declared to be of a + * constant size. See `getByteSize` for getting the number of bytes. + */ int getArraySize() { arraysizes(underlyingElement(this),result,_,_) } + /** + * Gets the byte size of this array. Only has a result for arrays declared to be of a constant + * size. See `getArraySize` for getting the number of elements. + */ int getByteSize() { arraysizes(underlyingElement(this),_,result,_) } override int getAlignment() { arraysizes(underlyingElement(this), _, _, result) } /** - * Gets the size of this array (only valid for arrays declared to be of a constant - * size, will fail for all others). + * Gets the byte size of this array. Only has a result for arrays declared to be of a constant + * size. This predicate is a synonym for `getByteSize`. See `getArraySize` for getting the number + * of elements. */ override int getSize() { result = this.getByteSize() 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 aee11acca1a9..68a3e83d2db0 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 @@ -63,7 +63,7 @@ module InstructionSanity { * Holds if instruction `instr` has multiple operands with tag `tag`. */ query predicate duplicateOperand(Instruction instr, OperandTag tag) { - count(instr.getOperand(tag)) > 1 and + strictcount(instr.getOperand(tag)) > 1 and not tag instanceof UnmodeledUseOperand } 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 aee11acca1a9..68a3e83d2db0 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 @@ -63,7 +63,7 @@ module InstructionSanity { * Holds if instruction `instr` has multiple operands with tag `tag`. */ query predicate duplicateOperand(Instruction instr, OperandTag tag) { - count(instr.getOperand(tag)) > 1 and + strictcount(instr.getOperand(tag)) > 1 and not tag instanceof UnmodeledUseOperand } 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 aee11acca1a9..68a3e83d2db0 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 @@ -63,7 +63,7 @@ module InstructionSanity { * Holds if instruction `instr` has multiple operands with tag `tag`. */ query predicate duplicateOperand(Instruction instr, OperandTag tag) { - count(instr.getOperand(tag)) > 1 and + strictcount(instr.getOperand(tag)) > 1 and not tag instanceof UnmodeledUseOperand } diff --git a/cpp/ql/test/library-tests/qualifiers/class-enum/decls.expected b/cpp/ql/test/library-tests/qualifiers/class-enum/decls.expected new file mode 100644 index 000000000000..ddf489bd4df9 --- /dev/null +++ b/cpp/ql/test/library-tests/qualifiers/class-enum/decls.expected @@ -0,0 +1,21 @@ +| file://:0:0:0:0 | __va_list_tag | __va_list_tag | +| file://:0:0:0:0 | fp_offset | __va_list_tag::fp_offset | +| file://:0:0:0:0 | gp_offset | __va_list_tag::gp_offset | +| file://:0:0:0:0 | operator= | __va_list_tag::operator= | +| file://:0:0:0:0 | operator= | __va_list_tag::operator= | +| file://:0:0:0:0 | overflow_arg_area | __va_list_tag::overflow_arg_area | +| file://:0:0:0:0 | reg_save_area | __va_list_tag::reg_save_area | +| test.cpp:2:7:2:7 | operator= | MyEnumClass::operator= | +| test.cpp:2:7:2:7 | operator= | MyEnumClass::operator= | +| test.cpp:2:7:2:17 | MyEnumClass | MyEnumClass | +| test.cpp:4:10:4:15 | MyEnum | MyEnumClass::MyEnum | +| test.cpp:5:9:5:9 | A | MyEnumClass::MyEnum::A | +| test.cpp:6:9:6:9 | B | MyEnumClass::MyEnum::B | +| test.cpp:10:34:10:34 | v | v | +| test.cpp:12:7:12:7 | MyClass2 | MyClass2::MyClass2 | +| test.cpp:12:7:12:7 | MyClass2 | MyClass2::MyClass2 | +| test.cpp:12:7:12:7 | operator= | MyClass2::operator= | +| test.cpp:12:7:12:7 | operator= | MyClass2::operator= | +| test.cpp:12:7:12:14 | MyClass2 | MyClass2 | +| test.cpp:14:12:14:19 | MyClass2 | MyClass2::MyClass2 | +| test.cpp:17:6:17:6 | f | f | diff --git a/cpp/ql/test/library-tests/qualifiers/class-enum/decls.ql b/cpp/ql/test/library-tests/qualifiers/class-enum/decls.ql new file mode 100644 index 000000000000..48db95ba5a21 --- /dev/null +++ b/cpp/ql/test/library-tests/qualifiers/class-enum/decls.ql @@ -0,0 +1,5 @@ +import cpp + +from Declaration d +select d, d.getQualifiedName() + diff --git a/csharp/ql/test/library-tests/regressions/Program.cs b/csharp/ql/test/library-tests/regressions/Program.cs index eb7b2541e561..5723fb7593d7 100644 --- a/csharp/ql/test/library-tests/regressions/Program.cs +++ b/csharp/ql/test/library-tests/regressions/Program.cs @@ -106,3 +106,16 @@ void F() new Point() { Name = "Bob" }; } } + +class LiteralConversions +{ + struct Point + { + public int? x, y; + } + + void F() + { + new Point { x=1, y=2 }; + } +} diff --git a/csharp/ql/test/library-tests/regressions/TypeMentions.expected b/csharp/ql/test/library-tests/regressions/TypeMentions.expected index 2133ff2707b9..353c9156fdb5 100644 --- a/csharp/ql/test/library-tests/regressions/TypeMentions.expected +++ b/csharp/ql/test/library-tests/regressions/TypeMentions.expected @@ -46,3 +46,9 @@ | Program.cs:101:16:101:21 | Object | | Program.cs:104:5:104:8 | Void | | Program.cs:106:13:106:17 | Point | +| Program.cs:114:16:114:18 | Int32 | +| Program.cs:114:16:114:18 | Int32 | +| Program.cs:114:16:114:19 | Nullable | +| Program.cs:114:16:114:19 | Nullable | +| Program.cs:117:5:117:8 | Void | +| Program.cs:119:13:119:17 | Point | diff --git a/java/ql/src/Likely Bugs/Arithmetic/IntMultToLong.ql b/java/ql/src/Likely Bugs/Arithmetic/IntMultToLong.ql index acb99effb005..d77a98bcd069 100644 --- a/java/ql/src/Likely Bugs/Arithmetic/IntMultToLong.ql +++ b/java/ql/src/Likely Bugs/Arithmetic/IntMultToLong.ql @@ -15,6 +15,7 @@ * external/cwe/cwe-197 * external/cwe/cwe-681 */ + import java import semmle.code.java.dataflow.RangeUtils import semmle.code.java.Conversions @@ -25,7 +26,8 @@ predicate small(MulExpr e) { lhs = e.getLeftOperand().getProperExpr().(ConstantIntegerExpr).getIntValue() and rhs = e.getRightOperand().getProperExpr().(ConstantIntegerExpr).getIntValue() and lhs * rhs = res and - t.getOrdPrimitiveType().getMinValue() <= res and res <= t.getOrdPrimitiveType().getMaxValue() + t.getOrdPrimitiveType().getMinValue() <= res and + res <= t.getOrdPrimitiveType().getMaxValue() ) } @@ -52,4 +54,7 @@ where // not obviously small and ok not small(e) and e.getEnclosingCallable().fromSource() -select c, "$@ converted to "+ destType.getName() +" by use in " + ("a " + c.kind()).regexpReplaceAll("^a ([aeiou])", "an $1") + ".", e, sourceType.getName() + " multiplication" +select c, + "Potential overflow in $@ before it is converted to " + destType.getName() + " by use in " + + ("a " + c.kind()).regexpReplaceAll("^a ([aeiou])", "an $1") + ".", e, + sourceType.getName() + " multiplication" diff --git a/java/ql/test/query-tests/security/CWE-190/semmle/tests/IntMultToLong.expected b/java/ql/test/query-tests/security/CWE-190/semmle/tests/IntMultToLong.expected index e4a6143ee59c..421575b07a65 100644 --- a/java/ql/test/query-tests/security/CWE-190/semmle/tests/IntMultToLong.expected +++ b/java/ql/test/query-tests/security/CWE-190/semmle/tests/IntMultToLong.expected @@ -1,4 +1,4 @@ -| Test.java:20:23:20:48 | ... * ... | $@ converted to long by use in an assignment context. | Test.java:20:23:20:48 | ... * ... | int multiplication | -| Test.java:27:23:27:52 | ... + ... | $@ converted to long by use in an assignment context. | Test.java:27:23:27:48 | ... * ... | int multiplication | -| Test.java:34:23:34:63 | ...?...:... | $@ converted to long by use in an assignment context. | Test.java:34:30:34:55 | ... * ... | int multiplication | -| Test.java:41:25:41:49 | ... * ... | $@ converted to double by use in an assignment context. | Test.java:41:25:41:49 | ... * ... | long multiplication | \ No newline at end of file +| Test.java:20:23:20:48 | ... * ... | Potential overflow in $@ before it is converted to long by use in an assignment context. | Test.java:20:23:20:48 | ... * ... | int multiplication | +| Test.java:27:23:27:52 | ... + ... | Potential overflow in $@ before it is converted to long by use in an assignment context. | Test.java:27:23:27:48 | ... * ... | int multiplication | +| Test.java:34:23:34:63 | ...?...:... | Potential overflow in $@ before it is converted to long by use in an assignment context. | Test.java:34:30:34:55 | ... * ... | int multiplication | +| Test.java:41:25:41:49 | ... * ... | Potential overflow in $@ before it is converted to double by use in an assignment context. | Test.java:41:25:41:49 | ... * ... | long multiplication | diff --git a/javascript/ql/src/semmle/javascript/frameworks/Bundling.qll b/javascript/ql/src/semmle/javascript/frameworks/Bundling.qll index 280f4013f6b4..0adab311f6e3 100644 --- a/javascript/ql/src/semmle/javascript/frameworks/Bundling.qll +++ b/javascript/ql/src/semmle/javascript/frameworks/Bundling.qll @@ -213,6 +213,7 @@ Comment getExclamationPointCommentInRun(ExclamationPointComment head) { * Holds if this is a bundle containing multiple licenses. */ predicate isMultiLicenseBundle(TopLevel tl) { + // case: comments preserved by minifiers count(ExclamationPointComment head | head.getTopLevel() = tl and exists(ExclamationPointComment licenseIndicator | @@ -220,6 +221,12 @@ predicate isMultiLicenseBundle(TopLevel tl) { licenseIndicator.getLine(_).regexpMatch("(?i).*\\b(copyright|license|\\d+\\.\\d+)\\b.*") ) ) > 1 + or + // case: ordinary block comments with "@license" lines + count(BlockComment head | + head.getTopLevel() = tl and + head.getLine(_).regexpMatch("(?i) *\\* @license .*") + ) > 1 } /** diff --git a/javascript/ql/test/query-tests/Security/CWE-730/RegExpInjection.js b/javascript/ql/test/query-tests/Security/CWE-730/RegExpInjection.js index 18dd843897b6..5d1288f3a7e0 100644 --- a/javascript/ql/test/query-tests/Security/CWE-730/RegExpInjection.js +++ b/javascript/ql/test/query-tests/Security/CWE-730/RegExpInjection.js @@ -1,6 +1,6 @@ var express = require('express'); var app = express(); -var URI = reuires("urijs"); +var URI = require("urijs"); app.get('/findKey', function(req, res) { var key = req.param("key"), input = req.param("input"); diff --git a/javascript/ql/test/query-tests/filters/ClassifyFiles/ClassifyFiles.expected b/javascript/ql/test/query-tests/filters/ClassifyFiles/ClassifyFiles.expected index 2efab05a9b18..5709a9ad1ffa 100644 --- a/javascript/ql/test/query-tests/filters/ClassifyFiles/ClassifyFiles.expected +++ b/javascript/ql/test/query-tests/filters/ClassifyFiles/ClassifyFiles.expected @@ -11,6 +11,7 @@ | jsx.js:0:0:0:0 | jsx.js | generated | | multi-part-bundle.html:0:0:0:0 | multi-part-bundle.html | generated | | multi-part-bundle.js:0:0:0:0 | multi-part-bundle.js | generated | +| multiple-licenses-2.js:0:0:0:0 | multiple-licenses-2.js | generated | | multiple-licenses.js:0:0:0:0 | multiple-licenses.js | generated | | opal-test.js:0:0:0:0 | opal-test.js | generated | | peg-js.js:0:0:0:0 | peg-js.js | generated | diff --git a/javascript/ql/test/query-tests/filters/ClassifyFiles/multiple-licenses-2.js b/javascript/ql/test/query-tests/filters/ClassifyFiles/multiple-licenses-2.js new file mode 100644 index 000000000000..856c468f81a4 --- /dev/null +++ b/javascript/ql/test/query-tests/filters/ClassifyFiles/multiple-licenses-2.js @@ -0,0 +1,10 @@ +/* + * @copyright (c) ... + * @copyright (c) ... + * @license ... + */ + +/** + * @copyright ... + * @license ... + */