Skip to content

Implement MISRA RULE-21-13 and RULE-21-15 #190

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 44 commits into from
Mar 25, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
44 commits
Select commit Hold shift + click to select a range
fcc4fc6
update rules.csv
jeongsoolee09 Feb 16, 2023
05d577f
Update rule package description file
jeongsoolee09 Feb 16, 2023
13feea8
Create rule files
jeongsoolee09 Feb 17, 2023
ea40969
update ql files and add test.c for RULE-21-13
jeongsoolee09 Feb 17, 2023
cf0d756
Implement RULE-21-13
jeongsoolee09 Feb 17, 2023
5104114
Refine RULE-21-13 and its unit test
jeongsoolee09 Feb 17, 2023
e0e0193
Draft of RULE-21-15
jeongsoolee09 Feb 17, 2023
3185856
Refine RULE-21-15
jeongsoolee09 Feb 17, 2023
f9deae5
Refine RULE-21-15
jeongsoolee09 Feb 17, 2023
eca1f26
Refine RULE-21-15
jeongsoolee09 Feb 17, 2023
4064b6b
Update `.expected` files
jeongsoolee09 Feb 18, 2023
9adcc36
Refine analysis messages
jeongsoolee09 Feb 18, 2023
75ea8ff
Format test.c
jeongsoolee09 Feb 18, 2023
cc43205
Merge branch 'main' into jeongsoolee09/MISRA_21-13_and-21-15
jeongsoolee09 Feb 18, 2023
9336a3e
Some minor comments
jeongsoolee09 Feb 21, 2023
f798abe
Merge branch 'jeongsoolee09/MISRA_21-13_and-21-15' of github.com:gith…
jeongsoolee09 Feb 21, 2023
f09cc5d
Minor comment
jeongsoolee09 Feb 21, 2023
ddb85d0
Oh no
jeongsoolee09 Feb 21, 2023
9be18f2
Oh no (2)
jeongsoolee09 Feb 21, 2023
044350b
Add `CtypeGetcharFunctions` modelling class
jeongsoolee09 Feb 23, 2023
71f4dc4
Minor comments
jeongsoolee09 Feb 23, 2023
4d55a70
Modify/Add test cases to 21-13
jeongsoolee09 Feb 23, 2023
a9f2fbe
checkpoint
jeongsoolee09 Feb 23, 2023
9c1b343
Merge branch 'main' into jeongsoolee09/MISRA_21-13_and-21-15
jeongsoolee09 Feb 24, 2023
0aad1c6
Model getchar, Finalize query
jeongsoolee09 Mar 7, 2023
9456800
Merge branch 'main' into jeongsoolee09/MISRA_21-13_and-21-15
jeongsoolee09 Mar 7, 2023
c66a9d6
Minor comments && Update outdated .expected
jeongsoolee09 Mar 14, 2023
e3075df
Merge branch 'jeongsoolee09/MISRA_21-13_and-21-15' of github.com:gith…
jeongsoolee09 Mar 14, 2023
a0a2615
STR37-C: Handle macros in <ctype.h>
lcartey Mar 10, 2023
6d477c0
remove an empty comment
jeongsoolee09 Mar 15, 2023
9e60a8f
Use UseOfToOrIsChar from CharFunctions
jeongsoolee09 Mar 15, 2023
7ee8379
Remove redundant predicate uses
jeongsoolee09 Mar 15, 2023
f7eadb0
Merge branch 'main' into jeongsoolee09/MISRA_21-13_and-21-15
jeongsoolee09 Mar 15, 2023
aa3b81f
Add .expected for clang and qcc
jeongsoolee09 Mar 18, 2023
bf6e11d
Merge branch 'jeongsoolee09/MISRA_21-13_and-21-15' of github.com:gith…
jeongsoolee09 Mar 18, 2023
ea4383e
Merge branch 'main' into jeongsoolee09/MISRA_21-13_and-21-15
jeongsoolee09 Mar 18, 2023
4c9f192
Add FP suspect case
jeongsoolee09 Mar 20, 2023
f9f8ecb
Oops, wrong branch
jeongsoolee09 Mar 20, 2023
535470f
Merge branch 'jeongsoolee09/MISRA_21-13_and-21-15' of github.com:gith…
jeongsoolee09 Mar 20, 2023
3928d06
Add test for gcc
jeongsoolee09 Mar 23, 2023
2a38ec7
Merge branch 'main' into jeongsoolee09/MISRA_21-13_and-21-15
jeongsoolee09 Mar 24, 2023
e2ef453
Put back StandardLibraryFunctionTypes
jeongsoolee09 Mar 24, 2023
63b1256
Modify RuleMetadata
jeongsoolee09 Mar 24, 2023
7dba082
Rename .expected.gcc file
jeongsoolee09 Mar 24, 2023
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
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
/**
* @id c/misra/ctype-function-arg-not-unsigned-char-or-eof
* @name RULE-21-13: <ctype.h> function arguments shall be represented as unsigned char
* @description Passing arguments to <ctype.h> functions outside the range of unsigned char or EOF
* causes undefined behavior.
* @kind problem
* @precision very-high
* @problem.severity error
* @tags external/misra/id/rule-21-13
* external/misra/obligation/mandatory
*/

