From 10fc89e9de32d8322c1174a21c0aa8c10eed6c33 Mon Sep 17 00:00:00 2001 From: David Svoboda Date: Mon, 6 Jul 2026 17:12:54 -0400 Subject: [PATCH 1/9] str33-c --- .../03.rules/05.concurrency-con/05.con33-c.md | 70 ++++++++++++++++++- .../04.back-matter/4.cc-undefined-behavior.md | 3 +- 2 files changed, 71 insertions(+), 2 deletions(-) diff --git a/content/4.sei-cert-c-coding-standard/03.rules/05.concurrency-con/05.con33-c.md b/content/4.sei-cert-c-coding-standard/03.rules/05.concurrency-con/05.con33-c.md index 85a7cf0a..197e0947 100644 --- a/content/4.sei-cert-c-coding-standard/03.rules/05.concurrency-con/05.con33-c.md +++ b/content/4.sei-cert-c-coding-standard/03.rules/05.concurrency-con/05.con33-c.md @@ -21,7 +21,7 @@ According to the C Standard, the library functions listed in the following table Section 2.9.1 of the *Portable Operating System Interface (POSIX ® ), Base Specifications, Issue 7* \[ [IEEE Std 1003.1:2013](/sei-cert-c-coding-standard/back-matter/aa-bibliography#AA.Bibliography-IEEEStd1003.1-2013) \] extends the list of functions that are not required to be thread-safe. -## Noncompliant Code Example +## Noncompliant Code Example (`strerror()`) In this noncompliant code example, the function `f()` is called from within a multithreaded application but encounters an error while calling a system function. The `strerror()` function returns a human-readable error string given an error number. @@ -80,6 +80,74 @@ void f(FILE *fp) { Linux provides two versions of `strerror_r()` , known as the *XSI-compliant version* and the *GNU-specific version* . This compliant solution assumes the XSI-compliant version, which is the default when an application is compiled as required by POSIX (that is, by defining `_POSIX_C_SOURCE` or `_XOPEN_SOURCE` appropriately). The `strerror_r()` manual page lists versions that are available on a particular system. +## Noncompliant Code Example (`strtok()`) + +Invoking the `strtok()` function from multiple threads is [undefined behavior 199](/sei-cert-c-coding-standard/back-matter/cc-undefined-behavior#CC.UndefinedBehavior-ub_199), according to ISO C section 7.26.5.9. + +::code-block{quality="bad"} +``` c +#include +#include + +int bar(void *) { + char *t = strtok(NULL, "#,"); // Undefined Behavior + return t[0]; +} + +int main() { + char str[] = "?a???b,,,#c"; + char *t = strtok(str, "?"); + thrd_t thr; + if (thrd_success != thrd_create(&thr, bar, 0)) { + // Handle Error + } + + t = strtok(NULL, ","); // Undefined Behavior + + int retval; + if (thrd_success != thrd_join(thr, &retval)) { + // Handle Error + } +} +``` +:: + +## Compliant Solution (POSIX, `strtok_r()` ) + +This compliant solution uses the POSIX `strtok_r()` function, which is reentrant. It relies on no static variables, always tokenizing the string in its 3rd `saveptr` argument. + +::code-block{quality="good"} +``` c +#include +#include + +static char str[] = "?a???b,,,#c"; +char *saveptr = NULL; + +int bar(void *) { + char *t = strtok_r(NULL, ",", &saveptr); + return t[0]; +} + +int main(void) { + char *t = strtok_r(str, "?", &saveptr); + thrd_t thr; + if (thrd_success != thrd_create(&thr, bar, NULL)) { + // Handle Error + } + + t = strtok_r(NULL, ",", &saveptr); + + int retval; + if (thrd_success != thrd_join(thr, &retval)) { + // Handle Error + } + return 0; +} +``` +:: + + ## Risk Assessment Race conditions caused by multiple threads invoking the same library function can lead to [abnormal termination](/sei-cert-c-coding-standard/back-matter/bb-definitions#BB.Definitions-abnormaltermination) of the application, data integrity violations, or a [denial-of-service attack](/sei-cert-c-coding-standard/back-matter/bb-definitions#BB.Definitions-denial-of-service) . diff --git a/content/4.sei-cert-c-coding-standard/04.back-matter/4.cc-undefined-behavior.md b/content/4.sei-cert-c-coding-standard/04.back-matter/4.cc-undefined-behavior.md index 22dc85f7..ac5d21dc 100644 --- a/content/4.sei-cert-c-coding-standard/04.back-matter/4.cc-undefined-behavior.md +++ b/content/4.sei-cert-c-coding-standard/04.back-matter/4.cc-undefined-behavior.md @@ -162,7 +162,8 @@ EXP39-C

37

197

A string or wide string utility function is called with an invalid pointer argument, even if the length is zero (7.26.1, 7.31.4).


198

The contents of the destination array are used after a call to the strxfrm , strftime , wcsxfrm , or wcsftime function in which the specified length was too small to hold the entire null-terminated result (7.26.4.5, 7.29.3.5, 7.31.4.4.4, 7.31.5.1).


199


-

A sequence of calls of the strtok function is made from different threads (7.26.5.9).


+

A sequence of calls of the strtok function is made from different threads (7.26.5.9). +

CON33-C

200

The first argument in the very first call to the strtok or wcstok is a null pointer (7.26.5.9, 7.31.4.5.8).


201


A pointer returned by the strerror function is used after a subsequent call to the function, or after the calling thread has exited (7.26.6.3).


From c719d98c3459e742059b3bf0ae860002f445c189 Mon Sep 17 00:00:00 2001 From: David Svoboda Date: Wed, 8 Jul 2026 09:07:22 -0400 Subject: [PATCH 2/9] Documented & mitigated race condition --- .../03.rules/05.concurrency-con/05.con33-c.md | 68 ++++++++++++++++--- 1 file changed, 59 insertions(+), 9 deletions(-) diff --git a/content/4.sei-cert-c-coding-standard/03.rules/05.concurrency-con/05.con33-c.md b/content/4.sei-cert-c-coding-standard/03.rules/05.concurrency-con/05.con33-c.md index 197e0947..91c23dd4 100644 --- a/content/4.sei-cert-c-coding-standard/03.rules/05.concurrency-con/05.con33-c.md +++ b/content/4.sei-cert-c-coding-standard/03.rules/05.concurrency-con/05.con33-c.md @@ -102,7 +102,40 @@ int main() { // Handle Error } - t = strtok(NULL, ","); // Undefined Behavior + t = strtok(NULL, ","); + + int retval; + if (thrd_success != thrd_join(thr, &retval)) { + // Handle Error + } +} +``` +:: + +## Noncompliant Code Example (`strtok_r()`) + +This noncompliant code example the POSIX `strtok_r()` function, which is reentrant. It relies on no static variables, always tokenizing the string in its 3rd `saveptr` argument. However, by permitting a data race on `str` via `saveptr`, this code violates [CON43-C. Do not allow data races in multithreaded code](/sei-cert-c-coding-standard/rules/concurrency-con/con43-c). + +::code-block{quality="bad"} +``` c +#include +#include + +int bar(void * saveptr) { + char *t = strtok_r(NULL, "#,", (char**) &saveptr); + return t[0]; +} + +int main() { + char str[] = "?a???b,,,#c"; + char *saveptr = NULL; + char *t = strtok_r(str, "?", &saveptr); + thrd_t thr; + if (thrd_success != thrd_create(&thr, bar, saveptr)) { + // Handle Error + } + + t = strtok_r(NULL, ",", &saveptr); int retval; if (thrd_success != thrd_join(thr, &retval)) { @@ -114,35 +147,52 @@ int main() { ## Compliant Solution (POSIX, `strtok_r()` ) -This compliant solution uses the POSIX `strtok_r()` function, which is reentrant. It relies on no static variables, always tokenizing the string in its 3rd `saveptr` argument. +This compliant solution uses a mutex to prevent data races. There is still a race condition as to which thread invokes `strtok_r()`, but there is no data race on `saveptr` or `str`, as proscribed by [CON43-C. Do not allow data races in multithreaded code](/sei-cert-c-coding-standard/rules/concurrency-con/con43-c). ::code-block{quality="good"} ``` c #include #include -static char str[] = "?a???b,,,#c"; -char *saveptr = NULL; +static mtx_t lock; -int bar(void *) { - char *t = strtok_r(NULL, ",", &saveptr); +int bar(void * saveptr) { + if (mtx_lock(&lock) == thrd_error) { + return -1; /* Indicate error to caller */ + } + char *t = strtok_r(NULL, "#,", (char**) &saveptr); + if (mtx_unlock(&lock) == thrd_error) { + return -1; /* Indicate error to caller */ + } return t[0]; } -int main(void) { +int main() { + char str[] = "?a???b,,,#c"; + char *saveptr = NULL; char *t = strtok_r(str, "?", &saveptr); + + if(mtx_init(&lock, mtx_plain) == thrd_error) { + /* Handle error */ + } + thrd_t thr; - if (thrd_success != thrd_create(&thr, bar, NULL)) { + if (thrd_success != thrd_create(&thr, bar, saveptr)) { // Handle Error } + if (mtx_lock(&lock) == thrd_error) { + return -1; /* Indicate error to caller */ + } t = strtok_r(NULL, ",", &saveptr); + if (mtx_unlock(&lock) == thrd_error) { + return -1; /* Indicate error to caller */ + } int retval; if (thrd_success != thrd_join(thr, &retval)) { // Handle Error } - return 0; } ``` :: From 122b0712feb522ec62f31a33ee484536836544f4 Mon Sep 17 00:00:00 2001 From: David Svoboda Date: Wed, 8 Jul 2026 09:09:37 -0400 Subject: [PATCH 3/9] data race --- .../03.rules/05.concurrency-con/05.con33-c.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/content/4.sei-cert-c-coding-standard/03.rules/05.concurrency-con/05.con33-c.md b/content/4.sei-cert-c-coding-standard/03.rules/05.concurrency-con/05.con33-c.md index 91c23dd4..e83cd656 100644 --- a/content/4.sei-cert-c-coding-standard/03.rules/05.concurrency-con/05.con33-c.md +++ b/content/4.sei-cert-c-coding-standard/03.rules/05.concurrency-con/05.con33-c.md @@ -114,7 +114,7 @@ int main() { ## Noncompliant Code Example (`strtok_r()`) -This noncompliant code example the POSIX `strtok_r()` function, which is reentrant. It relies on no static variables, always tokenizing the string in its 3rd `saveptr` argument. However, by permitting a data race on `str` via `saveptr`, this code violates [CON43-C. Do not allow data races in multithreaded code](/sei-cert-c-coding-standard/rules/concurrency-con/con43-c). +This noncompliant code example the POSIX `strtok_r()` function, which is reentrant. It relies on no static variables, always tokenizing the string in its 3rd `saveptr` argument. However, by permitting a [data race](/sei-cert-c-coding-standard/back-matter/bb-definitions#BB.Definitions-datarace) on `str` via `saveptr`, this code violates [CON43-C. Do not allow data races in multithreaded code](/sei-cert-c-coding-standard/rules/concurrency-con/con43-c). ::code-block{quality="bad"} ``` c From b6d87d45ae64fa39ea63bd03d74654de7a102d2c Mon Sep 17 00:00:00 2001 From: David Svoboda Date: Wed, 8 Jul 2026 11:06:48 -0400 Subject: [PATCH 4/9] cast *void, not **void --- .../03.rules/05.concurrency-con/05.con33-c.md | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/content/4.sei-cert-c-coding-standard/03.rules/05.concurrency-con/05.con33-c.md b/content/4.sei-cert-c-coding-standard/03.rules/05.concurrency-con/05.con33-c.md index e83cd656..db1d954c 100644 --- a/content/4.sei-cert-c-coding-standard/03.rules/05.concurrency-con/05.con33-c.md +++ b/content/4.sei-cert-c-coding-standard/03.rules/05.concurrency-con/05.con33-c.md @@ -112,7 +112,7 @@ int main() { ``` :: -## Noncompliant Code Example (`strtok_r()`) +## Noncompliant Code Example (POSIX, `strtok_r()`) This noncompliant code example the POSIX `strtok_r()` function, which is reentrant. It relies on no static variables, always tokenizing the string in its 3rd `saveptr` argument. However, by permitting a [data race](/sei-cert-c-coding-standard/back-matter/bb-definitions#BB.Definitions-datarace) on `str` via `saveptr`, this code violates [CON43-C. Do not allow data races in multithreaded code](/sei-cert-c-coding-standard/rules/concurrency-con/con43-c). @@ -121,8 +121,9 @@ This noncompliant code example the POSIX `strtok_r()` function, which is reentra #include #include -int bar(void * saveptr) { - char *t = strtok_r(NULL, "#,", (char**) &saveptr); +int bar(void * p) { + char* saveptr = p;; + char *t = strtok_r(NULL, "#,", &saveptr); return t[0]; } @@ -156,11 +157,13 @@ This compliant solution uses a mutex to prevent data races. There is still a ra static mtx_t lock; -int bar(void * saveptr) { +int bar(void * p) { + char* saveptr = p;; + if (mtx_lock(&lock) == thrd_error) { return -1; /* Indicate error to caller */ } - char *t = strtok_r(NULL, "#,", (char**) &saveptr); + char *t = strtok_r(NULL, "#,", &saveptr); if (mtx_unlock(&lock) == thrd_error) { return -1; /* Indicate error to caller */ } From 452e7072ec0468c88b3f6e0b29d5be601e5bab65 Mon Sep 17 00:00:00 2001 From: David Svoboda Date: Fri, 10 Jul 2026 16:02:03 -0400 Subject: [PATCH 5/9] Feedback --- .../03.rules/05.concurrency-con/05.con33-c.md | 72 ++++++++++++++----- 1 file changed, 55 insertions(+), 17 deletions(-) diff --git a/content/4.sei-cert-c-coding-standard/03.rules/05.concurrency-con/05.con33-c.md b/content/4.sei-cert-c-coding-standard/03.rules/05.concurrency-con/05.con33-c.md index db1d954c..92e8e42c 100644 --- a/content/4.sei-cert-c-coding-standard/03.rules/05.concurrency-con/05.con33-c.md +++ b/content/4.sei-cert-c-coding-standard/03.rules/05.concurrency-con/05.con33-c.md @@ -89,25 +89,37 @@ Invoking the `strtok()` function from multiple threads is [undefined behavior 19 #include #include -int bar(void *) { +int child(void *) { char *t = strtok(NULL, "#,"); // Undefined Behavior + + // Work with token... + return t[0]; } -int main() { - char str[] = "?a???b,,,#c"; +int main(int argc, char** argv[]) { + if (argc < 2) { + // handle error + abort(); + } + char str[] = argv[1]; // Example: "?a???b,,,#c" + char *t = strtok(str, "?"); thrd_t thr; - if (thrd_success != thrd_create(&thr, bar, 0)) { + if (thrd_success != thrd_create(&thr, child, 0)) { // Handle Error } t = strtok(NULL, ","); + // Work with token... + int retval; if (thrd_success != thrd_join(thr, &retval)) { // Handle Error } + + return 0; } ``` :: @@ -120,28 +132,40 @@ This noncompliant code example the POSIX `strtok_r()` function, which is reentra ``` c #include #include +#include + + +int child(void *) { + char *t = strtok(NULL, "#,"); // Undefined Behavior + + // Work with token... -int bar(void * p) { - char* saveptr = p;; - char *t = strtok_r(NULL, "#,", &saveptr); return t[0]; } -int main() { - char str[] = "?a???b,,,#c"; - char *saveptr = NULL; - char *t = strtok_r(str, "?", &saveptr); +int main(int argc, char** argv) { + if (argc < 2) { + // handle error + abort(); + } + char *str = argv[1]; // Example: "?a???b,,,#c" + + char *t = strtok(str, "?"); thrd_t thr; - if (thrd_success != thrd_create(&thr, bar, saveptr)) { + if (thrd_success != thrd_create(&thr, child, 0)) { // Handle Error } - t = strtok_r(NULL, ",", &saveptr); + t = strtok(NULL, ","); + + // Work with token... int retval; if (thrd_success != thrd_join(thr, &retval)) { // Handle Error } + + return 0; } ``` :: @@ -154,10 +178,12 @@ This compliant solution uses a mutex to prevent data races. There is still a ra ``` c #include #include +#include + static mtx_t lock; -int bar(void * p) { +int child(void *) { char* saveptr = p;; if (mtx_lock(&lock) == thrd_error) { @@ -167,11 +193,19 @@ int bar(void * p) { if (mtx_unlock(&lock) == thrd_error) { return -1; /* Indicate error to caller */ } + + // Work with token... + return t[0]; } -int main() { - char str[] = "?a???b,,,#c"; +int main(int argc, char** argv) { + if (argc < 2) { + // handle error + abort(); + } + char *str = argv[1]; // Example: "?a???b,,,#c" + char *saveptr = NULL; char *t = strtok_r(str, "?", &saveptr); @@ -180,7 +214,7 @@ int main() { } thrd_t thr; - if (thrd_success != thrd_create(&thr, bar, saveptr)) { + if (thrd_success != thrd_create(&thr, child, saveptr)) { // Handle Error } @@ -192,10 +226,14 @@ int main() { return -1; /* Indicate error to caller */ } + // Work with token... + int retval; if (thrd_success != thrd_join(thr, &retval)) { // Handle Error } + + return 0; } ``` :: From e7c07ad51dce473a732f0f3e2c9b71628ebfa347 Mon Sep 17 00:00:00 2001 From: David Svoboda Date: Fri, 10 Jul 2026 16:12:36 -0400 Subject: [PATCH 6/9] Feedback --- .../03.rules/05.concurrency-con/05.con33-c.md | 23 +++++++++++-------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/content/4.sei-cert-c-coding-standard/03.rules/05.concurrency-con/05.con33-c.md b/content/4.sei-cert-c-coding-standard/03.rules/05.concurrency-con/05.con33-c.md index 92e8e42c..938ce267 100644 --- a/content/4.sei-cert-c-coding-standard/03.rules/05.concurrency-con/05.con33-c.md +++ b/content/4.sei-cert-c-coding-standard/03.rules/05.concurrency-con/05.con33-c.md @@ -88,8 +88,10 @@ Invoking the `strtok()` function from multiple threads is [undefined behavior 19 ``` c #include #include +#include + -int child(void *) { +int child(void *p) { char *t = strtok(NULL, "#,"); // Undefined Behavior // Work with token... @@ -97,12 +99,12 @@ int child(void *) { return t[0]; } -int main(int argc, char** argv[]) { +int main(int argc, char** argv) { if (argc < 2) { // handle error abort(); } - char str[] = argv[1]; // Example: "?a???b,,,#c" + char *str = argv[1]; // Example: "?a???b,,,#c" char *t = strtok(str, "?"); thrd_t thr; @@ -135,8 +137,8 @@ This noncompliant code example the POSIX `strtok_r()` function, which is reentra #include -int child(void *) { - char *t = strtok(NULL, "#,"); // Undefined Behavior +int child(void *p) { + char *t = strtok_r(NULL, "#,", &saveptr); // Work with token... @@ -150,13 +152,14 @@ int main(int argc, char** argv) { } char *str = argv[1]; // Example: "?a???b,,,#c" - char *t = strtok(str, "?"); + char *saveptr = NULL; + char *t = strtok_r(str, "?", &saveptr); thrd_t thr; if (thrd_success != thrd_create(&thr, child, 0)) { // Handle Error } - t = strtok(NULL, ","); + t = strtok_r(NULL, ",", &saveptr); // Work with token... @@ -168,7 +171,7 @@ int main(int argc, char** argv) { return 0; } ``` -:: + :: ## Compliant Solution (POSIX, `strtok_r()` ) @@ -183,8 +186,8 @@ This compliant solution uses a mutex to prevent data races. There is still a ra static mtx_t lock; -int child(void *) { - char* saveptr = p;; +int child(void *p) { + char* saveptr = p; if (mtx_lock(&lock) == thrd_error) { return -1; /* Indicate error to caller */ From 003f9173e94ba2f91ee4e3221ce7db38331e9d07 Mon Sep 17 00:00:00 2001 From: David Svoboda Date: Fri, 10 Jul 2026 16:28:47 -0400 Subject: [PATCH 7/9] Feedback --- .../03.rules/05.concurrency-con/05.con33-c.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/content/4.sei-cert-c-coding-standard/03.rules/05.concurrency-con/05.con33-c.md b/content/4.sei-cert-c-coding-standard/03.rules/05.concurrency-con/05.con33-c.md index 938ce267..72966a1c 100644 --- a/content/4.sei-cert-c-coding-standard/03.rules/05.concurrency-con/05.con33-c.md +++ b/content/4.sei-cert-c-coding-standard/03.rules/05.concurrency-con/05.con33-c.md @@ -138,6 +138,7 @@ This noncompliant code example the POSIX `strtok_r()` function, which is reentra int child(void *p) { + char *saveptr = p; char *t = strtok_r(NULL, "#,", &saveptr); // Work with token... @@ -155,7 +156,7 @@ int main(int argc, char** argv) { char *saveptr = NULL; char *t = strtok_r(str, "?", &saveptr); thrd_t thr; - if (thrd_success != thrd_create(&thr, child, 0)) { + if (thrd_success != thrd_create(&thr, child, &saveptr)) { // Handle Error } From 94883afc24b91fcbfde2f5a6b82f7fd44f8073bc Mon Sep 17 00:00:00 2001 From: David Svoboda <57185056+sei-dsvoboda@users.noreply.github.com> Date: Fri, 17 Jul 2026 12:36:53 -0400 Subject: [PATCH 8/9] Update content/4.sei-cert-c-coding-standard/03.rules/05.concurrency-con/05.con33-c.md Co-authored-by: sei-jsible <105077289+sei-jsible@users.noreply.github.com> --- .../03.rules/05.concurrency-con/05.con33-c.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/content/4.sei-cert-c-coding-standard/03.rules/05.concurrency-con/05.con33-c.md b/content/4.sei-cert-c-coding-standard/03.rules/05.concurrency-con/05.con33-c.md index 72966a1c..3414cf1c 100644 --- a/content/4.sei-cert-c-coding-standard/03.rules/05.concurrency-con/05.con33-c.md +++ b/content/4.sei-cert-c-coding-standard/03.rules/05.concurrency-con/05.con33-c.md @@ -82,7 +82,7 @@ Linux provides two versions of `strerror_r()` , known as the *XSI-compliant vers ## Noncompliant Code Example (`strtok()`) -Invoking the `strtok()` function from multiple threads is [undefined behavior 199](/sei-cert-c-coding-standard/back-matter/cc-undefined-behavior#CC.UndefinedBehavior-ub_199), according to ISO C section 7.26.5.9. +Starting a sequence of calls to the `strtok()` function from one thread and making a subsequent call in the same sequence from a different thread is [undefined behavior 199](/sei-cert-c-coding-standard/back-matter/cc-undefined-behavior#CC.UndefinedBehavior-ub_199), according to ISO C section 7.26.5.9. ::code-block{quality="bad"} ``` c From 216ad1e53d04f1fb56a8d551b0615b115fb4dea2 Mon Sep 17 00:00:00 2001 From: David Svoboda Date: Fri, 17 Jul 2026 16:56:12 -0400 Subject: [PATCH 9/9] feedback --- .../03.rules/05.concurrency-con/05.con33-c.md | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/content/4.sei-cert-c-coding-standard/03.rules/05.concurrency-con/05.con33-c.md b/content/4.sei-cert-c-coding-standard/03.rules/05.concurrency-con/05.con33-c.md index b4be3646..9b6057e2 100644 --- a/content/4.sei-cert-c-coding-standard/03.rules/05.concurrency-con/05.con33-c.md +++ b/content/4.sei-cert-c-coding-standard/03.rules/05.concurrency-con/05.con33-c.md @@ -27,7 +27,7 @@ According to the C Standard, the library functions listed in the following table | ` tmpnam() ` | ` tmpnam_r() ` in POSIX | | ` mbrtoc16() ` , ` c16rtomb() ` ,
` mbrtoc32() ` , ` c32rtomb() ` | Do not call with a null ` mbstate_t * ` argument | -Section 2.9.1 of the *Portable Operating System Interface (POSIX ® ), Base Specifications, Issue 7* \[ [IEEE Std 1003.1:2013](/sei-cert-c-coding-standard/back-matter/aa-bibliography#AA.Bibliography-IEEEStd1003.1-2013) \] extends the list of functions that are not required to be thread-safe. +Section 2.9.1 of the *Portable Operating System Interface (POSIX ® ), Base Specifications, Issue 7* \[ [IEEE Std 1003.1:2013](/sei-cert-c-coding-standard/back-matter/aa-bibliography#AA.Bibliography-IEEEStd1003.1-2013) \] extends the list of functions that are not required to be thread-safe. ## Noncompliant Code Example (`strerror()`) @@ -44,7 +44,7 @@ An [implementation](/sei-cert-c-coding-standard/back-matter/bb-definitions#BB.De #include #include #include -  + void f(FILE *fp) { fpos_t pos; errno = 0; @@ -70,7 +70,7 @@ This compliant solution uses the POSIX `strerror_r()` function, which has the sa #include enum { BUFFERSIZE = 64 }; -  + void f(FILE *fp) { fpos_t pos; errno = 0; @@ -104,7 +104,7 @@ int child(void *p) { // Work with token... - return t[0]; + return t ? (unsigned char) t[0] : -1; } int main(int argc, char** argv) { @@ -136,7 +136,7 @@ int main(int argc, char** argv) { ## Noncompliant Code Example (POSIX, `strtok_r()`) -This noncompliant code example the POSIX `strtok_r()` function, which is reentrant. It relies on no static variables, always tokenizing the string in its 3rd `saveptr` argument. However, by permitting a [data race](/sei-cert-c-coding-standard/back-matter/bb-definitions#BB.Definitions-datarace) on `str` via `saveptr`, this code violates [CON43-C. Do not allow data races in multithreaded code](/sei-cert-c-coding-standard/rules/concurrency-con/con43-c). +This noncompliant code example the POSIX `strtok_r()` function, which is reentrant. It relies on no static variables, always tokenizing the string in its 3rd `saveptr` argument, so it complies with this rule. However, by permitting a [data race](/sei-cert-c-coding-standard/back-matter/bb-definitions#BB.Definitions-datarace) on `str` via `saveptr`, this code violates [CON43-C. Do not allow data races in multithreaded code](/sei-cert-c-coding-standard/rules/concurrency-con/con43-c). ::code-block{quality="bad"} ``` c @@ -151,7 +151,7 @@ int child(void *p) { // Work with token... - return t[0]; + return t ? (unsigned char) t[0] : -1; } int main(int argc, char** argv) { @@ -208,7 +208,7 @@ int child(void *p) { // Work with token... - return t[0]; + return t ? (unsigned char) t[0] : -1; } int main(int argc, char** argv) { @@ -270,7 +270,7 @@ Search for [vulnerabilities](http://BB.%20Definitions#vulnerability) resulting f | Astrée |

25.10
| **bad-function-use** | Partially checked + soundly supported | | Axivion Suite |
7.12.0
| **CertC-CON33** | | | CodeSonar |
9.2p0
| **CONCURRENCY.C_ATOMIC.INIT**
**BADFUNC.RANDOM.RAND**
**BADFUNC.TEMP.TMPNAM**
**BADFUNC.TTYNAME** | Inappropriate C Atomic Initialization
Use of rand (includes check for uses of srand())
Use of tmpnam (includes check for uses of tmpnam_r())
Use of ttyname | -| Compass/ROSE | | | A module written in Compass/ROSE can detect violations of this rule | +| Compass/ROSE | | | A module written in Compass/ROSE can detect violations of this rule | | Cppcheck Premium |
24.11.0
| **premium-cert-con33-c** | | | Helix QAC |
2025.2
| **C5037**
**C++5021**
**DF4976, DF4977** | | | Klocwork |
2025.2
| **CERT.CONC.LIB_FUNC_USE** | |