Skip to content

Implement Language4 package, banning obsolete language features. #730

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Show file tree
Hide file tree
Changes from 9 commits
Commits
Show all changes
17 commits
Select commit Hold shift + click to select a range
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
25 changes: 25 additions & 0 deletions c/misra/src/rules/RULE-1-5/CallToReallocWithSizeZero.ql
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
/**
* @id c/misra/call-to-realloc-with-size-zero
* @name RULE-1-5: Disallowed size argument value equal to zero in call to realloc
* @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

from FunctionCall call, Expr arg
where
not isExcluded(call, Language4Package::callToReallocWithSizeZeroQuery()) and
call.getTarget().hasGlobalOrStdName("realloc") and
arg = call.getArgument(1) and
upperBound(arg) = 0
select arg, "Calling realloc with size zero results in implementation-defined behavior."
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 + "'."
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."
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
| test.c:11:14:11:14 | 0 | Calling realloc with size zero results in implementation-defined behavior. |
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
rules/RULE-1-5/CallToReallocWithSizeZero.ql
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
| test.c:38:6:38:7 | f2 | Function f2 does not specify void for no parameters present. |
| test.c:42:5:42:6 | f5 | Function f5 declares parameter in unsupported declaration list. |
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
rules/RULE-8-2/FunctionTypesNotInPrototypeForm.ql
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
| test.c:21:1:21:14 | #define true 3 | Invalid define of boolean standard macro 'true'. |
| test.c:22:1:22:15 | #define false 3 | Invalid define of boolean standard macro 'false'. |
| test.c:23:1:23:18 | #define bool int * | Invalid define of boolean standard macro 'bool'. |
| test.c:24:1:24:11 | #undef true | Invalid undefine of boolean standard macro 'true'. |
| test.c:25:1:25:12 | #undef false | Invalid undefine of boolean standard macro 'false'. |
| test.c:26:1:26: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,3 @@
| test.c:8:12:8:17 | call to malloc | Use of banned dynamic memory allocation. |
| test.c:11:3:11:9 | call to realloc | Use of banned dynamic memory allocation. |
| test.c:14:3:14:9 | call to realloc | Use of banned dynamic memory allocation. |
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
rules/RULE-21-3/MemoryAllocDeallocFunctionsOfStdlibhUsed.ql
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
| test.c:35:12:35:13 | declaration of g5 | The redeclaration of $@ with internal linkage misses the static specifier. | test.c:34:12:34:13 | definition of g5 | g5 |
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
rules/RULE-8-8/MissingStaticSpecifierObjectRedeclarationC.ql
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
| test.c:53:3:53:8 | call to ungetc | Call to banned function ungetc. |
| test.c:56:3:56:7 | call to fread | Call to banned function fread. |
| test.c:58:3:58:8 | call to ungetc | Call to banned function ungetc. |
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
rules/RULE-21-6/StandardLibraryInputoutputFunctionsUsed.ql
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
| test.c:28:18:28:36 | ATOMIC_VAR_INIT(value) | Usage of macro ATOMIC_VAR_INIT() is declared obscelescent in C18, and discouraged in earlier C versions. |
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
rules/RULE-1-5/UseOfObsoleteMacroAtomicVarInit.ql
59 changes: 59 additions & 0 deletions c/misra/test/rules/RULE-1-5/test.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
#include "stdatomic.h"
#include "stdbool.h"
#include "stdio.h"
#include "stdlib.h"

void f1(void) {
// malloc() is not obsolete, but banned by Rule 21.3
int *t = malloc(10); // COMPLIANT[False Negative]

// Obsolete usage of realloc.
realloc(t, 0); // NON-COMPLIANT

// Valid usage of realloc, but all use of realloc is banned by Rule 21.3
realloc(t, 20); // NON-COMPLIANT
}

extern const int g1; // COMPLIANT
const extern int g2; // NON-COMPLIANT

#define MY_TRUE 3 // COMPLIANT
#define true 3 // NON-COMPLIANT
#define false 3 // NON-COMPLIANT
#define bool int * // NON-COMPLIANT
#undef true // NON-COMPLIANT
#undef false // NON-COMPLIANT
#undef bool // NON-COMPLIANT

_Atomic int g3 = ATOMIC_VAR_INIT(18); // NON-COMPLIANT
_Atomic int g4 = 18; // COMPLIANT

// The following cases are already covered by other rules:

// Rule 8.8:
static int g5 = 3; // COMPLIANT
extern int g5; // NON-COMPLIANT

// Rule 8.2:
void f2(); // NON-COMPLIANT
void f3(void); // COMPLIANT

void f4(int p1){}; // COMPLIANT
int f5(x) // NON_COMPLIANT
int x;
{ return 1; }

// Rule 21.6 covers the below cases:
void f6(void) {
// `gets` was removed from C11.
// gets(stdin); // NON_COMPLIANT

FILE *file = fopen("", 0);
// Obsolete usage of ungetc.
ungetc('c', file); // NON-COMPLIANT

char buf[10];
fread(buf, sizeof(buf), 10, file);
// This is not an obsolete usage of ungetc, but ungetc isn't allowed.
ungetc('c', file); // NON-COMPLIANT[FALSE NEGATIVE]
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
| test.c:8:15:8:20 | call to malloc | Use of banned dynamic memory allocation. |
| test.c:9:15:9:20 | call to calloc | Use of banned dynamic memory allocation. |
| test.c:10:8:10:14 | call to realloc | Use of banned dynamic memory allocation. |
| test.c:11:3:11:6 | call to free | Use of banned dynamic memory deallocation. |
| test.c:12:3:12:6 | call to free | Use of banned dynamic memory deallocation. |
| test.c:13:15:13:20 | call to malloc | Use of banned dynamic memory allocation. |
| test.c:14:15:14:20 | call to calloc | Use of banned dynamic memory allocation. |
| test.c:15:8:15:14 | call to realloc | Use of banned dynamic memory allocation. |
| test.c:16:3:16:6 | call to free | Use of banned dynamic memory deallocation. |
| test.c:17:3:17:6 | call to free | Use of banned dynamic memory deallocation. |
5 changes: 5 additions & 0 deletions c/misra/test/rules/RULE-21-3/test.c
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
// Note: A subset of these cases are also tested in c/misra/test/rules/RULE-1-5
// via a MemoryAllocDeallocFunctionsOfStdlibhUsed.qlref and .expected file in
// that directory. Changes to these tests may require updating the test code or
// expectations in that directory as well.

#include <stdio.h>
#include <stdlib.h>
void f2();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
| test.c:8:10:8:14 | call to scanf | Call to banned function scanf. |
| test.c:9:5:9:10 | call to printf | Call to banned function printf. |
| test.c:16:16:16:21 | call to fgetwc | Call to banned function fgetwc. |
| test.c:17:5:17:12 | call to putwchar | Call to banned function putwchar. |
| test.c:22:7:22:10 | call to puts | Call to banned function puts. |
| test.c:24:7:24:10 | call to puts | Call to banned function puts. |
| test.c:26:5:26:8 | call to puts | Call to banned function puts. |
| test.c:13:10:13:14 | call to scanf | Call to banned function scanf. |
| test.c:14:5:14:10 | call to printf | Call to banned function printf. |
| test.c:21:16:21:21 | call to fgetwc | Call to banned function fgetwc. |
| test.c:22:5:22:12 | call to putwchar | Call to banned function putwchar. |
| test.c:27:7:27:10 | call to puts | Call to banned function puts. |
| test.c:29:7:29:10 | call to puts | Call to banned function puts. |
| test.c:31:5:31:8 | call to puts | Call to banned function puts. |
5 changes: 5 additions & 0 deletions c/misra/test/rules/RULE-21-6/test.c
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
// Note: A subset of these cases are also tested in c/misra/test/rules/RULE-1-5
// via a StandardLibraryInputoutputFunctionsUsed.qlref and .expected file in
// that directory. Changes to these tests may require updating the test code or
// expectations in that directory as well.

#include <errno.h>
#include <locale.h>
#include <stdio.h>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
| test.c:3:6:3:7 | f1 | Function f1 declares parameter that is unnamed. |
| test.c:4:6:4:7 | f2 | Function f2 does not specify void for no parameters present. |
| test.c:5:6:5:7 | f3 | Function f3 does not specify void for no parameters present. |
| test.c:7:5:7:6 | f5 | Function f5 declares parameter in unsupported declaration list. |
| test.c:8:6:8:7 | f1 | Function f1 declares parameter that is unnamed. |
| test.c:9:6:9:7 | f2 | Function f2 does not specify void for no parameters present. |
| test.c:10:6:10:7 | f3 | Function f3 does not specify void for no parameters present. |
| test.c:12:5:12:6 | f5 | Function f5 declares parameter in unsupported declaration list. |
5 changes: 5 additions & 0 deletions c/misra/test/rules/RULE-8-2/test.c
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
// Note: A subset of these cases are also tested in c/misra/test/rules/RULE-1-5
// via a FunctionTypesNotInPrototypeForm.qlref and .expected file in that
// directory. Changes to these tests may require updating the test code or
// expectations in that directory as well.

void f(int x); // COMPLIANT
void f0(void); // COMPLIANT
void f1(int); // NON_COMPLIANT
Expand Down
Original file line number Diff line number Diff line change
@@ -1 +1 @@
| test.c:2:12:2:12 | declaration of g | The redeclaration of $@ with internal linkage misses the static specifier. | test.c:1:12:1:12 | definition of g | g |
| test.c:7:12:7:12 | declaration of g | The redeclaration of $@ with internal linkage misses the static specifier. | test.c:6:12:6:12 | definition of g | g |
5 changes: 5 additions & 0 deletions c/misra/test/rules/RULE-8-8/test.c
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
// Note: A subset of these cases are also tested in c/misra/test/rules/RULE-1-5
// via a MissingStaticSpecifierObjectRedeclarationC.qlref and .expected file in
// that directory. Changes to these tests may require updating the test code or
// expectations in that directory as well.

static int g = 0;
extern int g; // NON_COMPLIANT

Expand Down
61 changes: 61 additions & 0 deletions cpp/common/src/codingstandards/cpp/exclusions/c/Language4.qll
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
//** THIS FILE IS AUTOGENERATED, DO NOT MODIFY DIRECTLY. **/
import cpp
import RuleMetadata
import codingstandards.cpp.exclusions.RuleMetadata