import cpp
import codingstandards.c.misra
import codingstandards.cpp.CharFunctions
import semmle.code.cpp.rangeanalysis.SimpleRangeAnalysis

from UseOfToOrIsChar ctypeCall
where
not isExcluded(ctypeCall,
StandardLibraryFunctionTypesPackage::ctypeFunctionArgNotUnsignedCharOrEofQuery()) and
not exists(Expr ctypeCallArgument | ctypeCallArgument = ctypeCall.getConvertedArgument() |
/* The argument's value should be in the EOF + `unsigned char` range. */
-1 <= lowerBound(ctypeCallArgument) and upperBound(ctypeCallArgument) <= 255
)
select ctypeCall,
"The <ctype.h> function " + ctypeCall + " accepts an argument " + ctypeCall.getConvertedArgument()
+ " that is not an unsigned char nor an EOF."
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
/**
* @id c/misra/memcpy-memmove-memcmp-arg-not-pointers-to-compatible-types
* @name RULE-21-15: The pointer arguments to the Standard Library functions memcpy, memmove and memcmp shall be pointers
* @description Passing pointers to incompatible types as arguments to memcpy, memmove and memcmp
* indicates programmers' confusion.
* @kind problem
* @precision very-high
* @problem.severity error
* @tags external/misra/id/rule-21-15
* external/misra/obligation/required
*/

import cpp
import codingstandards.c.misra
import codingstandards.c.Pointers

class MemCmpMoveCpy extends Function {
// Couldn't extend BuiltInFunction because it misses `memcmp`
MemCmpMoveCpy() {
this.getName().regexpMatch("mem(cmp|cpy|move)") and
this.getADeclaration().getAFile().(HeaderFile).getBaseName() = "string.h"
}
}

from FunctionCall fc
where
not isExcluded(fc,
StandardLibraryFunctionTypesPackage::memcpyMemmoveMemcmpArgNotPointersToCompatibleTypesQuery()) and
exists(MemCmpMoveCpy memfun, Type dstType, Type srcType | fc.getTarget() = memfun |
dstType = fc.getArgument(0).getUnspecifiedType() and
srcType = fc.getArgument(1).getUnspecifiedType() and
(
/* Case 1: dst and src are pointer types */
dstType instanceof PointerType and
srcType instanceof PointerType
or
/* Case 2: dst and src are array types */
dstType instanceof ArrayType and
srcType instanceof ArrayType
) and
not dstType = srcType
)
select fc,
"The dest type " + fc.getArgument(0).getUnspecifiedType() + " and src type " +
fc.getArgument(1).getUnspecifiedType() + " of function " + fc.getTarget() +
" are not compatible."
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
| test.c:14:7:14:13 | call to isalnum | The <ctype.h> function call to isalnum accepts an argument c3 that is not an unsigned char nor an EOF. |
| test.c:20:7:20:13 | call to isalnum | The <ctype.h> function call to isalnum accepts an argument c4 that is not an unsigned char nor an EOF. |
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
| test.c:14:7:14:17 | isalnum(c) | The <ctype.h> function isalnum(c) accepts an argument (...) that is not an unsigned char nor an EOF. |
| test.c:20:7:20:17 | isalnum(c) | The <ctype.h> function isalnum(c) accepts an argument (...) that is not an unsigned char nor an EOF. |
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
| test.c:14:7:14:17 | isalnum(c) | The <ctype.h> function isalnum(c) accepts an argument (...) that is not an unsigned char nor an EOF. |
| test.c:20:7:20:17 | isalnum(c) | The <ctype.h> function isalnum(c) accepts an argument (...) that is not an unsigned char nor an EOF. |
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
| test.c:14:7:14:17 | isalnum(c) | The <ctype.h> function isalnum(c) accepts an argument (...) that is not an unsigned char nor an EOF. |
| test.c:20:7:20:17 | isalnum(c) | The <ctype.h> function isalnum(c) accepts an argument (...) that is not an unsigned char nor an EOF. |
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
rules/RULE-21-13/CtypeFunctionArgNotUnsignedCharOrEof.ql
39 changes: 39 additions & 0 deletions c/misra/test/rules/RULE-21-13/test.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
#include <ctype.h>
#include <stdio.h>

