Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions c/misra/src/codeql-suites/misra-c-2023.qls
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
- description: MISRA C 2023 - Third Edition, Second Revision
- qlpack: codeql/misra-c-coding-standards
- include:
kind:
- problem
- path-problem
tags contain:
- external/misra/c/2012/third-edition-first-revision
- external/misra/c/2012/amendment2
- external/misra/c/2012/amendment3
- external/misra/c/2012/amendment4
- exclude:
tags contain:
- external/misra/audit
- external/misra/strict
- external/misra/default-disabled
3 changes: 2 additions & 1 deletion c/misra/src/codeql-suites/misra-c-advisory.qls
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
- description: MISRA C 2023 (Advisory)
- description: MISRA C 2025 (Advisory)
- qlpack: codeql/misra-c-coding-standards
- include:
kind:
Expand All @@ -10,3 +10,4 @@
tags contain:
- external/misra/audit
- external/misra/default-disabled
- external/misra/legacy
2 changes: 1 addition & 1 deletion c/misra/src/codeql-suites/misra-c-audit.qls
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
- description: MISRA C 2023 (Audit)
- description: MISRA C 2025 (Audit)
- qlpack: codeql/misra-c-coding-standards
- include:
kind:
Expand Down
3 changes: 2 additions & 1 deletion c/misra/src/codeql-suites/misra-c-default.qls
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
- description: MISRA C 2023 (Default)
- description: MISRA C 2025 (Default)
- qlpack: codeql/misra-c-coding-standards
- include:
kind:
Expand All @@ -9,3 +9,4 @@
- external/misra/audit
- external/misra/strict
- external/misra/default-disabled
- external/misra/legacy
3 changes: 2 additions & 1 deletion c/misra/src/codeql-suites/misra-c-mandatory.qls
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
- description: MISRA C 2023 (Advisory)
- description: MISRA C 2025 (Mandatory)
- qlpack: codeql/misra-c-coding-standards
- include:
kind:
Expand All @@ -10,3 +10,4 @@
tags contain:
- external/misra/audit
- external/misra/default-disabled
- external/misra/legacy
3 changes: 2 additions & 1 deletion c/misra/src/codeql-suites/misra-c-required.qls
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
- description: MISRA C 2023 (Required)
- description: MISRA C 2025 (Required)
- qlpack: codeql/misra-c-coding-standards
- include:
kind:
Expand All @@ -10,3 +10,4 @@
tags contain:
- external/misra/audit
- external/misra/default-disabled
- external/misra/legacy
2 changes: 1 addition & 1 deletion c/misra/src/codeql-suites/misra-c-strict.qls
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
- description: MISRA C 2023 (Strict)
- description: MISRA C 2025 (Strict)
- qlpack: codeql/misra-c-coding-standards
- include:
kind:
Expand Down
108 changes: 108 additions & 0 deletions c/misra/src/codingstandards/c/misra/PlainNumericalTypes.qll
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
/** Provides the numeric-type detector shared by legacy and current directive wrappers. */

import cpp
import codingstandards.cpp.BuiltInNumericTypes

/** A numeric type covered by the legacy directive. */
private class NumericType extends BuiltInType {
NumericType() {
this.(CharType).isExplicitlySigned()
or
this.(CharType).isExplicitlyUnsigned()
or
this instanceof BuiltInIntegerType
or
this instanceof FloatType
or
this instanceof DoubleType
or
this instanceof LongDoubleType
or
this instanceof ComplexNumberType
}
}

/** A typedef name that encodes numeric width and signedness. */
private class SizedTypeName extends string {
string pattern;
int width;

bindingset[this]
pragma[inline]
SizedTypeName() {
pattern = "(u?int|c?float)(4|8|16|32|64|128)_t" and
this.regexpMatch(pattern) and
width = this.regexpCapture(pattern, 2).toInt()
}

/** Gets the width encoded by this name. */
bindingset[this]
pragma[inline]
int getWidth() { result = width }

/** Holds if this name denotes a complex type. */
bindingset[this]
pragma[inline]
predicate isComplex() { this.charAt(0) = "c" }
}

/** Holds if `type` has an invalid complex name, with `message` explaining why. */
private predicate forbiddenComplexType(CTypedefType type, string message) {
type.getName().(SizedTypeName).isComplex() and
(
if type.getBaseType().stripTopLevelSpecifiers() instanceof ComplexNumberType
then
type.getSize() * 8 != type.getName().(SizedTypeName).getWidth() * 2 and
message = "The typedef type " + type.getName() + " does not have its indicated real size."
else message = "The typedef type " + type.getName() + " is not a complex type."
)
}

