Skip to content

Commit

Permalink
Merge pull request #730 from github/michaelrfairhurst/implement-lanug…
Browse files Browse the repository at this point in the history
…age4-package-rule-1-5

Implement Language4 package, banning obsolete language features.
  • Loading branch information
MichaelRFairhurst authored Nov 15, 2024
2 parents 85036d5 + b1c7619 commit 373b793
Show file tree
Hide file tree
Showing 52 changed files with 836 additions and 79 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
// GENERATED FILE - DO NOT MODIFY
import codingstandards.cpp.rules.functiontypesnotinprototypeformshared.FunctionTypesNotInPrototypeFormShared

class TestFileQuery extends FunctionTypesNotInPrototypeFormSharedSharedQuery, TestQuery { }
File renamed without changes.
File renamed without changes.
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
// GENERATED FILE - DO NOT MODIFY
import codingstandards.cpp.rules.missingstaticspecifierobjectredeclarationshared.MissingStaticSpecifierObjectRedeclarationShared

class TestFileQuery extends MissingStaticSpecifierObjectRedeclarationSharedSharedQuery, TestQuery {
}
File renamed without changes.
22 changes: 22 additions & 0 deletions c/misra/src/rules/RULE-1-5/CallToObsolescentFunctionGets.ql
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
/**
* @id c/misra/call-to-obsolescent-function-gets
* @name RULE-1-5: Disallowed usage of obsolescent function 'gets'
* @description The function 'gets' is an obsolescent language feature which was removed in C11.
* @kind problem
* @precision very-high
* @problem.severity error
* @tags external/misra/id/rule-1-5
* external/misra/c/2012/amendment3
* security
* maintainability
* external/misra/obligation/required
*/

import cpp
import codingstandards.c.misra

from FunctionCall fc
where
not isExcluded(fc, Language4Package::callToObsolescentFunctionGetsQuery()) and
fc.getTarget().hasGlobalOrStdName("gets")
select fc, "Call to obsolescent function 'gets'."
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
/**
* @id c/misra/function-types-not-in-prototype-form-obsolete
* @name RULE-1-5: Function types shall be in prototype form with named parameters
* @description The use of non-prototype format parameter type declarators is an obsolescent
* language feature.
* @kind problem
* @precision medium
* @problem.severity error
* @tags external/misra/id/rule-1-5
* correctness
* external/misra/c/2012/amendment3
* external/misra/obligation/required
*/

import cpp
import codingstandards.c.misra
import codingstandards.cpp.rules.functiontypesnotinprototypeformshared.FunctionTypesNotInPrototypeFormShared

class FunctionTypesNotInPrototypeFormObsoleteQuery extends FunctionTypesNotInPrototypeFormSharedSharedQuery
{
FunctionTypesNotInPrototypeFormObsoleteQuery() {
this = Language4Package::functionTypesNotInPrototypeFormObsoleteQuery()
}
}
32 changes: 32 additions & 0 deletions c/misra/src/rules/RULE-1-5/InvalidDefineOrUndefOfStdBoolMacro.ql
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/**
* @id c/misra/invalid-define-or-undef-of-std-bool-macro
* @name RULE-1-5: Programs may not undefine or redefine the macros bool, true, or false
* @description Directives that undefine and/or redefine the standard boolean macros has been
* declared an obsolescent language feature since C99.
* @kind problem
* @precision very-high
* @problem.severity warning
* @tags external/misra/id/rule-1-5
* maintainability
* readability
* external/misra/c/2012/amendment3
* external/misra/obligation/required
*/

import cpp
import codingstandards.c.misra

string getABoolMacroName() { result = ["true", "false", "bool"] }

from PreprocessorDirective directive, string opString, string macroName
where
not isExcluded(directive, Language4Package::invalidDefineOrUndefOfStdBoolMacroQuery()) and
macroName = getABoolMacroName() and
(
macroName = directive.(Macro).getName() and
opString = "define"
or
macroName = directive.(PreprocessorUndef).getName() and
opString = "undefine"
)
select directive, "Invalid " + opString + " of boolean standard macro '" + macroName + "'."
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
/**
* @id c/misra/missing-static-specifier-func-redeclaration-obsolete
* @name RULE-1-5: If a function has internal linkage then all re-declarations shall include the static storage class
* @description Declaring a function with internal linkage without the static storage class
* specifier is an obselescent feature.
* @kind problem
* @precision very-high
* @problem.severity warning
* @tags external/misra/id/rule-1-5
* readability
* external/misra/c/2012/amendment3
* external/misra/obligation/required
*/

