Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
be7f810
Add module for names from the C/C++ library
lcartey Mar 8, 2024
1554d78
Add mad generator for the C Standard Library
lcartey Mar 8, 2024
057c684
Add mad generator for the C++ Standard Library
lcartey Mar 8, 2024
bf715b1
Fix output locations
lcartey Mar 8, 2024
af00c9f
Update models file
lcartey Mar 8, 2024
ea7e3b5
C: Support pointer return types in library generator
lcartey Mar 12, 2024
e21f6d3
Add missing update
lcartey Mar 12, 2024
cae5660
Add manual member variable models for C11 and C99.
lcartey Mar 12, 2024
189d66f
Expose libraryMemberVariableModels
lcartey Mar 13, 2024
fcbe4e7
Adopt StandardLibraryNames in the C DeclaredAReservedIdentifier query
lcartey Mar 13, 2024
5f738b3
Update message, add additional tests
lcartey Mar 13, 2024
221c0c1
Refine detection of reserved identifiers
lcartey Mar 13, 2024
ca51fda
Correctly reflect tag and typedef name spaces
lcartey Mar 13, 2024
122a020
Exclude identifiers generated from library macros
lcartey Mar 13, 2024
172378f
Only include macro names when the relevant header is included
lcartey Mar 13, 2024
b91d527
Improve performance on large databases
lcartey Mar 13, 2024
1fd72e2
Migrate STR32-C to new naming library
lcartey Mar 14, 2024
f5210ac
Extract ReservedNames library.
lcartey Mar 14, 2024
92cfb2f
Exclude NDEBUG, regenerate
lcartey Mar 14, 2024
6998ed0
Migrate Rule 21.2 to the ReservedNames library
lcartey Mar 14, 2024
927640b
Unshared Rule 21.2, and implement with MISRA rules
lcartey Mar 14, 2024
a821de9
Replace Naming with StandardLibraryNames
lcartey Mar 14, 2024
7c94c8c
Migrate A17-1-1 to use StandardLibraryNames
lcartey Mar 15, 2024
c3977f2
Migrate M17-0-2 to StandardLibraryNames.
lcartey Mar 15, 2024
b2ea30a
C++: More accurately report declaring header
lcartey Mar 25, 2024
d18ada0
C++: Remove unnamed and specialization types
lcartey Mar 25, 2024
a9a4613
C++: Exclude operator bool from the reserved names
lcartey Mar 25, 2024
bbd56e0
C++: Exclude member names unless the declaring type is visible
lcartey Mar 26, 2024
384b245
C++: Exclude name-header mappings for specializations
lcartey Mar 26, 2024
6ca9153
Add a predicate for identifying any name in a standard
lcartey Mar 28, 2024
cb5ddf5
Support C++ in reserved names
lcartey Mar 28, 2024
740c76d
Migrate A17-0-1 to use ReservedName
lcartey Mar 28, 2024
7a1eeb2
M17-0-3: Migrate to StandardNaming
lcartey Aug 28, 2025
deb849b
A17-0-1: Accept output
lcartey Aug 28, 2025
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
2 changes: 1 addition & 1 deletion .codeqlmanifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,6 @@
"cpp/*/test/qlpack.yml",
"c/*/src/qlpack.yml",
"c/*/test/qlpack.yml",
"scripts/generate_modules/queries/qlpack.yml"
"scripts/generate_standard_library_models/cpp/queries/qlpack.yml"
]
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@

