Uploaded image for project: 'Rules Repository'
  1. Rules Repository
  2. RSPEC-1912

Non-reentrant POSIX functions should be replaced with their reentrant versions

    Details

    • Type: Code Smell Detection
    • Status: Active
    • Resolution: Unresolved
    • Labels:
    • Message:
      Replace this call to the non-reentrant "{0}" with a call to "{0}_r"
    • List of parameters:
      Hide
      • key = nonReentrantFunctionList
      • description = List of non-reentrant functions
      • default = asctime,crypt,ctermid,ctime,fgetgrent,fgetpwent,fgetspent,getgrent,getgrgid,getgrnam,gethostbyaddr,gethostbyname,gethostbyname2,gethostent,getlogin,getnetbyaddr,getnetbyname,getnetent,getnetgrent,getprotobyname,getprotobynumber,getprotoent,getpwent,getpwnam,getpwuid,getrpcbyname,getrpcbynumber,getrpcent,getservbyname,getservbyport,getservent,getspent,getspnam,gmtime,localtime,sgetspent,strtok,ttyname
      • type = STRING
      Show
      key = nonReentrantFunctionList description = List of non-reentrant functions default = asctime,crypt,ctermid,ctime,fgetgrent,fgetpwent,fgetspent,getgrent,getgrgid,getgrnam,gethostbyaddr,gethostbyname,gethostbyname2,gethostent,getlogin,getnetbyaddr,getnetbyname,getnetent,getnetgrent,getprotobyname,getprotobynumber,getprotoent,getpwent,getpwnam,getpwuid,getrpcbyname,getrpcbynumber,getrpcent,getservbyname,getservbyport,getservent,getspent,getspnam,gmtime,localtime,sgetspent,strtok,ttyname type = STRING
    • Default Severity:
      Blocker
    • Impact:
      High
    • Likelihood:
      High
    • Default Quality Profiles:
      Sonar way
    • Legacy Key:
      NonReentrantFunction
    • Covered Languages:
      C, C++, Objective-C
    • Remediation Function:
      Constant/Issue
    • Constant Cost:
      30min
    • CPPCheck:
      nonreentrantFunctions.*

      Description

      A function is called reentrant if it can be interrupted in the middle of its execution and then safely called again ("re-entered") before its previous invocations complete execution.

      It is especially important that multi-threaded applications do not call the same non-reentrant function from different threads.

      This rule will trigger an issue each time a function in the configurable list is invoked.

      Noncompliant Code Example

      Given a function that includes localtime:

      #include <stdio.h>
      #include <time.h>
      
      void print_date_and_time(struct tm *time_ptr)
      {
        printf(
          "Current date and time: %d/%02d/%02d %02d:%02d:%02d\n",
          time_ptr->tm_year + 1900,
          time_ptr->tm_mon,
          time_ptr->tm_mday,
          time_ptr->tm_hour,
          time_ptr->tm_min,
          time_ptr->tm_sec);
      }
      
      void print_unix_epoch_date_and_time()
      {
        time_t unix_epoch_time = (time_t)0;
        struct tm *local_time_ptr = localtime(&unix_epoch_time); // Noncompliant, call to the non-reentrant localtime() function
        print_date_and_time(local_time_ptr);
      }
      
      int main(int argc, char* argv[])
      {
        time_t current_time;
        struct tm *local_time_ptr;
      
        time(&current_time);
      
        local_time_ptr = localtime(&current_time); // Noncompliant, call to the non-reentrant localtime() function
      
        // As expected, this will print: Current date and time: 1970/00/01 01:00:00
        print_unix_epoch_date_and_time();
      
        // This will actually also print Current date and time: 1970/00/01 01:00:00
        // Indeed, localtime() is non-reentrant, and always returns the same pointer
        print_date_and_time(local_time_ptr);
      
        return 0;
      }
      

      Compliant Solution

      #include <stdio.h>
      #include <time.h>
      
      void print_date_and_time(struct tm *time_ptr)
      {
        printf(
          "Current date and time: %d/%02d/%02d %02d:%02d:%02d\n",
          time_ptr->tm_year + 1900,
          time_ptr->tm_mon,
          time_ptr->tm_mday,
          time_ptr->tm_hour,
          time_ptr->tm_min,
          time_ptr->tm_sec);
      }
      
      void print_unix_epoch_date_and_time()
      {
        time_t unix_epoch_time = (time_t)0;
        struct tm local_time;
        localtime_r(&unix_epoch_time, &local_time); // Compliant
        print_date_and_time(&local_time);
      }
      
      int main(int argc, char* argv[])
      {
        time_t current_time;
        struct tm local_time;
      
        time(&current_time);
      
        localtime_r(&current_time, &local_time); // Compliant
      
        // As expected, this will print: Current date and time: 1970/00/01 01:00:00
        print_unix_epoch_date_and_time();
      
        // As expected, this will print the current date and time
        print_date_and_time(&local_time);
      
        return 0;
      }
      

        Attachments

          Issue Links

          1.
          C-Family RSPEC-4379 Language-Specification Active Unassigned

            Activity

              People

              • Assignee:
                Unassigned
                Reporter:
                ann.campbell.2 Ann Campbell
              • Votes:
                0 Vote for this issue
                Watchers:
                1 Start watching this issue

                Dates

                • Created:
                  Updated: