Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

  • rand()
  • getenv()
  • strtok()
  • strerror()
  • asctime()
  • ctime()

Non Compliant Code Example

Consider a multithreaded application which involves a function which returns a random value each time it is invoked. According to POSIX implementation, rand() returns the next pseudorandom number in the sequence determined by an initial seed value. The rand() function updates the seed value, which is stored at a library allocated static memory location. If two threads concurrently invoke the rand() function, it may result in undefined behavior and may also result in rand() returning the same value in both the encounters an error while calling a system function. The strerror() function returns a human-readable error string given an error number. According to C99, Section 7.22.6.2 specifically states that strerror() is not required to avoid data races. Conventionally it could rely on a static array that maps error numbers to error strings, and said array might be accessible and modifiable by other threads.

Code Block
bgColor#FFCCCC

int get_secret(
FILE* fd = fopen( filename, "r");
if (fd == NULL) {
  intchar* secreterrmsg = (rand() % 100) + 100;
  return secretstrerror(errno);
  printf("Could not open file because of %s\n", errmsg);
}

Compliant Solution

The compliant solution uses a mutex to make each call to rand() function atomic strerror_r(), which has the same functionality as strerror() but guarantees thread-safety.

Code Block
bgColor#ccccff
#include <threads.h>
mtx_t rand_lock; 

int get_secret() {
  int secret;

  mtx_lock(&rand_lock) ;
  secret = (rand() % 100) + 100;
  mtx_unlock(&rand_lock);

  return secret;
}


void init(){
  /* initialize a simple non-recursive mutex */
  if(mtx_init(&rand_lock, mtx_plain) == thrd_error){
    abort();
  }

  /* other initialization code */FILE* fd = fopen( filename, "r");
if (fd == NULL) {
  char errmsg[BUFSIZ];
  if (strerror_r( errno, errmsg, BUFSIZ) == -1) {
    /* handle error */
  }
  printf("Could not open file because of %s\n", errmsg);
}

Risk Assessment

Race conditions caused by multiple threads invoking the same library function can lead to abnormal termination of the application, data integrity violations or denial of service attack.

...