diff --git a/cpp/ql/lib/change-notes/2025-01-07-config.md b/cpp/ql/lib/change-notes/2025-01-07-config.md new file mode 100644 index 000000000000..73b4962cf345 --- /dev/null +++ b/cpp/ql/lib/change-notes/2025-01-07-config.md @@ -0,0 +1,4 @@ +--- +category: feature +--- +* A new abstract class `ConfigurationTestFile` (`semmle.code.cpp.ConfigurationTestFile.ConfigurationTestFile`) was introduced, which represents files created to test the build configuration. A subclass `CmakeTryCompileFile` of `ConfigurationTestFile` was also introduced, which represents files created by CMake to test the build configuration. diff --git a/cpp/ql/lib/semmle/code/cpp/ConfigurationTestFile.qll b/cpp/ql/lib/semmle/code/cpp/ConfigurationTestFile.qll new file mode 100644 index 000000000000..fe89a556f74f --- /dev/null +++ b/cpp/ql/lib/semmle/code/cpp/ConfigurationTestFile.qll @@ -0,0 +1,28 @@ +/** + * Provides classes for identifying files that created to test the + * build configuration. It is often desirable to exclude these files + * from analysis. + */ + +import File + +/** + * A file created to test the system configuration. + */ +abstract class ConfigurationTestFile extends File { } + +/** + * A file created by CMake to test the system configuration. + */ +class CmakeTryCompileFile extends ConfigurationTestFile { + CmakeTryCompileFile() { + exists(Folder folder, Folder parent | + folder = this.getParentContainer() and + parent = folder.getParentContainer() + | + folder.getBaseName().matches("TryCompile-%") and + parent.getBaseName() = "CMakeScratch" and + parent.getParentContainer().getBaseName() = "CMakeFiles" + ) + } +} diff --git a/cpp/ql/src/Best Practices/SloppyGlobal.ql b/cpp/ql/src/Best Practices/SloppyGlobal.ql index 050590c1816f..4c1935627d52 100644 --- a/cpp/ql/src/Best Practices/SloppyGlobal.ql +++ b/cpp/ql/src/Best Practices/SloppyGlobal.ql @@ -9,11 +9,13 @@ */ import cpp +import semmle.code.cpp.ConfigurationTestFile from GlobalVariable gv where gv.getName().length() <= 3 and - not gv.isStatic() + not gv.isStatic() and + not gv.getFile() instanceof ConfigurationTestFile // variables in files generated during configuration are likely false positives select gv, "Poor global variable name '" + gv.getName() + "'. Prefer longer, descriptive names for globals (eg. kMyGlobalConstant, not foo)." diff --git a/cpp/ql/src/Critical/OverflowStatic.ql b/cpp/ql/src/Critical/OverflowStatic.ql index 519c3f9b4015..f0bc8383271d 100644 --- a/cpp/ql/src/Critical/OverflowStatic.ql +++ b/cpp/ql/src/Critical/OverflowStatic.ql @@ -17,6 +17,7 @@ import cpp import semmle.code.cpp.commons.Buffer import semmle.code.cpp.ir.dataflow.DataFlow import semmle.code.cpp.rangeanalysis.SimpleRangeAnalysis +import semmle.code.cpp.ConfigurationTestFile import LoopBounds private predicate staticBufferBase(VariableAccess access, Variable v) { @@ -148,7 +149,10 @@ predicate outOfBounds(BufferAccess bufaccess, string msg) { from Element error, string msg where - overflowOffsetInLoop(error, msg) or - wrongBufferSize(error, msg) or - outOfBounds(error, msg) + ( + overflowOffsetInLoop(error, msg) or + wrongBufferSize(error, msg) or + outOfBounds(error, msg) + ) and + not error.getFile() instanceof ConfigurationTestFile // elements in files generated during configuration are likely false positives select error, msg diff --git a/cpp/ql/src/Likely Bugs/Arithmetic/FloatComparison.ql b/cpp/ql/src/Likely Bugs/Arithmetic/FloatComparison.ql index 5a2180bfaf39..1f2a7ca506fd 100644 --- a/cpp/ql/src/Likely Bugs/Arithmetic/FloatComparison.ql +++ b/cpp/ql/src/Likely Bugs/Arithmetic/FloatComparison.ql @@ -12,6 +12,7 @@ */ import cpp +import semmle.code.cpp.ConfigurationTestFile from EqualityOperation ro, Expr left, Expr right where @@ -20,5 +21,6 @@ where ro.getAnOperand().getExplicitlyConverted().getType().getUnderlyingType() instanceof FloatingPointType and not ro.getAnOperand().isConstant() and // comparisons to constants generate too many false positives - not left.(VariableAccess).getTarget() = right.(VariableAccess).getTarget() // skip self comparison + not left.(VariableAccess).getTarget() = right.(VariableAccess).getTarget() and // skip self comparison + not ro.getFile() instanceof ConfigurationTestFile // expressions in files generated during configuration are likely false positives select ro, "Equality checks on floating point values can yield unexpected results." diff --git a/cpp/ql/src/Likely Bugs/Likely Typos/ExprHasNoEffect.ql b/cpp/ql/src/Likely Bugs/Likely Typos/ExprHasNoEffect.ql index 6f240fa2d2a0..7d64d50f46c1 100644 --- a/cpp/ql/src/Likely Bugs/Likely Typos/ExprHasNoEffect.ql +++ b/cpp/ql/src/Likely Bugs/Likely Typos/ExprHasNoEffect.ql @@ -12,7 +12,8 @@ */ import cpp -private import semmle.code.cpp.commons.Exclusions +import semmle.code.cpp.commons.Exclusions +import semmle.code.cpp.ConfigurationTestFile class PureExprInVoidContext extends ExprInVoidContext { PureExprInVoidContext() { this.isPure() } @@ -90,6 +91,7 @@ where not peivc.getType() instanceof UnknownType and not functionContainsDisabledCodeRecursive(peivc.(FunctionCall).getTarget()) and not functionDefinedInIfDefRecursive(peivc.(FunctionCall).getTarget()) and + not peivc.getFile() instanceof ConfigurationTestFile and // expressions in files generated during configuration are likely false positives if peivc instanceof FunctionCall then exists(Function target | diff --git a/cpp/ql/src/Likely Bugs/Underspecified Functions/TooFewArguments.ql b/cpp/ql/src/Likely Bugs/Underspecified Functions/TooFewArguments.ql index bc53015c9056..c09eb7ffffb7 100644 --- a/cpp/ql/src/Likely Bugs/Underspecified Functions/TooFewArguments.ql +++ b/cpp/ql/src/Likely Bugs/Underspecified Functions/TooFewArguments.ql @@ -19,7 +19,10 @@ import cpp import TooFewArguments +import semmle.code.cpp.ConfigurationTestFile from FunctionCall fc, Function f -where tooFewArguments(fc, f) +where + tooFewArguments(fc, f) and + not fc.getFile() instanceof ConfigurationTestFile // calls in files generated during configuration are likely false positives select fc, "This call has fewer arguments than required by $@.", f, f.toString() diff --git a/cpp/ql/src/Security/CWE/CWE-120/BadlyBoundedWrite.ql b/cpp/ql/src/Security/CWE/CWE-120/BadlyBoundedWrite.ql index 69e6e675aa0d..1edf70080252 100644 --- a/cpp/ql/src/Security/CWE/CWE-120/BadlyBoundedWrite.ql +++ b/cpp/ql/src/Security/CWE/CWE-120/BadlyBoundedWrite.ql @@ -16,6 +16,7 @@ */ import semmle.code.cpp.security.BufferWrite +import semmle.code.cpp.ConfigurationTestFile /* * See CWE-120/UnboundedWrite.ql for a summary of CWE-120 alert cases. @@ -26,7 +27,8 @@ where bw.hasExplicitLimit() and // has an explicit size limit destSize = max(getBufferSize(bw.getDest(), _)) and bw.getExplicitLimit() > destSize and // but it's larger than the destination - not bw.getDest().getType().stripType() instanceof ErroneousType // destSize may be incorrect + not bw.getDest().getType().stripType() instanceof ErroneousType and // destSize may be incorrect + not bw.getFile() instanceof ConfigurationTestFile // expressions in files generated during configuration are likely false positives select bw, "This '" + bw.getBWDesc() + "' operation is limited to " + bw.getExplicitLimit() + " bytes but the destination is only " + destSize + " bytes." diff --git a/cpp/ql/src/Security/CWE/CWE-732/DoNotCreateWorldWritable.ql b/cpp/ql/src/Security/CWE/CWE-732/DoNotCreateWorldWritable.ql index 03666b429347..35fc2a7e9b86 100644 --- a/cpp/ql/src/Security/CWE/CWE-732/DoNotCreateWorldWritable.ql +++ b/cpp/ql/src/Security/CWE/CWE-732/DoNotCreateWorldWritable.ql @@ -12,6 +12,7 @@ import cpp import FilePermissions +import semmle.code.cpp.ConfigurationTestFile predicate worldWritableCreation(FileCreationExpr fc, int mode) { mode = localUmask(fc).mask(fc.getMode()) and @@ -27,6 +28,7 @@ predicate setWorldWritable(FunctionCall fc, int mode) { from Expr fc, int mode, string message where worldWritableCreation(fc, mode) and + not fc.getFile() instanceof ConfigurationTestFile and // expressions in files generated during configuration are likely false positives message = "A file may be created here with mode " + octalFileMode(mode) + ", which would make it world-writable." diff --git a/cpp/ql/src/change-notes/2025-01-07-cmake.md b/cpp/ql/src/change-notes/2025-01-07-cmake.md new file mode 100644 index 000000000000..e2909a8bcead --- /dev/null +++ b/cpp/ql/src/change-notes/2025-01-07-cmake.md @@ -0,0 +1,4 @@ +--- +category: minorAnalysis +--- +* The `cpp/badly-bounded-write`, `cpp/equality-on-floats`, `cpp/short-global-name`, `cpp/static-buffer-overflow`, `cpp/too-few-arguments`, `cpp/useless-expression`, `cpp/world-writable-file-creation` queries no longer produce alerts on files created by CMake to test the build configuration. diff --git a/cpp/ql/test/query-tests/Likely Bugs/Likely Typos/ExprHasNoEffect/CMakeFiles/CMakeScratch/TryCompile-abcdef/CheckFunctionExists.c b/cpp/ql/test/query-tests/Likely Bugs/Likely Typos/ExprHasNoEffect/CMakeFiles/CMakeScratch/TryCompile-abcdef/CheckFunctionExists.c new file mode 100644 index 000000000000..ab5a8cc27f0a --- /dev/null +++ b/cpp/ql/test/query-tests/Likely Bugs/Likely Typos/ExprHasNoEffect/CMakeFiles/CMakeScratch/TryCompile-abcdef/CheckFunctionExists.c @@ -0,0 +1,8 @@ +typedef long long size_t; + +size_t strlen(const char *s); + +int main() { + strlen(""); // GOOD: the source file occurs in a `CMakeFiles/CMakeScratch/TryCompile-...` directory + return 0; +} diff --git a/cpp/ql/test/query-tests/Likely Bugs/Likely Typos/ExprHasNoEffect/CMakeFiles/CMakeScratch/TryCompile-abcdef/ExprHasNoEffect.expected b/cpp/ql/test/query-tests/Likely Bugs/Likely Typos/ExprHasNoEffect/CMakeFiles/CMakeScratch/TryCompile-abcdef/ExprHasNoEffect.expected new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/cpp/ql/test/query-tests/Likely Bugs/Likely Typos/ExprHasNoEffect/CMakeFiles/CMakeScratch/TryCompile-abcdef/ExprHasNoEffect.qlref b/cpp/ql/test/query-tests/Likely Bugs/Likely Typos/ExprHasNoEffect/CMakeFiles/CMakeScratch/TryCompile-abcdef/ExprHasNoEffect.qlref new file mode 100644 index 000000000000..82a90f5413a9 --- /dev/null +++ b/cpp/ql/test/query-tests/Likely Bugs/Likely Typos/ExprHasNoEffect/CMakeFiles/CMakeScratch/TryCompile-abcdef/ExprHasNoEffect.qlref @@ -0,0 +1 @@ +Likely Bugs/Likely Typos/ExprHasNoEffect.ql