import cpp
import codingstandards.c.misra
import codingstandards.cpp.rules.missingstaticspecifierfunctionredeclarationshared.MissingStaticSpecifierFunctionRedeclarationShared

class MissingStaticSpecifierFuncRedeclarationObsoleteQuery extends MissingStaticSpecifierFunctionRedeclarationSharedSharedQuery
{
MissingStaticSpecifierFuncRedeclarationObsoleteQuery() {
this = Language4Package::missingStaticSpecifierFuncRedeclarationObsoleteQuery()
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
/**
* @id c/misra/missing-static-specifier-object-redeclaration-obsolete
* @name RULE-1-5: If an object has internal linkage then all re-declarations shall include the static storage class
* @description Declaring an identifier with internal linkage without the static storage class
* specifier is an obselescent feature.
* @kind problem
* @precision very-high
* @problem.severity warning
* @tags external/misra/id/rule-1-5
* readability
* external/misra/c/2012/amendment3
* external/misra/obligation/required
*/

import cpp
import codingstandards.c.misra
import codingstandards.cpp.rules.missingstaticspecifierobjectredeclarationshared.MissingStaticSpecifierObjectRedeclarationShared

class MissingStaticSpecifierObjectRedeclarationObsoleteQuery extends MissingStaticSpecifierObjectRedeclarationSharedSharedQuery
{
MissingStaticSpecifierObjectRedeclarationObsoleteQuery() {
this = Language4Package::missingStaticSpecifierObjectRedeclarationObsoleteQuery()
}
}
26 changes: 26 additions & 0 deletions c/misra/src/rules/RULE-1-5/SizeInReallocCallIsZero.ql
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
/**
* @id c/misra/size-in-realloc-call-is-zero
* @name RULE-1-5: Size argument value in realloc call is equal zero
* @description Invoking realloc with a size argument set to zero is implementation-defined behavior
* and declared as an obsolete feature in C18.
* @kind problem
* @precision very-high
* @problem.severity error
* @tags external/misra/id/rule-1-5
* correctness
* external/misra/c/2012/amendment3
* external/misra/obligation/required
*/

import cpp
import codingstandards.c.misra
import semmle.code.cpp.rangeanalysis.new.RangeAnalysis
import codingstandards.cpp.Realloc

from ReallocCall call
where
not isExcluded(call, Language4Package::sizeInReallocCallIsZeroQuery()) and
call.sizeIsExactlyZero()
select call,
"Size argument '$@' may equal zero in realloc call, resulting in obsolescent and/or implementation-defined behavior.",
call.getSizeArgument(), call.getSizeArgument().toString()
26 changes: 26 additions & 0 deletions c/misra/src/rules/RULE-1-5/SizeInReallocCallMayBeZero.ql
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
/**
* @id c/misra/size-in-realloc-call-may-be-zero
* @name RULE-1-5: Size argument value in realloc call may equal zero
* @description Invoking realloc with a size argument set to zero is implementation-defined behavior
* and declared as an obsolete feature in C18.
* @kind problem
* @precision medium
* @problem.severity error
* @tags external/misra/id/rule-1-5
* correctness
* external/misra/c/2012/amendment3
* external/misra/obligation/required
*/

import cpp
import codingstandards.c.misra
import codingstandards.cpp.Realloc

from ReallocCall call
where
not isExcluded(call, Language4Package::sizeInReallocCallMayBeZeroQuery()) and
call.sizeMayBeZero() and
not call.sizeIsExactlyZero()
select call,
"Size argument '$@' equals zero in realloc call, resulting in obsolescent and/or implementation-defined behavior.",
call.getSizeArgument(), call.getSizeArgument().toString()
81 changes: 81 additions & 0 deletions c/misra/src/rules/RULE-1-5/UngetcCallOnStreamPositionZero.ql
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
/**
* @id c/misra/ungetc-call-on-stream-position-zero
* @name RULE-1-5: Disallowed obsolescent usage of 'ungetc' on a file stream at position zero
* @description Calling the function 'ungetc' on a file stream with a position of zero is an
* obsolescent language feature.
* @kind path-problem
* @precision high
* @problem.severity error
* @tags external/misra/id/rule-1-5
* external/misra/c/2012/amendment3
* security
* maintainability
* external/misra/obligation/required
*/

import cpp
import semmle.code.cpp.dataflow.new.DataFlow
import semmle.code.cpp.controlflow.Dominance
import codingstandards.c.misra

/**
* This is an inconclusive list, which is adequate, as RULE-21-3 provides
* assurance we won't have false negatives, or care too much about false
* positives.
*/
class MoveStreamPositionCall extends FunctionCall {
Expr streamArgument;

MoveStreamPositionCall() {
getTarget().hasGlobalOrStdName("fgetc") and
streamArgument = getArgument(0)
or
getTarget().hasGlobalOrStdName("getc") and
streamArgument = getArgument(0)
or
getTarget().hasGlobalOrStdName("fget") and
streamArgument = getArgument(2)
or
getTarget().hasGlobalOrStdName("fscanf") and
streamArgument = getArgument(0)
or
getTarget().hasGlobalOrStdName("fsetpos") and
streamArgument = getArgument(0)
or
getTarget().hasGlobalOrStdName("fseek") and
streamArgument = getArgument(0)
or
getTarget().hasGlobalOrStdName("fread") and
streamArgument = getArgument(3)
}

Expr getStreamArgument() { result = streamArgument }
}

module FilePositionZeroFlowConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node node) {
node.asIndirectExpr().(FunctionCall).getTarget().hasGlobalOrStdName("fopen")
}

predicate isSink(DataFlow::Node node) {
exists(FunctionCall fc |
fc.getTarget().hasGlobalOrStdName("ungetc") and
node.asIndirectExpr() = fc.getArgument(1)
)
}

predicate isBarrierIn(DataFlow::Node node) {
exists(MoveStreamPositionCall fc | node.asIndirectExpr() = fc.getStreamArgument())
}
}