newtype Language4Query =
TUseOfObsoleteMacroAtomicVarInitQuery() or
TInvalidDefineOrUndefOfStdBoolMacroQuery() or
TCallToReallocWithSizeZeroQuery()

predicate isLanguage4QueryMetadata(Query query, string queryId, string ruleId, string category) {
query =
// `Query` instance for the `useOfObsoleteMacroAtomicVarInit` query
Language4Package::useOfObsoleteMacroAtomicVarInitQuery() and
queryId =
// `@id` for the `useOfObsoleteMacroAtomicVarInit` query
"c/misra/use-of-obsolete-macro-atomic-var-init" and
ruleId = "RULE-1-5" and
category = "required"
or
query =
// `Query` instance for the `invalidDefineOrUndefOfStdBoolMacro` query
Language4Package::invalidDefineOrUndefOfStdBoolMacroQuery() and
queryId =
// `@id` for the `invalidDefineOrUndefOfStdBoolMacro` query
"c/misra/invalid-define-or-undef-of-std-bool-macro" and
ruleId = "RULE-1-5" and
category = "required"
or
query =
// `Query` instance for the `callToReallocWithSizeZero` query
Language4Package::callToReallocWithSizeZeroQuery() and
queryId =
// `@id` for the `callToReallocWithSizeZero` query
"c/misra/call-to-realloc-with-size-zero" and
ruleId = "RULE-1-5" and
category = "required"
}