/** Holds if `type` has an invalid real name, with `message` explaining why. */
private predicate forbiddenRealType(CTypedefType type, string message) {
not type.getName().(SizedTypeName).isComplex() and
(
if type.getBaseType().stripTopLevelSpecifiers() instanceof ComplexNumberType
then message = "The typedef name " + type.getName() + " does not indicate a complex type."
else (
type.getSize() * 8 != type.getName().(SizedTypeName).getWidth() and
message = "The typedef type " + type.getName() + " does not have its indicated size."
)
)
}

/** Holds if `type` is a forbidden alias, with `message` explaining why. */
private predicate forbiddenAlias(CTypedefType type, string message) {
if type.getName() instanceof SizedTypeName
then forbiddenRealType(type, message) or forbiddenComplexType(type, message)
else (
(
type.getBaseType() instanceof NumericType
or
forbiddenAlias(type.getBaseType(), _)
) and
message = "The type " + type.getName() + " is not an alias to a fixed-width numeric type."
)
}

/** Holds if `element` violates the legacy directive, with `message` explaining why. */
predicate problems(Element element, string message) {
exists(Variable variable | variable = element |
variable.getType() instanceof NumericType and
not variable instanceof ExcludedVariable and
message = "The type " + variable.getType() + " is not a fixed-width numeric type."
)
or
forbiddenAlias(element, message)
}

/** Holds if `element` declares or aliases a real or complex floating-point type. */
predicate hasFloatingType(Element element) {
exists(Type type |
type = element.(Variable).getType() or type = element.(CTypedefType).getBaseType()
|
type.stripType() instanceof FloatingPointType
or
type.stripType() instanceof ComplexNumberType
)
}
22 changes: 22 additions & 0 deletions c/misra/src/codingstandards/c/misra/ReservedMacroNames.qll
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
/** Provides the reserved-macro detector shared by MISRA C guideline identities. */

import cpp
import codingstandards.cpp.Naming

/** Gets a reserved name defined or undefined by `directive`. */
string getReservedMacroName(PreprocessorDirective directive) {
(
directive.(Macro).hasName(result)
or
directive.(PreprocessorUndef).getName() = result
) and
(
Naming::Cpp14::hasStandardLibraryMacroName(result)
or
Naming::Cpp14::hasStandardLibraryObjectName(result)
or
result.regexpMatch("_.*")
or
result = "defined"
)
}
25 changes: 25 additions & 0 deletions c/misra/src/codingstandards/c/misra/SinglePointOfExit.qll
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
/** Provides the exit detector shared by Advisory and Disapplied query wrappers. */

import cpp

/** A return statement explicitly written in source code. */
private class UserReturn extends ReturnStmt {
UserReturn() { not this.isCompilerGenerated() }
}

/** Holds if `function` has an offending `statement`, with `message` explaining why. */
predicate problems(Function function, string message, ReturnStmt statement) {
function.hasDefinition() and
count(function.getBlock()) = 1 and
not function.isCompilerGenerated() and
statement instanceof UserReturn and
statement.getEnclosingFunction() = function and
(
count(UserReturn other | other.getEnclosingFunction() = function) > 1 and
message = "Function has more than one $@."
or
count(UserReturn other | other.getEnclosingFunction() = function) = 1 and
not function.getBlock().getLastStmt() instanceof UserReturn and
message = "The $@ is not the last statement of the function."
)
}
25 changes: 25 additions & 0 deletions c/misra/src/rules/DIR-1-2/LanguageExtensionsShouldBeMinimized.ql
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
/**
* @id c/misra/language-extensions-should-be-minimized
* @name DIR-1-2: Language extensions should be minimized
* @description Language extensions are not portable to other compilers and their use should be
* minimized.
* @kind problem
* @precision high
* @problem.severity error
* @tags external/misra/id/dir-1-2
* maintainability
* readability
* external/misra/c/2025
* external/misra/obligation/advisory
*/

import cpp
import codingstandards.c.misra
import codingstandards.cpp.AlertReporting
import codingstandards.c.Extensions

