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
|
| 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** | |
|