module Language4Package {
Query useOfObsoleteMacroAtomicVarInitQuery() {
//autogenerate `Query` type
result =
// `Query` type for `useOfObsoleteMacroAtomicVarInit` query
TQueryC(TLanguage4PackageQuery(TUseOfObsoleteMacroAtomicVarInitQuery()))
}

Query invalidDefineOrUndefOfStdBoolMacroQuery() {
//autogenerate `Query` type
result =
// `Query` type for `invalidDefineOrUndefOfStdBoolMacro` query
TQueryC(TLanguage4PackageQuery(TInvalidDefineOrUndefOfStdBoolMacroQuery()))
}

Query callToReallocWithSizeZeroQuery() {
//autogenerate `Query` type
result =
// `Query` type for `callToReallocWithSizeZero` query
TQueryC(TLanguage4PackageQuery(TCallToReallocWithSizeZeroQuery()))
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ import InvalidMemory2
import Language1
import Language2
import Language3
import Language4
import Memory1
import Memory2
import Memory3
Expand Down Expand Up @@ -112,6 +113,7 @@ newtype TCQuery =
TLanguage1PackageQuery(Language1Query q) or
TLanguage2PackageQuery(Language2Query q) or
TLanguage3PackageQuery(Language3Query q) or
TLanguage4PackageQuery(Language4Query q) or
TMemory1PackageQuery(Memory1Query q) or
TMemory2PackageQuery(Memory2Query q) or
TMemory3PackageQuery(Memory3Query q) or
Expand Down Expand Up @@ -185,6 +187,7 @@ predicate isQueryMetadata(Query query, string queryId, string ruleId, string cat
isLanguage1QueryMetadata(query, queryId, ruleId, category) or
isLanguage2QueryMetadata(query, queryId, ruleId, category) or
isLanguage3QueryMetadata(query, queryId, ruleId, category) or
isLanguage4QueryMetadata(query, queryId, ruleId, category) or
isMemory1QueryMetadata(query, queryId, ruleId, category) or
isMemory2QueryMetadata(query, queryId, ruleId, category) or
isMemory3QueryMetadata(query, queryId, ruleId, category) or
Expand Down
Loading
Loading