Contenu principal

Invalid use of standard library routine

Standard library function is called with invalid arguments

Description

This check on a standard library function call determines whether the function is called with valid arguments.

The check works differently for memory routines, floating point routines or string routines because their arguments can be invalid in different ways. For more information on each type of routines, see the following examples.

Examples

expand all

#include <assert.h>
#include <math.h>

#define LARGE_EXP 710

enum operation {
    ASIN,
    ACOS,
    TAN,
    SQRT,
    LOG,
    EXP,
};

enum operation getOperation(void);
double getVal(void);

void main() {
    enum operation myOperation = getOperation();
    double myVal=getVal(), res;
    switch(myOperation) {
    case ASIN:
        assert( myVal <- 1.0 || myVal > 1.0);
        res = asin(myVal);
        break;
    case ACOS:
        assert( myVal < -1.0 || myVal > 1.0);
        res = acos(myVal);
        break;
    case SQRT:
        assert( myVal < 0.0);
        res = sqrt(myVal);
        break;
    case LOG:
        assert(myVal <= 0.0);
        res = log(myVal);
        break;
    case EXP:
        assert(myVal > LARGE_EXP);
        res = exp(myVal);
        break;
    }
}

In this example, following each assert statement, Polyspace® considers that myVal contains only those values that make the assert condition true. For example, following assert(myVal < 1.0);, Polyspace considers that myVal contains values less than 1.0.

When myVal is used as argument in a standard library function, its values are invalid for the function. Therefore, the Invalid use of standard library routine check produces a red error.

To learn more about the specifications of this check for floating point routines, see Invalid Use of Standard Library Floating Point Routines.

#include <string.h>
#include <stdio.h>

char* Copy_First_Six_Letters(void) {
  char str1[10],str2[5];
  printf("Enter string:\n");
  scanf("%s",str1);
  memcpy(str2,str1,6);
  return str2;
}

int main(void) {
  (void*)Copy_First_Six_Letters();
  return 0;
}

In this example, the size of string str2 is 5, but 6 characters of string str1 are copied into str2 using the memcpy function. Therefore, the Invalid use of standard library routine check on the call to memcpy produces a red error.

For other examples, see Code Prover Assumptions About memset and memcpy.

Correction — Call function with valid arguments

One possible correction is to adjust the size of str2 so that it accommodates the characters copied with the memcpy function.

#include <string.h>
#include <stdio.h>

char* Copy_First_Six_Letters(void) {
  char str1[10],str2[6];
  printf("Enter string:\n");
  scanf("%s",str1);
  memcpy(str2,str1,6);
  return str2;
}

int main(void) {
  (void*)Copy_First_Six_Letters();
  return 0;
}
#include <stdio.h>
#include <string.h>

char* Copy_String(void)
{
  char *res;
  char gbuffer[5],text[20]="ABCDEFGHIJKL";
  res=strcpy(gbuffer,text);
  return(res);
}

int main(void) {
  (void*)Copy_String();
}

In this example, the string text is larger in size than gbuffer. Therefore, when you copy text into gbuffer. the Invalid use of standard library routine check on the call to strcpy produces a red error.

Correction — Call function with valid arguments

One possible correction is to declare the destination string gbuffer with equal or larger size than the source string text.

#include <stdio.h>
#include <string.h>

char* Copy_String(void)
{
  char *res;
  char gbuffer[20],text[20]="ABCDEFGHIJKL";
  res=strcpy(gbuffer,text);
  return(res);
}

int main(void) {
  (void*)Copy_String();
}
        
#include <string>

void main() {
    std::string str = "";
    const char txt[3] = {'n','o','p'};
    str.append(txt);  //txt is not a valid string
}

In this example, txt is not a null-terminated character sequence (C-string). Therefore, the Invalid use of standard library routine check on the call to std::string::append is red.

Correction – Use null-terminated C-string when expected

For methods that take a const char* argument str, make sure that str is non-NULL and points to a valid null-terminated C-string.

          
#include <string>