import cpp
import codingstandards.c.cert
import codingstandards.cpp.Naming
import codingstandards.cpp.StandardLibraryNames
import semmle.code.cpp.dataflow.TaintTracking
import codingstandards.cpp.PossiblyUnsafeStringOperation
import semmle.code.cpp.valuenumbering.GlobalValueNumbering
Expand All @@ -34,7 +34,7 @@ class ExpectsNullTerminatedStringAsArgumentFunctionCall extends FunctionCall {
Expr e;

ExpectsNullTerminatedStringAsArgumentFunctionCall() {
Naming::Cpp14::hasStandardLibraryFunctionName(getTarget().getName()) and
CStandardLibrary::C11::hasFunctionName(_, _, _, getTarget().getName(), _, _, _) and
exists(Type t |
e = getAnArgument() and
t = getTarget().getAParameter().getType().(DerivedType).getBaseType*() and
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,42 @@
| test.c:2:1:2:23 | #define _RESERVED_MACRO | Reserved identifier '_RESERVED_MACRO' is declared. |
| test.c:11:8:11:9 | _s | Reserved identifier '_s' is declared. |
| test.c:15:6:15:7 | _f | Reserved identifier '_f' is declared. |
| test.c:19:7:19:12 | malloc | Reserved identifier 'malloc' is declared. |
| test.c:24:12:24:16 | errno | Reserved identifier 'errno' is declared. |
| test.c:2:1:2:23 | #define _RESERVED_MACRO | Macro '_RESERVED_MACRO' declares a reserved name beginning _ followed by an uppercase letter. |
| test.c:6:1:6:28 | #define _also_reserved_MACRO | Macro '_also_reserved_MACRO' declares a name beginning with _ which is reserved in the ordinary and tag namespaces. |
| test.c:11:8:11:9 | _s | Type '_s' declares a name beginning with _ which is reserved in the tag name space. |
| test.c:15:6:15:7 | _f | Function '_f' declares a name beginning with _ which is reserved in the ordinary name space. |
| test.c:19:7:19:12 | malloc | Function 'malloc' declares a name which is reserved for external linkage from the C11 standard library header 'stdlib.h'. |
| test.c:25:5:25:9 | errno | Global variable 'errno' declares a name which is reserved for external linkage from the C11 standard library header 'errno.h'. |
| test.c:39:16:39:18 | log | Parameter 'log' declares a name reserved for a macro from the C11 standard library header 'tgmath.h'. |
| test.c:43:5:43:16 | _Test_global | Global variable '_Test_global' declares a reserved name beginning _ followed by an uppercase letter. |
| test.c:44:6:44:15 | _Test_func | Function '_Test_func' declares a reserved name beginning _ followed by an uppercase letter. |
| test.c:45:9:45:19 | _Test_param | Parameter '_Test_param' declares a reserved name beginning _ followed by an uppercase letter. |
| test.c:46:7:46:17 | _Test_local | Local variable '_Test_local' declares a reserved name beginning _ followed by an uppercase letter. |
| test.c:47:10:47:27 | _Test_struct_local | Type '_Test_struct_local' declares a reserved name beginning _ followed by an uppercase letter. |
| test.c:49:9:49:20 | _Test_member | Member variable '_Test_member' declares a reserved name beginning _ followed by an uppercase letter. |
| test.c:52:8:52:19 | _Test_struct | Type '_Test_struct' declares a reserved name beginning _ followed by an uppercase letter. |
| test.c:53:7:53:18 | _Test_member | Member variable '_Test_member' declares a reserved name beginning _ followed by an uppercase letter. |
| test.c:55:1:56:3 | #define _TEST_MACRO x | Macro '_TEST_MACRO' declares a reserved name beginning _ followed by an uppercase letter. |
| test.c:60:5:60:24 | __test_double_global | Global variable '__test_double_global' declares a reserved name beginning with __. |
| test.c:61:6:61:23 | __test_double_func | Function '__test_double_func' declares a reserved name beginning with __. |
| test.c:62:9:62:27 | __test_double_param | Parameter '__test_double_param' declares a reserved name beginning with __. |
| test.c:63:7:63:25 | __test_double_local | Local variable '__test_double_local' declares a reserved name beginning with __. |
| test.c:64:10:64:35 | __test_double_struct_local | Type '__test_double_struct_local' declares a reserved name beginning with __. |
| test.c:65:9:65:28 | __test_double_member | Member variable '__test_double_member' declares a reserved name beginning with __. |
| test.c:68:8:68:27 | __test_double_struct | Type '__test_double_struct' declares a reserved name beginning with __. |
| test.c:69:7:69:26 | __test_double_member | Member variable '__test_double_member' declares a reserved name beginning with __. |
| test.c:71:1:71:22 | #define __TEST_MACRO x | Macro '__TEST_MACRO' declares a reserved name beginning with __. |
| test.c:78:5:78:22 | _test_lower_global | Global variable '_test_lower_global' declares a name beginning with _ which is reserved in the ordinary name space. |
| test.c:79:6:79:21 | _test_lower_func | Function '_test_lower_func' declares a name beginning with _ which is reserved in the ordinary name space. |
| test.c:88:8:88:19 | _test_struct | Type '_test_struct' declares a name beginning with _ which is reserved in the tag name space. |
| test.c:91:1:92:3 | #define _test_macro x | Macro '_test_macro' declares a name beginning with _ which is reserved in the ordinary and tag namespaces. |
| test.c:96:5:96:14 | FE_INEXACT | Global variable 'FE_INEXACT' declares a name reserved for a macro from the C11 standard library header 'fenv.h'. |
| test.c:97:6:97:17 | FE_DIVBYZERO | Function 'FE_DIVBYZERO' declares a name reserved for a macro from the C11 standard library header 'fenv.h'. |
| test.c:98:9:98:18 | FE_INEXACT | Parameter 'FE_INEXACT' declares a name reserved for a macro from the C11 standard library header 'fenv.h'. |
| test.c:99:7:99:16 | FE_INVALID | Local variable 'FE_INVALID' declares a name reserved for a macro from the C11 standard library header 'fenv.h'. |
| test.c:100:10:100:19 | FE_INEXACT | Type 'FE_INEXACT' declares a name reserved for a macro from the C11 standard library header 'fenv.h'. |
| test.c:101:9:101:18 | FE_INEXACT | Member variable 'FE_INEXACT' declares a name reserved for a macro from the C11 standard library header 'fenv.h'. |
| test.c:104:8:104:17 | FE_INEXACT | Type 'FE_INEXACT' declares a name reserved for a macro from the C11 standard library header 'fenv.h'. |
| test.c:105:7:105:16 | FE_INEXACT | Member variable 'FE_INEXACT' declares a name reserved for a macro from the C11 standard library header 'fenv.h'. |
| test.c:107:1:108:3 | #define FE_INEXACT x | Macro 'FE_INEXACT' declares a name reserved for a macro from the C11 standard library header 'fenv.h'. |
| test.c:118:5:118:8 | exit | Global variable 'exit' declares a name which is reserved for external linkage from the C11 standard library header 'stdlib.h'. |
| test.c:120:6:120:9 | free | Function 'free' declares a name which is reserved for external linkage from the C11 standard library header 'stdlib.h'. |
| test.c:130:1:130:16 | #define strlen 0 | Macro 'strlen' declares a reserved name from the C11 standard library header 'string.h' which is included directly or indirectly in this translation unit. |
| test.c:140:1:140:16 | #define tm_sec 0 | Macro 'tm_sec' declares a reserved name from the C11 standard library header 'time.h' which is included directly or indirectly in this translation unit. |
166 changes: 162 additions & 4 deletions c/common/test/rules/declaredareservedidentifier/test.c
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@
#define _RESERVED_MACRO // NON_COMPLIANT
#endif /* _RESERVED_MACRO */

#ifndef _not_reserved_MACRO
#define _not_reserved_MACRO // COMPLIANT
#endif /* _not_reserved_MACRO */
#ifndef _also_reserved_MACRO
#define _also_reserved_MACRO // NON_COMPLIANT
#endif /* _not_reserved_MACRO */

static const int INT_LIMIT_MAX = 12000; // COMPLIANT future library directions

Expand All @@ -21,4 +21,162 @@ void *malloc(int bytes) { // NON_COMPLIANT
return ptr;
}

extern int errno; // NON_COMPLIANT
extern int
errno; // NON_COMPLIANT - errno is explicitly reserved for external linkage

void output(int a, int b, int c);

#define DEBUG(...) \
output(__VA_ARGS__) // COMPLIANT - using not declaring `__VA_ARGS__`

void test() {
DEBUG(1, 2, 3);
__FUNCTION__; // COMPLIANT - use, not declaration of `__FUNCTION__`
__PRETTY_FUNCTION__; // COMPLIANT - use, not declaration of
// `__PRETTY_FUNCTION__`
}
#include <tgmath.h>
void test2(int log); // NON_COMPLIANT - tgmath.h defines log as a reserved macro

/* Test _[A-Z] */

int _Test_global; // NON_COMPLIANT - _ followed by capital is reserved
void _Test_func( // NON_COMPLIANT - _ followed by capital is reserved
int _Test_param) { // NON_COMPLIANT - _ followed by capital is reserved
int _Test_local; // NON_COMPLIANT - _ followed by capital is reserved
struct _Test_struct_local { // NON_COMPLIANT - _ followed by capital is
// reserved
int _Test_member; // NON_COMPLIANT - _ followed by capital is reserved
};
}
struct _Test_struct { // NON_COMPLIANT - _ followed by capital is reserved
int _Test_member; // NON_COMPLIANT - _ followed by capital is reserved
};
#define _TEST_MACRO \
x // NON_COMPLIANT - single _ followed by capital is reserved

/* Test __ */

int __test_double_global; // NON_COMPLIANT - double _ is reserved
void __test_double_func( // NON_COMPLIANT - double _ is reserved
int __test_double_param) { // NON_COMPLIANT - double _ is reserved
int __test_double_local; // NON_COMPLIANT - double _ is reserved
struct __test_double_struct_local { // NON_COMPLIANT - double _ is reserved
int __test_double_member; // NON_COMPLIANT - double _ is reserved
};
}
struct __test_double_struct { // NON_COMPLIANT - double _ is reserved
int __test_double_member; // NON_COMPLIANT - double _ is reserved
};
#define __TEST_MACRO x // NON_COMPLIANT - double _ is reserved

/*
* Test _, but not followed by underscore or upper case, which is reserved in
* file scope and ordinary/tag name spaces
*/

int _test_lower_global; // NON_COMPLIANT - _ is reserved in ordinary name space
void _test_lower_func( // NON_COMPLIANT - _ is reserved as a function name in
// ordinary name space
int _test_lower_param) { // COMPLIANT - _ is not reserved in the block name
// space
int _test; // COMPLIANT - _ is not reserved in the block name space
struct _test_struct { // COMPLIANT - _ is not reserved in the block name space
int _test; // COMPLIANT - _ is not reserved in the block name space
};
}
struct _test_struct { // NON_COMPLIANT - _ is reserved in the tag name space
int _test; // COMPLIANT - _ is not reserved in the member name space
};
#define _test_macro \
x // NON_COMPLIANT - _ is reserved for for file scope names and so cannot be
// used as a macro name

/* Identify names reserved as a macro when the relevant header is included. */
int FE_INEXACT; // NON_COMPLIANT - FE_INEXACT is reserved as a macro name
void FE_DIVBYZERO( // NON_COMPLIANT - FE_DIVBYZERO is reserved as a macro name
int FE_INEXACT) { // NON_COMPLIANT - FE_INEXACT is reserved as a macro name
int FE_INVALID; // NON_COMPLIANT - FE_INEXACT is reserved as a macro name
struct FE_INEXACT { // NON_COMPLIANT - FE_INEXACT is reserved as a macro name
int FE_INEXACT; // NON_COMPLIANT - FE_INEXACT is reserved as a macro name
};
}
struct FE_INEXACT { // NON_COMPLIANT - FE_INEXACT is reserved as a macro name
int FE_INEXACT; // NON_COMPLIANT - FE_INEXACT is reserved as a macro name
};
#define FE_INEXACT \
x // NON_COMPLIANT - FE_INEXACT is reserved as a macro name for the standard
// library

// We include the header after the declarations to avoid the inbuilt macros
// expanding in the declarations above. The rule is not, however, sensitive
// to location, so we should still report in this case.
#include <fenv.h>

/* Functions and objects with external linkage */

int exit; // NON_COMPLIANT - reserved for external linkage, even though header
// was not included
void free() { // NON_COMPLIANT - reserved for external linkage, even though
// header was not included
}
static int rand; // COMPLIANT - only reserved for external linkage or if random
// was included
static int srand() { // COMPLIANT - only reserved for external linkage or if
// random was included
}

#include <string.h>
#define strlen 0 // NON_COMPLIANT - reserved when string.h is included

// The examples below are non compliant, because those symbols are reserved in
// file scope when string.h is included. However, the compiler/edg rejects the
// declaration cases, so we cannot test them.

// static int strlen;
// static void *memcpy(void *s1, const void *s2, size_t n) {}

#include <time.h>
#define tm_sec 0 // NON_COMPLIANT - reserved when time.h is included

// The examples below are non compliant, because those symbols are reserved in
// file scope when time.h is included. However, the compiler/edg rejects the
// declaration cases, so we cannot test them.

// struct tm {
// int tm_sec;
// int tm_min;
// int tm_hour;
// int tm_mday;
// int tm_mon;
// int tm_year;
// int tm_wday;
// int tm_yday;
// int tm_isdst;
// long __tm_gmtoff;
// const char *__tm_zone;
// };

// Examples below are compliant because threads.h is not included

#define tss_set 0 // COMPLIANT - threads.h not included
static int tss_get; // COMPLIANT - threads.h not included, not external linkage
static void
tss_delete( // COMPLIANT - threads.h not included, not external linkage
int tss_create // COMPLIANT - threads.h not included
) {
int thrd_detach; // COMPLIANT - threads.h not included
struct thrd_join { // COMPLIANT - threads.h not included
int thrd_equal; // COMPLIANT - threads.h not included
};
}
struct thrd_yield { // COMPLIANT - threads.h not included
int thrd_exit; // COMPLIANT - threads.h not included
};

#include <sys/select.h>
void test_macro() {
fd_set test_set;
FD_ZERO(&test_set); // COMPLIANT - macro expands to variables with `__`
// prefixes, but should be excluded
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,23 +16,10 @@

import cpp
import codingstandards.c.misra
import codingstandards.cpp.Naming
import codingstandards.cpp.ReservedNames

from PreprocessorDirective p, string name
from PreprocessorDirective p, string message
where
not isExcluded(p, Preprocessor4Package::defineAndUndefUsedOnReservedIdentifierOrMacroNameQuery()) and
(
p.(Macro).hasName(name)
or
p.(PreprocessorUndef).getName() = name
) and
(
Naming::Cpp14::hasStandardLibraryMacroName(name)
or
Naming::Cpp14::hasStandardLibraryObjectName(name)
or
name.regexpMatch("_.*")
or
name = "defined"
)
select p, "Reserved identifier '" + name + "' has been undefined or redefined."
ReservedNames::C11::isAReservedIdentifier(p, message, false)
select p, message
14 changes: 8 additions & 6 deletions c/misra/src/rules/RULE-21-2/DoNotDeclareAReservedIdentifier.ql
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,12 @@

import cpp
import codingstandards.c.misra
import codingstandards.cpp.rules.declaredareservedidentifier.DeclaredAReservedIdentifier
import codingstandards.cpp.ReservedNames

class DoNotDeclareAReservedIdentifierQuery extends DeclaredAReservedIdentifierSharedQuery {
DoNotDeclareAReservedIdentifierQuery() {
this = Declarations1Package::doNotDeclareAReservedIdentifierQuery()
}
}
from Element e, string message
where
not isExcluded(e, Declarations1Package::doNotDeclareAReservedIdentifierQuery()) and
ReservedNames::C11::isAReservedIdentifier(e, message, true) and
// Not covered by this rule - covered by Rule 21.2
not e instanceof PreprocessorDirective
select e, message
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
| test.c:1:1:1:17 | #define _NOT_OKAY | Reserved identifier '_NOT_OKAY' has been undefined or redefined. |
| test.c:2:1:2:16 | #undef _NOT_OKAY | Reserved identifier '_NOT_OKAY' has been undefined or redefined. |
| test.c:5:1:5:13 | #define errno | Reserved identifier 'errno' has been undefined or redefined. |
| test.c:1:1:1:17 | #define _NOT_OKAY | Macro '_NOT_OKAY' declares a reserved name beginning _ followed by an uppercase letter. |
| test.c:2:1:2:16 | #undef _NOT_OKAY | Undef '_NOT_OKAY' declares a reserved name beginning _ followed by an uppercase letter. |
| test.c:5:1:5:13 | #define errno | Macro 'errno' declares a name reserved for a macro from the C11 standard library header 'errno.h'. |
Loading
Loading