Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: Updated references from C11->C23

The C Standard, 7.2224.4.6, paragraph 4 [ISO/IEC 9899:20112024], states

The getenv function returns a pointer to a string associated with the matched list member. The string pointed to shall not be modified by the program but may be overwritten by a subsequent call to the getenv function. If the specified name cannot be found, a null pointer is returned.

This paragraph gives an implementation the latitude, for example, to return a pointer to a statically allocated buffer. Consequently, do not store this pointer because the string data it points to may be overwritten by a subsequent call to the getenv() function or invalidated by modifications to the environment. This string should be referenced immediately and discarded. If later use is anticipated, the string should be copied so the copy can be safely referenced as needed.

...

Code Block
bgColor#ccccff
langc
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
 
void func(void) {
  char *tmpvar;
  char *tempvar;

  const char *temp = getenv("TMP");
  if (temp != NULL) {
    tmpvar = (char *)malloc(strlen(temp)+1);
    if (tmpvar != NULL) {
      strcpy(tmpvar, temp);
    } else {
      /* Handle error */
    }
  } else {
    /* Handle error */
  }

  temp = getenv("TEMP");
  if (temp != NULL) {
    tempvar = (char *)malloc(strlen(temp)+1);
    if (tempvar != NULL) {
      strcpy(tempvar, temp);
    } else {
      /* Handle error */
    }
  } else {
    /* Handle error */
  }

  if (strcmp(tmpvar, tempvar) == 0) {
    printf("TMP and TEMP are the same.\n");
  } else {
    printf("TMP and TEMP are NOT the same.\n");
  }
  free(tmpvar);
  free(tempvar);
}

Compliant Solution (

...

Annex K)

The C Standard, Annex K, provides the getenv_s() function for getting a value from the current environment. However, getenv_s() can still have data races with other threads of execution that modify the environment list.

Code Block
bgColor#ccccff
langc
#define __STDC_WANT_LIB_EXT1__ 1
#include <errno.h>

This compliant solution uses the strdup() function to copy the string returned by getenv() into a dynamically allocated buffer:

Code Block
languagecpp
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
  
void func(void) {
  char *tmpvar;
  char *tempvar;

  const char *tempsize_t requiredSize;
  errno_t err;
  err = getenv_s(&requiredSize, NULL, 0, "TMP");

  if (temp != NULLerr) {
    /* tmpvarHandle = strdup(temp);error */
   }
 
 if (tmpvar == NULL) {
      /* Handle error */(char *)malloc(requiredSize);
    }
  } elseif (!tmpvar) {
    /* Handle error */
  }

  temperr = getenv("TEMP");
  if (temp != NULL) {
    tempvar = strdup(temp);
  _s(&requiredSize, tmpvar, requiredSize, "TMP" );

  if (tempvar == NULLerr) {
      /* Handle error */
    }
  }err else {
    = getenv_s(&requiredSize, NULL, 0, "TEMP");
  if (err) {
    /* Handle error */
  }
 
  iftempvar = (strcmp(tmpvar, tempvar) == 0char *)malloc(requiredSize);
  if (!tempvar) {
    printf("TMP and TEMP are the same.\n");/* Handle error */
  } else {
  err = printf("TMP and TEMP are NOT the same.\n");
  }
  free(tmpvar);
  free(tempvar);
}

Compliant Solution (Annex K)

The C Standard, Annex K, provides the getenv_s() function for getting a value from the current environment. However, getenv_s() can still have data races with other threads of execution that modify the environment list.

Code Block
bgColor#ccccff
langc
#define __STDC_WANT_LIB_EXT1__ 1
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
 