void sample() {
unsigned char c1 = 'c';
int r1 = isalnum(
c1); // COMPLIANT: ASCII 99 is within unsigned char range of [0, 255]
int r2 = isalnum(EOF); // COMPLIANT: EOF (-1)

int x3 = 256;
int x4 = x3;
int c3 = x4;
int r3 =
isalnum(c3); // NON_COMPLIANT: is outside unsigned char range of [0, 255]

unsigned char x5 = EOF;
unsigned char x6 = x5;
int c4 = x6 + 10000;
int r4 =
isalnum(c4); // NON_COMPLIANT: is outside unsigned char range of [0, 255]

int c5 = getchar();
int r5 = isalnum(
c5); // COMPLIANT: <stdio.h> source functions like getchar are modelled

unsigned char x7;
int c6;
if (x7 == 1) {
c6 = EOF;
} else {
c6 = 'c';
}
int r6 =
isalnum(c6); // COMPLIANT: either control branch make this call compliant

int r7 = isalnum(EOF); // COMPLIANT: EOF (-1)
}

int main() { return 0; }
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
| test.c:6:3:6:8 | call to memcpy | The dest type int * and src type char * of function memcpy are not compatible. |
| test.c:18:3:18:9 | call to memmove | The dest type char[9] and src type int[2] of function memmove are not compatible. |
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
rules/RULE-21-15/MemcpyMemmoveMemcmpArgNotPointersToCompatibleTypes.ql
25 changes: 25 additions & 0 deletions c/misra/test/rules/RULE-21-15/test.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
#include <string.h>

void sample() {
int from1 = 1000000;
char to1;
memcpy(&from1, &to1, 1); // NON_COMPLIANT, the types are not compatible

int from2 = 1000000;
int to2;
memcpy(&from2, &to2, 2); // COMPLIANT

char from3[] = "string";
char to3[7];
memmove(from3, to3, 7); // COMPLIANT

char from4[] = "sstringg";
int to4[2];
memmove(from4, to4, 8); // NON_COMPLIANT, despite being equal in byte counts

char from5[] = "STRING";
char to5[] = "string";
memcmp(from5, to5, 2); // COMPLIANT
}

