From a9d71bb39101ee3190d8a468727bb47d37084bb8 Mon Sep 17 00:00:00 2001 From: Remco Vermeulen Date: Tue, 26 Mar 2024 16:53:02 -0700 Subject: [PATCH 1/4] Add support for implementation specific bitfield types --- ...hallOnlyBeDeclaredWithAnAppropriateType.ql | 25 ++++++++---- ...lyBeDeclaredWithAnAppropriateType.expected | 2 +- ...lyBeDeclaredWithAnAppropriateType.expected | 0 ...lOnlyBeDeclaredWithAnAppropriateType.qlref | 1 + c/misra/test/rules/RULE-6-1/clang/options | 1 + c/misra/test/rules/RULE-6-1/clang/test.c | 13 +++++++ ...lyBeDeclaredWithAnAppropriateType.expected | 0 ...lOnlyBeDeclaredWithAnAppropriateType.qlref | 1 + c/misra/test/rules/RULE-6-1/gcc/options | 1 + c/misra/test/rules/RULE-6-1/gcc/test.c | 13 +++++++ c/misra/test/rules/RULE-6-1/options | 1 + change_notes/2024-04-26-fix-fp-rule-6-1.md | 2 + .../src/codingstandards/cpp/Compiler.qll | 39 +++++++++++++++++++ 13 files changed, 91 insertions(+), 8 deletions(-) create mode 100644 c/misra/test/rules/RULE-6-1/clang/BitFieldsShallOnlyBeDeclaredWithAnAppropriateType.expected create mode 100644 c/misra/test/rules/RULE-6-1/clang/BitFieldsShallOnlyBeDeclaredWithAnAppropriateType.qlref create mode 100644 c/misra/test/rules/RULE-6-1/clang/options create mode 100644 c/misra/test/rules/RULE-6-1/clang/test.c create mode 100644 c/misra/test/rules/RULE-6-1/gcc/BitFieldsShallOnlyBeDeclaredWithAnAppropriateType.expected create mode 100644 c/misra/test/rules/RULE-6-1/gcc/BitFieldsShallOnlyBeDeclaredWithAnAppropriateType.qlref create mode 100644 c/misra/test/rules/RULE-6-1/gcc/options create mode 100644 c/misra/test/rules/RULE-6-1/gcc/test.c create mode 100644 c/misra/test/rules/RULE-6-1/options create mode 100644 change_notes/2024-04-26-fix-fp-rule-6-1.md create mode 100644 cpp/common/src/codingstandards/cpp/Compiler.qll diff --git a/c/misra/src/rules/RULE-6-1/BitFieldsShallOnlyBeDeclaredWithAnAppropriateType.ql b/c/misra/src/rules/RULE-6-1/BitFieldsShallOnlyBeDeclaredWithAnAppropriateType.ql index 81c7fb69a3..c05e2d1cde 100644 --- a/c/misra/src/rules/RULE-6-1/BitFieldsShallOnlyBeDeclaredWithAnAppropriateType.ql +++ b/c/misra/src/rules/RULE-6-1/BitFieldsShallOnlyBeDeclaredWithAnAppropriateType.ql @@ -12,16 +12,26 @@ import cpp import codingstandards.c.misra +import codingstandards.cpp.Compiler -predicate isAppropriatePrimitive(Type type) { - /* An appropriate primitive types to which a bit-field can be declared. */ - type instanceof IntType and +Type getSupportedBitFieldType(Compiler compiler) { + compiler instanceof UnsupportedCompiler and ( - type.(IntegralType).isExplicitlySigned() or - type.(IntegralType).isExplicitlyUnsigned() + result instanceof IntType and + ( + result.(IntegralType).isExplicitlySigned() or + result.(IntegralType).isExplicitlyUnsigned() + ) + or + result instanceof BoolType ) or - type instanceof BoolType + (compiler instanceof Gcc or compiler instanceof Clang) and + ( + result instanceof IntegralOrEnumType + or + result instanceof BoolType + ) } from BitField bitField @@ -29,5 +39,6 @@ where not isExcluded(bitField, BitfieldTypesPackage::bitFieldsShallOnlyBeDeclaredWithAnAppropriateTypeQuery()) and /* A violation would neither be an appropriate primitive type nor an appropriate typedef. */ - not isAppropriatePrimitive(bitField.getType().resolveTypedefs()) + not getSupportedBitFieldType(getCompiler(bitField.getFile())) = + bitField.getType().resolveTypedefs() select bitField, "Bit-field " + bitField + " is declared on type " + bitField.getType() + "." diff --git a/c/misra/test/rules/RULE-6-1/BitFieldsShallOnlyBeDeclaredWithAnAppropriateType.expected b/c/misra/test/rules/RULE-6-1/BitFieldsShallOnlyBeDeclaredWithAnAppropriateType.expected index aaba0ee30c..345e75a4bb 100644 --- a/c/misra/test/rules/RULE-6-1/BitFieldsShallOnlyBeDeclaredWithAnAppropriateType.expected +++ b/c/misra/test/rules/RULE-6-1/BitFieldsShallOnlyBeDeclaredWithAnAppropriateType.expected @@ -1,4 +1,4 @@ | test.c:6:7:6:8 | x1 | Bit-field x1 is declared on type int. | | test.c:10:15:10:16 | x5 | Bit-field x5 is declared on type signed long. | | test.c:12:15:12:16 | x6 | Bit-field x6 is declared on type signed char. | -| test.c:14:14:14:15 | x7 | Bit-field x7 is declared on type Color. | +| test.c:14:14:14:15 | x7 | Bit-field x7 is declared on type Color. | \ No newline at end of file diff --git a/c/misra/test/rules/RULE-6-1/clang/BitFieldsShallOnlyBeDeclaredWithAnAppropriateType.expected b/c/misra/test/rules/RULE-6-1/clang/BitFieldsShallOnlyBeDeclaredWithAnAppropriateType.expected new file mode 100644 index 0000000000..e69de29bb2 diff --git a/c/misra/test/rules/RULE-6-1/clang/BitFieldsShallOnlyBeDeclaredWithAnAppropriateType.qlref b/c/misra/test/rules/RULE-6-1/clang/BitFieldsShallOnlyBeDeclaredWithAnAppropriateType.qlref new file mode 100644 index 0000000000..7000f50ab1 --- /dev/null +++ b/c/misra/test/rules/RULE-6-1/clang/BitFieldsShallOnlyBeDeclaredWithAnAppropriateType.qlref @@ -0,0 +1 @@ +rules/RULE-6-1/BitFieldsShallOnlyBeDeclaredWithAnAppropriateType.ql \ No newline at end of file diff --git a/c/misra/test/rules/RULE-6-1/clang/options b/c/misra/test/rules/RULE-6-1/clang/options new file mode 100644 index 0000000000..d37493684d --- /dev/null +++ b/c/misra/test/rules/RULE-6-1/clang/options @@ -0,0 +1 @@ +semmle-extractor-options:--mimic clang --std=c11 --edg --diag_error=implicit_func_decl -nostdinc -I../../../../common/test/includes/standard-library \ No newline at end of file diff --git a/c/misra/test/rules/RULE-6-1/clang/test.c b/c/misra/test/rules/RULE-6-1/clang/test.c new file mode 100644 index 0000000000..65c6900fdf --- /dev/null +++ b/c/misra/test/rules/RULE-6-1/clang/test.c @@ -0,0 +1,13 @@ +typedef unsigned int UINT16; + +enum Color { R, G, B }; + +struct SampleStruct { + int x1 : 2; // COMPLIANT + unsigned int x2 : 2; // COMPLIANT - explicitly unsigned + signed int x3 : 2; // COMPLIANT - explicitly signed + UINT16 x4 : 2; // COMPLIANT - type alias resolves to a compliant type + signed long x5 : 2; // COMPLIANT + signed char x6 : 2; // COMPLIANT + enum Color x7 : 3; // COMPLIANT +} sample_struct; diff --git a/c/misra/test/rules/RULE-6-1/gcc/BitFieldsShallOnlyBeDeclaredWithAnAppropriateType.expected b/c/misra/test/rules/RULE-6-1/gcc/BitFieldsShallOnlyBeDeclaredWithAnAppropriateType.expected new file mode 100644 index 0000000000..e69de29bb2 diff --git a/c/misra/test/rules/RULE-6-1/gcc/BitFieldsShallOnlyBeDeclaredWithAnAppropriateType.qlref b/c/misra/test/rules/RULE-6-1/gcc/BitFieldsShallOnlyBeDeclaredWithAnAppropriateType.qlref new file mode 100644 index 0000000000..7000f50ab1 --- /dev/null +++ b/c/misra/test/rules/RULE-6-1/gcc/BitFieldsShallOnlyBeDeclaredWithAnAppropriateType.qlref @@ -0,0 +1 @@ +rules/RULE-6-1/BitFieldsShallOnlyBeDeclaredWithAnAppropriateType.ql \ No newline at end of file diff --git a/c/misra/test/rules/RULE-6-1/gcc/options b/c/misra/test/rules/RULE-6-1/gcc/options new file mode 100644 index 0000000000..b2d1a92f7a --- /dev/null +++ b/c/misra/test/rules/RULE-6-1/gcc/options @@ -0,0 +1 @@ +semmle-extractor-options:--mimic gcc --std=c11 --edg --diag_error=implicit_func_decl -nostdinc -I../../../../common/test/includes/standard-library \ No newline at end of file diff --git a/c/misra/test/rules/RULE-6-1/gcc/test.c b/c/misra/test/rules/RULE-6-1/gcc/test.c new file mode 100644 index 0000000000..65c6900fdf --- /dev/null +++ b/c/misra/test/rules/RULE-6-1/gcc/test.c @@ -0,0 +1,13 @@ +typedef unsigned int UINT16; + +enum Color { R, G, B }; + +struct SampleStruct { + int x1 : 2; // COMPLIANT + unsigned int x2 : 2; // COMPLIANT - explicitly unsigned + signed int x3 : 2; // COMPLIANT - explicitly signed + UINT16 x4 : 2; // COMPLIANT - type alias resolves to a compliant type + signed long x5 : 2; // COMPLIANT + signed char x6 : 2; // COMPLIANT + enum Color x7 : 3; // COMPLIANT +} sample_struct; diff --git a/c/misra/test/rules/RULE-6-1/options b/c/misra/test/rules/RULE-6-1/options new file mode 100644 index 0000000000..52175e51f9 --- /dev/null +++ b/c/misra/test/rules/RULE-6-1/options @@ -0,0 +1 @@ +semmle-extractor-options:--no-clang --std=c11 --edg --diag_error=implicit_func_decl -nostdinc -I../../../../common/test/includes/standard-library \ No newline at end of file diff --git a/change_notes/2024-04-26-fix-fp-rule-6-1.md b/change_notes/2024-04-26-fix-fp-rule-6-1.md new file mode 100644 index 0000000000..856c15623f --- /dev/null +++ b/change_notes/2024-04-26-fix-fp-rule-6-1.md @@ -0,0 +1,2 @@ +- `RULE-6-1` - `BitFieldsShallOnlyBeDeclaredWithAnAppropriateType.ql`: + - Address FP reported in #318. Add support for implementation specific bitfield types for Clang and Gcc. \ No newline at end of file diff --git a/cpp/common/src/codingstandards/cpp/Compiler.qll b/cpp/common/src/codingstandards/cpp/Compiler.qll new file mode 100644 index 0000000000..20aade5827 --- /dev/null +++ b/cpp/common/src/codingstandards/cpp/Compiler.qll @@ -0,0 +1,39 @@ +/** A module to reason about the compiler used to compile translation units. */ + +import cpp +import codingstandards.cpp.Scope + +newtype Compiler = + Gcc() or + Clang() or + UnsupportedCompiler() + +/** Get the match pattern to detect the compiler being mimicked by the extractor to determine the compiler used to compile a file. */ +string getMimicMatch(Compiler compiler) { + result = ["%gcc", "%g++"] and compiler instanceof Gcc + or + result = ["%clang", "%clang++"] and compiler instanceof Clang +} + +/** Get the compiler used to compile the translation unit the file `f` is part of. */ +Compiler getCompiler(File f) { + exists(Compilation compilation, TranslationUnit translationUnit | + compilation.getAFileCompiled() = translationUnit and + (f = translationUnit or f = translationUnit.getAUserFile()) + | + if exists(int mimicIndex | compilation.getArgument(mimicIndex) = "--mimic") + then + exists(int mimicIndex | + compilation.getArgument(mimicIndex) = "--mimic" and + ( + compilation.getArgument(mimicIndex + 1).matches(getMimicMatch(result)) + or + forall(string match | match = getMimicMatch(_) | + not compilation.getArgument(mimicIndex + 1).matches(match) + ) and + result = UnsupportedCompiler() + ) + ) + else result = UnsupportedCompiler() + ) +} From 4dc49a114efd854705d6ff10a41ec17958956ad1 Mon Sep 17 00:00:00 2001 From: Remco Vermeulen Date: Wed, 3 Apr 2024 13:46:34 -0700 Subject: [PATCH 2/4] Address incorrect format code elements in alert message --- .../BitFieldsShallOnlyBeDeclaredWithAnAppropriateType.ql | 2 +- ...ieldsShallOnlyBeDeclaredWithAnAppropriateType.expected | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/c/misra/src/rules/RULE-6-1/BitFieldsShallOnlyBeDeclaredWithAnAppropriateType.ql b/c/misra/src/rules/RULE-6-1/BitFieldsShallOnlyBeDeclaredWithAnAppropriateType.ql index c05e2d1cde..fce1d9ad1a 100644 --- a/c/misra/src/rules/RULE-6-1/BitFieldsShallOnlyBeDeclaredWithAnAppropriateType.ql +++ b/c/misra/src/rules/RULE-6-1/BitFieldsShallOnlyBeDeclaredWithAnAppropriateType.ql @@ -41,4 +41,4 @@ where /* A violation would neither be an appropriate primitive type nor an appropriate typedef. */ not getSupportedBitFieldType(getCompiler(bitField.getFile())) = bitField.getType().resolveTypedefs() -select bitField, "Bit-field " + bitField + " is declared on type " + bitField.getType() + "." +select bitField, "Bit-field '" + bitField + "' is declared on type '" + bitField.getType() + "'." diff --git a/c/misra/test/rules/RULE-6-1/BitFieldsShallOnlyBeDeclaredWithAnAppropriateType.expected b/c/misra/test/rules/RULE-6-1/BitFieldsShallOnlyBeDeclaredWithAnAppropriateType.expected index 345e75a4bb..4ff4c2aaa1 100644 --- a/c/misra/test/rules/RULE-6-1/BitFieldsShallOnlyBeDeclaredWithAnAppropriateType.expected +++ b/c/misra/test/rules/RULE-6-1/BitFieldsShallOnlyBeDeclaredWithAnAppropriateType.expected @@ -1,4 +1,4 @@ -| test.c:6:7:6:8 | x1 | Bit-field x1 is declared on type int. | -| test.c:10:15:10:16 | x5 | Bit-field x5 is declared on type signed long. | -| test.c:12:15:12:16 | x6 | Bit-field x6 is declared on type signed char. | -| test.c:14:14:14:15 | x7 | Bit-field x7 is declared on type Color. | \ No newline at end of file +| test.c:6:7:6:8 | x1 | Bit-field 'x1' is declared on type 'int'. | +| test.c:10:15:10:16 | x5 | Bit-field 'x5' is declared on type 'signed long'. | +| test.c:12:15:12:16 | x6 | Bit-field 'x6' is declared on type 'signed char'. | +| test.c:14:14:14:15 | x7 | Bit-field 'x7' is declared on type 'Color'. | From b87fec54ad106521687ce8ada026f44c564920d2 Mon Sep 17 00:00:00 2001 From: Remco Vermeulen Date: Wed, 3 Apr 2024 16:44:29 -0700 Subject: [PATCH 3/4] Add test case with atomic types for documentation --- c/misra/test/rules/RULE-6-1/clang/test.c | 2 ++ c/misra/test/rules/RULE-6-1/gcc/test.c | 2 ++ 2 files changed, 4 insertions(+) diff --git a/c/misra/test/rules/RULE-6-1/clang/test.c b/c/misra/test/rules/RULE-6-1/clang/test.c index 65c6900fdf..3c7f000329 100644 --- a/c/misra/test/rules/RULE-6-1/clang/test.c +++ b/c/misra/test/rules/RULE-6-1/clang/test.c @@ -10,4 +10,6 @@ struct SampleStruct { signed long x5 : 2; // COMPLIANT signed char x6 : 2; // COMPLIANT enum Color x7 : 3; // COMPLIANT + //_Atomic(int) x8 : 2; // NON_COMPLIANT[COMPILER_CHECKED] - atomic types are + //not permitted for bit-fields. } sample_struct; diff --git a/c/misra/test/rules/RULE-6-1/gcc/test.c b/c/misra/test/rules/RULE-6-1/gcc/test.c index 65c6900fdf..3c7f000329 100644 --- a/c/misra/test/rules/RULE-6-1/gcc/test.c +++ b/c/misra/test/rules/RULE-6-1/gcc/test.c @@ -10,4 +10,6 @@ struct SampleStruct { signed long x5 : 2; // COMPLIANT signed char x6 : 2; // COMPLIANT enum Color x7 : 3; // COMPLIANT + //_Atomic(int) x8 : 2; // NON_COMPLIANT[COMPILER_CHECKED] - atomic types are + //not permitted for bit-fields. } sample_struct; From 570dd8006544171da46f1a21b1b9f50e02a6a6a3 Mon Sep 17 00:00:00 2001 From: Remco Vermeulen Date: Thu, 4 Apr 2024 11:35:30 -0700 Subject: [PATCH 4/4] Properly format the test case --- c/misra/test/rules/RULE-6-1/clang/test.c | 2 +- c/misra/test/rules/RULE-6-1/gcc/test.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/c/misra/test/rules/RULE-6-1/clang/test.c b/c/misra/test/rules/RULE-6-1/clang/test.c index 3c7f000329..c8b377b0fd 100644 --- a/c/misra/test/rules/RULE-6-1/clang/test.c +++ b/c/misra/test/rules/RULE-6-1/clang/test.c @@ -11,5 +11,5 @@ struct SampleStruct { signed char x6 : 2; // COMPLIANT enum Color x7 : 3; // COMPLIANT //_Atomic(int) x8 : 2; // NON_COMPLIANT[COMPILER_CHECKED] - atomic types are - //not permitted for bit-fields. + // not permitted for bit-fields. } sample_struct; diff --git a/c/misra/test/rules/RULE-6-1/gcc/test.c b/c/misra/test/rules/RULE-6-1/gcc/test.c index 3c7f000329..c8b377b0fd 100644 --- a/c/misra/test/rules/RULE-6-1/gcc/test.c +++ b/c/misra/test/rules/RULE-6-1/gcc/test.c @@ -11,5 +11,5 @@ struct SampleStruct { signed char x6 : 2; // COMPLIANT enum Color x7 : 3; // COMPLIANT //_Atomic(int) x8 : 2; // NON_COMPLIANT[COMPILER_CHECKED] - atomic types are - //not permitted for bit-fields. + // not permitted for bit-fields. } sample_struct;