void main() {
    std::string str = "";
    const char txtStr[4] = {'n','o','p', '\0'};
    str.append(txtStr); //txtStr is valid string
}

The Invalid use of standard library routine check on the free() function determines if the pointer argument to the function:

  • Is a non-null pointer.

  • Can be deallocated. That is, the pointer was previously allocated dynamically by an authorized allocation function such as malloc() or realloc() and not already deallocated.

The check can detect issues associated with freeing of memory such as:

  • Consecutive freeing of memory.

    #include <stdlib.h>
    #include <stdio.h>
    
    int increment_content_of_address(int base_val, int shift)
    {
        int j;
        int* pi = (int*)malloc(sizeof(int));
        if (pi == NULL) return 0;
    
        *pi = base_val;
    
        if(shift < 0)
            {
                j = *pi - shift;
                free(pi);
            }
    
        else if(shift > 0)
            {
                j = *pi + shift;
                free(pi);
            }
        else
            {
                j = *pi;
            }
    
        free(pi);
        return j;
    }

    In this example, the pointer pi is freed twice on some execution paths. The Invalid use of standard library routine check detects this issue and reports a possible run-time error (orange check).

  • Freeing of memory that was not allocated dynamically:

    #include <stdlib.h>
    
    int performOperationsWithAllocatedMemory(unsigned int size) {
        char base = 0;
        char *ptr = &base;
        if(size > 0) {
            ptr = (char*)malloc(sizeof(char)*size);
        }
        //Some operations
        free(ptr);    
        return 0;
    }

    In this example, if the argument size to the function performOperationsWithAllocatedMemory is zero, the pointer ptr is not allocated memory dynamically. However, the free() function is used on this pointer in all cases including when the argument size is zero. The Invalid use of standard library routine check detects this issue and reports a possible run-time error (orange check).

Note that the Invalid use of standard library routine check reports a possible run-time error (orange check) if the pointer is an external pointer and its dynamic memory allocation status is not known. For instance, if a function with a pointer argument is not called anywhere in the source files and you use free() on this pointer inside the function body (without dynamically allocating memory first), an orange check is displayed on free().

Polyspace Code Prover™ supports analyzing dynamic memory allocation and deallocation using these operator pairs in C++:

  • new - delete

  • new[] - delete[]

  • new(std::size_t, std::align_val_t) - delete(void*, std::align_val_t) C++17

The Invalid use of standard library routine check on these operator pairs to check:

  • Whether the pointer argument is null.

  • Whether the pointer argument can be deallocated. That is, the pointer was previously allocated dynamically by an authorized allocation function and not already deallocated.

This check detects issues associated with freeing. For example, In this code, the pointer p is deleted twice on some execution paths. The Invalid use of standard library routine check detects this issue and reports a possible run-time error (orange check).

void double_delete(bool condition) {
	if(condition) {
		int *p = new int;
		*p = 2;
		delete(p);//GREEN
		delete(p); //RED
	}
}

Consider this code:

#include <array>
#include <iostream>

void empty_array_examples() {
    
    std::array<int, 0> empty_arr;
    // The following lines are undefined behavior and may crash
    // Uncomment to test, but expect a crash or exception
     int a = empty_arr.front(); // Invalid use of standard library routine
     
}


void out_of_bounds_array_examples(){
   
    std::array<int, 2> arr = {10, 20};
    try {
        int c = arr.at(5); // Invalid use of standard library routine
        std::cout << c << std::endl;
    } catch (const std::out_of_range& e) {
        std::cout << "Exception: " << e.what() << std::endl;
    }

    
    int d = arr[5]; // Invalid use of standard library routine
    std::cout << d << std::endl;
}

  • The operation empty_arr.front() attempts to access the first element of an empty array, which is invalid use of the std::array::front method.

  • The operations arr.at(5) and arr[5] attempts to access an out of bound element of the std::array object arr.

Polyspace reports red Invalid use of standard library routine runtime checks for these invalid use of the std::array methods.

Check Information

Group: Other
Language: C | C++
Acronym: STD_LIB

Version History

expand all