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:
Jonas Jensen
2019-09-05 15:35:00 +02:00
parent 1784122929
commit 4ef5c9af62
1141 changed files with 21968 additions and 23174 deletions

View File

@@ -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."

View File

@@ -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."

View File

@@ -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."

View File

@@ -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()

View File

@@ -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()

View File

@@ -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."

View File

@@ -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."

View File

@@ -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."

View File

@@ -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."

View File

@@ -7,6 +7,7 @@
* @tags maintainability
* external/jsf
*/
import cpp
from Include incl

View File

@@ -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."

View File

@@ -8,6 +8,7 @@
* portability
* external/jsf
*/
import cpp
from Include incl

View File

@@ -8,6 +8,7 @@
* portability
* external/jsf
*/
import cpp
from Include incl

View File

@@ -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."

View File

@@ -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."

View File

@@ -8,6 +8,7 @@
* portability
* external/jsf
*/
import cpp
from Include incl

View File

@@ -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."

View File

@@ -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."

View File

@@ -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."

View File

@@ -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"

View File

@@ -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."

View File

@@ -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."

View 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."

View File

@@ -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."

View File

@@ -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()

View File

@@ -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."

View File

@@ -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

View File

@@ -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()

View File

@@ -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."

View File

@@ -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()

View File

@@ -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()

View File

@@ -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."

View File

@@ -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

View File

@@ -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."

View File

@@ -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() + ")"

View File

@@ -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() + "."

View File

@@ -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."

View File

@@ -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."

View File

@@ -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."

View File

@@ -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 + "'"

View File

@@ -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."

View File

@@ -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."

View File

@@ -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."

View File

@@ -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"

View File

@@ -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."

View File

@@ -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()

View File

@@ -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()

View File

@@ -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."

View File

@@ -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"'
)
}
}
}

View File

@@ -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

View File

@@ -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."

View File

@@ -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."

View File

@@ -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()

View File

@@ -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

View File

@@ -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()

View File

@@ -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."

View File

@@ -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."

View File

@@ -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."

View File

@@ -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."

View File

@@ -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."

View File

@@ -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

View File

@@ -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."

View File

@@ -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

View File

@@ -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 + "."

View File

@@ -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."

View File

@@ -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."

View File

@@ -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."

View File

@@ -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."

View File

@@ -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"

View File

@@ -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."

View File

@@ -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."

View File

@@ -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"

View File

@@ -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()
+ "."

View File

@@ -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."

View File

@@ -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."

View File

@@ -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."

View File

@@ -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."

View File

@@ -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."

View File

@@ -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

View File

@@ -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."

View File

@@ -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"

View File

@@ -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."

View File

@@ -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

View File

@@ -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"

View File

@@ -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."

View File

@@ -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

View File

@@ -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."

View File

@@ -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."

View File

@@ -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."

View File

@@ -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."

View File

@@ -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

View File

@@ -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."

View File

@@ -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."

View File

@@ -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."

View File

@@ -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."

View File

@@ -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."

View File

@@ -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."

View File

@@ -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."

View File

@@ -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."

View File

@@ -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