ISO/IEC TS 17961 [insufmem]
Allocating insufficient memory
Description
Rule Definition
Allocating insufficient memory.1
Polyspace Implementation
This checker checks for these issues:
Wrong allocated object size for cast.
Pointer access out of bounds.
Wrong type used in sizeof.
Possible misuse of sizeof.
Examples
Wrong allocated object size for cast occurs during pointer conversion when the pointer’s address is misaligned. If a pointer is converted to a different pointer type, the size of the allocated memory must be a multiple of the size of the destination pointer.
Dereferencing a misaligned pointer has undefined behavior and can cause your program to crash.
Suppose you convert a pointer ptr1 to ptr2.
If ptr1 points to a buffer of N bytes and
ptr2 is a pointer where
type
*sizeof( is
type)n bytes, make sure that N is an integer
multiple of n.
See examples of fixes below.
If you do not want to fix the issue, add comments to your result or code to avoid another review. See:
Address Results in Polyspace User Interface Through Bug Fixes or Justifications if you review results in the Polyspace user interface.
Address Results in Polyspace Access Through Bug Fixes or Justifications (Polyspace Access) if you review results in a web browser.
Annotate Code and Hide Known or Acceptable Results if you review results in an IDE.
#include <stdlib.h>
void dyn_non_align(void){
void *ptr = malloc(13);
long *dest;
dest = (long*)ptr; //defect
}In this example, the software raises a defect on the
conversion of ptr to a long*. The dynamically
allocated memory of ptr, 13 bytes, is not a multiple of the size of
dest, 4 bytes. This misalignment causes the Wrong allocated object size for cast defect.
One possible correction is to use a pointer size that is a multiple of the destination size. In this example, resolve the defect by changing the allocated memory to 12 instead of 13.
#include <stdlib.h>
void dyn_non_align(void){
void *ptr = malloc(12);
long *dest;
dest = (long*)ptr;
}void static_non_align(void){
char arr[13], *ptr;
int *dest;
ptr = &arr[0];
dest = (int*)ptr; //defect
}In this example, the software raises a defect on the conversion
of ptr to an int* in line 6. ptr has
a memory size of 13 bytes because the array arr has
a size of 13 bytes. The size of dest is 4 bytes,
which is not a multiple of 13. This misalignment causes the Wrong allocated object size for cast defect.
One possible correction is to use a pointer size that is a multiple
of the destination size. In this example, resolve the defect by changing
the size of the array arr to a multiple of 4.
void static_non_align(void){
char arr[12], *ptr;
int *dest;
ptr = &arr[0];
dest = (int*)ptr;
}#include <stdlib.h>
void *my_alloc(int size) {
void *ptr_func = malloc(size);
if(ptr_func == NULL) exit(-1);
return ptr_func;
}
void fun_non_align(void){
int *dest1;
char *dest2;
dest1 = (int*)my_alloc(13); //defect
dest2 = (char*)my_alloc(13); //not a defect
}In this example, the software raises a defect on the conversion
of the pointer returned by my_alloc(13) to an int* in
line 11. my_alloc(13) returns a pointer with a
dynamically allocated size of 13 bytes. The size of dest1 is
4 bytes, which is not a divisor of 13. This misalignment causes the Wrong allocated object size for cast defect.
In line 12, the same function call, my_alloc(13),
does not call a defect for the conversion to dest2 because
the size of char*, 1 byte, a divisor of 13.
One possible correction is to use a pointer size that is a multiple
of the destination size. In this example, resolve the defect by changing
the argument for my_alloc to a multiple of 4.
#include <stdlib.h>
void *my_alloc(int size) {
void *ptr_func = malloc(size);
if(ptr_func == NULL) exit(-1);
return ptr_func;
}
void fun_non_align(void){
int *dest1;
char *dest2;
dest1 = (int*)my_alloc(12);
dest2 = (char*)my_alloc(13);
}Pointer access out of bounds occurs when a pointer is dereferenced outside its bounds.
When a pointer is assigned an address, a block of memory is associated with the pointer. You cannot access memory beyond that block using the pointer.
Dereferencing a pointer outside its bounds is undefined behavior. You can read an unpredictable value or try to access a location that is not allowed and encounter a segmentation fault.
The fix depends on the root cause of the defect. For instance, you dereferenced a pointer inside a loop and one of these situations happened:
The upper bound of the loop is too large.
You used pointer arithmetic to advance the pointer with an incorrect value for the pointer increment.
To fix the issue, you have to modify the loop bound or the pointer increment value.
Often the result details show a sequence of events that led to the defect. You can implement the fix on any event in the sequence. If the result details do not show the event history, you can trace back using right-click options in the source code and see previous related events. See also Interpret Bug Finder Results in Polyspace Desktop User Interface.
See examples of fixes below.
If you do not want to fix the issue, add comments to your result or code to avoid another review. See:
Address Results in Polyspace User Interface Through Bug Fixes or Justifications if you review results in the Polyspace user interface.
Address Results in Polyspace Access Through Bug Fixes or Justifications (Polyspace Access) if you review results in a web browser.
Annotate Code and Hide Known or Acceptable Results if you review results in an IDE.
int* Initialize(void)
{
int arr[10];
int *ptr=arr;
for (int i=0; i<=9;i++)
{
ptr++;
*ptr=i;
/* Defect: ptr out of bounds for i=9 */
}
return(arr);
}ptr is assigned the address arr that
points to a memory block of size 10*sizeof(int).
In the for-loop, ptr is incremented
10 times. In the last iteration of the loop, ptr points
outside the memory block assigned to it. Therefore, it cannot be dereferenced.
One possible correction is to reverse the order
of increment and dereference of ptr.
int* Initialize(void)
{
int arr[10];
int *ptr=arr;
for (int i=0; i<=9;i++)
{
/* Fix: Dereference pointer before increment */
*ptr=i;
ptr++;
}
return(arr);
}After the last increment, even though ptr points
outside the memory block assigned to it, it is not dereferenced more.
Wrong type used in sizeof occurs when both of the following conditions hold:
You assign the address of a block of memory to a pointer, or transfer data between two blocks of memory. The assignment or copy uses the
sizeofoperator.For instance, you initialize a pointer using
malloc(sizeof(or copy data between two addresses usingtype))memcpy(.destination_ptr,source_ptr, sizeof(type))You use an incorrect type as argument of the
sizeofoperator. You use the pointer type instead of the type that the pointer points to.For instance, to initialize a
pointer, you usetype*malloc(sizeof(instead oftype*))malloc(sizeof(.type))
Irrespective of what type stands
for, the expression sizeof( always
returns a fixed size. The size returned is the pointer size on your
platform in bytes. The appearance of type*)sizeof( often
indicates an unintended usage. The error can cause allocation of a
memory block that is much smaller than what you need and lead to weaknesses
such as buffer overflows.type*)
For instance, assume that structType is a
structure with ten int variables. If you initialize
a structType* pointer using malloc(sizeof(structType*)) on
a 32-bit platform, the pointer is assigned a memory block of four
bytes. However, to be allocated completely for one structType variable,
the structType* pointer must point to a memory
block of sizeof(structType) = 10 * sizeof(int) bytes.
The required size is much greater than the actual allocated size of
four bytes.
To initialize a pointer,
replace type*sizeof( in
your pointer initialization expression with type*)sizeof(.type)
sizeof#include <stdlib.h>
void test_case_1(void) {
char* str;
str = (char*)malloc(sizeof(char*) * 5);
free(str);
}In this example, memory is allocated for the character pointer str using
a malloc of five char pointers. However, str is
a pointer to a character, not a pointer to a character pointer. Therefore
the sizeof argument, char*,
is incorrect.
sizeof ArgumentOne possible correction is to match the argument
to the pointer type. In this example, str is a
character pointer, therefore the argument must also be a character.
#include <stdlib.h>
void test_case_1(void) {
char* str;
str = (char*)malloc(sizeof(char) * 5);
free(str);
}Possible misuse of sizeof occurs
when Polyspace®
Bug Finder™ detects possibly unintended results from
the use of sizeof operator. For instance:
You use the
sizeofoperator on an array parameter name, expecting the array size. However, the array parameter name by itself is a pointer. Thesizeofoperator returns the size of that pointer.You use the
sizeofoperator on an array element, expecting the array size. However, the operator returns the size of the array element.The size argument of certain functions such as
strncmporwcsncpyis incorrect because you used thesizeofoperator earlier with possibly incorrect expectations. For instance:In a function call
strncmp(string1, string2, num),numis obtained from an incorrect use of thesizeofoperator on a pointer.In a function call
wcsncpy(destination, source, num),numis the not the number of wide characters but a size in bytes obtained by using thesizeofoperator. For instance, you usewcsncpy(destination, source, sizeof(destination) - 1)instead ofwcsncpy(destination, source, (sizeof(desintation)/sizeof(wchar_t)) - 1).
Incorrect use of the sizeof operator can
cause the following issues:
If you expect the
sizeofoperator to return array size and use the return value to constrain a loop, the number of loop runs are smaller than what you expect.If you use the return value of
sizeofoperator to allocate a buffer, the buffer size is smaller than what you require. Insufficient buffer can lead to resultant weaknesses such as buffer overflows.If you use the return value of
sizeofoperator incorrectly in a function call, the function does not behave as you expect.
Possible fixes are:
Do not use the
sizeofoperator on an array parameter name or array element to determine array size.The best practice is to pass the array size as a separate function parameter and use that parameter in the function body.
Use the
sizeofoperator carefully to determine the number argument of functions such asstrncmporwcsncpy. For instance, for wide string functions such aswcsncpy, use the number of wide characters as argument instead of the number of bytes.
sizeof Used Incorrectly to Determine Array
Size#define MAX_SIZE 1024
void func(int a[MAX_SIZE]) {
int i;
for (i = 0; i < sizeof(a)/sizeof(int); i++) {
a[i] = i + 1;
}
}In this example, sizeof(a) returns the size
of the pointer a and not the array size.
One possible correction is to use another means to determine the array size.
#define MAX_SIZE 1024
void func(int a[MAX_SIZE]) {
int i;
for (i = 0; i < MAX_SIZE; i++) {
a[i] = i + 1;
}
}Check Information
| Decidability: Undecidable |
Version History
Introduced in R2019a
1 Extracts from the standard "ISO/IEC TS 17961 Technical Specification - 2013-11-15" are reproduced with the agreement of AFNOR. Only the original and complete text of the standard, as published by AFNOR Editions - accessible via the website www.boutique.afnor.org - has normative value.
MATLAB Command
You clicked a link that corresponds to this MATLAB command:
Run the command by entering it in the MATLAB Command Window. Web browsers do not support MATLAB commands.
Seleccione un país/idioma
Seleccione un país/idioma para obtener contenido traducido, si está disponible, y ver eventos y ofertas de productos y servicios locales. Según su ubicación geográfica, recomendamos que seleccione: .
También puede seleccionar uno de estos países/idiomas:
Cómo obtener el mejor rendimiento
Seleccione China (en idioma chino o inglés) para obtener el mejor rendimiento. Los sitios web de otros países no están optimizados para ser accedidos desde su ubicación geográfica.
América
- América Latina (Español)
- Canada (English)
- United States (English)
Europa
- Belgium (English)
- Denmark (English)
- Deutschland (Deutsch)
- España (Español)
- Finland (English)
- France (Français)
- Ireland (English)
- Italia (Italiano)
- Luxembourg (English)
- Netherlands (English)
- Norway (English)
- Österreich (Deutsch)
- Portugal (English)
- Sweden (English)
- Switzerland
- United Kingdom (English)