void func(void) {
  char *tmpvar;
  char *tempvar;
  size_t requiredSize;
  errno_t err;
  err = getenv_s(&requiredSize, NULL, 0, "TMP");

  if (err) {
    /* Handle error */
  }
 
  tmpvar = (char *)malloc(requiredSize);
  if (!tmpvar) {
    /* Handle error */
  }
  err = getenv_s(&requiredSize, tmpvar, requiredSize, "TMP" );

  if (err) {
    /* Handle error */
  }
  err = getenv_s(&requiredSize, NULL, 0, "TEMP");
  if (err) {
    /* Handle error */
  }
 
  tempvar = (char *)malloc(requiredSize);
  if (!tempvar) {
    /* Handle error */
  }
  err = getenv_s(&requiredSize, tempvar, requiredSize, "TEMP" );

  if (err) {
    /* Handle error */
  }
  if (strcmp(tmpvar, tempvar) == 0) {
    printf("getenv_s(&requiredSize, tempvar, requiredSize, "TEMP" );

  if (err) {
    /* Handle error */
  }
  if (strcmp(tmpvar, tempvar) == 0) {
    printf("TMP and TEMP are the same.\n");
  } else {
    printf("TMP and TEMP are NOT the same.\n");
  }
  free(tmpvar);
  tmpvar = NULL;
  free(tempvar);
  tempvar = NULL;
}

...

Code Block
bgColor#ccccff
langc
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <stdio.h>
 
void func(void) {
  char *tmpvar;
  char *tempvar;
  size_t len;

  errno_t err = _dupenv_s(&tmpvar, &len, "TMP");
  if (err) {
    /* Handle error */
  }
  err = _dupenv_s(&tempvar, &len, "TEMP");
  if (err) {
    /* Handle error */
  }

  if (strcmp(tmpvar, tempvar) == 0) {
    printf("TMP and TEMP are the same.\n");
  } else {
    printf("TMP and TEMP are NOT the same.\n");
  }
  free(tmpvar);
  tmpvar = NULL;
  free(tempvar);
  tempvar = NULL;
}

Compliant Solution (POSIX or C2x)

POSIX provides the strdup() function, which can make a copy of the environment variable string [IEEE Std 1003.1:2013]. The strdup() function is also included in Extensions to the C Library—Part II [ISO/IEC TR 24731-2:2010]. Further, it is expected to be present in the C2x standard.

Code Block
bgColor#ccccff
langc
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
 
void func(void) {
  char *tmpvar;
  char *tempvar;

  const char *temp = getenv("TMP");
  if (temp != NULL) {
    tmpvar = strdup(temp);
    if (tmpvar == NULL) {
      /* Handle error */
    }
  } else {
    /* Handle error */
  }

  temp = getenv("TEMP");
  if (temp != NULL) {
    tempvar = strdup(temp);
    if (tempvar == NULL) {
      /* Handle error */
    }
  } else {
    /* Handle error */
  }

  if (strcmp(tmpvar, tempvar) == 0) {
    printf("TMP and TEMP are the same.\n");
  } else {
    printf("TMP and TEMP are NOT the same.\n");
  }
  free(tmpvar);
  tmpvar = NULL;
  free(tempvar);
  tempvar = NULL;
}

...

LDRALDRAParasoftParasoft 2681, 2682, 2683

Tool

Version

Checker

Description

Compass/ROSE




Cppcheck Premium
24.9.0
premium-cert-env34-c

Fully implemented

Helix QACLDRA tool suite

Include Page

Helix QAC_V

Helix QAC_V

133 D

Fully implemented

DF2681, DF2682, DF2683


Klocwork
Include Page
Klocwork
Parasoft C/C++test
Include Page
_V
Klocwork_V

CERT_C-ENV34-a

Pointers returned by certain Standard Library functions should not be used following a subsequent call to the same or related function

Polyspace Bug Finder

Include Page
Polyspace Bug Finder_VPolyspace Bug Finder_VCERT C: Rule ENV34-CChecks for misuse of return value from nonreentrant standard function (rule fully covered)PRQA QA-C
Include Page
PRQA QA-C_vPRQA QA-C_v2681, 2682, 2683PRQA QA-C++
Include Page
cplusplus:PRQA QA-C++_Vcplusplus:PRQA QA-C++_V

MISRA.STDLIB.ILLEGAL_REUSE.2012_AMD1


LDRA tool suite
Include Page
LDRA_V
LDRA_V

133 D

Fully implemented
Parasoft C/C++test

Include Page
Parasoft_V
Parasoft_V

CERT_C-ENV34-a

Pointers returned by certain Standard Library functions should not be used following a subsequent call to the same or related function

Polyspace Bug Finder

Include Page
Polyspace Bug Finder_V
Polyspace Bug Finder_V

CERT C: Rule ENV34-CChecks for misuse of return value from nonreentrant standard function (rule fully covered)

Related Guidelines

Key here (explains table format and definitions)

...

[IEEE Std 1003.1:2013]Chapter 8, "Environment Variables"
XSH, System Interfaces, strdup
[ISO/IEC 9899:20112024]Subclause 7.2224.4, "Communication with the Environment"
Subclause 7.2224.4.6, "The getenv Function"
Subclause K.3.6.2.1, "The getenv_s Function"
[MSDN]_dupenv_s(), _wdupenv_s()
[Viega 2003]Section 3.6, "Using Environment Variables Securely"

...