from CCompilerExtension extension
where
not isExcluded(MacroUnwrapper<CCompilerExtension>::unwrapElement(extension),
Language3Package::languageExtensionsShouldBeMinimizedQuery())
select MacroUnwrapper<CCompilerExtension>::unwrapElement(extension), extension.getMessage()
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
/**
* @id c/misra/plain-integer-type-used-over-explicit-typedef
* @name DIR-4-6: Plain integer types should use explicit typedefs
* @description Using integer typedefs makes their size and signedness explicit.
* @kind problem
* @precision high
* @problem.severity error
* @tags external/misra/id/dir-4-6
* external/misra/c/2025
* external/misra/obligation/advisory
*/

import cpp
import codingstandards.c.misra
import codingstandards.c.misra.PlainNumericalTypes

from Element element, string message
where
not isExcluded(element, Types1Package::plainIntegerTypeUsedOverExplicitTypedefQuery()) and
problems(element, message) and
not hasFloatingType(element)
select element, message
Original file line number Diff line number Diff line change
Expand Up @@ -8,110 +8,16 @@
* @problem.severity error
* @tags external/misra/id/dir-4-6
* external/misra/c/2012/third-edition-first-revision
* external/misra/legacy
* external/misra/obligation/advisory
*/

import cpp
import codingstandards.c.misra
import codingstandards.cpp.BuiltInNumericTypes

class BuiltInNumericType extends BuiltInType {
BuiltInNumericType() {
/* Exclude the plain char because it does not count as a numeric type */
this.(CharType).isExplicitlySigned()
or
this.(CharType).isExplicitlyUnsigned()
or
this instanceof BuiltInIntegerType
or
this instanceof FloatType
or
this instanceof DoubleType
or
this instanceof LongDoubleType
or
this instanceof ComplexNumberType
}
}

predicate forbiddenBuiltinNumericUsedInDecl(Variable var, string message) {
var.getType() instanceof BuiltInNumericType and
not var instanceof ExcludedVariable and
message = "The type " + var.getType() + " is not a fixed-width numeric type."
}

class SizedTypeString extends string {
string pattern;
int size;

bindingset[this]
pragma[inline]
SizedTypeString() {
pattern = "(u?int|c?float)(4|8|16|32|64|128)_t" and
this.regexpMatch(pattern) and
size = this.regexpCapture(pattern, 2).toInt()
}

bindingset[this]
pragma[inline]
int getSize() { result = size }

bindingset[this]
pragma[inline]
predicate isComplex() { this.charAt(0) = "c" }
}

predicate forbiddenComplexType(CTypedefType typedef, string message) {
typedef.getName().(SizedTypeString).isComplex() and
(
if typedef.getBaseType().stripTopLevelSpecifiers() instanceof ComplexNumberType
then
typedef.getSize() * 8 != typedef.getName().(SizedTypeString).getSize() * 2 and
message = "The typedef type " + typedef.getName() + " does not have its indicated real size."
else message = "The typedef type " + typedef.getName() + " is not a complex type."
)
}

predicate forbiddenRealType(CTypedefType typedef, string message) {
not typedef.getName().(SizedTypeString).isComplex() and
(
if typedef.getBaseType().stripTopLevelSpecifiers() instanceof ComplexNumberType
then message = "The typedef name " + typedef.getName() + " does not indicate a complex type."
else (
typedef.getSize() * 8 != typedef.getName().(SizedTypeString).getSize() and
message = "The typedef type " + typedef.getName() + " does not have its indicated size."
)
)
}

predicate forbiddenTypedef(CTypedefType typedef, string message) {
/* If the typedef's name contains an explicit size */
(
if typedef.getName() instanceof SizedTypeString
then (
forbiddenRealType(typedef, message)
or
forbiddenComplexType(typedef, message)
) else (
(
// type def is to a built in numeric type
typedef.getBaseType() instanceof BuiltInNumericType and
// but does not include the size in the name
not typedef.getName() instanceof SizedTypeString
or
// this is a typedef to a forbidden type def
forbiddenTypedef(typedef.getBaseType(), _)
) and
message = "The type " + typedef.getName() + " is not an alias to a fixed-width numeric type."
)
)
}
import codingstandards.c.misra.PlainNumericalTypes

from Element elem, string message
where
not isExcluded(elem, Types1Package::plainNumericalTypeUsedOverExplicitTypedefQuery()) and
(
forbiddenBuiltinNumericUsedInDecl(elem, message) or
forbiddenTypedef(elem, message)
)
problems(elem, message)
select elem, message
Loading
Loading