module FilePositionZeroFlow = DataFlow::Global<FilePositionZeroFlowConfig>;

import FilePositionZeroFlow::PathGraph

from FilePositionZeroFlow::PathNode sink, FilePositionZeroFlow::PathNode source
where
not isExcluded(sink.getNode().asExpr(), Language4Package::ungetcCallOnStreamPositionZeroQuery()) and
FilePositionZeroFlow::flowPath(source, sink)
select sink.getNode(), source, sink,
"Obsolescent call to ungetc on file stream $@ at position zero.", source, source.toString()
24 changes: 24 additions & 0 deletions c/misra/src/rules/RULE-1-5/UseOfObsoleteMacroAtomicVarInit.ql
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
/**
* @id c/misra/use-of-obsolete-macro-atomic-var-init
* @name RULE-1-5: Disallowed usage of obsolete macro ATOMIC_VAR_INIT compiled as C18
* @description The macro ATOMIC_VAR_INIT is has been declared an obsolescent language feature since
* C18.
* @kind problem
* @precision very-high
* @problem.severity recommendation
* @tags external/misra/id/rule-1-5
* maintainability
* readability
* external/misra/c/2012/amendment3
* external/misra/obligation/required
*/

import cpp
import codingstandards.c.misra

from MacroInvocation invoke
where
not isExcluded(invoke, Language4Package::useOfObsoleteMacroAtomicVarInitQuery()) and
invoke.getMacroName() = "ATOMIC_VAR_INIT"
select invoke,
"Usage of macro ATOMIC_VAR_INIT() is declared obscelescent in C18, and discouraged in earlier C versions."
44 changes: 5 additions & 39 deletions c/misra/src/rules/RULE-8-2/FunctionTypesNotInPrototypeForm.ql
Original file line number Diff line number Diff line change
Expand Up @@ -14,44 +14,10 @@

