mirror of
https://github.com/github/codeql.git
synced 2026-05-05 13:45:19 +02:00
C++: Autoformat everything
Some files that will change in #1736 have been spared. ./build -j4 target/jars/qlformat find ql/cpp/ql -name "*.ql" -print0 | xargs -0 target/jars/qlformat --input find ql/cpp/ql -name "*.qll" -print0 | xargs -0 target/jars/qlformat --input (cd ql && git checkout 'cpp/ql/src/semmle/code/cpp/ir/implementation/**/*SSA*.qll') buildutils-internal/scripts/pr-checks/sync-identical-files.py --latest
This commit is contained in:
@@ -7,9 +7,13 @@
|
||||
* @tags maintainability
|
||||
* external/jsf
|
||||
*/
|
||||
|
||||
import cpp
|
||||
|
||||
from Function f, int n
|
||||
where n = f.getMetrics().getNumberOfLinesOfCode()
|
||||
and n > 200
|
||||
select f, "AV Rule 1: any one function (or method) will contain no more than 200 logical source lines of code. Function '" + f.toString() + "' contains " + n.toString() + " lines of code."
|
||||
where
|
||||
n = f.getMetrics().getNumberOfLinesOfCode() and
|
||||
n > 200
|
||||
select f,
|
||||
"AV Rule 1: any one function (or method) will contain no more than 200 logical source lines of code. Function '"
|
||||
+ f.toString() + "' contains " + n.toString() + " lines of code."
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
* testability
|
||||
* external/jsf
|
||||
*/
|
||||
|
||||
import cpp
|
||||
|
||||
// We look for code that converts between function pointers and non-function, non-void
|
||||
@@ -16,14 +17,16 @@ import cpp
|
||||
// self-modification, nor will it spot the use of OS mechanisms to write into process
|
||||
// memory (such as WriteProcessMemory under Windows).
|
||||
predicate maybeSMCConversion(Type t1, Type t2) {
|
||||
t1 instanceof FunctionPointerType and
|
||||
t2 instanceof PointerType and
|
||||
not t2 instanceof FunctionPointerType and
|
||||
not t2 instanceof VoidPointerType
|
||||
or maybeSMCConversion(t2, t1)
|
||||
t1 instanceof FunctionPointerType and
|
||||
t2 instanceof PointerType and
|
||||
not t2 instanceof FunctionPointerType and
|
||||
not t2 instanceof VoidPointerType
|
||||
or
|
||||
maybeSMCConversion(t2, t1)
|
||||
}
|
||||
|
||||
from Expr e
|
||||
where e.fromSource() and
|
||||
maybeSMCConversion(e.getUnderlyingType(), e.getActualType())
|
||||
select e, "AV Rule 2: There shall not be any self-modifying code."
|
||||
where
|
||||
e.fromSource() and
|
||||
maybeSMCConversion(e.getUnderlyingType(), e.getActualType())
|
||||
select e, "AV Rule 2: There shall not be any self-modifying code."
|
||||
|
||||
@@ -7,9 +7,11 @@
|
||||
* @tags maintainability
|
||||
* external/jsf
|
||||
*/
|
||||
|
||||
import cpp
|
||||
|
||||
from Function f, int c
|
||||
where c = f.getMetrics().getCyclomaticComplexity() and
|
||||
c > 20
|
||||
where
|
||||
c = f.getMetrics().getCyclomaticComplexity() and
|
||||
c > 20
|
||||
select f, "AV Rule 3: All functions shall have a cyclomatic complexity number of 20 or less."
|
||||
|
||||
@@ -8,9 +8,10 @@
|
||||
* readability
|
||||
* external/jsf
|
||||
*/
|
||||
|
||||
import cpp
|
||||
import external.ExternalArtifact
|
||||
|
||||
from DefectExternalData d
|
||||
where d.getQueryPath() = "jsf/4.04 Environment/AV Rule 11.ql"
|
||||
select d, d.getMessage()
|
||||
select d, d.getMessage()
|
||||
|
||||
@@ -14,4 +14,4 @@ import external.ExternalArtifact
|
||||
|
||||
from DefectExternalData d
|
||||
where d.getQueryPath() = "jsf/4.04 Environment/AV Rule 12.ql"
|
||||
select d, d.getMessage()
|
||||
select d, d.getMessage()
|
||||
|
||||
@@ -8,9 +8,11 @@
|
||||
* portability
|
||||
* external/jsf
|
||||
*/
|
||||
|
||||
import cpp
|
||||
|
||||
from Literal l
|
||||
where l.getType() instanceof Wchar_t or
|
||||
l.getType().(ArrayType).getBaseType().getUnspecifiedType() instanceof Wchar_t
|
||||
select l, "AV Rule 13: Multi-byte characters and wide string literals will not be used."
|
||||
where
|
||||
l.getType() instanceof Wchar_t or
|
||||
l.getType().(ArrayType).getBaseType().getUnspecifiedType() instanceof Wchar_t
|
||||
select l, "AV Rule 13: Multi-byte characters and wide string literals will not be used."
|
||||
|
||||
@@ -8,9 +8,11 @@
|
||||
* readability
|
||||
* external/jsf
|
||||
*/
|
||||
|
||||
import cpp
|
||||
|
||||
from Literal l
|
||||
where l.fromSource() and
|
||||
l.getValueText().regexpMatch(".*[ul][uUlL]*\\s*")
|
||||
select l, "AV Rule 14: Literal suffixes shall use uppercase rather than lowercase letters."
|
||||
where
|
||||
l.fromSource() and
|
||||
l.getValueText().regexpMatch(".*[ul][uUlL]*\\s*")
|
||||
select l, "AV Rule 14: Literal suffixes shall use uppercase rather than lowercase letters."
|
||||
|
||||
@@ -7,10 +7,15 @@
|
||||
* @tags maintainability
|
||||
* external/jsf
|
||||
*/
|
||||
|
||||
import cpp
|
||||
|
||||
from Locatable errno, Locatable use
|
||||
where ( errno.(Macro).getHead() = "errno" and use = errno.(Macro).getAnInvocation()
|
||||
or errno.(Variable).hasName("errno") and use = errno.(Variable).getAnAccess()) and
|
||||
errno.getFile().getAbsolutePath().matches("%errno.h")
|
||||
where
|
||||
(
|
||||
errno.(Macro).getHead() = "errno" and use = errno.(Macro).getAnInvocation()
|
||||
or
|
||||
errno.(Variable).hasName("errno") and use = errno.(Variable).getAnAccess()
|
||||
) and
|
||||
errno.getFile().getAbsolutePath().matches("%errno.h")
|
||||
select use, "AV Rule 17: The error indicator errno shall not be used."
|
||||
|
||||
@@ -7,9 +7,12 @@
|
||||
* @tags maintainability
|
||||
* external/jsf
|
||||
*/
|
||||
|
||||
import cpp
|
||||
|
||||
from Macro offsetof
|
||||
where offsetof.getHead().matches("offsetof(%,%)") and
|
||||
offsetof.getFile().getAbsolutePath().matches("%stddef.h")
|
||||
select offsetof.getAnInvocation(), "AV Rule 18: The macro offsetof, in library <stddef.h>, shall not be used."
|
||||
where
|
||||
offsetof.getHead().matches("offsetof(%,%)") and
|
||||
offsetof.getFile().getAbsolutePath().matches("%stddef.h")
|
||||
select offsetof.getAnInvocation(),
|
||||
"AV Rule 18: The macro offsetof, in library <stddef.h>, shall not be used."
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
* @tags maintainability
|
||||
* external/jsf
|
||||
*/
|
||||
|
||||
import cpp
|
||||
|
||||
from Include incl
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
* readability
|
||||
* external/jsf
|
||||
*/
|
||||
|
||||
import cpp
|
||||
|
||||
class Setjmp extends Macro {
|
||||
@@ -27,6 +28,7 @@ class Longjmp extends Function {
|
||||
}
|
||||
|
||||
from Setjmp setjmp, Longjmp longjmp, Locatable use
|
||||
where use = setjmp.getAnInvocation()
|
||||
or use = longjmp.getACallToThisFunction()
|
||||
where
|
||||
use = setjmp.getAnInvocation() or
|
||||
use = longjmp.getACallToThisFunction()
|
||||
select use, "AV Rule 20: The setjmp macro and the longjmp function shall not be used."
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
* portability
|
||||
* external/jsf
|
||||
*/
|
||||
|
||||
import cpp
|
||||
|
||||
from Include incl
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
* portability
|
||||
* external/jsf
|
||||
*/
|
||||
|
||||
import cpp
|
||||
|
||||
from Include incl
|
||||
|
||||
@@ -8,9 +8,12 @@
|
||||
* portability
|
||||
* external/jsf
|
||||
*/
|
||||
|
||||
import cpp
|
||||
|
||||
from Function f
|
||||
where f.getName().regexpMatch("atof|atoi|atol") and
|
||||
f.getFile().getAbsolutePath().matches("%stdlib.h")
|
||||
select f.getACallToThisFunction(), "AV Rule 23: The library functions atof, atoi and atol from library <stdlib.h> shall not be used."
|
||||
where
|
||||
f.getName().regexpMatch("atof|atoi|atol") and
|
||||
f.getFile().getAbsolutePath().matches("%stdlib.h")
|
||||
select f.getACallToThisFunction(),
|
||||
"AV Rule 23: The library functions atof, atoi and atol from library <stdlib.h> shall not be used."
|
||||
|
||||
@@ -8,9 +8,12 @@
|
||||
* portability
|
||||
* external/jsf
|
||||
*/
|
||||
|
||||
import cpp
|
||||
|
||||
from Function f
|
||||
where f.getName().regexpMatch("abort|exit|getenv|system") and
|
||||
f.getFile().getAbsolutePath().matches("%stdlib.h")
|
||||
select f.getACallToThisFunction(), "The library functions abort, exit, getenv and system from library <stdlib.h> should not be used."
|
||||
where
|
||||
f.getName().regexpMatch("abort|exit|getenv|system") and
|
||||
f.getFile().getAbsolutePath().matches("%stdlib.h")
|
||||
select f.getACallToThisFunction(),
|
||||
"The library functions abort, exit, getenv and system from library <stdlib.h> should not be used."
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
* portability
|
||||
* external/jsf
|
||||
*/
|
||||
|
||||
import cpp
|
||||
|
||||
from Include incl
|
||||
|
||||
@@ -7,11 +7,14 @@
|
||||
* @tags maintainability
|
||||
* external/jsf
|
||||
*/
|
||||
|
||||
import cpp
|
||||
|
||||
from PreprocessorDirective directive
|
||||
where not directive instanceof PreprocessorIfndef and
|
||||
not directive instanceof PreprocessorEndif and
|
||||
not directive instanceof Macro and
|
||||
not directive instanceof Include
|
||||
select directive, "AV Rule 26: only the #ifndef, #endif, #define and #include directives shall be used."
|
||||
where
|
||||
not directive instanceof PreprocessorIfndef and
|
||||
not directive instanceof PreprocessorEndif and
|
||||
not directive instanceof Macro and
|
||||
not directive instanceof Include
|
||||
select directive,
|
||||
"AV Rule 26: only the #ifndef, #endif, #define and #include directives shall be used."
|
||||
|
||||
@@ -8,8 +8,10 @@
|
||||
* portability
|
||||
* external/jsf
|
||||
*/
|
||||
|
||||
import cpp
|
||||
import semmle.code.cpp.headers.MultipleInclusion
|
||||
|
||||
from BadIncludeGuard bad
|
||||
select bad.blame(), "AV Rule 27: techniques other than #ifndef/#define/#endif will not be used to prevent multiple inclusions of header files."
|
||||
select bad.blame(),
|
||||
"AV Rule 27: techniques other than #ifndef/#define/#endif will not be used to prevent multiple inclusions of header files."
|
||||
|
||||
@@ -7,10 +7,13 @@
|
||||
* @tags maintainability
|
||||
* external/jsf
|
||||
*/
|
||||
|
||||
import cpp
|
||||
import semmle.code.cpp.headers.MultipleInclusion
|
||||
|
||||
from PreprocessorDirective directive
|
||||
where (directive instanceof PreprocessorIfndef or directive instanceof PreprocessorEndif) and
|
||||
not exists(CorrectIncludeGuard cig | directive = cig.getIfndef() or directive = cig.getEndif())
|
||||
select directive, "AV Rule 28: the #ifndef and #endif directives will only be used as defined in AV Rule 27."
|
||||
where
|
||||
(directive instanceof PreprocessorIfndef or directive instanceof PreprocessorEndif) and
|
||||
not exists(CorrectIncludeGuard cig | directive = cig.getIfndef() or directive = cig.getEndif())
|
||||
select directive,
|
||||
"AV Rule 28: the #ifndef and #endif directives will only be used as defined in AV Rule 27."
|
||||
|
||||
@@ -7,8 +7,9 @@
|
||||
* @tags maintainability
|
||||
* external/jsf
|
||||
*/
|
||||
|
||||
import cpp
|
||||
|
||||
from Macro m
|
||||
where m.getHead().matches("%(%") // Macro functions are simply macros with brackets in the head
|
||||
select m, "The #define pre-processor directive shall not be used to create inline macros"
|
||||
select m, "The #define pre-processor directive shall not be used to create inline macros"
|
||||
|
||||
@@ -7,20 +7,22 @@
|
||||
* @tags maintainability
|
||||
* external/jsf
|
||||
*/
|
||||
|
||||
import cpp
|
||||
|
||||
/** A macro defining a simple constant. */
|
||||
class ConstantDefMacro extends Macro {
|
||||
ConstantDefMacro() {
|
||||
// Exclude functions
|
||||
not (this.getHead().matches("%(%")) and
|
||||
exists(string body | body = this.getBody() and
|
||||
// Empty defines are allowed (rule 31 restricts their use though)
|
||||
body != "" and
|
||||
// No special characters in the body
|
||||
not (body.matches("%(%")) and
|
||||
not (body.matches("%{%"))
|
||||
)
|
||||
not this.getHead().matches("%(%") and
|
||||
exists(string body |
|
||||
body = this.getBody() and
|
||||
// Empty defines are allowed (rule 31 restricts their use though)
|
||||
body != "" and
|
||||
// No special characters in the body
|
||||
not body.matches("%(%") and
|
||||
not body.matches("%{%")
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,6 +32,7 @@ predicate commonMacro(string name) {
|
||||
}
|
||||
|
||||
from ConstantDefMacro m
|
||||
where not commonMacro(m.getHead())
|
||||
and m.fromSource()
|
||||
select m, "The #define pre-processor directive shall not be used to define constant values."
|
||||
where
|
||||
not commonMacro(m.getHead()) and
|
||||
m.fromSource()
|
||||
select m, "The #define pre-processor directive shall not be used to define constant values."
|
||||
|
||||
@@ -7,9 +7,11 @@
|
||||
* @tags maintainability
|
||||
* external/jsf
|
||||
*/
|
||||
|
||||
import cpp
|
||||
import semmle.code.cpp.headers.MultipleInclusion
|
||||
|
||||
from Macro macro
|
||||
where not exists(CorrectIncludeGuard cig | macro = cig.getDefine())
|
||||
select macro, "AV Rule 31: The #define directive will only be used as part of the technique to prevent multiple inclusions of the same header file."
|
||||
select macro,
|
||||
"AV Rule 31: The #define directive will only be used as part of the technique to prevent multiple inclusions of the same header file."
|
||||
|
||||
@@ -10,16 +10,19 @@
|
||||
* readability
|
||||
* external/jsf
|
||||
*/
|
||||
|
||||
import cpp
|
||||
import semmle.code.cpp.AutogeneratedFile
|
||||
|
||||
from Include i, File f, string extension
|
||||
where f = i.getIncludedFile() and extension = f.getExtension().toLowerCase()
|
||||
and extension != "inl"
|
||||
and extension != "tcc"
|
||||
and extension != "tpp"
|
||||
and extension != "txx"
|
||||
and extension != "xpm"
|
||||
and not (f instanceof AutogeneratedFile)
|
||||
and not (f instanceof HeaderFile)
|
||||
where
|
||||
f = i.getIncludedFile() and
|
||||
extension = f.getExtension().toLowerCase() and
|
||||
extension != "inl" and
|
||||
extension != "tcc" and
|
||||
extension != "tpp" and
|
||||
extension != "txx" and
|
||||
extension != "xpm" and
|
||||
not f instanceof AutogeneratedFile and
|
||||
not f instanceof HeaderFile
|
||||
select i, "The #include pre-processor directive should only be used to include header files."
|
||||
|
||||
@@ -8,8 +8,9 @@
|
||||
* portability
|
||||
* external/jsf
|
||||
*/
|
||||
|
||||
import cpp
|
||||
|
||||
from Include i
|
||||
where i.getIncludeText().matches("<%")
|
||||
select i, "AV Rule 33: the #include <filename.h> notation shall be used."
|
||||
select i, "AV Rule 33: the #include <filename.h> notation shall be used."
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
* modularity
|
||||
* external/jsf
|
||||
*/
|
||||
|
||||
import cpp
|
||||
import semmle.code.cpp.headers.MultipleInclusion
|
||||
|
||||
@@ -29,37 +30,26 @@ newtype TMaybePreprocessorDirective =
|
||||
|
||||
abstract class MaybePreprocessorDirective extends TMaybePreprocessorDirective {
|
||||
abstract string toString();
|
||||
|
||||
abstract Location getLocation();
|
||||
}
|
||||
|
||||
class NoPreprocessorDirective extends TNoPreprocessorDirective, MaybePreprocessorDirective {
|
||||
override string toString() {
|
||||
result = ""
|
||||
}
|
||||
|
||||
override Location getLocation() {
|
||||
result instanceof UnknownDefaultLocation
|
||||
}
|
||||
override string toString() { result = "" }
|
||||
|
||||
override Location getLocation() { result instanceof UnknownDefaultLocation }
|
||||
}
|
||||
|
||||
class SomePreprocessorDirective extends TSomePreprocessorDirective, MaybePreprocessorDirective {
|
||||
PreprocessorDirective pd;
|
||||
|
||||
SomePreprocessorDirective() {
|
||||
this = TSomePreprocessorDirective(pd)
|
||||
}
|
||||
SomePreprocessorDirective() { this = TSomePreprocessorDirective(pd) }
|
||||
|
||||
override string toString() {
|
||||
result = pd.toString()
|
||||
}
|
||||
|
||||
override Location getLocation() {
|
||||
result = pd.getLocation()
|
||||
}
|
||||
|
||||
PreprocessorDirective getPreprocessorDirective() {
|
||||
result = pd
|
||||
}
|
||||
override string toString() { result = pd.toString() }
|
||||
|
||||
override Location getLocation() { result = pd.getLocation() }
|
||||
|
||||
PreprocessorDirective getPreprocessorDirective() { result = pd }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -67,20 +57,30 @@ class SomePreprocessorDirective extends TSomePreprocessorDirective, MaybePreproc
|
||||
* The second and third parameters are option typed, and are only present
|
||||
* when there are additional links in the detail string.
|
||||
*/
|
||||
string extraDetail(HeaderFile hf, SomePreprocessorDirective detail1, SomePreprocessorDirective detail2) {
|
||||
exists(string s, PreprocessorEndif endif, PreprocessorDirective ifndef | startsWithIfndef(hf, ifndef, s) and endif.getIf() = ifndef |
|
||||
string extraDetail(
|
||||
HeaderFile hf, SomePreprocessorDirective detail1, SomePreprocessorDirective detail2
|
||||
) {
|
||||
exists(string s, PreprocessorEndif endif, PreprocessorDirective ifndef |
|
||||
startsWithIfndef(hf, ifndef, s) and endif.getIf() = ifndef
|
||||
|
|
||||
detail1.getPreprocessorDirective() = endif and
|
||||
detail2.getPreprocessorDirective() = ifndef and
|
||||
if not endsWithEndif(hf, endif) then
|
||||
result = " ($@ matching $@ occurs before the end of the file)."
|
||||
else if exists(Macro m | m.getFile() = hf and m.getHead() = s) then
|
||||
result = " (#define " + s + " needs to appear immediately after #ifndef " + s + ")."
|
||||
else if strictcount(possibleGuard(hf, _)) = 1 then
|
||||
result = " (" + possibleGuard(hf, _) + " should appear in the #ifndef rather than " + s + ")."
|
||||
else if strictcount(possibleGuard(hf, "")) = 1 then
|
||||
result = " (" + possibleGuard(hf, "") + " should appear in the #ifndef rather than " + s + ")."
|
||||
if not endsWithEndif(hf, endif)
|
||||
then result = " ($@ matching $@ occurs before the end of the file)."
|
||||
else
|
||||
result = " (the macro " + s + " is checked for, but is not defined)."
|
||||
if exists(Macro m | m.getFile() = hf and m.getHead() = s)
|
||||
then result = " (#define " + s + " needs to appear immediately after #ifndef " + s + ")."
|
||||
else
|
||||
if strictcount(possibleGuard(hf, _)) = 1
|
||||
then
|
||||
result = " (" + possibleGuard(hf, _) + " should appear in the #ifndef rather than " + s +
|
||||
")."
|
||||
else
|
||||
if strictcount(possibleGuard(hf, "")) = 1
|
||||
then
|
||||
result = " (" + possibleGuard(hf, "") + " should appear in the #ifndef rather than " + s
|
||||
+ ")."
|
||||
else result = " (the macro " + s + " is checked for, but is not defined)."
|
||||
)
|
||||
}
|
||||
|
||||
@@ -130,9 +130,7 @@ predicate hasXMacro(HeaderFile hf) {
|
||||
// used in `hf`.
|
||||
exists(string macroName |
|
||||
usesMacro(hf, macroName) and
|
||||
forex(File f | f.getAnIncludedFile() = hf |
|
||||
defUndef(f, macroName)
|
||||
)
|
||||
forex(File f | f.getAnIncludedFile() = hf | defUndef(f, macroName))
|
||||
)
|
||||
or
|
||||
// Every header that includes `hf` defines a macro that's used in `hf`, and
|
||||
@@ -140,27 +138,33 @@ predicate hasXMacro(HeaderFile hf) {
|
||||
exists(string macroName |
|
||||
usesMacro(hf, macroName) and
|
||||
undefinesMacro(hf, macroName) and
|
||||
forex(File f | f.getAnIncludedFile() = hf |
|
||||
definesMacro(f, macroName)
|
||||
)
|
||||
forex(File f | f.getAnIncludedFile() = hf | definesMacro(f, macroName))
|
||||
)
|
||||
}
|
||||
|
||||
from HeaderFile hf, string detail, MaybePreprocessorDirective detail1, MaybePreprocessorDirective detail2
|
||||
where not hf instanceof IncludeGuardedHeader
|
||||
and (if exists(extraDetail(hf, _, _))
|
||||
from
|
||||
HeaderFile hf, string detail, MaybePreprocessorDirective detail1,
|
||||
MaybePreprocessorDirective detail2
|
||||
where
|
||||
not hf instanceof IncludeGuardedHeader and
|
||||
(
|
||||
if exists(extraDetail(hf, _, _))
|
||||
then detail = extraDetail(hf, detail1, detail2)
|
||||
else (detail = "." and
|
||||
else (
|
||||
detail = "." and
|
||||
detail1 instanceof NoPreprocessorDirective and
|
||||
detail2 instanceof NoPreprocessorDirective))
|
||||
detail2 instanceof NoPreprocessorDirective
|
||||
)
|
||||
) and
|
||||
// Exclude files which contain no declaration entries or top level
|
||||
// declarations (e.g. just preprocessor directives; or non-top level
|
||||
// code).
|
||||
and not hf.noTopLevelCode()
|
||||
not hf.noTopLevelCode() and
|
||||
// Exclude files which look like they contain 'x-macros'
|
||||
and not hasXMacro(hf)
|
||||
not hasXMacro(hf) and
|
||||
// Exclude files which are always #imported.
|
||||
and not forex(Include i | i.getIncludedFile() = hf | i instanceof Import)
|
||||
not forex(Include i | i.getIncludedFile() = hf | i instanceof Import) and
|
||||
// Exclude files which are only included once.
|
||||
and not strictcount(Include i | i.getIncludedFile() = hf) = 1
|
||||
select hf, "This header file should contain a header guard to prevent multiple inclusion" + detail, detail1, detail1.toString(), detail2, detail2.toString()
|
||||
not strictcount(Include i | i.getIncludedFile() = hf) = 1
|
||||
select hf, "This header file should contain a header guard to prevent multiple inclusion" + detail,
|
||||
detail1, detail1.toString(), detail2, detail2.toString()
|
||||
|
||||
@@ -7,14 +7,18 @@
|
||||
* @tags maintainability
|
||||
* external/jsf
|
||||
*/
|
||||
|
||||
import cpp
|
||||
|
||||
predicate forbidden(Declaration d) {
|
||||
d instanceof Variable and not d.(Variable).isConst()
|
||||
or (d instanceof Function and not d.hasSpecifier("inline"))
|
||||
or
|
||||
d instanceof Function and not d.hasSpecifier("inline")
|
||||
}
|
||||
|
||||
from Declaration d
|
||||
where d.getDefinitionLocation().getFile() instanceof HeaderFile
|
||||
and forbidden(d)
|
||||
select d.getDefinitionLocation(), "AV Rule 38: header files will not contain non-const variable definitions or function definitions."
|
||||
where
|
||||
d.getDefinitionLocation().getFile() instanceof HeaderFile and
|
||||
forbidden(d)
|
||||
select d.getDefinitionLocation(),
|
||||
"AV Rule 38: header files will not contain non-const variable definitions or function definitions."
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
* @tags correctness
|
||||
* external/jsf
|
||||
*/
|
||||
|
||||
import cpp
|
||||
|
||||
/*
|
||||
@@ -40,10 +41,14 @@ predicate definedInImplementationFile(Declaration d) {
|
||||
}
|
||||
|
||||
from Declaration d, string message
|
||||
where relevant(d) and
|
||||
((hasTwoDefinitions(d) and message = " should not have several definitions.")
|
||||
or definedInImplementationFile(d) and message = " should be defined in a header file.")
|
||||
// Don't count member functions - the only way they can match this rule is by
|
||||
// being in a class definition that already matches, so it would be redundant
|
||||
and not d instanceof MemberFunction
|
||||
select d.getDefinitionLocation(), "AV Rule 40: " + d.getName() + message
|
||||
where
|
||||
relevant(d) and
|
||||
(
|
||||
hasTwoDefinitions(d) and message = " should not have several definitions."
|
||||
or
|
||||
definedInImplementationFile(d) and message = " should be defined in a header file."
|
||||
) and
|
||||
// Don't count member functions - the only way they can match this rule is by
|
||||
// being in a class definition that already matches, so it would be redundant
|
||||
not d instanceof MemberFunction
|
||||
select d.getDefinitionLocation(), "AV Rule 40: " + d.getName() + message
|
||||
|
||||
@@ -14,4 +14,4 @@ import external.ExternalArtifact
|
||||
|
||||
from DefectExternalData d
|
||||
where d.getQueryPath() = "jsf/4.09 Style/AV Rule 41.ql"
|
||||
select d, d.getMessage()
|
||||
select d, d.getMessage()
|
||||
|
||||
@@ -8,12 +8,13 @@
|
||||
* readability
|
||||
* external/jsf
|
||||
*/
|
||||
|
||||
import cpp
|
||||
|
||||
predicate exprInStmtContext(Expr e, Location l, File f) {
|
||||
e.getParent() instanceof ExprStmt
|
||||
and l = e.getLocation()
|
||||
and f = l.getFile()
|
||||
e.getParent() instanceof ExprStmt and
|
||||
l = e.getLocation() and
|
||||
f = l.getFile()
|
||||
}
|
||||
|
||||
predicate overlappingExprs(Expr e1, Expr e2) {
|
||||
@@ -21,11 +22,11 @@ predicate overlappingExprs(Expr e1, Expr e2) {
|
||||
exprInStmtContext(e1, l1, f) and
|
||||
exprInStmtContext(e2, l2, f) and
|
||||
e1 != e2 and
|
||||
(l1.getEndLine() >= l2.getStartLine()) and
|
||||
(l1.getStartLine() <= l2.getEndLine())
|
||||
l1.getEndLine() >= l2.getStartLine() and
|
||||
l1.getStartLine() <= l2.getEndLine()
|
||||
)
|
||||
}
|
||||
|
||||
from Expr e
|
||||
where overlappingExprs(e, _) and not e.isInMacroExpansion()
|
||||
select e, "AV Rule 42: Each expression-statement will be on a separate line."
|
||||
select e, "AV Rule 42: Each expression-statement will be on a separate line."
|
||||
|
||||
@@ -14,4 +14,4 @@ import external.ExternalArtifact
|
||||
|
||||
from DefectExternalData d
|
||||
where d.getQueryPath() = "jsf/4.09 Style/AV Rule 43.ql"
|
||||
select d, d.getMessage()
|
||||
select d, d.getMessage()
|
||||
|
||||
@@ -14,4 +14,4 @@ import external.ExternalArtifact
|
||||
|
||||
from DefectExternalData d
|
||||
where d.getQueryPath() = "jsf/4.09 Style/AV Rule 44.ql"
|
||||
select d, d.getMessage()
|
||||
select d, d.getMessage()
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
* readability
|
||||
* external/jsf
|
||||
*/
|
||||
|
||||
import cpp
|
||||
|
||||
/*
|
||||
@@ -16,10 +17,12 @@ import cpp
|
||||
*/
|
||||
|
||||
from Declaration d, string name, string lowerCase, string upperCase, int pos
|
||||
where name = d.getName() and
|
||||
d.fromSource() and
|
||||
lowerCase = name.charAt(pos) and
|
||||
upperCase = name.charAt(pos+1) and
|
||||
lowerCase.regexpMatch("[a-z]") and
|
||||
upperCase.regexpMatch("[A-Z]")
|
||||
select d, "AV Rule 45: All words in an identifier will be separated by the underscore character. Camel-case is not allowed."
|
||||
where
|
||||
name = d.getName() and
|
||||
d.fromSource() and
|
||||
lowerCase = name.charAt(pos) and
|
||||
upperCase = name.charAt(pos + 1) and
|
||||
lowerCase.regexpMatch("[a-z]") and
|
||||
upperCase.regexpMatch("[A-Z]")
|
||||
select d,
|
||||
"AV Rule 45: All words in an identifier will be separated by the underscore character. Camel-case is not allowed."
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
* readability
|
||||
* external/jsf
|
||||
*/
|
||||
|
||||
import cpp
|
||||
|
||||
/*
|
||||
@@ -25,8 +26,8 @@ predicate longNameSignificance(Element e, string significance) {
|
||||
}
|
||||
|
||||
predicate elementName(Element e, string name) {
|
||||
name = e.(Declaration).getName() or name = e.(Namespace).getName()
|
||||
}
|
||||
name = e.(Declaration).getName() or name = e.(Namespace).getName()
|
||||
}
|
||||
|
||||
predicate clash(Element e1, Element e2) {
|
||||
exists(string significance, string n1, string n2 |
|
||||
@@ -39,6 +40,7 @@ predicate clash(Element e1, Element e2) {
|
||||
}
|
||||
|
||||
from Element e1, Element e2, string name
|
||||
where clash(e1, e2)
|
||||
and elementName(e2, name)
|
||||
select e1, "AV Rule 46: relies on more than 64 characters to separate from " + name
|
||||
where
|
||||
clash(e1, e2) and
|
||||
elementName(e2, name)
|
||||
select e1, "AV Rule 46: relies on more than 64 characters to separate from " + name
|
||||
|
||||
@@ -7,9 +7,11 @@
|
||||
* @tags maintainability
|
||||
* external/jsf
|
||||
*/
|
||||
|
||||
import cpp
|
||||
|
||||
from Declaration d
|
||||
where d.fromSource() and
|
||||
d.getName().matches("\\_%")
|
||||
select d, "Identifiers will not begin with the underscore character."
|
||||
where
|
||||
d.fromSource() and
|
||||
d.getName().matches("\\_%")
|
||||
select d, "Identifiers will not begin with the underscore character."
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
* readability
|
||||
* external/jsf
|
||||
*/
|
||||
|
||||
import cpp
|
||||
|
||||
/*
|
||||
@@ -29,63 +30,67 @@ predicate canonicalName1(Declaration d, string canonical) {
|
||||
}
|
||||
|
||||
predicate canonicalName2(Declaration d, string canonical) {
|
||||
canonical = d.getName()
|
||||
.replaceAll("_", "")
|
||||
.replaceAll("0", "O")
|
||||
.replaceAll("D", "O")
|
||||
.replaceAll("1", "I")
|
||||
.replaceAll("l", "I")
|
||||
.replaceAll("S", "5")
|
||||
.replaceAll("Z", "2")
|
||||
.replaceAll("n", "h")
|
||||
canonical = d
|
||||
.getName()
|
||||
.replaceAll("_", "")
|
||||
.replaceAll("0", "O")
|
||||
.replaceAll("D", "O")
|
||||
.replaceAll("1", "I")
|
||||
.replaceAll("l", "I")
|
||||
.replaceAll("S", "5")
|
||||
.replaceAll("Z", "2")
|
||||
.replaceAll("n", "h")
|
||||
}
|
||||
|
||||
predicate same(Declaration d1, Declaration d2) {
|
||||
exists (string common | canonicalName1(d1, common) and canonicalName1(d2, common))
|
||||
exists(string common | canonicalName1(d1, common) and canonicalName1(d2, common))
|
||||
or
|
||||
exists (string common | canonicalName2(d1, common) and canonicalName2(d2, common))
|
||||
exists(string common | canonicalName2(d1, common) and canonicalName2(d2, common))
|
||||
}
|
||||
|
||||
/** Is the declaration local to that function? */
|
||||
predicate local(Declaration d, Function f) {
|
||||
d.(Parameter).getFunction() = f
|
||||
or exists(DeclStmt ds | d = ds.getADeclaration().(LocalVariable) and ds.getEnclosingFunction() = f)
|
||||
or
|
||||
exists(DeclStmt ds | d = ds.getADeclaration().(LocalVariable) and ds.getEnclosingFunction() = f)
|
||||
}
|
||||
|
||||
/** Is the declaration local to that struct? Reduce false warning by taking into
|
||||
* account struct lookup rules - since a struct members can never be referred to
|
||||
* other than in a qualified way it doesn't really count.*/
|
||||
predicate structLocal(Declaration d, Struct s) {
|
||||
d = s.getAMemberVariable()
|
||||
}
|
||||
/**
|
||||
* Is the declaration local to that struct? Reduce false warning by taking into
|
||||
* account struct lookup rules - since a struct members can never be referred to
|
||||
* other than in a qualified way it doesn't really count.
|
||||
*/
|
||||
predicate structLocal(Declaration d, Struct s) { d = s.getAMemberVariable() }
|
||||
|
||||
predicate compatibleScopes(Declaration d1, Declaration d2) {
|
||||
// Either they're both local to the same struct, or
|
||||
exists (Struct s | structLocal(d1,s) and structLocal(d2,s))
|
||||
or
|
||||
(
|
||||
// Neither of them is a struct member and ...
|
||||
not(structLocal(d1,_)) and not(structLocal(d2,_)) and
|
||||
same(d1, d2) and
|
||||
(
|
||||
// d2 is global and d1 is either, or
|
||||
not local(d2, _) or
|
||||
// both are local to the same function
|
||||
exists (Function f | local(d1,f) and local(d2,f))
|
||||
)
|
||||
)
|
||||
// Either they're both local to the same struct, or
|
||||
exists(Struct s | structLocal(d1, s) and structLocal(d2, s))
|
||||
or
|
||||
// Neither of them is a struct member and ...
|
||||
not structLocal(d1, _) and
|
||||
not structLocal(d2, _) and
|
||||
same(d1, d2) and
|
||||
(
|
||||
// d2 is global and d1 is either, or
|
||||
not local(d2, _)
|
||||
or
|
||||
// both are local to the same function
|
||||
exists(Function f | local(d1, f) and local(d2, f))
|
||||
)
|
||||
}
|
||||
|
||||
from Declaration d1, Declaration d2
|
||||
where d1.fromSource() and d2.fromSource() and
|
||||
// Test that the names are confusing according to the above criteria
|
||||
same(d1, d2) and
|
||||
d1.getName() != d2.getName() and
|
||||
(
|
||||
// either they are both type names, or
|
||||
(d1 instanceof UserType and d2 instanceof UserType)
|
||||
or
|
||||
// they are both variable names in close enough scopes for the confusion to matter
|
||||
(d1 instanceof Variable and d2 instanceof Variable and compatibleScopes(d1, d2))
|
||||
)
|
||||
select d1, "AV Rule 48: this identifier is too close to another identifier (" + d2.getName() + ")"
|
||||
where
|
||||
d1.fromSource() and
|
||||
d2.fromSource() and
|
||||
// Test that the names are confusing according to the above criteria
|
||||
same(d1, d2) and
|
||||
d1.getName() != d2.getName() and
|
||||
(
|
||||
// either they are both type names, or
|
||||
d1 instanceof UserType and d2 instanceof UserType
|
||||
or
|
||||
// they are both variable names in close enough scopes for the confusion to matter
|
||||
d1 instanceof Variable and d2 instanceof Variable and compatibleScopes(d1, d2)
|
||||
)
|
||||
select d1, "AV Rule 48: this identifier is too close to another identifier (" + d2.getName() + ")"
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
* readability
|
||||
* external/jsf
|
||||
*/
|
||||
|
||||
import cpp
|
||||
import Naming
|
||||
|
||||
@@ -16,9 +17,12 @@ import Naming
|
||||
*/
|
||||
|
||||
from Declaration d, Name n, Word w
|
||||
where d.fromSource() and
|
||||
n = d.getName() and
|
||||
w = n.getAWord() and
|
||||
w.isDefiniteAcronym() and
|
||||
not w.isUppercase()
|
||||
select d, "AV Rule 49: acronyms in identifiers will be uppercase. Incorrect case for acronym " + w.toString() + "."
|
||||
where
|
||||
d.fromSource() and
|
||||
n = d.getName() and
|
||||
w = n.getAWord() and
|
||||
w.isDefiniteAcronym() and
|
||||
not w.isUppercase()
|
||||
select d,
|
||||
"AV Rule 49: acronyms in identifiers will be uppercase. Incorrect case for acronym " +
|
||||
w.toString() + "."
|
||||
|
||||
@@ -8,23 +8,32 @@
|
||||
* readability
|
||||
* external/jsf
|
||||
*/
|
||||
|
||||
import cpp
|
||||
import Naming
|
||||
|
||||
predicate relevant(Element elem, Element blame, string kind, string name) {
|
||||
exists(Class c | elem = c and blame = c and kind = "class or struct" and name = c.getName()) or // includes struct
|
||||
exists(Namespace n | elem = n and blame = n.getADeclarationEntry() and kind = "namespace" and name = n.getName()) or
|
||||
exists(Enum e | elem = e and blame = e and kind = "enumeration" and name = e.getName()) or
|
||||
exists(Class c | elem = c and blame = c and kind = "class or struct" and name = c.getName()) // includes struct
|
||||
or
|
||||
exists(Namespace n |
|
||||
elem = n and blame = n.getADeclarationEntry() and kind = "namespace" and name = n.getName()
|
||||
)
|
||||
or
|
||||
exists(Enum e | elem = e and blame = e and kind = "enumeration" and name = e.getName())
|
||||
or
|
||||
exists(TypedefType t | elem = t and blame = t and kind = "typedef" and name = t.getName())
|
||||
}
|
||||
|
||||
from Element d, Element blame, Word w, int pos, string kind, string name
|
||||
where relevant(d, blame, kind, name) and
|
||||
w = name.(Name).getWord(pos) and
|
||||
not (w.couldBeUppercaseAcronym() and w != name) and
|
||||
(
|
||||
(pos = 0 and not w.isCapitalized())
|
||||
or
|
||||
(pos > 0 and not w.isLowercase())
|
||||
)
|
||||
select blame, "AV Rule 50: The first word of a " + kind + " will begin with an uppercase letter, and all other letters will be lowercase."
|
||||
where
|
||||
relevant(d, blame, kind, name) and
|
||||
w = name.(Name).getWord(pos) and
|
||||
not (w.couldBeUppercaseAcronym() and w != name) and
|
||||
(
|
||||
pos = 0 and not w.isCapitalized()
|
||||
or
|
||||
pos > 0 and not w.isLowercase()
|
||||
)
|
||||
select blame,
|
||||
"AV Rule 50: The first word of a " + kind +
|
||||
" will begin with an uppercase letter, and all other letters will be lowercase."
|
||||
|
||||
@@ -8,17 +8,20 @@
|
||||
* readability
|
||||
* external/jsf
|
||||
*/
|
||||
|
||||
import cpp
|
||||
import Naming
|
||||
|
||||
predicate relevant(Declaration d, string kind) {
|
||||
(d instanceof Function and kind = "function") or
|
||||
(d instanceof Variable and kind = "variable")
|
||||
d instanceof Function and kind = "function"
|
||||
or
|
||||
d instanceof Variable and kind = "variable"
|
||||
}
|
||||
|
||||
from Declaration d, Word w, string kind
|
||||
where relevant(d, kind) and
|
||||
w = d.getName().(Name).getAWord() and
|
||||
not (w.couldBeUppercaseAcronym() and w != d.getName()) and
|
||||
not w.isLowercase()
|
||||
select d, "AV Rule 51: All letters contained in " + kind + " names will be lowercase."
|
||||
where
|
||||
relevant(d, kind) and
|
||||
w = d.getName().(Name).getAWord() and
|
||||
not (w.couldBeUppercaseAcronym() and w != d.getName()) and
|
||||
not w.isLowercase()
|
||||
select d, "AV Rule 51: All letters contained in " + kind + " names will be lowercase."
|
||||
|
||||
@@ -8,17 +8,20 @@
|
||||
* readability
|
||||
* external/jsf
|
||||
*/
|
||||
|
||||
import cpp
|
||||
import Naming
|
||||
|
||||
predicate relevant(Declaration d, string kind) {
|
||||
(d instanceof EnumConstant and kind = "enumerator") or
|
||||
(d.(Variable).isConst() and kind = "constant")
|
||||
d instanceof EnumConstant and kind = "enumerator"
|
||||
or
|
||||
d.(Variable).isConst() and kind = "constant"
|
||||
}
|
||||
|
||||
from Declaration d, Word w, string kind
|
||||
where relevant(d, kind) and
|
||||
w = d.getName().(Name).getAWord() and
|
||||
not (w.couldBeUppercaseAcronym() and w != d.getName()) and
|
||||
not w.isLowercase()
|
||||
where
|
||||
relevant(d, kind) and
|
||||
w = d.getName().(Name).getAWord() and
|
||||
not (w.couldBeUppercaseAcronym() and w != d.getName()) and
|
||||
not w.isLowercase()
|
||||
select d, "AV Rule 52: identifiers for " + kind + " values shall be lowercase."
|
||||
|
||||
@@ -8,14 +8,18 @@
|
||||
* portability
|
||||
* external/jsf
|
||||
*/
|
||||
|
||||
import cpp
|
||||
|
||||
from Include i, string name
|
||||
where name = i.getIncludeText()
|
||||
and (name.matches("%'%") or
|
||||
name.matches("%\\\\%") or
|
||||
name.matches("%/*%") or
|
||||
name.matches("%//%") or
|
||||
name.matches("%\"%\"%\"%") or
|
||||
name.matches("%<%\"%>%"))
|
||||
where
|
||||
name = i.getIncludeText() and
|
||||
(
|
||||
name.matches("%'%") or
|
||||
name.matches("%\\\\%") or
|
||||
name.matches("%/*%") or
|
||||
name.matches("%//%") or
|
||||
name.matches("%\"%\"%\"%") or
|
||||
name.matches("%<%\"%>%")
|
||||
)
|
||||
select i, "AV Rule 53.1: Invalid character sequence in header file name '" + name + "'"
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
* readability
|
||||
* external/jsf
|
||||
*/
|
||||
|
||||
import cpp
|
||||
|
||||
/*
|
||||
@@ -16,6 +17,7 @@ import cpp
|
||||
*/
|
||||
|
||||
from File f
|
||||
where (f.getExtension().toLowerCase() = "h" or f.getExtension().toLowerCase() = "hpp")
|
||||
and f.getExtension() != "h"
|
||||
select f, "AV Rule 53: Header files will always have a file name extension of .h."
|
||||
where
|
||||
(f.getExtension().toLowerCase() = "h" or f.getExtension().toLowerCase() = "hpp") and
|
||||
f.getExtension() != "h"
|
||||
select f, "AV Rule 53: Header files will always have a file name extension of .h."
|
||||
|
||||
@@ -8,8 +8,9 @@
|
||||
* readability
|
||||
* external/jsf
|
||||
*/
|
||||
|
||||
import cpp
|
||||
|
||||
from CppFile f
|
||||
where f.getExtension() != "cpp"
|
||||
select f, "AV Rule 53: Implementation files will always have a file name extension of .cpp."
|
||||
select f, "AV Rule 53: Implementation files will always have a file name extension of .cpp."
|
||||
|
||||
@@ -8,13 +8,20 @@
|
||||
* readability
|
||||
* external/jsf
|
||||
*/
|
||||
|
||||
import cpp
|
||||
|
||||
from Class c, Declaration m1, Declaration m2, int pos1, int pos2
|
||||
where m1 = c.getCanonicalMember(pos1) and
|
||||
m2 = c.getCanonicalMember(pos2) and
|
||||
pos1 < pos2 and
|
||||
( (m1.hasSpecifier("private") and m2.hasSpecifier("protected"))
|
||||
or (m1.hasSpecifier("private") and m2.hasSpecifier("public"))
|
||||
or (m1.hasSpecifier("protected") and m2.hasSpecifier("public")))
|
||||
select c, "AV Rule 57: The public, protected, and private sections of a class will be declared in that order."
|
||||
where
|
||||
m1 = c.getCanonicalMember(pos1) and
|
||||
m2 = c.getCanonicalMember(pos2) and
|
||||
pos1 < pos2 and
|
||||
(
|
||||
m1.hasSpecifier("private") and m2.hasSpecifier("protected")
|
||||
or
|
||||
m1.hasSpecifier("private") and m2.hasSpecifier("public")
|
||||
or
|
||||
m1.hasSpecifier("protected") and m2.hasSpecifier("public")
|
||||
)
|
||||
select c,
|
||||
"AV Rule 57: The public, protected, and private sections of a class will be declared in that order."
|
||||
|
||||
@@ -8,10 +8,13 @@
|
||||
* readability
|
||||
* external/jsf
|
||||
*/
|
||||
|
||||
import cpp
|
||||
|
||||
class ParamLoc extends Parameter {
|
||||
int getValidLine() { result = this.getLocation().getStartLine() and result = this.getLocation().getEndLine() }
|
||||
int getValidLine() {
|
||||
result = this.getLocation().getStartLine() and result = this.getLocation().getEndLine()
|
||||
}
|
||||
}
|
||||
|
||||
predicate valid(Function f) {
|
||||
@@ -19,16 +22,19 @@ predicate valid(Function f) {
|
||||
f.getParameter(0).(ParamLoc).getValidLine() = f.getLocation().getStartLine() and
|
||||
// Check that each subsequent parameter is on its own line
|
||||
not exists(ParamLoc p1, ParamLoc p2 |
|
||||
p1 = f.getAParameter() and p2 = f.getAParameter() and
|
||||
p1 != p2 and
|
||||
p1.getValidLine() = p2.getValidLine()
|
||||
p1 = f.getAParameter() and
|
||||
p2 = f.getAParameter() and
|
||||
p1 != p2 and
|
||||
p1.getValidLine() = p2.getValidLine()
|
||||
) and
|
||||
// Check that there are no parameters on two lines
|
||||
forall (ParamLoc p | p = f.getAParameter() | exists(p.getValidLine()))
|
||||
forall(ParamLoc p | p = f.getAParameter() | exists(p.getValidLine()))
|
||||
}
|
||||
|
||||
from Function f
|
||||
where f.getNumberOfParameters() > 2
|
||||
and f.hasDefinition()
|
||||
and not valid(f)
|
||||
select f, "AV Rule 58: functions with more than two parameters will conform to style rules for declaring parameters"
|
||||
where
|
||||
f.getNumberOfParameters() > 2 and
|
||||
f.hasDefinition() and
|
||||
not valid(f)
|
||||
select f,
|
||||
"AV Rule 58: functions with more than two parameters will conform to style rules for declaring parameters"
|
||||
|
||||
@@ -8,15 +8,22 @@
|
||||
* readability
|
||||
* external/jsf
|
||||
*/
|
||||
|
||||
import cpp
|
||||
|
||||
from Stmt parent, Stmt child
|
||||
where not child instanceof Block
|
||||
and
|
||||
(child = parent.(IfStmt).getThen() or
|
||||
child = parent.(WhileStmt).getStmt() or
|
||||
child = parent.(DoStmt).getStmt() or
|
||||
child = parent.(ForStmt).getStmt() or
|
||||
(child = parent.(IfStmt).getElse() and not child instanceof IfStmt)
|
||||
)
|
||||
select child.findRootCause(), "The statements forming the body of an if, else if, else, while, do...while or for statement shall always be enclosed in braces, even if the braces form an empty block."
|
||||
where
|
||||
not child instanceof Block and
|
||||
(
|
||||
child = parent.(IfStmt).getThen()
|
||||
or
|
||||
child = parent.(WhileStmt).getStmt()
|
||||
or
|
||||
child = parent.(DoStmt).getStmt()
|
||||
or
|
||||
child = parent.(ForStmt).getStmt()
|
||||
or
|
||||
child = parent.(IfStmt).getElse() and not child instanceof IfStmt
|
||||
)
|
||||
select child.findRootCause(),
|
||||
"The statements forming the body of an if, else if, else, while, do...while or for statement shall always be enclosed in braces, even if the braces form an empty block."
|
||||
|
||||
@@ -14,4 +14,4 @@ import external.ExternalArtifact
|
||||
|
||||
from DefectExternalData d
|
||||
where d.getQueryPath() = "jsf/4.09 Style/AV Rule 60.ql"
|
||||
select d, d.getMessage()
|
||||
select d, d.getMessage()
|
||||
|
||||
@@ -14,4 +14,4 @@ import external.ExternalArtifact
|
||||
|
||||
from DefectExternalData d
|
||||
where d.getQueryPath() = "jsf/4.09 Style/AV Rule 61.ql"
|
||||
select d, d.getMessage()
|
||||
select d, d.getMessage()
|
||||
|
||||
@@ -8,41 +8,43 @@
|
||||
* readability
|
||||
* external/jsf
|
||||
*/
|
||||
|
||||
import cpp
|
||||
|
||||
predicate hasLocation(Expr e) {
|
||||
e.getLocation().getStartLine() != 0
|
||||
}
|
||||
predicate hasLocation(Expr e) { e.getLocation().getStartLine() != 0 }
|
||||
|
||||
predicate outermostConvWithLocation(Expr e, Expr res) {
|
||||
if(exists(Expr p | e.getConversion+() = p and hasLocation(p))) then
|
||||
outermostConvWithLocation(e.getConversion(), res)
|
||||
else
|
||||
res = e
|
||||
if exists(Expr p | e.getConversion+() = p and hasLocation(p))
|
||||
then outermostConvWithLocation(e.getConversion(), res)
|
||||
else res = e
|
||||
}
|
||||
|
||||
predicate diffEndBegin(Expr lhs, Expr rhs, int length) {
|
||||
exists(Location l, Location r |
|
||||
l = lhs.getLocation() and r = rhs.getLocation()
|
||||
and length = r.getStartColumn() - l.getEndColumn()
|
||||
and l.getEndLine() = r.getStartLine()
|
||||
)
|
||||
}
|
||||
predicate diffEndEnd(Expr lhs, Expr rhs, int length) {
|
||||
exists(Location l, Location r |
|
||||
l = lhs.getLocation() and r = rhs.getLocation()
|
||||
and length = r.getEndColumn() - l.getEndColumn()
|
||||
and l.getEndLine() = r.getEndLine()
|
||||
)
|
||||
}
|
||||
predicate diffBeginBegin(Expr lhs, Expr rhs, int length) {
|
||||
exists(Location l, Location r |
|
||||
l = lhs.getLocation() and r = rhs.getLocation()
|
||||
and length = r.getStartColumn() - l.getStartColumn()
|
||||
and l.getStartLine() = r.getStartLine()
|
||||
l = lhs.getLocation() and
|
||||
r = rhs.getLocation() and
|
||||
length = r.getStartColumn() - l.getEndColumn() and
|
||||
l.getEndLine() = r.getStartLine()
|
||||
)
|
||||
}
|
||||
|
||||
predicate diffEndEnd(Expr lhs, Expr rhs, int length) {
|
||||
exists(Location l, Location r |
|
||||
l = lhs.getLocation() and
|
||||
r = rhs.getLocation() and
|
||||
length = r.getEndColumn() - l.getEndColumn() and
|
||||
l.getEndLine() = r.getEndLine()
|
||||
)
|
||||
}
|
||||
|
||||
predicate diffBeginBegin(Expr lhs, Expr rhs, int length) {
|
||||
exists(Location l, Location r |
|
||||
l = lhs.getLocation() and
|
||||
r = rhs.getLocation() and
|
||||
length = r.getStartColumn() - l.getStartColumn() and
|
||||
l.getStartLine() = r.getStartLine()
|
||||
)
|
||||
}
|
||||
|
||||
/*
|
||||
* Unary postfix operations: PostfixDecrExpr, PostfixIncrExpr
|
||||
@@ -52,39 +54,79 @@ predicate diffBeginBegin(Expr lhs, Expr rhs, int length) {
|
||||
|
||||
from Expr err
|
||||
where
|
||||
not err.isInMacroExpansion() and hasLocation(err)
|
||||
and
|
||||
not err.isInMacroExpansion() and
|
||||
hasLocation(err) and
|
||||
(
|
||||
exists(Call c, Expr e | c = err and outermostConvWithLocation(c.getQualifier(), e)
|
||||
and e.getType() instanceof PointerType and not diffEndBegin(e, c, 3))
|
||||
or
|
||||
exists(Call c, Expr e | c = err and outermostConvWithLocation(c.getQualifier(), e)
|
||||
and not e.getType() instanceof PointerType and not diffEndBegin(e, c, 2))
|
||||
or
|
||||
exists(VariableAccess c, Expr e | c = err and outermostConvWithLocation(c.getQualifier(), e)
|
||||
and e.getType() instanceof PointerType and not diffEndBegin(e, c, 3))
|
||||
or
|
||||
exists(VariableAccess c, Expr e | c = err and outermostConvWithLocation(c.getQualifier(), e)
|
||||
and not e.getType() instanceof PointerType and not diffEndBegin(e, c, 2))
|
||||
or
|
||||
exists(UnaryOperation c, Expr e | c = err and outermostConvWithLocation(c.getOperand(), e)
|
||||
and (c instanceof ComplementExpr or c instanceof NotExpr or c instanceof UnaryMinusExpr
|
||||
or c instanceof UnaryPlusExpr or c instanceof AddressOfExpr)
|
||||
and not diffBeginBegin(c, e, 1))
|
||||
or
|
||||
exists(PrefixIncrExpr c, Expr e | c = err and outermostConvWithLocation(c.getOperand(), e)
|
||||
and not diffBeginBegin(c, e, 2))
|
||||
or
|
||||
exists(PrefixDecrExpr c, Expr e | c = err and outermostConvWithLocation(c.getOperand(), e)
|
||||
and not diffBeginBegin(c, e, 2))
|
||||
or
|
||||
exists(PointerDereferenceExpr c, Expr e | c = err and outermostConvWithLocation(c.getChild(0), e)
|
||||
and not diffBeginBegin(c, e, 1))
|
||||
or
|
||||
exists(PostfixIncrExpr c, Expr e | c = err and outermostConvWithLocation(c.getOperand(), e)
|
||||
and not diffEndEnd(e, c, 2))
|
||||
or
|
||||
exists(PostfixDecrExpr c, Expr e | c = err and outermostConvWithLocation(c.getOperand(), e)
|
||||
and not diffEndEnd(e, c, 2))
|
||||
exists(Call c, Expr e |
|
||||
c = err and
|
||||
outermostConvWithLocation(c.getQualifier(), e) and
|
||||
e.getType() instanceof PointerType and
|
||||
not diffEndBegin(e, c, 3)
|
||||
)
|
||||
or
|
||||
exists(Call c, Expr e |
|
||||
c = err and
|
||||
outermostConvWithLocation(c.getQualifier(), e) and
|
||||
not e.getType() instanceof PointerType and
|
||||
not diffEndBegin(e, c, 2)
|
||||
)
|
||||
or
|
||||
exists(VariableAccess c, Expr e |
|
||||
c = err and
|
||||
outermostConvWithLocation(c.getQualifier(), e) and
|
||||
e.getType() instanceof PointerType and
|
||||
not diffEndBegin(e, c, 3)
|
||||
)
|
||||
or
|
||||
exists(VariableAccess c, Expr e |
|
||||
c = err and
|
||||
outermostConvWithLocation(c.getQualifier(), e) and
|
||||
not e.getType() instanceof PointerType and
|
||||
not diffEndBegin(e, c, 2)
|
||||
)
|
||||
or
|
||||
exists(UnaryOperation c, Expr e |
|
||||
c = err and
|
||||
outermostConvWithLocation(c.getOperand(), e) and
|
||||
(
|
||||
c instanceof ComplementExpr or
|
||||
c instanceof NotExpr or
|
||||
c instanceof UnaryMinusExpr or
|
||||
c instanceof UnaryPlusExpr or
|
||||
c instanceof AddressOfExpr
|
||||
) and
|
||||
not diffBeginBegin(c, e, 1)
|
||||
)
|
||||
or
|
||||
exists(PrefixIncrExpr c, Expr e |
|
||||
c = err and
|
||||
outermostConvWithLocation(c.getOperand(), e) and
|
||||
not diffBeginBegin(c, e, 2)
|
||||
)
|
||||
or
|
||||
exists(PrefixDecrExpr c, Expr e |
|
||||
c = err and
|
||||
outermostConvWithLocation(c.getOperand(), e) and
|
||||
not diffBeginBegin(c, e, 2)
|
||||
)
|
||||
or
|
||||
exists(PointerDereferenceExpr c, Expr e |
|
||||
c = err and
|
||||
outermostConvWithLocation(c.getChild(0), e) and
|
||||
not diffBeginBegin(c, e, 1)
|
||||
)
|
||||
or
|
||||
exists(PostfixIncrExpr c, Expr e |
|
||||
c = err and
|
||||
outermostConvWithLocation(c.getOperand(), e) and
|
||||
not diffEndEnd(e, c, 2)
|
||||
)
|
||||
or
|
||||
exists(PostfixDecrExpr c, Expr e |
|
||||
c = err and
|
||||
outermostConvWithLocation(c.getOperand(), e) and
|
||||
not diffEndEnd(e, c, 2)
|
||||
)
|
||||
)
|
||||
select err, "AV Rule 63: Spaces will not be used around '.' or '->', nor between unary operators and operands."
|
||||
select err,
|
||||
"AV Rule 63: Spaces will not be used around '.' or '->', nor between unary operators and operands."
|
||||
|
||||
@@ -1,45 +1,44 @@
|
||||
/*
|
||||
Common functions for implementing naming conventions
|
||||
|
||||
Naming rules are the following:
|
||||
|
||||
[45] All words in an ident will be separated by '_'
|
||||
[46] Idents will not rely on significance of more than 64 characters
|
||||
[47] Idents will not begin with '_'
|
||||
[48] Idents will not differ in certain confusing ways (listed)
|
||||
[49] All acronyms in an ident will be uppercase
|
||||
[50] Classes, namespaces, enums, structs, typedefs:
|
||||
begin first word with uppercase, all other lowercase
|
||||
[51] Functions and variables:
|
||||
lowercase
|
||||
[52] Constants and enum values:
|
||||
lowercase
|
||||
|
||||
The tricky rules are: 45, 49, 50, 51, 52. There are two reasons:
|
||||
|
||||
- Reference to 'words'. We ignore this (beyond the scope). For 45,
|
||||
detect camel-case and any other bad conventions. For 50 this just
|
||||
means the first letter should be uppercase.
|
||||
- Acronyms. [49] has a comment that it applies to *all* identifiers,
|
||||
even if some other rule specified that they should be lowercase or
|
||||
differently capitalized.
|
||||
|
||||
The strategy is as follows:
|
||||
- apart from 45, 'words' are just _-separated parts of the identifier
|
||||
- apart from 49, always allow a 'word' to be entirely in uppercase (URL),
|
||||
but make sure that the whole identifier is not in uppercase.
|
||||
- 49: check common acronyms and allow extensibility to check that they are
|
||||
uppercase.
|
||||
*/
|
||||
* Common functions for implementing naming conventions
|
||||
*
|
||||
* Naming rules are the following:
|
||||
*
|
||||
* [45] All words in an ident will be separated by '_'
|
||||
* [46] Idents will not rely on significance of more than 64 characters
|
||||
* [47] Idents will not begin with '_'
|
||||
* [48] Idents will not differ in certain confusing ways (listed)
|
||||
* [49] All acronyms in an ident will be uppercase
|
||||
* [50] Classes, namespaces, enums, structs, typedefs:
|
||||
* begin first word with uppercase, all other lowercase
|
||||
* [51] Functions and variables:
|
||||
* lowercase
|
||||
* [52] Constants and enum values:
|
||||
* lowercase
|
||||
*
|
||||
* The tricky rules are: 45, 49, 50, 51, 52. There are two reasons:
|
||||
*
|
||||
* - Reference to 'words'. We ignore this (beyond the scope). For 45,
|
||||
* detect camel-case and any other bad conventions. For 50 this just
|
||||
* means the first letter should be uppercase.
|
||||
* - Acronyms. [49] has a comment that it applies to *all* identifiers,
|
||||
* even if some other rule specified that they should be lowercase or
|
||||
* differently capitalized.
|
||||
*
|
||||
* The strategy is as follows:
|
||||
* - apart from 45, 'words' are just _-separated parts of the identifier
|
||||
* - apart from 49, always allow a 'word' to be entirely in uppercase (URL),
|
||||
* but make sure that the whole identifier is not in uppercase.
|
||||
* - 49: check common acronyms and allow extensibility to check that they are
|
||||
* uppercase.
|
||||
*/
|
||||
|
||||
import cpp
|
||||
|
||||
/** The name of an identifier, for the purpose of JSF naming conventions */
|
||||
class Name extends string {
|
||||
|
||||
Name() {
|
||||
exists(Declaration d | this = d.getName() )
|
||||
or exists(Namespace n | this = n.getName() )
|
||||
exists(Declaration d | this = d.getName()) or
|
||||
exists(Namespace n | this = n.getName())
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -52,20 +51,18 @@ class Name extends string {
|
||||
* just portions separated by underscores.
|
||||
*/
|
||||
Word getWord(int index) { result = this.splitAt("_", index) }
|
||||
|
||||
}
|
||||
|
||||
/** A (nonempty) word in an identifier, for JSF naming conventions */
|
||||
class Word extends string {
|
||||
|
||||
Word() { exists(Name n | this = n.splitAt("_") and this != "") }
|
||||
|
||||
/**
|
||||
* Gets the 0-based position of this word in the identifier.
|
||||
*/
|
||||
int getIndex() { exists (Name n | this = n.getWord(result)) }
|
||||
int getIndex() { exists(Name n | this = n.getWord(result)) }
|
||||
|
||||
/**
|
||||
/**
|
||||
* Holds if this word is capitalized (for example 'Word', not 'word'
|
||||
* or 'WORD').
|
||||
*/
|
||||
@@ -98,10 +95,9 @@ class Word extends string {
|
||||
// Don't look at case
|
||||
exists(string s | s = this.toLowerCase() |
|
||||
// A few standard acronyms
|
||||
s = "url"
|
||||
or s = "http"
|
||||
or s = "html"
|
||||
|
||||
s = "url" or
|
||||
s = "http" or
|
||||
s = "html"
|
||||
// //
|
||||
// // CUSTOMIZATION:
|
||||
// // ANY ACRONYMS TO ENFORCE IN A PROJECT CAN BE ADDED HERE
|
||||
@@ -109,5 +105,4 @@ class Word extends string {
|
||||
// eg. 'or s = "myacronym"'
|
||||
)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
* @tags correctness
|
||||
* external/jsf
|
||||
*/
|
||||
|
||||
import cpp
|
||||
|
||||
/*
|
||||
@@ -29,27 +30,24 @@ import cpp
|
||||
*/
|
||||
|
||||
predicate definesDefaultConstructor(Class c) {
|
||||
exists(Constructor constr |
|
||||
constr.getDeclaringType() = c and constr.isDefault())
|
||||
or definesDefaultConstructor(c.getABaseClass())
|
||||
exists(Constructor constr | constr.getDeclaringType() = c and constr.isDefault())
|
||||
or
|
||||
definesDefaultConstructor(c.getABaseClass())
|
||||
}
|
||||
|
||||
predicate definesCopyConstructor(Class c) {
|
||||
exists(CopyConstructor constr |
|
||||
constr.getDeclaringType() = c)
|
||||
or definesCopyConstructor(c.getABaseClass())
|
||||
exists(CopyConstructor constr | constr.getDeclaringType() = c) or
|
||||
definesCopyConstructor(c.getABaseClass())
|
||||
}
|
||||
|
||||
predicate definesCopyAssignmentOperator(Class c) {
|
||||
exists(CopyAssignmentOperator op |
|
||||
op.getDeclaringType() = c)
|
||||
or definesCopyAssignmentOperator(c.getABaseClass())
|
||||
exists(CopyAssignmentOperator op | op.getDeclaringType() = c) or
|
||||
definesCopyAssignmentOperator(c.getABaseClass())
|
||||
}
|
||||
|
||||
predicate definesDestructor(Class c) {
|
||||
exists(Destructor op |
|
||||
op.getDeclaringType() = c)
|
||||
or definesDestructor(c.getABaseClass())
|
||||
exists(Destructor op | op.getDeclaringType() = c) or
|
||||
definesDestructor(c.getABaseClass())
|
||||
}
|
||||
|
||||
class ProperClass extends Class {
|
||||
@@ -61,9 +59,23 @@ class ProperClass extends Class {
|
||||
* and (c) it will be generated (ie for default constructors, if there is any constructor at all then default
|
||||
* constructors will not be generated)
|
||||
*/
|
||||
|
||||
from ProperClass c, string msg
|
||||
where (not definesDefaultConstructor(c) and not c.hasConstructor() and msg="AV Rule 68: class " + c.getName() + " does not need a default constructor and should explicitly disallow it.") or
|
||||
(not definesCopyConstructor(c) and msg="AV Rule 68: class " + c.getName() + " does not need a copy constructor and should explicitly disallow it.") or
|
||||
(not definesCopyAssignmentOperator(c) and msg="AV Rule 68: class " + c.getName() + " does not need a copy assignment operator and should explicitly disallow it.") or
|
||||
(not definesDestructor(c) and msg="AV Rule 68: class " + c.getName() + " does not need a destructor and should explicitly disallow it.")
|
||||
select c, msg
|
||||
where
|
||||
not definesDefaultConstructor(c) and
|
||||
not c.hasConstructor() and
|
||||
msg = "AV Rule 68: class " + c.getName() +
|
||||
" does not need a default constructor and should explicitly disallow it."
|
||||
or
|
||||
not definesCopyConstructor(c) and
|
||||
msg = "AV Rule 68: class " + c.getName() +
|
||||
" does not need a copy constructor and should explicitly disallow it."
|
||||
or
|
||||
not definesCopyAssignmentOperator(c) and
|
||||
msg = "AV Rule 68: class " + c.getName() +
|
||||
" does not need a copy assignment operator and should explicitly disallow it."
|
||||
or
|
||||
not definesDestructor(c) and
|
||||
msg = "AV Rule 68: class " + c.getName() +
|
||||
" does not need a destructor and should explicitly disallow it."
|
||||
select c, msg
|
||||
|
||||
@@ -8,16 +8,23 @@
|
||||
* @tags maintainability
|
||||
* external/jsf
|
||||
*/
|
||||
|
||||
import cpp
|
||||
|
||||
from MemberFunction mf
|
||||
where mf.fromSource() and
|
||||
mf.hasDefinition() and
|
||||
not mf instanceof Constructor and
|
||||
not exists(VariableAccess va | va.isLValue() and
|
||||
va.getEnclosingFunction() = mf and
|
||||
(va.getTarget() instanceof MemberVariable
|
||||
or va.getTarget() instanceof GlobalVariable)) and
|
||||
forall(Call c | c.getEnclosingFunction() = mf | c.isPure()) and
|
||||
not mf.hasSpecifier("const")
|
||||
select mf, "AV Rule 69: A member function that does not affect the state of an object will be declared const."
|
||||
where
|
||||
mf.fromSource() and
|
||||
mf.hasDefinition() and
|
||||
not mf instanceof Constructor and
|
||||
not exists(VariableAccess va |
|
||||
va.isLValue() and
|
||||
va.getEnclosingFunction() = mf and
|
||||
(
|
||||
va.getTarget() instanceof MemberVariable or
|
||||
va.getTarget() instanceof GlobalVariable
|
||||
)
|
||||
) and
|
||||
forall(Call c | c.getEnclosingFunction() = mf | c.isPure()) and
|
||||
not mf.hasSpecifier("const")
|
||||
select mf,
|
||||
"AV Rule 69: A member function that does not affect the state of an object will be declared const."
|
||||
|
||||
@@ -9,18 +9,23 @@
|
||||
* @tags maintainability
|
||||
* external/jsf
|
||||
*/
|
||||
|
||||
import cpp
|
||||
|
||||
// whether b is the same as a, or b is "const a&"
|
||||
predicate isTypeOrConstRef(Type a, Type b) {
|
||||
a=b
|
||||
or exists(ReferenceType r, SpecifiedType s | b=r and s=r.getBaseType() and s.hasSpecifier("const") and a=s.getUnspecifiedType())
|
||||
a = b
|
||||
or
|
||||
exists(ReferenceType r, SpecifiedType s |
|
||||
b = r and s = r.getBaseType() and s.hasSpecifier("const") and a = s.getUnspecifiedType()
|
||||
)
|
||||
}
|
||||
|
||||
// whether the first parameter of f may be subject to implicit conversions
|
||||
predicate implicitConvOnFirstParm(Function f) {
|
||||
exists(ImplicitConversionFunction conv |
|
||||
isTypeOrConstRef(conv.getDestType(), f.getParameter(0).getUnderlyingType()))
|
||||
isTypeOrConstRef(conv.getDestType(), f.getParameter(0).getUnderlyingType())
|
||||
)
|
||||
}
|
||||
|
||||
// whether f is declared as a friend by all its parameter types
|
||||
@@ -29,10 +34,14 @@ predicate multiFriend(Function f) {
|
||||
forall(Parameter p | p = f.getAParameter() |
|
||||
exists(FriendDecl fd |
|
||||
fd.getFriend() = f and
|
||||
p.getType().refersTo(fd.getDeclaringClass())))
|
||||
p.getType().refersTo(fd.getDeclaringClass())
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
from FriendDecl fd
|
||||
where not implicitConvOnFirstParm(fd.getFriend()) and
|
||||
not multiFriend(fd.getFriend())
|
||||
select fd, "AV Rule 70: Friend declarations will only be used if the friend is unable to be a member of the class for logical or efficiency reasons."
|
||||
where
|
||||
not implicitConvOnFirstParm(fd.getFriend()) and
|
||||
not multiFriend(fd.getFriend())
|
||||
select fd,
|
||||
"AV Rule 70: Friend declarations will only be used if the friend is unable to be a member of the class for logical or efficiency reasons."
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
* language-features
|
||||
* external/jsf
|
||||
*/
|
||||
|
||||
import cpp
|
||||
|
||||
predicate thisCall(FunctionCall c) {
|
||||
@@ -30,44 +31,62 @@ predicate virtualThisCall(FunctionCall c, Function overridingFunction) {
|
||||
|
||||
predicate nonVirtualMember(MemberFunction mf, Class c) {
|
||||
mf = c.getAMemberFunction() and
|
||||
not (mf instanceof Constructor) and not (mf instanceof Destructor) and
|
||||
not mf instanceof Constructor and
|
||||
not mf instanceof Destructor and
|
||||
not mf.isVirtual()
|
||||
}
|
||||
|
||||
predicate callFromNonVirtual(MemberFunction source, Class c, MemberFunction targ) {
|
||||
exists (FunctionCall fc | fc.getEnclosingFunction() = source and fc.getTarget() = targ and thisCall(fc)) and
|
||||
exists(FunctionCall fc |
|
||||
fc.getEnclosingFunction() = source and fc.getTarget() = targ and thisCall(fc)
|
||||
) and
|
||||
targ = c.getAMemberFunction() and
|
||||
nonVirtualMember(source, c)
|
||||
}
|
||||
|
||||
pragma[noopt]
|
||||
predicate indirectlyCallsVirtualFunction(MemberFunction caller, Function target, Class c) {
|
||||
exists (FunctionCall fc |
|
||||
virtualThisCall(fc,_) and
|
||||
exists(FunctionCall fc |
|
||||
virtualThisCall(fc, _) and
|
||||
fc.getEnclosingFunction() = caller and
|
||||
fc.getTarget() = target and
|
||||
nonVirtualMember(caller, c)
|
||||
) or
|
||||
exists (MemberFunction mid |
|
||||
)
|
||||
or
|
||||
exists(MemberFunction mid |
|
||||
indirectlyCallsVirtualFunction(mid, target, c) and
|
||||
callFromNonVirtual(caller, c, mid)
|
||||
)
|
||||
}
|
||||
|
||||
from FunctionCall call, string explanation, Function virtFunction, Function overridingFunction
|
||||
where (call.getEnclosingFunction() instanceof Constructor or call.getEnclosingFunction() instanceof Destructor) and
|
||||
(
|
||||
(virtualThisCall(call, overridingFunction) and explanation = "Call to virtual function $@ which is overridden in $@. If you intend to statically call this virtual function, it should be qualified with " + virtFunction.getDeclaringType().toString() + "::.")
|
||||
and virtFunction = call.getTarget()
|
||||
and overridingFunction.getDeclaringType().getABaseClass+() = call.getEnclosingFunction().getDeclaringType()
|
||||
or
|
||||
exists(VirtualFunction target | thisCall(call) and indirectlyCallsVirtualFunction(call.getTarget(), target, _) |
|
||||
explanation = "Call to function " + call.getTarget().getName() + " that calls virtual function $@ (overridden in $@)."
|
||||
and virtFunction = target
|
||||
and overridingFunction = target.getAnOverridingFunction()
|
||||
and overridingFunction.getDeclaringType().getABaseClass+() = call.getEnclosingFunction().getDeclaringType()
|
||||
)
|
||||
)
|
||||
select call, explanation,
|
||||
virtFunction, virtFunction.getName(),
|
||||
overridingFunction, overridingFunction.getDeclaringType().getName()
|
||||
where
|
||||
(
|
||||
call.getEnclosingFunction() instanceof Constructor or
|
||||
call.getEnclosingFunction() instanceof Destructor
|
||||
) and
|
||||
(
|
||||
(
|
||||
virtualThisCall(call, overridingFunction) and
|
||||
explanation = "Call to virtual function $@ which is overridden in $@. If you intend to statically call this virtual function, it should be qualified with "
|
||||
+ virtFunction.getDeclaringType().toString() + "::."
|
||||
) and
|
||||
virtFunction = call.getTarget() and
|
||||
overridingFunction.getDeclaringType().getABaseClass+() = call
|
||||
.getEnclosingFunction()
|
||||
.getDeclaringType()
|
||||
or
|
||||
exists(VirtualFunction target |
|
||||
thisCall(call) and indirectlyCallsVirtualFunction(call.getTarget(), target, _)
|
||||
|
|
||||
explanation = "Call to function " + call.getTarget().getName() +
|
||||
" that calls virtual function $@ (overridden in $@)." and
|
||||
virtFunction = target and
|
||||
overridingFunction = target.getAnOverridingFunction() and
|
||||
overridingFunction.getDeclaringType().getABaseClass+() = call
|
||||
.getEnclosingFunction()
|
||||
.getDeclaringType()
|
||||
)
|
||||
)
|
||||
select call, explanation, virtFunction, virtFunction.getName(), overridingFunction,
|
||||
overridingFunction.getDeclaringType().getName()
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
* @tags correctness
|
||||
* external/jsf
|
||||
*/
|
||||
|
||||
import cpp
|
||||
|
||||
/*
|
||||
@@ -32,13 +33,16 @@ predicate memberDirectlyNeedsVariable(MemberFunction mf, Class c, MemberVariable
|
||||
(mf.isPublic() or mf.isProtected()) and
|
||||
c = mf.getDeclaringType() and
|
||||
c = mv.getDeclaringType() and
|
||||
exists(VariableAccess va | va = mv.getAnAccess() and
|
||||
not exists(Assignment a | va = a.getLValue()) and
|
||||
va.getEnclosingFunction() = mf)
|
||||
exists(VariableAccess va |
|
||||
va = mv.getAnAccess() and
|
||||
not exists(Assignment a | va = a.getLValue()) and
|
||||
va.getEnclosingFunction() = mf
|
||||
)
|
||||
}
|
||||
|
||||
predicate memberNeedsVariable(MemberFunction mf, Class c, MemberVariable mv) {
|
||||
memberDirectlyNeedsVariable(mf, c, mv) or
|
||||
memberDirectlyNeedsVariable(mf, c, mv)
|
||||
or
|
||||
exists(MemberFunction mf2 |
|
||||
memberNeedsVariable(mf2, c, mv) and
|
||||
mf.getDeclaringType() = c and
|
||||
@@ -59,7 +63,8 @@ predicate memberDirectlyInitialisesVariable(MemberFunction mf, Class c, MemberVa
|
||||
}
|
||||
|
||||
predicate memberInitialisesVariable(MemberFunction mf, Class c, MemberVariable mv) {
|
||||
memberDirectlyInitialisesVariable(mf, c, mv) or
|
||||
memberDirectlyInitialisesVariable(mf, c, mv)
|
||||
or
|
||||
exists(MemberFunction mf2 |
|
||||
memberDirectlyInitialisesVariable(_, c, mv) and // (optimizer hint)
|
||||
memberInitialisesVariable(mf2, c, mv) and
|
||||
@@ -80,14 +85,14 @@ predicate preInitialises(Constructor c, MemberVariable mv) {
|
||||
predicate exprInitialises(Constructor c, ControlFlowNode cf, MemberVariable mv) {
|
||||
cf.getControlFlowScope() = c and
|
||||
(
|
||||
cf.(Assignment).getLValue() = mv.getAnAccess()
|
||||
or memberInitialisesVariable(cf.(FunctionCall).getTarget(), c.getDeclaringType(), mv)
|
||||
cf.(Assignment).getLValue() = mv.getAnAccess() or
|
||||
memberInitialisesVariable(cf.(FunctionCall).getTarget(), c.getDeclaringType(), mv)
|
||||
)
|
||||
}
|
||||
|
||||
predicate initialises(Constructor c, MemberVariable mv) {
|
||||
exprInitialises(c, _, mv)
|
||||
or preInitialises(c, mv)
|
||||
exprInitialises(c, _, mv) or
|
||||
preInitialises(c, mv)
|
||||
}
|
||||
|
||||
predicate doesNotInitialise(Constructor c, MemberVariable mv) {
|
||||
@@ -102,14 +107,14 @@ predicate doesNotInitialise(Constructor c, MemberVariable mv) {
|
||||
*/
|
||||
|
||||
predicate reachableWithoutInitialising(Constructor c, ControlFlowNode cf, MemberVariable mv) {
|
||||
not (preInitialises(c, mv))
|
||||
and
|
||||
not preInitialises(c, mv) and
|
||||
(
|
||||
cf = c.getBlock() or
|
||||
cf = c.getBlock()
|
||||
or
|
||||
exists(ControlFlowNode mid |
|
||||
reachableWithoutInitialising(c, mid, mv) and
|
||||
cf = mid.getASuccessor() and
|
||||
not exprInitialises(c, cf, mv)
|
||||
reachableWithoutInitialising(c, mid, mv) and
|
||||
cf = mid.getASuccessor() and
|
||||
not exprInitialises(c, cf, mv)
|
||||
)
|
||||
)
|
||||
}
|
||||
@@ -124,6 +129,10 @@ predicate badCall(Constructor c, FunctionCall call, MemberVariable mv) {
|
||||
*/
|
||||
|
||||
from Element e, MemberVariable mv, string message
|
||||
where (doesNotInitialise(e, mv) and message = "Constructor does not initialize member variable " + mv.getName() + ".") or
|
||||
(badCall(_, e, mv) and message = "Constructor calls function using " + mv.getName() + " before it is initialized.")
|
||||
select e, "AV Rule 71: " + message
|
||||
where
|
||||
doesNotInitialise(e, mv) and
|
||||
message = "Constructor does not initialize member variable " + mv.getName() + "."
|
||||
or
|
||||
badCall(_, e, mv) and
|
||||
message = "Constructor calls function using " + mv.getName() + " before it is initialized."
|
||||
select e, "AV Rule 71: " + message
|
||||
|
||||
@@ -8,31 +8,43 @@
|
||||
* @tags maintainability
|
||||
* external/jsf
|
||||
*/
|
||||
|
||||
import cpp
|
||||
|
||||
/* bug finding approach: look for no-argument constructors that set a certain field x,
|
||||
/*
|
||||
* bug finding approach: look for no-argument constructors that set a certain field x,
|
||||
* such that every member function reading x also contains a comparison involving x as
|
||||
* part of an if statement; the host class should not be used in an array type or as
|
||||
* part of an array new, it should not be used in a template instantiation, and it should
|
||||
* not be a virtual base class */
|
||||
* not be a virtual base class
|
||||
*/
|
||||
|
||||
from Constructor c, MemberVariable f
|
||||
where c.fromSource() and
|
||||
c.isDefault() and
|
||||
not c.isCompilerGenerated() and
|
||||
f = c.getAWrittenVariable() and
|
||||
forall(MemberFunction m, VariableAccess va |
|
||||
va = f.getAnAccess() and
|
||||
m = va.getEnclosingFunction() and
|
||||
not m instanceof Constructor and
|
||||
not va.getEnclosingStmt() instanceof IfStmt |
|
||||
exists(VariableAccess va2 | va2 = f.getAnAccess() and m = va2.getEnclosingFunction() |
|
||||
va != va2 and
|
||||
va2.getEnclosingStmt() instanceof IfStmt)) and
|
||||
not (exists(ArrayType at | at.getBaseType+() = c.getDeclaringType())
|
||||
or
|
||||
exists(NewArrayExpr nae | nae.getType().(ArrayType).getBaseType+() = c.getDeclaringType())
|
||||
or
|
||||
exists(ClassDerivation cd | cd.hasSpecifier("virtual") and cd.getBaseClass() = c.getDeclaringType()))
|
||||
select c, "This default constructor possibly doesn't put the object in a usable state, indicated by the member variable $@.",
|
||||
where
|
||||
c.fromSource() and
|
||||
c.isDefault() and
|
||||
not c.isCompilerGenerated() and
|
||||
f = c.getAWrittenVariable() and
|
||||
forall(MemberFunction m, VariableAccess va |
|
||||
va = f.getAnAccess() and
|
||||
m = va.getEnclosingFunction() and
|
||||
not m instanceof Constructor and
|
||||
not va.getEnclosingStmt() instanceof IfStmt
|
||||
|
|
||||
exists(VariableAccess va2 | va2 = f.getAnAccess() and m = va2.getEnclosingFunction() |
|
||||
va != va2 and
|
||||
va2.getEnclosingStmt() instanceof IfStmt
|
||||
)
|
||||
) and
|
||||
not (
|
||||
exists(ArrayType at | at.getBaseType+() = c.getDeclaringType())
|
||||
or
|
||||
exists(NewArrayExpr nae | nae.getType().(ArrayType).getBaseType+() = c.getDeclaringType())
|
||||
or
|
||||
exists(ClassDerivation cd |
|
||||
cd.hasSpecifier("virtual") and cd.getBaseClass() = c.getDeclaringType()
|
||||
)
|
||||
)
|
||||
select c,
|
||||
"This default constructor possibly doesn't put the object in a usable state, indicated by the member variable $@.",
|
||||
f, f.toString()
|
||||
|
||||
@@ -9,13 +9,16 @@
|
||||
* @tags correctness
|
||||
* external/jsf
|
||||
*/
|
||||
|
||||
import cpp
|
||||
|
||||
// find assignment to non-static member variable in constructor, where that variable is
|
||||
// not also initialised through the member initialisation list
|
||||
from Assignment ass, Field mv, Constructor ctor
|
||||
where ass.getEnclosingFunction() = ctor and
|
||||
mv.getDeclaringType() = ctor.getDeclaringType() and
|
||||
ass.getLValue().(Access).getTarget() = mv and
|
||||
not exists(ConstructorFieldInit cfi | cfi = ctor.getAnInitializer() | cfi.getTarget() = mv)
|
||||
select ass, "AV Rule 74: Nonstatic members will be initialized through the member initialization list, not through assignment."
|
||||
where
|
||||
ass.getEnclosingFunction() = ctor and
|
||||
mv.getDeclaringType() = ctor.getDeclaringType() and
|
||||
ass.getLValue().(Access).getTarget() = mv and
|
||||
not exists(ConstructorFieldInit cfi | cfi = ctor.getAnInitializer() | cfi.getTarget() = mv)
|
||||
select ass,
|
||||
"AV Rule 74: Nonstatic members will be initialized through the member initialization list, not through assignment."
|
||||
|
||||
@@ -8,8 +8,10 @@
|
||||
* readability
|
||||
* external/jsf
|
||||
*/
|
||||
|
||||
import cpp
|
||||
|
||||
from Diagnostic d
|
||||
where d.hasTag("out_of_order_ctor_init")
|
||||
select d, "AV Rule 75: Members of the initialization list shall be listed in the order in which they are declared in the class."
|
||||
select d,
|
||||
"AV Rule 75: Members of the initialization list shall be listed in the order in which they are declared in the class."
|
||||
|
||||
@@ -7,35 +7,41 @@
|
||||
* @tags maintainability
|
||||
* external/jsf
|
||||
*/
|
||||
|
||||
import cpp
|
||||
|
||||
predicate hasPointerMember(Class c) {
|
||||
// Note: any function pointers are fine
|
||||
exists (MemberVariable v, Type t |
|
||||
exists(MemberVariable v, Type t |
|
||||
v.getDeclaringType() = c and
|
||||
t = v.getType().getUnderlyingType() and
|
||||
(t instanceof PointerType or t instanceof PointerToMemberType) and
|
||||
not (t instanceof FunctionPointerType) and
|
||||
not t instanceof FunctionPointerType and
|
||||
not t.(PointerToMemberType).getBaseType() instanceof RoutineType
|
||||
)
|
||||
}
|
||||
|
||||
class TrivialStmt extends Stmt {
|
||||
TrivialStmt() {
|
||||
this instanceof EmptyStmt
|
||||
or this instanceof ReturnStmt and not this.(ReturnStmt).hasExpr()
|
||||
}
|
||||
TrivialStmt() {
|
||||
this instanceof EmptyStmt
|
||||
or
|
||||
this instanceof ReturnStmt and not this.(ReturnStmt).hasExpr()
|
||||
}
|
||||
}
|
||||
|
||||
// What is a nontrivial destructor? JSF is unclear about that. We'll just
|
||||
// take any nonempty destructor as nontrivial. Exclude the generated 'return' stmt
|
||||
predicate hasNontrivialDestructor(Class c) {
|
||||
exists (Stmt s | s = c.getDestructor().getBlock().getAStmt() | not s instanceof TrivialStmt)
|
||||
exists(Stmt s | s = c.getDestructor().getBlock().getAStmt() | not s instanceof TrivialStmt)
|
||||
}
|
||||
|
||||
from Class c
|
||||
where (hasPointerMember(c) or hasNontrivialDestructor(c)) and
|
||||
not (c.getAMemberFunction() instanceof CopyConstructor and
|
||||
c.getAMemberFunction() instanceof CopyAssignmentOperator) and
|
||||
not (c instanceof Struct)
|
||||
select c, "AV Rule 76: A copy constructor and an assignment operator shall be declared for classes that contain pointers to data items or nontrivial destructors."
|
||||
where
|
||||
(hasPointerMember(c) or hasNontrivialDestructor(c)) and
|
||||
not (
|
||||
c.getAMemberFunction() instanceof CopyConstructor and
|
||||
c.getAMemberFunction() instanceof CopyAssignmentOperator
|
||||
) and
|
||||
not c instanceof Struct
|
||||
select c,
|
||||
"AV Rule 76: A copy constructor and an assignment operator shall be declared for classes that contain pointers to data items or nontrivial destructors."
|
||||
|
||||
@@ -10,9 +10,13 @@
|
||||
* language-features
|
||||
* external/jsf
|
||||
*/
|
||||
|
||||
import cpp
|
||||
|
||||
from CopyConstructor f
|
||||
where f.getNumberOfParameters() > 1
|
||||
and not f.mayNotBeCopyConstructorInInstantiation()
|
||||
select f, f.getName() + " is signature-compatible with a copy constructor when its default arguments are taken into account."
|
||||
where
|
||||
f.getNumberOfParameters() > 1 and
|
||||
not f.mayNotBeCopyConstructorInInstantiation()
|
||||
select f,
|
||||
f.getName() +
|
||||
" is signature-compatible with a copy constructor when its default arguments are taken into account."
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
* language-features
|
||||
* external/jsf
|
||||
*/
|
||||
|
||||
import cpp
|
||||
|
||||
/*
|
||||
@@ -17,10 +18,13 @@ import cpp
|
||||
*/
|
||||
|
||||
from Class c
|
||||
where exists(VirtualFunction f | f.getDeclaringType() = c)
|
||||
and exists(Destructor d | d.getDeclaringType() = c and
|
||||
not d.isVirtual() and
|
||||
not d.isDeleted() and
|
||||
not d.isCompilerGenerated())
|
||||
and exists(ClassDerivation d | d.getBaseClass() = c)
|
||||
where
|
||||
exists(VirtualFunction f | f.getDeclaringType() = c) and
|
||||
exists(Destructor d |
|
||||
d.getDeclaringType() = c and
|
||||
not d.isVirtual() and
|
||||
not d.isDeleted() and
|
||||
not d.isCompilerGenerated()
|
||||
) and
|
||||
exists(ClassDerivation d | d.getBaseClass() = c)
|
||||
select c, "Base classes with a virtual function must define a virtual destructor."
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
* external/cwe/cwe-404
|
||||
* external/jsf
|
||||
*/
|
||||
|
||||
import cpp
|
||||
import Critical.NewDelete
|
||||
|
||||
@@ -21,22 +22,20 @@ predicate acquireExpr(Expr acquire, string kind) {
|
||||
exists(FunctionCall fc, Function f, string name |
|
||||
fc = acquire and
|
||||
f = fc.getTarget() and
|
||||
f.hasGlobalName(name) and
|
||||
f.hasGlobalName(name) and
|
||||
(
|
||||
(
|
||||
name = "fopen" and
|
||||
kind = "file"
|
||||
) or (
|
||||
name = "open" and
|
||||
kind = "file descriptor"
|
||||
) or (
|
||||
name = "socket" and
|
||||
kind = "file descriptor"
|
||||
)
|
||||
name = "fopen" and
|
||||
kind = "file"
|
||||
or
|
||||
name = "open" and
|
||||
kind = "file descriptor"
|
||||
or
|
||||
name = "socket" and
|
||||
kind = "file descriptor"
|
||||
)
|
||||
) or (
|
||||
allocExpr(acquire, kind)
|
||||
)
|
||||
or
|
||||
allocExpr(acquire, kind)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -47,31 +46,29 @@ predicate releaseExpr(Expr release, Expr resource, string kind) {
|
||||
exists(FunctionCall fc, Function f, string name |
|
||||
fc = release and
|
||||
f = fc.getTarget() and
|
||||
f.hasGlobalName(name) and
|
||||
f.hasGlobalName(name) and
|
||||
(
|
||||
(
|
||||
name = "fclose" and
|
||||
resource = fc.getArgument(0) and
|
||||
kind = "file"
|
||||
) or (
|
||||
name = "close" and
|
||||
resource = fc.getArgument(0) and
|
||||
kind = "file descriptor"
|
||||
)
|
||||
name = "fclose" and
|
||||
resource = fc.getArgument(0) and
|
||||
kind = "file"
|
||||
or
|
||||
name = "close" and
|
||||
resource = fc.getArgument(0) and
|
||||
kind = "file descriptor"
|
||||
)
|
||||
) or exists(string releaseKind |
|
||||
)
|
||||
or
|
||||
exists(string releaseKind |
|
||||
freeExpr(release, resource, releaseKind) and
|
||||
(
|
||||
(
|
||||
kind = "malloc" and
|
||||
releaseKind = "free"
|
||||
) or (
|
||||
kind = "new" and
|
||||
releaseKind = "delete"
|
||||
) or (
|
||||
kind = "new[]" and
|
||||
releaseKind = "delete[]"
|
||||
)
|
||||
kind = "malloc" and
|
||||
releaseKind = "free"
|
||||
or
|
||||
kind = "new" and
|
||||
releaseKind = "delete"
|
||||
or
|
||||
kind = "new[]" and
|
||||
releaseKind = "delete[]"
|
||||
)
|
||||
)
|
||||
}
|
||||
@@ -90,10 +87,10 @@ Expr exprOrDereference(Expr e) {
|
||||
* or via one or more function call(s).
|
||||
*/
|
||||
private predicate exprReleases(Expr e, Expr released, string kind) {
|
||||
(
|
||||
// `e` is a call to a release function and `released` is the released argument
|
||||
releaseExpr(e, released, kind)
|
||||
) or exists(Function f, int arg |
|
||||
// `e` is a call to a release function and `released` is the released argument
|
||||
releaseExpr(e, released, kind)
|
||||
or
|
||||
exists(Function f, int arg |
|
||||
// `e` is a call to a function that releases one of it's parameters,
|
||||
// and `released` is the corresponding argument
|
||||
(
|
||||
@@ -102,7 +99,9 @@ private predicate exprReleases(Expr e, Expr released, string kind) {
|
||||
) and
|
||||
e.(FunctionCall).getArgument(arg) = released and
|
||||
exprReleases(_, exprOrDereference(f.getParameter(arg).getAnAccess()), kind)
|
||||
) or exists(Function f, ThisExpr innerThis |
|
||||
)
|
||||
or
|
||||
exists(Function f, ThisExpr innerThis |
|
||||
// `e` is a call to a method that releases `this`, and `released`
|
||||
// is the object that is called
|
||||
(
|
||||
@@ -116,7 +115,6 @@ private predicate exprReleases(Expr e, Expr released, string kind) {
|
||||
}
|
||||
|
||||
class Resource extends MemberVariable {
|
||||
|
||||
Resource() { not isStatic() }
|
||||
|
||||
// Check that an expr is somewhere in this class - does not have to be a constructor
|
||||
@@ -125,19 +123,18 @@ class Resource extends MemberVariable {
|
||||
}
|
||||
|
||||
private predicate calledFromDestructor(Function f) {
|
||||
(f instanceof Destructor and f.getDeclaringType() = this.getDeclaringType())
|
||||
f instanceof Destructor and f.getDeclaringType() = this.getDeclaringType()
|
||||
or
|
||||
exists(Function mid, FunctionCall fc |
|
||||
calledFromDestructor(mid) and
|
||||
fc.getEnclosingFunction() = mid and
|
||||
fc.getTarget() = f and
|
||||
f.getDeclaringType() = this.getDeclaringType())
|
||||
f.getDeclaringType() = this.getDeclaringType()
|
||||
)
|
||||
}
|
||||
|
||||
predicate inDestructor(Expr e) {
|
||||
exists(Function f | f = e.getEnclosingFunction() |
|
||||
calledFromDestructor(f)
|
||||
)
|
||||
exists(Function f | f = e.getEnclosingFunction() | calledFromDestructor(f))
|
||||
}
|
||||
|
||||
predicate acquisitionWithRequiredKind(Assignment acquireAssign, string kind) {
|
||||
@@ -149,41 +146,38 @@ class Resource extends MemberVariable {
|
||||
acquireExpr(acquireAssign.getRValue(), kind)
|
||||
}
|
||||
|
||||
Expr getAReleaseExpr(string kind) {
|
||||
exprReleases(result, this.getAnAccess(), kind)
|
||||
}
|
||||
Expr getAReleaseExpr(string kind) { exprReleases(result, this.getAnAccess(), kind) }
|
||||
}
|
||||
|
||||
predicate unreleasedResource(Resource r, Expr acquire, File f, int acquireLine) {
|
||||
// Note: there could be several release functions, because there could be
|
||||
// several functions called 'fclose' for example. We want to check that
|
||||
// *none* of these functions are called to release the resource
|
||||
r.acquisitionWithRequiredKind(acquire, _) and
|
||||
not exists(Expr releaseExpr, string kind |
|
||||
r.acquisitionWithRequiredKind(acquire, kind) and
|
||||
releaseExpr = r.getAReleaseExpr(kind) and
|
||||
r.inDestructor(releaseExpr)
|
||||
)
|
||||
and f = acquire.getFile()
|
||||
and acquireLine = acquire.getLocation().getStartLine()
|
||||
|
||||
and not exists(ExprCall exprCall |
|
||||
// expression call (function pointer or lambda) with `r` as an
|
||||
// argument, which could release it.
|
||||
exprCall.getAnArgument() = r.getAnAccess() and
|
||||
r.inDestructor(exprCall)
|
||||
)
|
||||
|
||||
// check that any destructor for this class has a block; if it doesn't,
|
||||
// we must be missing information.
|
||||
and forall(Class c, Destructor d |
|
||||
r.getDeclaringType().isConstructedFrom*(c) and
|
||||
d = c.getAMember() and
|
||||
not d.isCompilerGenerated() and
|
||||
not d.isDefaulted() and
|
||||
not d.isDeleted() |
|
||||
exists(d.getBlock())
|
||||
)
|
||||
// Note: there could be several release functions, because there could be
|
||||
// several functions called 'fclose' for example. We want to check that
|
||||
// *none* of these functions are called to release the resource
|
||||
r.acquisitionWithRequiredKind(acquire, _) and
|
||||
not exists(Expr releaseExpr, string kind |
|
||||
r.acquisitionWithRequiredKind(acquire, kind) and
|
||||
releaseExpr = r.getAReleaseExpr(kind) and
|
||||
r.inDestructor(releaseExpr)
|
||||
) and
|
||||
f = acquire.getFile() and
|
||||
acquireLine = acquire.getLocation().getStartLine() and
|
||||
not exists(ExprCall exprCall |
|
||||
// expression call (function pointer or lambda) with `r` as an
|
||||
// argument, which could release it.
|
||||
exprCall.getAnArgument() = r.getAnAccess() and
|
||||
r.inDestructor(exprCall)
|
||||
) and
|
||||
// check that any destructor for this class has a block; if it doesn't,
|
||||
// we must be missing information.
|
||||
forall(Class c, Destructor d |
|
||||
r.getDeclaringType().isConstructedFrom*(c) and
|
||||
d = c.getAMember() and
|
||||
not d.isCompilerGenerated() and
|
||||
not d.isDefaulted() and
|
||||
not d.isDeleted()
|
||||
|
|
||||
exists(d.getBlock())
|
||||
)
|
||||
}
|
||||
|
||||
predicate freedInSameMethod(Resource r, Expr acquire) {
|
||||
@@ -210,14 +204,18 @@ predicate leakedInSameMethod(Resource r, Expr acquire) {
|
||||
// near to where it's acquired, and might be stored elsewhere.
|
||||
fc.getAnArgument().getAChild*() = r.getAnAccess() and
|
||||
fc.getEnclosingFunction() = f
|
||||
) or exists(Variable v, Expr e |
|
||||
)
|
||||
or
|
||||
exists(Variable v, Expr e |
|
||||
// `r` (or something computed from it) is stored in another variable
|
||||
// near to where it's acquired, and might be released through that
|
||||
// variable.
|
||||
v.getAnAssignedValue() = e and
|
||||
e.getAChild*() = r.getAnAccess() and
|
||||
e.getEnclosingFunction() = f
|
||||
) or exists(FunctionCall fc |
|
||||
)
|
||||
or
|
||||
exists(FunctionCall fc |
|
||||
// `this` (i.e. the class where `r` is acquired) is passed into `r` via a
|
||||
// method, or the constructor. `r` may use this to register itself with
|
||||
// `this` in some way, ensuring it is later deleted.
|
||||
@@ -228,7 +226,9 @@ predicate leakedInSameMethod(Resource r, Expr acquire) {
|
||||
fc = acquire.getAChild*() // e.g. `r = new MyClass(this)`
|
||||
)
|
||||
)
|
||||
) or exists(FunctionAccess fa, string kind |
|
||||
)
|
||||
or
|
||||
exists(FunctionAccess fa, string kind |
|
||||
// the address of a function that releases `r` is taken (and likely
|
||||
// used to release `r` at some point).
|
||||
r.acquisitionWithRequiredKind(acquire, kind) and
|
||||
@@ -237,10 +237,10 @@ predicate leakedInSameMethod(Resource r, Expr acquire) {
|
||||
)
|
||||
}
|
||||
|
||||
pragma[noopt] predicate badRelease(Resource r, Expr acquire, Function functionCallingRelease, int line) {
|
||||
pragma[noopt]
|
||||
predicate badRelease(Resource r, Expr acquire, Function functionCallingRelease, int line) {
|
||||
unreleasedResource(r, acquire, _, _) and
|
||||
exists(Expr releaseExpr, string kind,
|
||||
Location releaseExprLocation, Function acquireFunction |
|
||||
exists(Expr releaseExpr, string kind, Location releaseExprLocation, Function acquireFunction |
|
||||
r.acquisitionWithRequiredKind(acquire, kind) and
|
||||
releaseExpr = r.getAReleaseExpr(kind) and
|
||||
releaseExpr.getEnclosingFunction() = functionCallingRelease and
|
||||
@@ -253,7 +253,9 @@ pragma[noopt] predicate badRelease(Resource r, Expr acquire, Function functionCa
|
||||
}
|
||||
|
||||
Class qtObject() { result.getABaseClass*().hasGlobalName("QObject") }
|
||||
|
||||
PointerType qtObjectReference() { result.getBaseType() = qtObject() }
|
||||
|
||||
Constructor qtParentConstructor() {
|
||||
exists(Parameter p |
|
||||
p.getName() = "parent" and
|
||||
@@ -263,8 +265,7 @@ Constructor qtParentConstructor() {
|
||||
)
|
||||
}
|
||||
|
||||
predicate automaticallyReleased(Assignment acquire)
|
||||
{
|
||||
predicate automaticallyReleased(Assignment acquire) {
|
||||
// sub-types of the Qt type QObject are released by their parent (if they have one)
|
||||
exists(NewExpr alloc |
|
||||
alloc.getAllocatedType() = qtObject() and
|
||||
@@ -274,22 +275,24 @@ predicate automaticallyReleased(Assignment acquire)
|
||||
}
|
||||
|
||||
from Resource r, Expr acquire, File f, string message
|
||||
where unreleasedResource(r, acquire, f, _) and
|
||||
not freedInSameMethod(r, acquire) and
|
||||
not leakedInSameMethod(r, acquire) and
|
||||
(
|
||||
exists(Function releaseFunction, int releaseLine | badRelease(r, acquire, releaseFunction, releaseLine) and
|
||||
message =
|
||||
"Resource " + r.getName() + " is acquired by class " + r.getDeclaringType().getName() +
|
||||
" but not released in the destructor. It is released from " + releaseFunction.getName() + " on line " + releaseLine +
|
||||
where
|
||||
unreleasedResource(r, acquire, f, _) and
|
||||
not freedInSameMethod(r, acquire) and
|
||||
not leakedInSameMethod(r, acquire) and
|
||||
(
|
||||
exists(Function releaseFunction, int releaseLine |
|
||||
badRelease(r, acquire, releaseFunction, releaseLine) and
|
||||
message = "Resource " + r.getName() + " is acquired by class " +
|
||||
r.getDeclaringType().getName() +
|
||||
" but not released in the destructor. It is released from " + releaseFunction.getName() +
|
||||
" on line " + releaseLine +
|
||||
", so this function may need to be called from the destructor."
|
||||
)
|
||||
or
|
||||
(
|
||||
not badRelease(r, _, _, _) and
|
||||
message = "Resource " + r.getName() + " is acquired by class " + r.getDeclaringType().getName() + " but not released anywhere in this class."
|
||||
)
|
||||
) and
|
||||
not automaticallyReleased(acquire) and
|
||||
not r.getDeclaringType() instanceof TemplateClass // template classes may contain insufficient information for this analysis; results from instantiations will usually suffice.
|
||||
)
|
||||
or
|
||||
not badRelease(r, _, _, _) and
|
||||
message = "Resource " + r.getName() + " is acquired by class " + r.getDeclaringType().getName() +
|
||||
" but not released anywhere in this class."
|
||||
) and
|
||||
not automaticallyReleased(acquire) and
|
||||
not r.getDeclaringType() instanceof TemplateClass // template classes may contain insufficient information for this analysis; results from instantiations will usually suffice.
|
||||
select acquire, message
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
* @tags correctness
|
||||
* external/jsf
|
||||
*/
|
||||
|
||||
import cpp
|
||||
|
||||
/*
|
||||
@@ -18,18 +19,21 @@ import cpp
|
||||
* Hopefully correct implementations also pass, but 'cunning' implementations may not.
|
||||
*/
|
||||
|
||||
/** A copy assignment operator taking its parameter by reference.
|
||||
* For our purposes, copy assignment operators taking parameters by
|
||||
* value are likely fine, since the copy already happened
|
||||
*/
|
||||
/**
|
||||
* A copy assignment operator taking its parameter by reference.
|
||||
* For our purposes, copy assignment operators taking parameters by
|
||||
* value are likely fine, since the copy already happened
|
||||
*/
|
||||
class ReferenceCopyAssignmentOperator extends MemberFunction {
|
||||
ReferenceCopyAssignmentOperator() {
|
||||
this.getName() = "operator=" and
|
||||
this.getNumberOfParameters() = 1 and
|
||||
exists (ReferenceType rt |
|
||||
exists(ReferenceType rt |
|
||||
rt = this.getParameter(0).getType() and
|
||||
(rt.getBaseType() = this.getDeclaringType() or
|
||||
rt.getBaseType().(SpecifiedType).getBaseType() = this.getDeclaringType())
|
||||
(
|
||||
rt.getBaseType() = this.getDeclaringType() or
|
||||
rt.getBaseType().(SpecifiedType).getBaseType() = this.getDeclaringType()
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -45,10 +49,11 @@ class ReferenceCopyAssignmentOperator extends MemberFunction {
|
||||
)
|
||||
}
|
||||
|
||||
/** A call to a function called swap. Note: could be a member,
|
||||
* std::swap or a function overloading std::swap (not in std::)
|
||||
* so keep it simple
|
||||
*/
|
||||
/**
|
||||
* A call to a function called swap. Note: could be a member,
|
||||
* std::swap or a function overloading std::swap (not in std::)
|
||||
* so keep it simple
|
||||
*/
|
||||
FunctionCall getASwapCall() {
|
||||
result.getEnclosingFunction() = this and
|
||||
result.getTarget().getName() = "swap"
|
||||
@@ -57,25 +62,28 @@ class ReferenceCopyAssignmentOperator extends MemberFunction {
|
||||
/** A call to delete on a member variable */
|
||||
DeleteExpr getADeleteExpr() {
|
||||
result.getEnclosingFunction() = this and
|
||||
result.getExpr().(VariableAccess).getTarget().(MemberVariable).getDeclaringType() = this.getDeclaringType()
|
||||
result.getExpr().(VariableAccess).getTarget().(MemberVariable).getDeclaringType() = this
|
||||
.getDeclaringType()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/** Test whether a class has a resource that needs management. Value class types are
|
||||
* okay because they get their semantics from their assignment operator. Primitive
|
||||
* types are fine (no management needed). Constant and reference values are okay too
|
||||
* (they can't be changed anyway). All that remains are pointer types.
|
||||
*/
|
||||
/**
|
||||
* Test whether a class has a resource that needs management. Value class types are
|
||||
* okay because they get their semantics from their assignment operator. Primitive
|
||||
* types are fine (no management needed). Constant and reference values are okay too
|
||||
* (they can't be changed anyway). All that remains are pointer types.
|
||||
*/
|
||||
predicate hasResource(Class c) {
|
||||
exists (MemberVariable mv |
|
||||
exists(MemberVariable mv |
|
||||
mv.getDeclaringType() = c and
|
||||
mv.getType() instanceof PointerType)
|
||||
mv.getType() instanceof PointerType
|
||||
)
|
||||
}
|
||||
|
||||
from ReferenceCopyAssignmentOperator op
|
||||
where hasResource(op.getDeclaringType())
|
||||
and not exists(op.getASelfEqualityTest())
|
||||
and not exists(op.getASwapCall())
|
||||
and exists(op.getADeleteExpr())
|
||||
where
|
||||
hasResource(op.getDeclaringType()) and
|
||||
not exists(op.getASelfEqualityTest()) and
|
||||
not exists(op.getASwapCall()) and
|
||||
exists(op.getADeleteExpr())
|
||||
select op, "AV Rule 81: The assignment operator shall handle self-assignment correctly."
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
* language-features
|
||||
* external/jsf
|
||||
*/
|
||||
|
||||
import cpp
|
||||
|
||||
/*
|
||||
@@ -18,35 +19,31 @@ import cpp
|
||||
|
||||
predicate callOnThis(FunctionCall fc) {
|
||||
// `this->f(...)`
|
||||
fc.getQualifier() instanceof ThisExpr or
|
||||
|
||||
fc.getQualifier() instanceof ThisExpr
|
||||
or
|
||||
// `(*this).f(...)`
|
||||
fc.getQualifier().(PointerDereferenceExpr).getChild(0) instanceof ThisExpr
|
||||
}
|
||||
|
||||
predicate pointerThis(Expr e) {
|
||||
e instanceof ThisExpr or
|
||||
|
||||
e instanceof ThisExpr
|
||||
or
|
||||
// `f(...)`
|
||||
// (includes `this = ...`, where `=` is overloaded so a `FunctionCall`)
|
||||
exists(FunctionCall fc | fc = e and callOnThis(fc) |
|
||||
returnsPointerThis(fc.getTarget())
|
||||
) or
|
||||
|
||||
// `this = ...` (where `=` is not overloaded, so an `AssignExpr`)
|
||||
exists(FunctionCall fc | fc = e and callOnThis(fc) | returnsPointerThis(fc.getTarget()))
|
||||
or
|
||||
// `this = ...` (where `=` is not overloaded, so an `AssignExpr`)
|
||||
pointerThis(e.(AssignExpr).getLValue())
|
||||
}
|
||||
|
||||
predicate dereferenceThis(Expr e) {
|
||||
pointerThis(e.(PointerDereferenceExpr).getChild(0)) or
|
||||
|
||||
pointerThis(e.(PointerDereferenceExpr).getChild(0))
|
||||
or
|
||||
// `f(...)`
|
||||
// (includes `*this = ...`, where `=` is overloaded so a `FunctionCall`)
|
||||
exists(FunctionCall fc | fc = e and callOnThis(fc) |
|
||||
returnsDereferenceThis(fc.getTarget())
|
||||
) or
|
||||
|
||||
// `*this = ...` (where `=` is not overloaded, so an `AssignExpr`)
|
||||
exists(FunctionCall fc | fc = e and callOnThis(fc) | returnsDereferenceThis(fc.getTarget()))
|
||||
or
|
||||
// `*this = ...` (where `=` is not overloaded, so an `AssignExpr`)
|
||||
dereferenceThis(e.(AssignExpr).getLValue())
|
||||
}
|
||||
|
||||
@@ -74,25 +71,28 @@ predicate returnsDereferenceThis(Function f) {
|
||||
}
|
||||
|
||||
predicate assignOperatorWithWrongType(Operator op, string msg) {
|
||||
op.hasName("operator=")
|
||||
and exists(op.getBlock())
|
||||
and exists(Class c |
|
||||
c = op.getDeclaringType()
|
||||
and op.getUnspecifiedType() = c
|
||||
and msg = "Assignment operator in class " + c.getName() + " should have return type " + c.getName() + "&. Otherwise a copy is created at each call."
|
||||
op.hasName("operator=") and
|
||||
exists(op.getBlock()) and
|
||||
exists(Class c |
|
||||
c = op.getDeclaringType() and
|
||||
op.getUnspecifiedType() = c and
|
||||
msg = "Assignment operator in class " + c.getName() + " should have return type " + c.getName() +
|
||||
"&. Otherwise a copy is created at each call."
|
||||
)
|
||||
}
|
||||
|
||||
predicate assignOperatorWithWrongResult(Operator op, string msg) {
|
||||
op.hasName("operator=")
|
||||
and not returnsDereferenceThis(op)
|
||||
and exists(op.getBlock())
|
||||
and not op.getType() instanceof VoidType
|
||||
and not assignOperatorWithWrongType(op, _)
|
||||
and msg = "Assignment operator in class " + op.getDeclaringType().getName() + " does not return a reference to *this."
|
||||
op.hasName("operator=") and
|
||||
not returnsDereferenceThis(op) and
|
||||
exists(op.getBlock()) and
|
||||
not op.getType() instanceof VoidType and
|
||||
not assignOperatorWithWrongType(op, _) and
|
||||
msg = "Assignment operator in class " + op.getDeclaringType().getName() +
|
||||
" does not return a reference to *this."
|
||||
}
|
||||
|
||||
from Operator op, string msg
|
||||
where assignOperatorWithWrongType(op, msg)
|
||||
or assignOperatorWithWrongResult(op, msg)
|
||||
where
|
||||
assignOperatorWithWrongType(op, msg) or
|
||||
assignOperatorWithWrongResult(op, msg)
|
||||
select op, msg
|
||||
|
||||
@@ -8,13 +8,17 @@
|
||||
* reliability
|
||||
* external/jsf
|
||||
*/
|
||||
|
||||
import cpp
|
||||
|
||||
predicate oppositeOperators(string op1, string op2) {
|
||||
op1="operator<" and op2="operator>="
|
||||
or op1="operator<=" and op2="operator>"
|
||||
or op1="operator==" and op2="operator!="
|
||||
or oppositeOperators(op2, op1)
|
||||
op1 = "operator<" and op2 = "operator>="
|
||||
or
|
||||
op1 = "operator<=" and op2 = "operator>"
|
||||
or
|
||||
op1 = "operator==" and op2 = "operator!="
|
||||
or
|
||||
oppositeOperators(op2, op1)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -31,12 +35,18 @@ predicate implementedAsNegationOf(Operator op1, Operator op2) {
|
||||
n = r.getExpr() and
|
||||
o = n.getOperand() and
|
||||
(
|
||||
o instanceof LTExpr and op2.hasName("operator<") or
|
||||
o instanceof LEExpr and op2.hasName("operator<=") or
|
||||
o instanceof GTExpr and op2.hasName("operator>") or
|
||||
o instanceof GEExpr and op2.hasName("operator>=") or
|
||||
o instanceof EQExpr and op2.hasName("operator==") or
|
||||
o instanceof NEExpr and op2.hasName("operator!=") or
|
||||
o instanceof LTExpr and op2.hasName("operator<")
|
||||
or
|
||||
o instanceof LEExpr and op2.hasName("operator<=")
|
||||
or
|
||||
o instanceof GTExpr and op2.hasName("operator>")
|
||||
or
|
||||
o instanceof GEExpr and op2.hasName("operator>=")
|
||||
or
|
||||
o instanceof EQExpr and op2.hasName("operator==")
|
||||
or
|
||||
o instanceof NEExpr and op2.hasName("operator!=")
|
||||
or
|
||||
o.(FunctionCall).getTarget() = op2
|
||||
)
|
||||
)
|
||||
@@ -49,25 +59,32 @@ predicate classIsCheckableFor(Class c, string op) {
|
||||
// Member functions of templates are not necessarily instantiated, so
|
||||
// if the function we want to check exists, then make sure that its
|
||||
// body also exists
|
||||
((c instanceof TemplateClass)
|
||||
implies
|
||||
forall(Function f | f = c.getAMember() and f.hasName(op)
|
||||
| exists(f.getEntryPoint())))
|
||||
(
|
||||
c instanceof TemplateClass
|
||||
implies
|
||||
forall(Function f | f = c.getAMember() and f.hasName(op) | exists(f.getEntryPoint()))
|
||||
)
|
||||
}
|
||||
|
||||
from Class c, string op, string opp, Operator rator
|
||||
where c.fromSource() and
|
||||
oppositeOperators(op, opp) and
|
||||
classIsCheckableFor(c, op) and
|
||||
classIsCheckableFor(c, opp) and
|
||||
rator = c.getAMember() and
|
||||
rator.hasName(op) and
|
||||
forex(Operator aRator |
|
||||
aRator = c.getAMember() and aRator.hasName(op) |
|
||||
not exists(Operator oprator |
|
||||
oprator = c.getAMember() and
|
||||
oprator.hasName(opp) and
|
||||
( implementedAsNegationOf(aRator, oprator)
|
||||
or implementedAsNegationOf(oprator, aRator))))
|
||||
select c, "When two operators are opposites, both should be defined and one should be defined in terms of the other. Operator " + op +
|
||||
" is declared on line " + rator.getLocation().getStartLine().toString() + ", but it is not defined in terms of its opposite operator " + opp + "."
|
||||
where
|
||||
c.fromSource() and
|
||||
oppositeOperators(op, opp) and
|
||||
classIsCheckableFor(c, op) and
|
||||
classIsCheckableFor(c, opp) and
|
||||
rator = c.getAMember() and
|
||||
rator.hasName(op) and
|
||||
forex(Operator aRator | aRator = c.getAMember() and aRator.hasName(op) |
|
||||
not exists(Operator oprator |
|
||||
oprator = c.getAMember() and
|
||||
oprator.hasName(opp) and
|
||||
(
|
||||
implementedAsNegationOf(aRator, oprator) or
|
||||
implementedAsNegationOf(oprator, aRator)
|
||||
)
|
||||
)
|
||||
)
|
||||
select c,
|
||||
"When two operators are opposites, both should be defined and one should be defined in terms of the other. Operator "
|
||||
+ op + " is declared on line " + rator.getLocation().getStartLine().toString() +
|
||||
", but it is not defined in terms of its opposite operator " + opp + "."
|
||||
|
||||
@@ -7,12 +7,15 @@
|
||||
* @tags maintainability
|
||||
* external/jsf
|
||||
*/
|
||||
|
||||
import cpp
|
||||
|
||||
predicate derivesVirtual(Class c, Class base)
|
||||
{
|
||||
exists(ClassDerivation d | d.getDerivedClass() = c and d.getBaseClass() = base
|
||||
and d.hasSpecifier("virtual"))
|
||||
predicate derivesVirtual(Class c, Class base) {
|
||||
exists(ClassDerivation d |
|
||||
d.getDerivedClass() = c and
|
||||
d.getBaseClass() = base and
|
||||
d.hasSpecifier("virtual")
|
||||
)
|
||||
}
|
||||
|
||||
predicate derivesVirtualStar(Class c, Class base) {
|
||||
@@ -20,7 +23,8 @@ predicate derivesVirtualStar(Class c, Class base) {
|
||||
}
|
||||
|
||||
from Class c, Class base
|
||||
where c.getABaseClass+() = base
|
||||
and derivesVirtualStar(c, base)
|
||||
and not derivesVirtual(c, base)
|
||||
where
|
||||
c.getABaseClass+() = base and
|
||||
derivesVirtualStar(c, base) and
|
||||
not derivesVirtual(c, base)
|
||||
select c, "AV Rule 88.1: The virtual base " + base.getName() + " shall be explicitly declared."
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
* readability
|
||||
* external/jsf
|
||||
*/
|
||||
|
||||
import cpp
|
||||
|
||||
/**
|
||||
@@ -24,35 +25,62 @@ import cpp
|
||||
*/
|
||||
class InterfaceClass extends Class {
|
||||
InterfaceClass() {
|
||||
exists(MemberFunction m | m.getDeclaringType() = this and not compgenerated(unresolveElement(m)))
|
||||
and
|
||||
forall(MemberFunction m | m.getDeclaringType() = this and not compgenerated(unresolveElement(m)) | m instanceof PureVirtualFunction)
|
||||
and
|
||||
count(MemberVariable v | v.getDeclaringType() = this) < 3
|
||||
exists(MemberFunction m |
|
||||
m.getDeclaringType() = this and not compgenerated(unresolveElement(m))
|
||||
) and
|
||||
forall(MemberFunction m |
|
||||
m.getDeclaringType() = this and not compgenerated(unresolveElement(m))
|
||||
|
|
||||
m instanceof PureVirtualFunction
|
||||
) and
|
||||
count(MemberVariable v | v.getDeclaringType() = this) < 3
|
||||
}
|
||||
}
|
||||
|
||||
class InterfaceImplementor extends Class {
|
||||
InterfaceImplementor() {
|
||||
exists(ClassDerivation d | d.getDerivedClass() = this and d.getBaseClass() instanceof InterfaceClass)
|
||||
exists(ClassDerivation d |
|
||||
d.getDerivedClass() = this and d.getBaseClass() instanceof InterfaceClass
|
||||
)
|
||||
}
|
||||
|
||||
int getNumInterfaces() {
|
||||
result = count(ClassDerivation d | d.getDerivedClass() = this and d.getBaseClass() instanceof InterfaceClass)
|
||||
result = count(ClassDerivation d |
|
||||
d.getDerivedClass() = this and d.getBaseClass() instanceof InterfaceClass
|
||||
)
|
||||
}
|
||||
|
||||
int getNumProtectedImplementations() {
|
||||
result = count(ClassDerivation d | d.hasSpecifier("protected") and d.getDerivedClass() = this and not d.getBaseClass() instanceof InterfaceClass)
|
||||
result = count(ClassDerivation d |
|
||||
d.hasSpecifier("protected") and
|
||||
d.getDerivedClass() = this and
|
||||
not d.getBaseClass() instanceof InterfaceClass
|
||||
)
|
||||
}
|
||||
|
||||
int getNumPrivateImplementations() {
|
||||
result = count(ClassDerivation d | d.hasSpecifier("private") and d.getDerivedClass() = this and not d.getBaseClass() instanceof InterfaceClass)
|
||||
result = count(ClassDerivation d |
|
||||
d.hasSpecifier("private") and
|
||||
d.getDerivedClass() = this and
|
||||
not d.getBaseClass() instanceof InterfaceClass
|
||||
)
|
||||
}
|
||||
|
||||
int getNumPublicImplementations() {
|
||||
result = count(ClassDerivation d | d.hasSpecifier("public") and d.getDerivedClass() = this and not d.getBaseClass() instanceof InterfaceClass)
|
||||
result = count(ClassDerivation d |
|
||||
d.hasSpecifier("public") and
|
||||
d.getDerivedClass() = this and
|
||||
not d.getBaseClass() instanceof InterfaceClass
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
from InterfaceImplementor d
|
||||
where d.getNumPublicImplementations() > 0
|
||||
or d.getNumProtectedImplementations() > 1
|
||||
select d, "Multiple inheritance should not be used with " + d.getNumInterfaces().toString()
|
||||
+ " interfaces, " + d.getNumPrivateImplementations().toString() + " private implementations, " + d.getNumProtectedImplementations().toString() + " protected implementations, and "
|
||||
+ d.getNumPublicImplementations().toString() + " public implementations."
|
||||
where
|
||||
d.getNumPublicImplementations() > 0 or
|
||||
d.getNumProtectedImplementations() > 1
|
||||
select d,
|
||||
"Multiple inheritance should not be used with " + d.getNumInterfaces().toString() +
|
||||
" interfaces, " + d.getNumPrivateImplementations().toString() + " private implementations, " +
|
||||
d.getNumProtectedImplementations().toString() + " protected implementations, and " +
|
||||
d.getNumPublicImplementations().toString() + " public implementations."
|
||||
|
||||
@@ -9,22 +9,33 @@
|
||||
* readability
|
||||
* external/jsf
|
||||
*/
|
||||
|
||||
import cpp
|
||||
|
||||
predicate derivesVirtual(Class c, Class base) {
|
||||
exists(ClassDerivation d | d.getDerivedClass() = c and d.getBaseClass() = base
|
||||
and d.hasSpecifier("virtual"))
|
||||
or derivesVirtual(c.getABaseClass(), base)
|
||||
exists(ClassDerivation d |
|
||||
d.getDerivedClass() = c and
|
||||
d.getBaseClass() = base and
|
||||
d.hasSpecifier("virtual")
|
||||
)
|
||||
or
|
||||
derivesVirtual(c.getABaseClass(), base)
|
||||
}
|
||||
|
||||
predicate derivesNonVirtual(Class c, Class base) {
|
||||
exists(ClassDerivation d | d.getDerivedClass() = c and d.getBaseClass() = base
|
||||
and not d.hasSpecifier("virtual"))
|
||||
or derivesNonVirtual(c.getABaseClass(), base)
|
||||
exists(ClassDerivation d |
|
||||
d.getDerivedClass() = c and
|
||||
d.getBaseClass() = base and
|
||||
not d.hasSpecifier("virtual")
|
||||
)
|
||||
or
|
||||
derivesNonVirtual(c.getABaseClass(), base)
|
||||
}
|
||||
|
||||
from Class c, Class base
|
||||
where c.getABaseClass+() = base
|
||||
and derivesVirtual(c, base)
|
||||
and derivesNonVirtual(c, base)
|
||||
select c, "AV Rule 89: The base class " + base.getName() + " is derived both virtual and non-virtual."
|
||||
where
|
||||
c.getABaseClass+() = base and
|
||||
derivesVirtual(c, base) and
|
||||
derivesNonVirtual(c, base)
|
||||
select c,
|
||||
"AV Rule 89: The base class " + base.getName() + " is derived both virtual and non-virtual."
|
||||
|
||||
@@ -7,13 +7,17 @@
|
||||
* @tags maintainability
|
||||
* external/jsf
|
||||
*/
|
||||
|
||||
import cpp
|
||||
|
||||
from MemberFunction f1, MemberFunction f2
|
||||
where f1 != f2
|
||||
and not (f1 instanceof VirtualFunction)
|
||||
and not (f2 instanceof VirtualFunction)
|
||||
and f1.getDeclaringType().getABaseClass+() = f2.getDeclaringType()
|
||||
and f1.getName() = f2.getName()
|
||||
and forall(Parameter p1, Parameter p2, int i | f1.getParameter(i) = p1 and f2.getParameter(i) = p2 | p1.getType() = p2.getType() )
|
||||
where
|
||||
f1 != f2 and
|
||||
not f1 instanceof VirtualFunction and
|
||||
not f2 instanceof VirtualFunction and
|
||||
f1.getDeclaringType().getABaseClass+() = f2.getDeclaringType() and
|
||||
f1.getName() = f2.getName() and
|
||||
forall(Parameter p1, Parameter p2, int i | f1.getParameter(i) = p1 and f2.getParameter(i) = p2 |
|
||||
p1.getType() = p2.getType()
|
||||
)
|
||||
select f1, "AV Rule 94: An inherited nonvirtual function shall not be redefined in a derived class."
|
||||
|
||||
@@ -7,28 +7,29 @@
|
||||
* @tags correctness
|
||||
* external/jsf
|
||||
*/
|
||||
|
||||
import cpp
|
||||
|
||||
predicate compatible(Type t1, Type t2) {
|
||||
t1 = t2
|
||||
or compatible(t1.(DerivedType).getBaseType().getUnspecifiedType(), t2.(DerivedType).getBaseType().getUnspecifiedType())
|
||||
t1 = t2 or
|
||||
compatible(t1.(DerivedType).getBaseType().getUnspecifiedType(),
|
||||
t2.(DerivedType).getBaseType().getUnspecifiedType())
|
||||
}
|
||||
|
||||
predicate baseElement(ArrayType t, Type e) {
|
||||
t.getBaseType() instanceof ArrayType and baseElement(t.getBaseType(), e)
|
||||
or not t.getBaseType() instanceof ArrayType and e = t.getBaseType()
|
||||
or
|
||||
not t.getBaseType() instanceof ArrayType and e = t.getBaseType()
|
||||
}
|
||||
|
||||
from Expr e, Class cl
|
||||
where e.getType() instanceof ArrayType
|
||||
and exists(
|
||||
FunctionCall c, int i, Function f |
|
||||
c.getArgument(i) = e
|
||||
and
|
||||
c.getTarget() = f
|
||||
and
|
||||
exists(Parameter p | f.getParameter(i) = p) // varargs
|
||||
and
|
||||
baseElement(e.getType(), cl) // only interested in arrays with classes
|
||||
and
|
||||
not compatible(f.getParameter(i).getUnspecifiedType(), e.getUnspecifiedType()))
|
||||
select e, "AV Rule 96: Arrays shall not be teated polymorphically"
|
||||
where
|
||||
e.getType() instanceof ArrayType and
|
||||
exists(FunctionCall c, int i, Function f |
|
||||
c.getArgument(i) = e and
|
||||
c.getTarget() = f and
|
||||
exists(Parameter p | f.getParameter(i) = p) and // varargs
|
||||
baseElement(e.getType(), cl) and // only interested in arrays with classes
|
||||
not compatible(f.getParameter(i).getUnspecifiedType(), e.getUnspecifiedType())
|
||||
)
|
||||
select e, "AV Rule 96: Arrays shall not be teated polymorphically"
|
||||
|
||||
@@ -8,9 +8,13 @@
|
||||
* portability
|
||||
* external/jsf
|
||||
*/
|
||||
|
||||
import cpp
|
||||
|
||||
from EqualityOperation e, PointerToMemberType t, Class c
|
||||
where e.getAnOperand().getType() = t
|
||||
and t.getClass() = c and exists(VirtualFunction f | c.getAMemberFunction() = f)
|
||||
select e, "AV Rule 97.1: Neither operand of an equality operator shall be a pointer to a virtual member function."
|
||||
where
|
||||
e.getAnOperand().getType() = t and
|
||||
t.getClass() = c and
|
||||
exists(VirtualFunction f | c.getAMemberFunction() = f)
|
||||
select e,
|
||||
"AV Rule 97.1: Neither operand of an equality operator shall be a pointer to a virtual member function."
|
||||
|
||||
@@ -10,16 +10,21 @@
|
||||
* language-features
|
||||
* external/jsf
|
||||
*/
|
||||
|
||||
import cpp
|
||||
|
||||
predicate containsArray(Type t) {
|
||||
t instanceof ArrayType
|
||||
or containsArray(t.(PointerType).getBaseType())
|
||||
or containsArray(t.(SpecifiedType).getBaseType())
|
||||
or (containsArray(t.getUnderlyingType()) and not exists(TypedefType allowed | allowed = t |
|
||||
or
|
||||
containsArray(t.(PointerType).getBaseType())
|
||||
or
|
||||
containsArray(t.(SpecifiedType).getBaseType())
|
||||
or
|
||||
containsArray(t.getUnderlyingType()) and
|
||||
not exists(TypedefType allowed | allowed = t |
|
||||
allowed.hasGlobalName("jmp_buf") or
|
||||
allowed.hasGlobalName("va_list")
|
||||
))
|
||||
)
|
||||
}
|
||||
|
||||
predicate functionAPIViolation(MemberFunction f) {
|
||||
@@ -28,6 +33,7 @@ predicate functionAPIViolation(MemberFunction f) {
|
||||
}
|
||||
|
||||
from MemberFunction m
|
||||
where functionAPIViolation(m)
|
||||
and not m.getDeclaringType() instanceof Struct
|
||||
where
|
||||
functionAPIViolation(m) and
|
||||
not m.getDeclaringType() instanceof Struct
|
||||
select m, "Raw arrays should not be used in interfaces. A container class should be used instead."
|
||||
|
||||
@@ -8,15 +8,21 @@
|
||||
* readability
|
||||
* external/jsf
|
||||
*/
|
||||
|
||||
import cpp
|
||||
|
||||
// Pick a representative file for a namespace - more than a bit dodgy, but otherwise
|
||||
// the results don't show up anywhere which is less than helpful
|
||||
predicate namespaceRepresentative(Namespace ns, File rep) {
|
||||
rep.getAbsolutePath() = min(File f | exists(Declaration d | d = ns.getADeclaration() | d.getFile() = f) | f.getAbsolutePath())
|
||||
rep.getAbsolutePath() = min(File f |
|
||||
exists(Declaration d | d = ns.getADeclaration() | d.getFile() = f)
|
||||
|
|
||||
f.getAbsolutePath()
|
||||
)
|
||||
}
|
||||
|
||||
from Namespace ns, File rep
|
||||
where exists(ns.getParentNamespace().getParentNamespace().getParentNamespace())
|
||||
and namespaceRepresentative(ns, rep)
|
||||
where
|
||||
exists(ns.getParentNamespace().getParentNamespace().getParentNamespace()) and
|
||||
namespaceRepresentative(ns, rep)
|
||||
select rep, "AV Rule 99: namespace " + ns.toString() + " is nested more than two levels deep"
|
||||
|
||||
@@ -7,23 +7,26 @@
|
||||
* @tags correctness
|
||||
* external/jsf
|
||||
*/
|
||||
|
||||
import cpp
|
||||
|
||||
/** A compiler warning that a template specialization occurs after
|
||||
* what would have been its use. In C++ a template specialization
|
||||
* only applies after it is defined; if it would have applied had
|
||||
* it been defined earlier this warning is triggered.
|
||||
*
|
||||
* The warning is also triggered if the specialization would have
|
||||
* made a use ambiguous had it occurred earlier. */
|
||||
/**
|
||||
* A compiler warning that a template specialization occurs after
|
||||
* what would have been its use. In C++ a template specialization
|
||||
* only applies after it is defined; if it would have applied had
|
||||
* it been defined earlier this warning is triggered.
|
||||
*
|
||||
* The warning is also triggered if the specialization would have
|
||||
* made a use ambiguous had it occurred earlier.
|
||||
*/
|
||||
class WarningLateTemplateSpecialization extends CompilerWarning {
|
||||
|
||||
WarningLateTemplateSpecialization() {
|
||||
this.getTag() = "partial_spec_after_instantiation" or
|
||||
this.getTag() = "partial_spec_after_instantiation_ambiguous"
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
from WarningLateTemplateSpecialization warning
|
||||
select warning, "AV Rule 104: A template specialization shall be declared before its use; " + warning.getMessage() + "."
|
||||
select warning,
|
||||
"AV Rule 104: A template specialization shall be declared before its use; " + warning.getMessage()
|
||||
+ "."
|
||||
|
||||
@@ -9,10 +9,12 @@
|
||||
* readability
|
||||
* external/jsf
|
||||
*/
|
||||
|
||||
import cpp
|
||||
|
||||
from DeclStmt ds
|
||||
where ds.getADeclaration() instanceof Function
|
||||
and not ds.isInMacroExpansion()
|
||||
and not exists(MacroInvocation mi | mi.getLocation() = ds.getADeclarationEntry().getLocation())
|
||||
where
|
||||
ds.getADeclaration() instanceof Function and
|
||||
not ds.isInMacroExpansion() and
|
||||
not exists(MacroInvocation mi | mi.getLocation() = ds.getADeclarationEntry().getLocation())
|
||||
select ds, "Functions should be declared at file scope, not inside blocks."
|
||||
|
||||
@@ -7,8 +7,9 @@
|
||||
* @tags correctness
|
||||
* external/jsf
|
||||
*/
|
||||
|
||||
import cpp
|
||||
|
||||
from Function f
|
||||
where f.fromSource() and f.hasSpecifier("varargs")
|
||||
select f, "AV Rule 108: Functions with variable number of arguments shall not be used."
|
||||
select f, "AV Rule 108: Functions with variable number of arguments shall not be used."
|
||||
|
||||
@@ -8,9 +8,11 @@
|
||||
* readability
|
||||
* external/jsf
|
||||
*/
|
||||
|
||||
import cpp
|
||||
|
||||
from Function f
|
||||
where f.getNumberOfParameters() > 7
|
||||
and f.fromSource()
|
||||
select f, "AV Rule 110: Functions with more than 7 arguments will not be used."
|
||||
where
|
||||
f.getNumberOfParameters() > 7 and
|
||||
f.fromSource()
|
||||
select f, "AV Rule 110: Functions with more than 7 arguments will not be used."
|
||||
|
||||
@@ -8,20 +8,22 @@
|
||||
* reliability
|
||||
* external/jsf
|
||||
*/
|
||||
|
||||
import semmle.code.cpp.pointsto.PointsTo
|
||||
|
||||
class ReturnPointsToExpr extends PointsToExpr
|
||||
{
|
||||
class ReturnPointsToExpr extends PointsToExpr {
|
||||
override predicate interesting() {
|
||||
exists(ReturnStmt ret | ret.getExpr() = this)
|
||||
and pointerValue(this)
|
||||
exists(ReturnStmt ret | ret.getExpr() = this) and
|
||||
pointerValue(this)
|
||||
}
|
||||
|
||||
ReturnStmt getReturnStmt() { result.getExpr() = this }
|
||||
}
|
||||
|
||||
from ReturnPointsToExpr ret, LocalVariable dest
|
||||
where ret.pointsTo() = dest
|
||||
and ret.getReturnStmt().getParentStmt().getEnclosingFunction() = dest.getFunction()
|
||||
and not(dest.isStatic())
|
||||
select ret.getReturnStmt(), "AV Rule 111: A function shall not return a pointer or reference to a non-static local object."
|
||||
where
|
||||
ret.pointsTo() = dest and
|
||||
ret.getReturnStmt().getParentStmt().getEnclosingFunction() = dest.getFunction() and
|
||||
not dest.isStatic()
|
||||
select ret.getReturnStmt(),
|
||||
"AV Rule 111: A function shall not return a pointer or reference to a non-static local object."
|
||||
|
||||
@@ -7,10 +7,12 @@
|
||||
* @tags maintainability
|
||||
* external/jsf
|
||||
*/
|
||||
|
||||
import cpp
|
||||
|
||||
from Function f, Stmt s1, Stmt s2
|
||||
where s1 = f.getAPredecessor().getEnclosingStmt() and
|
||||
s2 = f.getAPredecessor().getEnclosingStmt() and
|
||||
s1 != s2
|
||||
select f, "AV Rule 113: Functions will have a single exit point."
|
||||
where
|
||||
s1 = f.getAPredecessor().getEnclosingStmt() and
|
||||
s2 = f.getAPredecessor().getEnclosingStmt() and
|
||||
s1 != s2
|
||||
select f, "AV Rule 113: Functions will have a single exit point."
|
||||
|
||||
@@ -10,13 +10,16 @@
|
||||
* language-features
|
||||
* external/jsf
|
||||
*/
|
||||
|
||||
import cpp
|
||||
|
||||
/* This is slightly subtle: The extractor adds a dummy 'return;' statement for control paths
|
||||
/*
|
||||
* This is slightly subtle: The extractor adds a dummy 'return;' statement for control paths
|
||||
* that fall off the end of a function. So we can simply look for non-void functions containing
|
||||
* a non-value carrying return. If the predecessor is a return statement it means that
|
||||
* the return did not return a value. (If that return was not added by the extractor but by the
|
||||
* programmer, we can flag it anyway, since this is arguably a bug.) */
|
||||
* programmer, we can flag it anyway, since this is arguably a bug.)
|
||||
*/
|
||||
|
||||
predicate functionsMissingReturnStmt(Function f, ControlFlowNode blame) {
|
||||
f.fromSource() and
|
||||
@@ -31,10 +34,12 @@ predicate functionsMissingReturnStmt(Function f, ControlFlowNode blame) {
|
||||
)
|
||||
}
|
||||
|
||||
/** If a function has a value-carrying return statement, but the extractor hit a snag
|
||||
/**
|
||||
* If a function has a value-carrying return statement, but the extractor hit a snag
|
||||
* whilst parsing the value, then the control flow graph will not include the value.
|
||||
* As such, to avoid embarrassing false positives, we exclude any function which
|
||||
* wasn't perfectly extracted. */
|
||||
* wasn't perfectly extracted.
|
||||
*/
|
||||
predicate functionImperfectlyExtracted(Function f) {
|
||||
exists(CompilerError e | f.getBlock().getLocation().subsumes(e.getLocation()))
|
||||
or
|
||||
@@ -49,5 +54,6 @@ where
|
||||
reachable(blame) and
|
||||
not functionImperfectlyExtracted(f) and
|
||||
(blame = stmt or blame.(Expr).getEnclosingStmt() = stmt) and
|
||||
msg = "Function " + f.getName() + " should return a value of type " + f.getType().getName() + " but does not return a value here"
|
||||
msg = "Function " + f.getName() + " should return a value of type " + f.getType().getName() +
|
||||
" but does not return a value here"
|
||||
select stmt, msg
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
* @tags correctness
|
||||
* external/jsf
|
||||
*/
|
||||
|
||||
import cpp
|
||||
|
||||
// a return statement that looks like it returns an error code
|
||||
@@ -19,9 +20,12 @@ class ErrorReturn extends ReturnStmt {
|
||||
ErrorReturn() {
|
||||
exists(Expr e |
|
||||
e = super.getExpr() and
|
||||
(e instanceof Literal
|
||||
or e.(VariableAccess).getTarget().isConst()) and
|
||||
not (e.getValue() = "0" and e.getActualType() instanceof IntegralType))
|
||||
(
|
||||
e instanceof Literal or
|
||||
e.(VariableAccess).getTarget().isConst()
|
||||
) and
|
||||
not (e.getValue() = "0" and e.getActualType() instanceof IntegralType)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,11 +35,13 @@ class FunctionReturningErrorCode extends Function {
|
||||
exists(ErrorReturn er, ReturnStmt nr |
|
||||
er.getEnclosingFunction() = this and
|
||||
nr.getEnclosingFunction() = this and
|
||||
not nr instanceof ErrorReturn)
|
||||
not nr instanceof ErrorReturn
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
from FunctionReturningErrorCode frec, Call c
|
||||
where c = frec.getACallToThisFunction() and
|
||||
c instanceof ExprInVoidContext
|
||||
select c, "AV Rule 115: If a function returns error information, it will be tested."
|
||||
where
|
||||
c = frec.getACallToThisFunction() and
|
||||
c instanceof ExprInVoidContext
|
||||
select c, "AV Rule 115: If a function returns error information, it will be tested."
|
||||
|
||||
@@ -7,9 +7,11 @@
|
||||
* @tags resources
|
||||
* external/jsf
|
||||
*/
|
||||
|
||||
import cpp
|
||||
|
||||
from Function f
|
||||
where f.fromSource() and
|
||||
f.calls+(f)
|
||||
select f, "Functions shall not call theselves, either directly or indirectly"
|
||||
where
|
||||
f.fromSource() and
|
||||
f.calls+(f)
|
||||
select f, "Functions shall not call theselves, either directly or indirectly"
|
||||
|
||||
@@ -8,9 +8,11 @@
|
||||
* documentation
|
||||
* external/jsf
|
||||
*/
|
||||
|
||||
import cpp
|
||||
|
||||
from Comment c
|
||||
where c.fromSource() and
|
||||
not c.getContents().regexpMatch("\\s*//.*")
|
||||
select c, "AV Rule 126: Only valid C++ style comments shall be used."
|
||||
where
|
||||
c.fromSource() and
|
||||
not c.getContents().regexpMatch("\\s*//.*")
|
||||
select c, "AV Rule 126: Only valid C++ style comments shall be used."
|
||||
|
||||
@@ -8,12 +8,17 @@
|
||||
* documentation
|
||||
* external/jsf
|
||||
*/
|
||||
|
||||
import cpp
|
||||
|
||||
class FirstComment extends Comment {
|
||||
|
||||
FirstComment() {
|
||||
not exists(Locatable l | l != this and shouldNotBeBefore(l) and l.getFile() = this.getFile() and l.getLocation().getEndLine() <= this.getLocation().getStartLine())
|
||||
not exists(Locatable l |
|
||||
l != this and
|
||||
shouldNotBeBefore(l) and
|
||||
l.getFile() = this.getFile() and
|
||||
l.getLocation().getEndLine() <= this.getLocation().getStartLine()
|
||||
)
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -22,17 +27,16 @@ class FirstComment extends Comment {
|
||||
* Simple checks only - if there is a comment at the beginning of the file, that
|
||||
* is pretty much enough
|
||||
*/
|
||||
predicate isValid() {
|
||||
// At least 3 lines long: make sure it's a proper comment
|
||||
this.getLocation().getEndLine() >= this.getLocation().getStartLine() + 2
|
||||
and
|
||||
exists (string contents | contents = this.getContents() |
|
||||
// Make sure the name of the file is included
|
||||
contents.matches("%" + this.getFile().getShortName() + "%")
|
||||
// Other checks could go here; for instance containing a standard copyright notice
|
||||
)
|
||||
}
|
||||
|
||||
predicate isValid() {
|
||||
// At least 3 lines long: make sure it's a proper comment
|
||||
this.getLocation().getEndLine() >= this.getLocation().getStartLine() + 2 and
|
||||
exists(string contents | contents = this.getContents() |
|
||||
// Make sure the name of the file is included
|
||||
contents.matches("%" + this.getFile().getShortName() + "%")
|
||||
// Other checks could go here; for instance containing a standard copyright notice
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/** Elements that should not appear before the 'first' comment */
|
||||
@@ -43,19 +47,17 @@ predicate shouldNotBeBefore(Locatable l) {
|
||||
}
|
||||
|
||||
from File f, Element blame, string message
|
||||
where f.fromSource() and
|
||||
(
|
||||
(
|
||||
not exists(FirstComment comment | comment.getFile() = f)
|
||||
and blame = f
|
||||
and message = ""
|
||||
)
|
||||
|
||||
or
|
||||
|
||||
(
|
||||
exists(FirstComment comment | comment.getFile() = f and not comment.isValid() and blame = comment )
|
||||
and message = "The introductory comment does not match the required style rules."
|
||||
)
|
||||
)
|
||||
select blame, "AV Rule 133: every source file will be documented with an introductory comment. " + message
|
||||
where
|
||||
f.fromSource() and
|
||||
(
|
||||
not exists(FirstComment comment | comment.getFile() = f) and
|
||||
blame = f and
|
||||
message = ""
|
||||
or
|
||||
exists(FirstComment comment |
|
||||
comment.getFile() = f and not comment.isValid() and blame = comment
|
||||
) and
|
||||
message = "The introductory comment does not match the required style rules."
|
||||
)
|
||||
select blame,
|
||||
"AV Rule 133: every source file will be documented with an introductory comment. " + message
|
||||
|
||||
@@ -7,16 +7,14 @@
|
||||
* @tags maintainability
|
||||
* external/jsf
|
||||
*/
|
||||
|
||||
import cpp
|
||||
import Best_Practices.Hiding.Shadowing
|
||||
|
||||
// Shadowing globals by locals or parameters. Only in the same file;
|
||||
// otherwise the rule is violated too often
|
||||
|
||||
class LocalVariableOrParameter extends Variable {
|
||||
LocalVariableOrParameter() {
|
||||
this instanceof LocalVariable or this instanceof Parameter
|
||||
}
|
||||
LocalVariableOrParameter() { this instanceof LocalVariable or this instanceof Parameter }
|
||||
|
||||
predicate shadowsGlobal(GlobalVariable gv) {
|
||||
this.getName() = gv.getName() and this.getFile() = gv.getFile()
|
||||
@@ -24,17 +22,17 @@ class LocalVariableOrParameter extends Variable {
|
||||
}
|
||||
|
||||
// Shadowing parameters by locals
|
||||
|
||||
predicate localShadowsParameter(LocalVariable lv, Parameter p) {
|
||||
p.getName() = lv.getName() and
|
||||
p.getFunction() = lv.getFunction()
|
||||
}
|
||||
|
||||
from Variable v, Variable shadowed
|
||||
where not v.getParentScope().(Block).isInMacroExpansion() and
|
||||
(
|
||||
v.(LocalVariableOrParameter).shadowsGlobal((GlobalVariable)shadowed)
|
||||
or localShadowsParameter(v, shadowed)
|
||||
or shadowing(v, shadowed)
|
||||
)
|
||||
where
|
||||
not v.getParentScope().(Block).isInMacroExpansion() and
|
||||
(
|
||||
v.(LocalVariableOrParameter).shadowsGlobal(shadowed.(GlobalVariable)) or
|
||||
localShadowsParameter(v, shadowed) or
|
||||
shadowing(v, shadowed)
|
||||
)
|
||||
select v, "Identifiers in an inner scope should not hide identifiers in an outer scope"
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
* @tags maintainability
|
||||
* external/jsf
|
||||
*/
|
||||
|
||||
import cpp
|
||||
|
||||
/*
|
||||
@@ -29,18 +30,21 @@ import cpp
|
||||
*/
|
||||
|
||||
predicate externalLinkage(Variable v) {
|
||||
v.getADeclarationEntry().hasSpecifier("extern")
|
||||
or v instanceof GlobalVariable and
|
||||
not v.isConst() and
|
||||
not v.isStatic()
|
||||
v.getADeclarationEntry().hasSpecifier("extern")
|
||||
or
|
||||
v instanceof GlobalVariable and
|
||||
not v.isConst() and
|
||||
not v.isStatic()
|
||||
}
|
||||
|
||||
predicate internalLinkage(GlobalVariable v) {
|
||||
v.isStatic()
|
||||
or v.isConst() and
|
||||
not v.hasSpecifier("extern")
|
||||
v.isStatic()
|
||||
or
|
||||
v.isConst() and
|
||||
not v.hasSpecifier("extern")
|
||||
}
|
||||
|
||||
from Variable v
|
||||
where externalLinkage(v) and internalLinkage(v)
|
||||
select v, "AV Rule 138: Identifiers shall not simultaneously have both internal and external linkage in the same translation unit."
|
||||
select v,
|
||||
"AV Rule 138: Identifiers shall not simultaneously have both internal and external linkage in the same translation unit."
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
* @tags maintainability
|
||||
* external/jsf
|
||||
*/
|
||||
|
||||
import cpp
|
||||
|
||||
predicate twoDeclarations(Declaration element, Location l1, Location l2) {
|
||||
@@ -18,25 +19,46 @@ predicate twoDeclarations(Declaration element, Location l1, Location l2) {
|
||||
}
|
||||
|
||||
predicate twoDeclarationFilesWithDifferentNames(Declaration d, string f1, string f2) {
|
||||
f1 = min(string s, File f, Location l | twoDeclarations(d, l, _) and l.getFile() = f and s = f.getBaseName() | s) and
|
||||
f2 = min(string s, File f, Location l | twoDeclarations(d, l, _) and l.getFile() = f and s = f.getBaseName() and s != f1 | s)
|
||||
f1 = min(string s, File f, Location l |
|
||||
twoDeclarations(d, l, _) and l.getFile() = f and s = f.getBaseName()
|
||||
|
|
||||
s
|
||||
) and
|
||||
f2 = min(string s, File f, Location l |
|
||||
twoDeclarations(d, l, _) and l.getFile() = f and s = f.getBaseName() and s != f1
|
||||
|
|
||||
s
|
||||
)
|
||||
}
|
||||
|
||||
predicate twoDeclarationFilesWithSameNames(Declaration d, string f1, string f2) {
|
||||
f1 = min(string s, File f, Location l | twoDeclarations(d, l, _) and l.getFile() = f and s = f.toString() | s) and
|
||||
f2 = min(string s, File f, Location l | twoDeclarations(d, l, _) and l.getFile() = f and s = f.toString() and s != f1 | s)
|
||||
f1 = min(string s, File f, Location l |
|
||||
twoDeclarations(d, l, _) and l.getFile() = f and s = f.toString()
|
||||
|
|
||||
s
|
||||
) and
|
||||
f2 = min(string s, File f, Location l |
|
||||
twoDeclarations(d, l, _) and l.getFile() = f and s = f.toString() and s != f1
|
||||
|
|
||||
s
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
predicate twoDeclarationFilesMessage(Declaration d, string msg) {
|
||||
// If we can get two files with different names, all the better for the error message
|
||||
if twoDeclarationFilesWithDifferentNames(d,_,_) then
|
||||
exists(string f1, string f2 | twoDeclarationFilesWithDifferentNames(d, f1, f2) and msg = "Declared in " + f1 + " and " + f2)
|
||||
if twoDeclarationFilesWithDifferentNames(d, _, _)
|
||||
then
|
||||
exists(string f1, string f2 |
|
||||
twoDeclarationFilesWithDifferentNames(d, f1, f2) and msg = "Declared in " + f1 + " and " + f2
|
||||
)
|
||||
else
|
||||
exists(string f1, string f2 | twoDeclarationFilesWithSameNames(d, f1, f2) and msg = "Declared in " + f1 + " and " + f2)
|
||||
exists(string f1, string f2 |
|
||||
twoDeclarationFilesWithSameNames(d, f1, f2) and msg = "Declared in " + f1 + " and " + f2
|
||||
)
|
||||
}
|
||||
|
||||
from Declaration d, string msg
|
||||
where twoDeclarations(d, _, _) and
|
||||
twoDeclarationFilesMessage(d, msg)
|
||||
where
|
||||
twoDeclarations(d, _, _) and
|
||||
twoDeclarationFilesMessage(d, msg)
|
||||
select d, "AV Rule 139: external objects will not be declared in more than one file. " + msg
|
||||
|
||||
@@ -8,8 +8,10 @@
|
||||
* portability
|
||||
* external/jsf
|
||||
*/
|
||||
|
||||
import cpp
|
||||
|
||||
from Declaration d
|
||||
where d.hasSpecifier("register")
|
||||
select d, "The register storage class specifier should not be used; compilers can be trusted to decide whether to store a variable in a register."
|
||||
select d,
|
||||
"The register storage class specifier should not be used; compilers can be trusted to decide whether to store a variable in a register."
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
* @tags correctness
|
||||
* external/jsf
|
||||
*/
|
||||
|
||||
import cpp
|
||||
|
||||
// whether s defines variable v (conservative)
|
||||
@@ -16,19 +17,22 @@ predicate defines(ControlFlowNode s, Variable lv) {
|
||||
|
||||
// whether s uses variable v (conservative)
|
||||
predicate uses(ControlFlowNode s, Variable lv) {
|
||||
exists(VariableAccess va | va = s and va.getTarget() = lv and va.isRValue()
|
||||
and not va.getParent+() instanceof SizeofOperator)
|
||||
exists(VariableAccess va |
|
||||
va = s and
|
||||
va.getTarget() = lv and
|
||||
va.isRValue() and
|
||||
not va.getParent+() instanceof SizeofOperator
|
||||
)
|
||||
}
|
||||
|
||||
// whether there is a path from the declaration of lv to n such that lv is definitely not defined before n
|
||||
predicate noDefPath(LocalVariable lv, ControlFlowNode n) {
|
||||
n.(DeclStmt).getADeclaration() = lv and not exists(lv.getInitializer())
|
||||
or exists(ControlFlowNode p | noDefPath(lv, p) and n = p.getASuccessor() and not defines(p, lv))
|
||||
n.(DeclStmt).getADeclaration() = lv and not exists(lv.getInitializer())
|
||||
or
|
||||
exists(ControlFlowNode p | noDefPath(lv, p) and n = p.getASuccessor() and not defines(p, lv))
|
||||
}
|
||||
|
||||
predicate isAggregateType(Type t) {
|
||||
t instanceof Class or t instanceof ArrayType
|
||||
}
|
||||
predicate isAggregateType(Type t) { t instanceof Class or t instanceof ArrayType }
|
||||
|
||||
// whether va is a use of a local variable that has not been previously defined
|
||||
predicate undefinedLocalUse(VariableAccess va) {
|
||||
@@ -38,7 +42,8 @@ predicate undefinedLocalUse(VariableAccess va) {
|
||||
not lv.getType().hasName("va_list") and
|
||||
va = lv.getAnAccess() and
|
||||
noDefPath(lv, va) and
|
||||
uses(va, lv))
|
||||
uses(va, lv)
|
||||
)
|
||||
}
|
||||
|
||||
// whether gv is a potentially uninitialised global variable
|
||||
@@ -48,9 +53,10 @@ predicate uninitialisedGlobal(GlobalVariable gv) {
|
||||
va = gv.getAnAccess() and
|
||||
va.isRValue() and
|
||||
not gv.hasInitializer() and
|
||||
not gv.hasSpecifier("extern"))
|
||||
not gv.hasSpecifier("extern")
|
||||
)
|
||||
}
|
||||
|
||||
from Element elt
|
||||
where undefinedLocalUse(elt) or uninitialisedGlobal(elt)
|
||||
select elt, "AV Rule 142: All variables shall be initialized before use."
|
||||
select elt, "AV Rule 142: All variables shall be initialized before use."
|
||||
|
||||
@@ -8,40 +8,50 @@
|
||||
* @tags maintainability
|
||||
* external/jsf
|
||||
*/
|
||||
|
||||
import cpp
|
||||
|
||||
// whether s defines variable v (conservative)
|
||||
predicate defines(VariableAccess va, Variable lv) {
|
||||
va.getTarget() = lv and va.isLValue()
|
||||
}
|
||||
predicate defines(VariableAccess va, Variable lv) { va.getTarget() = lv and va.isLValue() }
|
||||
|
||||
// whether s uses variable v (conservative)
|
||||
predicate uses(ControlFlowNode s, Variable lv) {
|
||||
exists(VariableAccess va | va = s and va.getTarget() = lv and va.isRValue()
|
||||
and not va.getParent+() instanceof SizeofOperator)
|
||||
exists(VariableAccess va |
|
||||
va = s and
|
||||
va.getTarget() = lv and
|
||||
va.isRValue() and
|
||||
not va.getParent+() instanceof SizeofOperator
|
||||
)
|
||||
}
|
||||
|
||||
// whether there is a path from the declaration of lv to n such that lv is definitely not used or defined
|
||||
// before n
|
||||
predicate noDefUsePath(LocalVariable lv, ControlFlowNode n) {
|
||||
n.(DeclStmt).getADeclaration() = lv
|
||||
or exists(ControlFlowNode p | noDefUsePath(lv, p) and
|
||||
n = p.getASuccessor() and
|
||||
not defines(p, lv) and
|
||||
not uses(p, lv))
|
||||
n.(DeclStmt).getADeclaration() = lv
|
||||
or
|
||||
exists(ControlFlowNode p |
|
||||
noDefUsePath(lv, p) and
|
||||
n = p.getASuccessor() and
|
||||
not defines(p, lv) and
|
||||
not uses(p, lv)
|
||||
)
|
||||
}
|
||||
|
||||
predicate neighbouringStmts(Stmt s1, Stmt s2) {
|
||||
exists(Block b, int i |
|
||||
i in [0..b.getNumStmt()-2] and
|
||||
i in [0 .. b.getNumStmt() - 2] and
|
||||
s1 = b.getStmt(i) and
|
||||
s2 = b.getStmt(i+1))
|
||||
s2 = b.getStmt(i + 1)
|
||||
)
|
||||
}
|
||||
|
||||
from LocalVariable lv, VariableAccess def, DeclStmt d
|
||||
where lv.fromSource() and
|
||||
d.getADeclaration() = lv and
|
||||
noDefUsePath(lv, def) and defines(def, lv) and
|
||||
not neighbouringStmts(d, def.getEnclosingStmt()) and
|
||||
not exists(ControlFlowNode use | noDefUsePath(lv, use) and uses(use, lv))
|
||||
select def, "AV Rule 143: Variables will not be introduced until they can be initialized with meaningful values."
|
||||
where
|
||||
lv.fromSource() and
|
||||
d.getADeclaration() = lv and
|
||||
noDefUsePath(lv, def) and
|
||||
defines(def, lv) and
|
||||
not neighbouringStmts(d, def.getEnclosingStmt()) and
|
||||
not exists(ControlFlowNode use | noDefUsePath(lv, use) and uses(use, lv))
|
||||
select def,
|
||||
"AV Rule 143: Variables will not be introduced until they can be initialized with meaningful values."
|
||||
|
||||
@@ -10,15 +10,14 @@
|
||||
* language-features
|
||||
* external/jsf
|
||||
*/
|
||||
|
||||
import cpp
|
||||
|
||||
predicate hasInitializer(EnumConstant c) {
|
||||
c.getInitializer().fromSource()
|
||||
}
|
||||
predicate hasInitializer(EnumConstant c) { c.getInitializer().fromSource() }
|
||||
|
||||
/** Does this have an initializer that is not just a ref to another constant in the same enum? */
|
||||
predicate hasNonReferenceInitializer(EnumConstant c) {
|
||||
exists (Initializer init |
|
||||
exists(Initializer init |
|
||||
init = c.getInitializer() and
|
||||
init.fromSource() and
|
||||
not init.getExpr().(EnumConstantAccess).getTarget().getDeclaringEnum() = c.getDeclaringEnum()
|
||||
@@ -26,14 +25,13 @@ predicate hasNonReferenceInitializer(EnumConstant c) {
|
||||
}
|
||||
|
||||
predicate hasReferenceInitializer(EnumConstant c) {
|
||||
exists (Initializer init |
|
||||
exists(Initializer init |
|
||||
init = c.getInitializer() and
|
||||
init.fromSource() and
|
||||
init.getExpr().(EnumConstantAccess).getTarget().getDeclaringEnum() = c.getDeclaringEnum()
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
// There exists another constant whose value is implicit, but it's
|
||||
// not the last one: the last value is okay to use to get the highest
|
||||
// enum value automatically. It can be followed by aliases though.
|
||||
@@ -50,15 +48,16 @@ predicate enumThatHasConstantWithImplicitValue(Enum e) {
|
||||
}
|
||||
|
||||
from Enum e, int i
|
||||
where // e is at position i, and has an explicit value in the source - but
|
||||
// not just a reference to another enum constant
|
||||
hasNonReferenceInitializer(e.getEnumConstant(i)) and
|
||||
// but e is not the first or the last constant of the enum
|
||||
i != 0 and
|
||||
exists(e.getEnumConstant(i+1)) and
|
||||
// and there exists another constant whose value is implicit, but it's
|
||||
// not the last one: the last value is okay to use to get the highest
|
||||
// enum value automatically. It can be followed by aliases though.
|
||||
enumThatHasConstantWithImplicitValue(e)
|
||||
|
||||
select e, "In an enumerator list, the = construct should not be used to explicitly initialize members other than the first, unless all items are explicitly initialized."
|
||||
where
|
||||
// e is at position i, and has an explicit value in the source - but
|
||||
// not just a reference to another enum constant
|
||||
hasNonReferenceInitializer(e.getEnumConstant(i)) and
|
||||
// but e is not the first or the last constant of the enum
|
||||
i != 0 and
|
||||
exists(e.getEnumConstant(i + 1)) and
|
||||
// and there exists another constant whose value is implicit, but it's
|
||||
// not the last one: the last value is okay to use to get the highest
|
||||
// enum value automatically. It can be followed by aliases though.
|
||||
enumThatHasConstantWithImplicitValue(e)
|
||||
select e,
|
||||
"In an enumerator list, the = construct should not be used to explicitly initialize members other than the first, unless all items are explicitly initialized."
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
* @tags reliability
|
||||
* external/jsf
|
||||
*/
|
||||
|
||||
import cpp
|
||||
|
||||
/*
|
||||
@@ -21,7 +22,6 @@ class GeneralPointerType extends DerivedType {
|
||||
}
|
||||
|
||||
class InvalidFloatCastExpr extends Expr {
|
||||
|
||||
InvalidFloatCastExpr() {
|
||||
exists(Type src, Type dst |
|
||||
src = this.getUnspecifiedType() and
|
||||
@@ -33,19 +33,28 @@ class InvalidFloatCastExpr extends Expr {
|
||||
}
|
||||
|
||||
class FloatUnion extends Union {
|
||||
|
||||
FloatUnion() {
|
||||
exists (MemberVariable mv | this.getAMemberVariable() = mv and mv.getType().getUnderlyingType() instanceof FloatingPointType)
|
||||
and exists (MemberVariable mv | this.getAMemberVariable() = mv and not mv.getType().getUnderlyingType() instanceof FloatingPointType)
|
||||
exists(MemberVariable mv |
|
||||
this.getAMemberVariable() = mv and
|
||||
mv.getType().getUnderlyingType() instanceof FloatingPointType
|
||||
) and
|
||||
exists(MemberVariable mv |
|
||||
this.getAMemberVariable() = mv and
|
||||
not mv.getType().getUnderlyingType() instanceof FloatingPointType
|
||||
)
|
||||
}
|
||||
|
||||
MemberVariable getAFloatMember() { result = this.getAMemberVariable() and result.getType().getUnderlyingType() instanceof FloatingPointType }
|
||||
|
||||
MemberVariable getAFloatMember() {
|
||||
result = this.getAMemberVariable() and
|
||||
result.getType().getUnderlyingType() instanceof FloatingPointType
|
||||
}
|
||||
}
|
||||
|
||||
from Element e, string message
|
||||
where
|
||||
(e instanceof InvalidFloatCastExpr and message = "Casting a float pointer to another pointer type exposes the bit representation of the float, leading to unportable code.")
|
||||
e instanceof InvalidFloatCastExpr and
|
||||
message = "Casting a float pointer to another pointer type exposes the bit representation of the float, leading to unportable code."
|
||||
or
|
||||
(exists (FloatUnion fu | e = fu.getAFloatMember()) and message = "Defining a union with a float member exposes the bit representation of the float, leading to unportable code.")
|
||||
exists(FloatUnion fu | e = fu.getAFloatMember()) and
|
||||
message = "Defining a union with a float member exposes the bit representation of the float, leading to unportable code."
|
||||
select e, message
|
||||
|
||||
@@ -10,12 +10,16 @@
|
||||
* language-features
|
||||
* external/jsf
|
||||
*/
|
||||
|
||||
import cpp
|
||||
|
||||
// flag switch statements where every non-default case dispatches on an integer constant
|
||||
from SwitchStmt s
|
||||
where forex(SwitchCase sc | sc = s.getASwitchCase() and not sc instanceof DefaultCase |
|
||||
sc.getExpr().(VariableAccess).getTarget().isConst())
|
||||
// Allow switch on character types
|
||||
and not (s.getExpr().getUnspecifiedType() instanceof CharType)
|
||||
select s, "Enumeration types should be used instead of integers to select from a limited series of choices."
|
||||
where
|
||||
forex(SwitchCase sc | sc = s.getASwitchCase() and not sc instanceof DefaultCase |
|
||||
sc.getExpr().(VariableAccess).getTarget().isConst()
|
||||
) and
|
||||
// Allow switch on character types
|
||||
not s.getExpr().getUnspecifiedType() instanceof CharType
|
||||
select s,
|
||||
"Enumeration types should be used instead of integers to select from a limited series of choices."
|
||||
|
||||
@@ -7,9 +7,11 @@
|
||||
* @tags maintainability
|
||||
* external/jsf
|
||||
*/
|
||||
|
||||
import cpp
|
||||
|
||||
from OctalLiteral l
|
||||
where l.fromSource() and
|
||||
l.getValue() != "0"
|
||||
select l, "AV Rule 149: Octal constants (other than zero) shall not be used."
|
||||
where
|
||||
l.fromSource() and
|
||||
l.getValue() != "0"
|
||||
select l, "AV Rule 149: Octal constants (other than zero) shall not be used."
|
||||
|
||||
@@ -7,9 +7,11 @@
|
||||
* @tags maintainability
|
||||
* external/jsf
|
||||
*/
|
||||
|
||||
import cpp
|
||||
|
||||
from HexLiteral l
|
||||
where l.fromSource() and
|
||||
l.getValueText().regexpMatch(".*[a-z].*")
|
||||
select l, "AV Rule 150: Hexadecimal constants will be represented using all uppercase letters."
|
||||
where
|
||||
l.fromSource() and
|
||||
l.getValueText().regexpMatch(".*[a-z].*")
|
||||
select l, "AV Rule 150: Hexadecimal constants will be represented using all uppercase letters."
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
* @tags correctness
|
||||
* external/jsf
|
||||
*/
|
||||
|
||||
import cpp
|
||||
|
||||
/*
|
||||
@@ -28,4 +29,5 @@ class NonConstStringType extends DerivedType {
|
||||
|
||||
from StringLiteral l
|
||||
where l.getFullyConverted().getType().getUnderlyingType() instanceof NonConstStringType
|
||||
select l, "A string literal must not be used as a non-const value: modifying string literals leads to undefined behavior."
|
||||
select l,
|
||||
"A string literal must not be used as a non-const value: modifying string literals leads to undefined behavior."
|
||||
|
||||
@@ -7,17 +7,22 @@
|
||||
* @tags maintainability
|
||||
* external/jsf
|
||||
*/
|
||||
|
||||
import cpp
|
||||
|
||||
from Literal l
|
||||
where l.fromSource() and
|
||||
l.getType() instanceof ArithmeticType and
|
||||
not l.isInMacroExpansion() and
|
||||
not l.getParent() instanceof ArrayExpr and
|
||||
not exists(Variable v | v.getInitializer().getExpr() = l) and
|
||||
not exists(Assignment a | a.getLValue() instanceof ArrayExpr and
|
||||
a.getRValue() = l and
|
||||
a.getControlFlowScope() instanceof Constructor) and
|
||||
not l.getValue() = "0" and
|
||||
not l.getValue() = "1"
|
||||
select l, "AV Rule 151: Numeric values in code will not be used; symbolic values will be used instead."
|
||||
where
|
||||
l.fromSource() and
|
||||
l.getType() instanceof ArithmeticType and
|
||||
not l.isInMacroExpansion() and
|
||||
not l.getParent() instanceof ArrayExpr and
|
||||
not exists(Variable v | v.getInitializer().getExpr() = l) and
|
||||
not exists(Assignment a |
|
||||
a.getLValue() instanceof ArrayExpr and
|
||||
a.getRValue() = l and
|
||||
a.getControlFlowScope() instanceof Constructor
|
||||
) and
|
||||
not l.getValue() = "0" and
|
||||
not l.getValue() = "1"
|
||||
select l,
|
||||
"AV Rule 151: Numeric values in code will not be used; symbolic values will be used instead."
|
||||
|
||||
@@ -8,27 +8,33 @@
|
||||
* readability
|
||||
* external/jsf
|
||||
*/
|
||||
|
||||
import cpp
|
||||
|
||||
predicate isNonSolitary(Declaration d) {
|
||||
exists(DeclStmt ds, Variable v |
|
||||
ds.fromSource() and
|
||||
d = ds.getADeclaration() and
|
||||
d instanceof Variable and
|
||||
v = ds.getADeclaration() and
|
||||
v != d)
|
||||
ds.fromSource() and
|
||||
d = ds.getADeclaration() and
|
||||
d instanceof Variable and
|
||||
v = ds.getADeclaration() and
|
||||
v != d
|
||||
)
|
||||
or
|
||||
exists(GlobalVariable g | g.fromSource() and
|
||||
g.getLocation().getStartLine() = d.(GlobalVariable).getLocation().getStartLine() and
|
||||
g.getLocation().getFile() = d.getLocation().getFile() and
|
||||
g != d)
|
||||
exists(GlobalVariable g |
|
||||
g.fromSource() and
|
||||
g.getLocation().getStartLine() = d.(GlobalVariable).getLocation().getStartLine() and
|
||||
g.getLocation().getFile() = d.getLocation().getFile() and
|
||||
g != d
|
||||
)
|
||||
or
|
||||
exists(Field f | f.fromSource() and
|
||||
f.getLocation().getStartLine() = d.(Field).getLocation().getStartLine() and
|
||||
f.getLocation().getFile() = d.getLocation().getFile() and
|
||||
f != d)
|
||||
exists(Field f |
|
||||
f.fromSource() and
|
||||
f.getLocation().getStartLine() = d.(Field).getLocation().getStartLine() and
|
||||
f.getLocation().getFile() = d.getLocation().getFile() and
|
||||
f != d
|
||||
)
|
||||
}
|
||||
|
||||
from Declaration d
|
||||
where isNonSolitary(d)
|
||||
select d, "AV Rule 152: Multiple variable declarations shall not be allowed on the same line."
|
||||
select d, "AV Rule 152: Multiple variable declarations shall not be allowed on the same line."
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
* @tags correctness
|
||||
* external/jsf
|
||||
*/
|
||||
|
||||
import cpp
|
||||
|
||||
/*
|
||||
@@ -15,4 +16,4 @@ import cpp
|
||||
|
||||
from Union u
|
||||
where u.fromSource()
|
||||
select u, "AV Rule 153: Unions shall not be used."
|
||||
select u, "AV Rule 153: Unions shall not be used."
|
||||
|
||||
@@ -13,13 +13,17 @@
|
||||
* external/jsf
|
||||
* external/cwe/cwe-190
|
||||
*/
|
||||
|
||||
import cpp
|
||||
|
||||
from BitField bf
|
||||
where not bf.getUnspecifiedType().(IntegralType).isUnsigned()
|
||||
and not bf.getUnderlyingType() instanceof Enum
|
||||
and not bf.getUnspecifiedType() instanceof BoolType
|
||||
and not bf.getType().hasName("BOOL") // At least for C programs on Windows, BOOL is a common typedef for a type representing BoolType.
|
||||
and not bf.getDeclaredNumBits() = bf.getType().getSize() * 8 // If this is true, then there cannot be unsigned sign extension or overflow.
|
||||
and not bf.isAnonymous()
|
||||
select bf, "Bit field " + bf.getName() + " of type " + bf.getUnderlyingType().getName() + " should have explicitly unsigned integral or enumeration type."
|
||||
where
|
||||
not bf.getUnspecifiedType().(IntegralType).isUnsigned() and
|
||||
not bf.getUnderlyingType() instanceof Enum and
|
||||
not bf.getUnspecifiedType() instanceof BoolType and
|
||||
not bf.getType().hasName("BOOL") and // At least for C programs on Windows, BOOL is a common typedef for a type representing BoolType.
|
||||
not bf.getDeclaredNumBits() = bf.getType().getSize() * 8 and // If this is true, then there cannot be unsigned sign extension or overflow.
|
||||
not bf.isAnonymous()
|
||||
select bf,
|
||||
"Bit field " + bf.getName() + " of type " + bf.getUnderlyingType().getName() +
|
||||
" should have explicitly unsigned integral or enumeration type."
|
||||
|
||||
@@ -8,9 +8,11 @@
|
||||
* @tags correctness
|
||||
* external/jsf
|
||||
*/
|
||||
|
||||
import cpp
|
||||
|
||||
from BitField bf
|
||||
where not bf.getUnderlyingType() instanceof Enum and
|
||||
not bf.getDeclaredNumBits() = 0
|
||||
where
|
||||
not bf.getUnderlyingType() instanceof Enum and
|
||||
not bf.getDeclaredNumBits() = 0
|
||||
select bf, "AV Rule 155: Bit fields will not be used purely to save space."
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user