int main() { return 0; }
1 change: 0 additions & 1 deletion cpp/common/src/codingstandards/cpp/CharFunctions.qll
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ private string getCToOrIsName() {
* the structure of the macro, or
*/
abstract class UseOfToOrIsChar extends Element {
/** */
abstract Expr getConvertedArgument();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,28 @@ private class CastEnumToIntegerSimpleRange extends SimpleRangeAnalysisExpr, Cast
override predicate dependsOnChild(Expr child) { child = getExpr() }
}

/**
* <stdio.h> functions that read a character from the STDIN,
* or return EOF if it fails to do so.
* Their return type is `int` by their signatures, but
* they actually return either an unsigned char or an EOF.
*/
private class CtypeGetcharFunctionsRange extends SimpleRangeAnalysisExpr, FunctionCall {
CtypeGetcharFunctionsRange() {
this.getTarget().getFile().(HeaderFile).getBaseName() = "stdio.h" and
this.getTarget().getName().regexpMatch("(fgetc|getc|getchar|)")
}

/* It can return an EOF, which is -1 on most implementations. */
override float getLowerBounds() { result = -1 }

/* Otherwise, it can return any unsigned char. */
override float getUpperBounds() { result = 255 }

/* No, its call does not depend on any of its child. */
override predicate dependsOnChild(Expr expr) { none() }
}

/**
* Gets the value of the expression `e`, if it is a constant.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ import Preprocessor6
import SideEffects1
import SideEffects2
import SignalHandlers
import StandardLibraryFunctionTypes
import Strings1
import Strings2
import Strings3
Expand Down Expand Up @@ -103,6 +104,7 @@ newtype TCQuery =
TSideEffects1PackageQuery(SideEffects1Query q) or
TSideEffects2PackageQuery(SideEffects2Query q) or
TSignalHandlersPackageQuery(SignalHandlersQuery q) or
TStandardLibraryFunctionTypesPackageQuery(StandardLibraryFunctionTypesQuery q) or
TStrings1PackageQuery(Strings1Query q) or
TStrings2PackageQuery(Strings2Query q) or
TStrings3PackageQuery(Strings3Query q) or
Expand Down Expand Up @@ -157,6 +159,7 @@ predicate isQueryMetadata(Query query, string queryId, string ruleId, string cat
isSideEffects1QueryMetadata(query, queryId, ruleId, category) or
isSideEffects2QueryMetadata(query, queryId, ruleId, category) or
isSignalHandlersQueryMetadata(query, queryId, ruleId, category) or
isStandardLibraryFunctionTypesQueryMetadata(query, queryId, ruleId, category) or
isStrings1QueryMetadata(query, queryId, ruleId, category) or
isStrings2QueryMetadata(query, queryId, ruleId, category) or
isStrings3QueryMetadata(query, queryId, ruleId, category) or
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
//** THIS FILE IS AUTOGENERATED, DO NOT MODIFY DIRECTLY. **/
import cpp
import RuleMetadata
import codingstandards.cpp.exclusions.RuleMetadata

newtype StandardLibraryFunctionTypesQuery =
TCtypeFunctionArgNotUnsignedCharOrEofQuery() or
TMemcpyMemmoveMemcmpArgNotPointersToCompatibleTypesQuery()

predicate isStandardLibraryFunctionTypesQueryMetadata(
Query query, string queryId, string ruleId, string category
) {
query =
// `Query` instance for the `ctypeFunctionArgNotUnsignedCharOrEof` query
StandardLibraryFunctionTypesPackage::ctypeFunctionArgNotUnsignedCharOrEofQuery() and
queryId =
// `@id` for the `ctypeFunctionArgNotUnsignedCharOrEof` query
"c/misra/ctype-function-arg-not-unsigned-char-or-eof" and
ruleId = "RULE-21-13" and
category = "mandatory"
or
query =
// `Query` instance for the `memcpyMemmoveMemcmpArgNotPointersToCompatibleTypes` query
StandardLibraryFunctionTypesPackage::memcpyMemmoveMemcmpArgNotPointersToCompatibleTypesQuery() and
queryId =
// `@id` for the `memcpyMemmoveMemcmpArgNotPointersToCompatibleTypes` query
"c/misra/memcpy-memmove-memcmp-arg-not-pointers-to-compatible-types" and
ruleId = "RULE-21-15" and
category = "required"
}

module StandardLibraryFunctionTypesPackage {
Query ctypeFunctionArgNotUnsignedCharOrEofQuery() {
//autogenerate `Query` type
result =
// `Query` type for `ctypeFunctionArgNotUnsignedCharOrEof` query
TQueryC(TStandardLibraryFunctionTypesPackageQuery(TCtypeFunctionArgNotUnsignedCharOrEofQuery()))
}

Query memcpyMemmoveMemcmpArgNotPointersToCompatibleTypesQuery() {
//autogenerate `Query` type
result =
// `Query` type for `memcpyMemmoveMemcmpArgNotPointersToCompatibleTypes` query
TQueryC(TStandardLibraryFunctionTypesPackageQuery(TMemcpyMemmoveMemcmpArgNotPointersToCompatibleTypesQuery()))
}
}
38 changes: 38 additions & 0 deletions rule_packages/c/StandardLibraryFunctionTypes.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
{
"MISRA-C-2012": {
"RULE-21-13": {
"properties": {
"obligation": "mandatory"
},
"queries": [
{
"description": "Passing arguments to <ctype.h> functions outside the range of unsigned char or EOF causes undefined behavior.",
"kind": "problem",
"name": "<ctype.h> function arguments shall be represented as unsigned char",
"precision": "very-high",
"severity": "error",
"short_name": "CtypeFunctionArgNotUnsignedCharOrEof",
"tags": []
}
],
"title": "Any value passed to a function in <ctype.h> shall be representable as an unsigned char or be the value EOF"
},
"RULE-21-15": {
"properties": {
"obligation": "required"
},
"queries": [
{
"description": "Passing pointers to incompatible types as arguments to memcpy, memmove and memcmp indicates programmers' confusion.",
"kind": "problem",
"name": "The pointer arguments to the Standard Library functions memcpy, memmove and memcmp shall be pointers",
"precision": "very-high",
"severity": "error",
"short_name": "MemcpyMemmoveMemcmpArgNotPointersToCompatibleTypes",
"tags": []
}
],
"title": "The pointer arguments to the Standard Library functions memcpy, memmove and memcmp shall be pointers to qualified or unqualified versions of compatible types"
}
}
}
4 changes: 2 additions & 2 deletions rules.csv
Original file line number Diff line number Diff line change
Expand Up @@ -755,9 +755,9 @@ c,MISRA-C-2012,RULE-21-9,Yes,Required,,,The Standard Library functions bsearch a
c,MISRA-C-2012,RULE-21-10,Yes,Required,,,The Standard Library time and date functions shall not be used,,Banned,Easy,
c,MISRA-C-2012,RULE-21-11,Yes,Required,,,The standard header file <tgmath.h> shall not be used,,Banned,Easy,
c,MISRA-C-2012,RULE-21-12,Yes,Advisory,,,The exception handling features of <fenv.h> should not be used,,Banned,Easy,
c,MISRA-C-2012,RULE-21-13,Yes,Mandatory,,,Any value passed to a function in <ctype.h> shall be representable as an unsigned char or be the value EOF,,Types,Medium,
c,MISRA-C-2012,RULE-21-13,Yes,Mandatory,,,Any value passed to a function in <ctype.h> shall be representable as an unsigned char or be the value EOF,,StandardLibraryFunctionTypes,Medium,
c,MISRA-C-2012,RULE-21-14,Yes,Required,,,The Standard Library function memcmp shall not be used to compare null terminated strings,,EssentialTypes,Hard,
c,MISRA-C-2012,RULE-21-15,Yes,Required,,,"The pointer arguments to the Standard Library functions memcpy, memmove and memcmp shall be pointers to qualified or unqualified versions of compatible types",,Types,Medium,
c,MISRA-C-2012,RULE-21-15,Yes,Required,,,"The pointer arguments to the Standard Library functions memcpy, memmove and memcmp shall be pointers to qualified or unqualified versions of compatible types",,StandardLibraryFunctionTypes,Medium,
c,MISRA-C-2012,RULE-21-16,Yes,Required,,,"The pointer arguments to the Standard Library function memcmp shall point to either a pointer type, an essentially signed type, an essentially unsigned type, an essentially Boolean type or an essentially enum type",,EssentialTypes,Medium,
c,MISRA-C-2012,RULE-21-17,Yes,Mandatory,,,Use of the string handling functions from <string.h> shall not result in accesses beyond the bounds of the objects referenced by their pointer parameters,,Memory2,Hard,
c,MISRA-C-2012,RULE-21-18,Yes,Mandatory,,,The size_t argument passed to any function in <string.h> shall have an appropriate value,,OutOfBounds,Hard,
Expand Down