import cpp
import codingstandards.c.misra
import codingstandards.cpp.Identifiers
import codingstandards.cpp.rules.functiontypesnotinprototypeformshared.FunctionTypesNotInPrototypeFormShared

/**
* `Parameter`s without names
*/
class UnnamedParameter extends Parameter {
UnnamedParameter() { not this.isNamed() }
class FunctionTypesNotInPrototypeFormQuery extends FunctionTypesNotInPrototypeFormSharedSharedQuery {
FunctionTypesNotInPrototypeFormQuery() {
this = Declarations4Package::functionTypesNotInPrototypeFormQuery()
}
}

/*
* This is a copy of the private `hasZeroParamDecl` predicate from the standard set of
* queries as of the `codeql-cli/2.11.2` tag in `github/codeql`.
*/

predicate hasZeroParamDecl(Function f) {
exists(FunctionDeclarationEntry fde | fde = f.getADeclarationEntry() |
not fde.isImplicit() and
not fde.hasVoidParamList() and
fde.getNumberOfParameters() = 0 and
not fde.isDefinition()
)
}

from Function f, string msg
where
not isExcluded(f, Declarations4Package::functionTypesNotInPrototypeFormQuery()) and
f instanceof InterestingIdentifiers and
(
f.getAParameter() instanceof UnnamedParameter and
msg = "Function " + f + " declares parameter that is unnamed."
or
hasZeroParamDecl(f) and
msg = "Function " + f + " does not specify void for no parameters present."
or
//parameters declared in declaration list (not in function signature)
//have no prototype
not f.isPrototyped() and
not hasZeroParamDecl(f) and
msg = "Function " + f + " declares parameter in unsupported declaration list."
)
select f, msg
Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,11 @@

import cpp
import codingstandards.c.misra
import codingstandards.cpp.rules.missingstaticspecifierobjectredeclarationshared.MissingStaticSpecifierObjectRedeclarationShared

from VariableDeclarationEntry redeclaration, VariableDeclarationEntry de
where
not isExcluded(redeclaration,
Declarations5Package::missingStaticSpecifierObjectRedeclarationCQuery()) and
//following implies de != redeclaration
de.hasSpecifier("static") and
not redeclaration.hasSpecifier("static") and
de.getDeclaration().isTopLevel() and
redeclaration.getDeclaration() = de.getDeclaration()
select redeclaration, "The redeclaration of $@ with internal linkage misses the static specifier.",
de, de.getName()
class MissingStaticSpecifierObjectRedeclarationCQuery extends MissingStaticSpecifierObjectRedeclarationSharedSharedQuery
{
MissingStaticSpecifierObjectRedeclarationCQuery() {
this = Declarations5Package::missingStaticSpecifierObjectRedeclarationCQuery()
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
| test.c:37:3:37:6 | call to gets | Call to obsolescent function 'gets'. |
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
rules/RULE-1-5/CallToObsolescentFunctionGets.ql
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
c/common/test/rules/functiontypesnotinprototypeformshared/FunctionTypesNotInPrototypeFormShared.ql
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
| test.c:22:1:22:14 | #define true 3 | Invalid define of boolean standard macro 'true'. |
| test.c:23:1:23:15 | #define false 3 | Invalid define of boolean standard macro 'false'. |
| test.c:24:1:24:18 | #define bool int * | Invalid define of boolean standard macro 'bool'. |
| test.c:25:1:25:11 | #undef true | Invalid undefine of boolean standard macro 'true'. |
| test.c:26:1:26:12 | #undef false | Invalid undefine of boolean standard macro 'false'. |
| test.c:27:1:27:11 | #undef bool | Invalid undefine of boolean standard macro 'bool'. |
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
rules/RULE-1-5/InvalidDefineOrUndefOfStdBoolMacro.ql
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
c/common/test/rules/missingstaticspecifierfunctionredeclarationshared/MissingStaticSpecifierFunctionRedeclarationShared.ql
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
c/common/test/rules/missingstaticspecifierobjectredeclarationshared/MissingStaticSpecifierObjectRedeclarationShared.ql
Loading

0 comments on commit 373b793

Please sign in to comment.