Call to a thread-unsafe (non-reentrant) libc function
ID |
c.correctness.mt_unsafe |
Severity |
low |
Remediation Complexity |
medium |
Remediation Risk |
medium |
Remediation Effort |
medium |
Resource |
Concurrency |
Language |
C / C++ |
Description
Call to a non-reentrant / thread-unsafe libc function. These functions use shared internal state (static buffers or global state) and misbehave when called concurrently from multiple threads. Prefer the reentrant _r variant (e.g. localtime_r, gmtime_r, strtok_r, rand_r) or a thread-safe alternative, and guard shared state where no reentrant variant exists.
Rationale
Call to a non-reentrant / thread-unsafe libc function. These functions use shared internal state (static buffers or global state) and misbehave when called concurrently from multiple threads. Prefer the reentrant _r variant (e.g. localtime_r, gmtime_r, strtok_r, rand_r) or a thread-safe alternative, and guard shared state where no reentrant variant exists.
The following code illustrates the pattern detected by this rule:
void foo(time_t *t, char *s)
{
// FLAGGED: Call to a thread-unsafe (non-reentrant) libc function
gmtime(t);
// FLAGGED: Call to a thread-unsafe (non-reentrant) libc function
localtime(t);
// FLAGGED: Call to a thread-unsafe (non-reentrant) libc function
asctime(NULL);
// FLAGGED: Call to a thread-unsafe (non-reentrant) libc function
ctime(t);
// FLAGGED: Call to a thread-unsafe (non-reentrant) libc function
strtok(s, ",");
// FLAGGED: Call to a thread-unsafe (non-reentrant) libc function
rand();
// FLAGGED: Call to a thread-unsafe (non-reentrant) libc function
srand(1);
// FLAGGED: Call to a thread-unsafe (non-reentrant) libc function
getenv("PATH");
// FLAGGED: Call to a thread-unsafe (non-reentrant) libc function
tmpnam(NULL);
// FLAGGED: Call to a thread-unsafe (non-reentrant) libc function
getpwnam("root");
// FLAGGED: Call to a thread-unsafe (non-reentrant) libc function
getlogin();
// FLAGGED: Call to a thread-unsafe (non-reentrant) libc function
ttyname(0);
}