Illegally dereferenced pointer
Pointer is dereferenced outside bounds
Description
This check on a pointer dereference determines whether the pointer is NULL, points outside its bounds or points to dynamically allocated memory that was later deallocated. The check occurs only when you dereference a pointer and not when you assign an address to the pointer, reassign to another pointer or pass the pointer to a function.
The check message shows you the points-to size of the pointer, the pointer offset and the allocated buffer size in bytes. A pointer points outside its bounds when the sum of the points-to size and the offset exceeds the buffer size.
Points-to size: This is the number of bytes accessed when you dereference the pointer. For instance, if you dereference an
int*
pointer, you access 4 bytes on most common targets.Buffer size: When you assign an address to a pointer, a block of memory is allocated to the pointer. You cannot access memory beyond that block using the pointer. The size of this block is the buffer size. For instance, if you assign the address of a
char
variable to a pointer, the allocated buffer size is 1 byte on most common targets.Sometimes, instead of a definite value, the size can be a range. For instance, if you create a buffer dynamically using
malloc
with an unknown input for the size, Polyspace® assumes that the array size can take the full range of values allowed by the input data type.Offset: You can move a pointer within the allocated memory block by using pointer arithmetic. The difference between the initial location of the pointer and its current location is the offset.
Sometimes, instead of a definite value, the offset can be a range. For instance, if you access an array in a loop, the offset changes value in each loop iteration and takes a range of values throughout the loop.
For instance, if the pointer points to an array:
The buffer size is the array size.
The offset is the difference between the beginning of the array and the current location of the pointer.
The check uses your specifications for Target processor type (-target)
to determine sizes of data types.
Diagnosing This Check
Examples
Pointer Cast to Larger Data Type
int main() {
short x=0;
int *ptr = (int *) &x;
*ptr = 2;
return 0;
}
In this example, the variable x
has the data type
short
. This data type corresponds to a buffer size of 2 bytes
on most targets.
However, the address of this buffer is cast to an int*
pointer,
ptr
. An int*
pointer points to a buffer of
size 4 bytes on most targets. Dereferencing ptr
involves
accessing those 4 bytes. Since the original allocation was 2 bytes only, the pointer
dereference leads to an access outside the allowed bounds. Therefore, the
Illegally dereferenced pointer check shows a red
error.
Result Details: The check message confirms that the pointer points to 4 bytes at offset 0 in buffer of 2 bytes, so is outside bounds:
Points-to size is 4 bytes because the pointer
ptr
points toint
.Buffer size is 2 bytes because the buffer size is based on the type of the variable pointed to, that is,
x
. The type ofx
isshort
.Offset is 0 because the pointer points to the beginning of the buffer. No pointer arithmetic is involved.
Note that the sizes of data types are target-dependent. The sizes in this example describe most common targets.
Pointer Points Outside Array Bounds
#define Size 1024 int input(void); void main() { int arr[Size]; int *p = arr; for (int index = 0; index < Size ; index++, p++){ *p = input(); } *p = input(); }
In this example:
Before the
for
loop,p
points to the beginning of the arrayarr
.After the
for
loop,p
points outside the array.
The Illegally dereferenced pointer check on
dereference of p
after the for
loop shows a
red error.
Result Details: The check message states that the pointer points to 4 bytes at offset 4096 in buffer of 4096 bytes, so is outside bounds:
Points-to size is 4 bytes because the pointer
p
points toint
.Buffer size is 4096 bytes because the buffer size is the size of the array times the size of an individual array element type (
int
), that is 1024 * 4 bytes.Offset is 4096 bytes because the pointer has moved across the array because of the operation
p++
and now points 1024*4 bytes away from the beginning of the buffer.
Note that the sizes of data types are target-dependent. The sizes in this example describe most common targets.
One possible correction is to remove the illegal dereference
of p
after the for
loop.
#define Size 1024
int input(void);
void main() {
int arr[Size];
int *p = arr;
for (int index = 0; index < Size ; index++, p++) {
*p = input();
}
}
Pointer Points Outside Structure Bounds
typedef struct S { int f1; int f2; int f3; } S; void Initialize(int *ptr) { *ptr = 0; *(ptr+1) = 0; *(ptr+2) = 0; } void main(void) { S myStruct; Initialize(&myStruct.f1); }
In this example, in the body of Initialize
, ptr
is an
int
pointer that points to the first field of the structure.
When you attempt to access the second field through ptr
, the
Illegally dereferenced pointer check shows a red
error.
Result Details: The check message states that the pointer points to 4 bytes at offset 4 in buffer of 4 bytes, so is outside bounds:
Points-to size is 4 bytes because the pointer
ptr
points toint
.Buffer size is 4 bytes because the buffer size is based on the type of the variable pointed to, that is,
myStruct.f1
. The type ofmyStruct.f1
isint
.Offset is 4 bytes because the operation
(ptr + 1)
moves the pointer oneint
size away from the beginning of the buffer.
Note that the sizes of data types are target-dependent. The sizes in this example describe most common targets.
One possible correction is to pass a pointer to the entire structure
to Initialize
.
typedef struct S { int f1; int f2; int f3; } S; void Initialize(S* ptr) { ptr->f1 = 0; ptr->f2 = 0; ptr->f3 = 0; } void main(void) { S myStruct; Initialize(&myStruct); }
NULL Pointer or Zero Absolute Address Is Dereferenced
#include<stdlib.h>
void main() {
int *ptr=NULL;
*ptr=0;
}
In this example, ptr
is assigned the value NULL
.
Therefore when you dereference ptr
, the Illegally
dereferenced pointer check shows a red error.
You see a similar error if the pointer is initialized with an absolute address such
as
0x0000
:
#define RAM_START 0x0000
void main() {
int *ptr;
ptr = RAM_START;
*ptr = 0;
}
Result Details: The check message states that the pointer is null. Because the pointer is null, the check does not proceed to verify if the pointer points within an allocated buffer.
One possible correction is to initialize ptr
with
the address of a variable instead of NULL
.
void main() {
int var;
int *ptr=&var;
*ptr=0;
}
Work around the error by replacing 0x0000
with another
address just for the purposes of the analysis. For
instance:
#ifdef POLYSPACE
#define RAM_START 0x0001
#else
#define RAM_START 0x0000
#endif
void main() {
int *ptr;
ptr = (int*)RAM_START;//Cast int to int*
*ptr = 0;
}
-D POLYSPACE
so that the address
0x0000
is replaced with an alternative address (in this
case, 0x0001
) for the Polyspace analysis. See also
Preprocessor definitions
(-D)
. Use this solution only when you know
RAM_START
is a valid address.Offset on NULL Pointer
int getOffset(void);
void main() {
int *ptr = (int*) 0 + getOffset();
if(ptr != (int*)0)
*ptr = 0;
}
In this example, although an offset is added to (int*) 0
, Polyspace does not treat the result as a valid address. Therefore when you
dereference ptr
, the Illegally dereferenced
pointer check shows a red error.
Result Details: The check message states that even though the pointer itself is not null, it might not be allocated any memory.
No Illegally Dereferenced Pointer Check without Pointer Dereference
int arr[10];
int main(int arg, char* argv[]) {
int *ptr = &arr[10];
int val_ptr = *ptr;
return 0;
}
In this example, the pointer ptr
is assigned an address past the memory allocated for the array arr
. However, this assignment does not trigger the Illegally dereferenced pointer check. The check occurs only when the pointer is dereferenced and shows a definite error (red).
Incorrect Bit Field Type
struct flagCollection {
unsigned int flag1: 1;
unsigned int flag2: 1;
unsigned int flag3: 1;
unsigned int flag4: 1;
unsigned int flag5: 1;
unsigned int flag6: 1;
unsigned int flag7: 1;
};
char getFlag(void);
int main()
{
unsigned char myFlag = getFlag();
struct flagCollection* myFlagCollection;
myFlagCollection = (struct flagCollection *) &myFlag;
if (myFlagCollection->flag1 == 1)
return 1;
return 0;
}
In this example:
The fields of
flagCollection
have typeunsigned int
. Therefore, aflagCollection
structure requires 32 bits of memory in a 32-bit architecture even though the fields themselves occupy 7 bits.When you cast a
char
address&myFlag
to aflagCollection
pointermyFlagCollection
, you assign only 8 bits of memory to the pointer. Therefore, the Illegally dereferenced pointer check on dereference ofmyFlagCollection
shows a red error.
Result Details: The check message states that the pointer points to 4 bytes at offset 0 in buffer of 1 bytes, so is outside bounds.:
Points-to size is 4 bytes because the pointer points to a structure with effectively one
unsigned int
field. All the bit fields can be accommodated within oneunsigned int
.Buffer size is 1 byte because the buffer size is based on the type of the variable pointed to, that is,
myFlag
. The variable data type ischar
.Offset is 0 because the pointer points to the beginning of the buffer. No pointer arithmetic is involved.
Note that the sizes of data types are target-dependent. The sizes in this example describe most common targets.
One possible correction is to use unsigned char
as
field type of flagCollection
instead of unsigned
int
. In this case:
The structure
flagCollection
requires 8 bits of memory.When you cast the
char
address&myFlag
to theflagCollection
pointermyFlagCollection
, you also assign 8 bits of memory to the pointer. Therefore, the Illegally dereferenced pointer check on dereference ofmyFlagCollection
is green.
struct flagCollection {
unsigned char flag1: 1;
unsigned char flag2: 1;
unsigned char flag3: 1;
unsigned char flag4: 1;
unsigned char flag5: 1;
unsigned char flag6: 1;
unsigned char flag7: 1;
};
char getFlag(void);
int main()
{
unsigned char myFlag = getFlag();
struct flagCollection* myFlagCollection;
myFlagCollection = (struct flagCollection *) &myFlag;
if (myFlagCollection->flag1 == 1)
return 1;
return 0;
}
Return Value of malloc
Is Not Checked for NULL
#include <stdlib.h>
void main(void)
{
char *p = (char*)malloc(1);
char *q = p;
*q = 'a';
}
In this example, malloc
can return NULL
to
p
. Therefore, when you assign p
to
q
and dereference q
, the
Illegally dereferenced pointer check shows an orange
error.
Result Details: The check message states that the pointer may be null.
malloc
for NULL
One possible correction is to check p
for NULL
before
dereferencing q
.
#include <stdlib.h>
void main(void)
{
char *p = (char*)malloc(1);
char *q = p;
if(p!=NULL) *q = 'a';
}
Pointer to Union Gets Insufficient Memory from malloc
#include <stdlib.h>
typedef struct {
int state;
union {
char myChar;
int myInt;
} myVar;
} myType;
void main() {
myType* myTypePtr;
myTypePtr = (myType*)malloc(sizeof(int) + sizeof(char));
if(myTypePtr != NULL) {
myTypePtr->state = 0;
}
}
In this example:
Because the union
myVar
has anint
variable as a field, it must be assigned 4 bytes in a 32-bit architecture. Therefore, the structuremyType
must be assigned 4+4 = 8 bytes.malloc
returnssizeof(int) + sizeof(char)
=4+1=5 bytes of memory tomyTypePtr
, a pointer to amyType
structure. Therefore, when you dereferencemyTypePtr
, the Illegally dereferenced pointer check returns a red error.
Result Details: The check message states that the pointer points to 8 bytes at offset 0 in buffer of 5 bytes, so is outside bounds:
Points-to size is 8 bytes because the pointer
myTypePtr
points to the typemyType
. The structuremyType
has two fields:An
int
field (4 bytes).An
union
field, where the largest type in the union isint
(4 bytes).
Buffer size is 5 bytes because the heap-allocated memory has size equal to
sizeof(int) + sizeof(char)
or 4+1 bytes.Offset is 0 because the pointer points to the beginning of the buffer. No pointer arithmetic is involved.
Note that the sizes of data types are target-dependent. The sizes in this example describe most common targets.
One possible correction is to assign 8 bytes of memory to myTypePtr
before
dereference.
#include <stdlib.h>
typedef struct {
int state;
union {
char myChar;
int myInt;
} myVar;
} myType;
void main() {
myType* myTypePtr;
myTypePtr = (myType*)malloc(sizeof(int) * 2);
if(myTypePtr != NULL) {
myTypePtr->state = 0;
}
}
Partial Memory Allocation to Structure
#include <stdlib.h>
typedef struct {
int length;
int breadth;
} rectangle;
typedef struct {
int length;
int breadth;
int height;
} cuboid;
void main() {
cuboid *cuboidPtr = (cuboid*)malloc(sizeof(rectangle));
if(cuboidPtr!=NULL) {
cuboidPtr->length = 10;
cuboidPtr->breadth = 10;
}
}
In this example, cuboidPtr
obtains
sufficient memory to accommodate two of its
fields. Because the ANSI® C standards do not allow such partial memory allocations, the
Illegally dereferenced pointer check on the dereference of
cuboidPtr
shows a red error.
Result Details: The check message states that the pointer points to 12 bytes at offset 0 in buffer of 8 bytes, so is outside bounds:
Points-to size is 12 bytes because the pointer
ptr
points to the typecuboid
. The typecuboid
has threeint
members, so its size is 3 * 4 bytes.Buffer size is 8 bytes because the heap-allocated memory has size equal to
sizeof(rectangle)
. The typerectange
has twoint
members, so its size is 2 * 4 bytes.Offset is 0 because the pointer points to the beginning of the buffer. No pointer arithmetic is involved.
Note that the sizes of data types are target-dependent. The sizes in this example describe most common targets.
To observe ANSI C
standards, cuboidPtr
must be allocated full memory.
#include <stdlib.h> typedef struct { int length; int breadth; } rectangle; typedef struct { int length; int breadth; int height; } cuboid; void main() { cuboid *cuboidPtr = (cuboid*)malloc(sizeof(cuboid)); if(cuboidPtr!=NULL) { cuboidPtr->length = 10; cuboidPtr->breadth = 10; } }
You can allow partial memory allocation for structures, yet not have a red Illegally dereferenced pointer error. To allow partial memory allocation, on the Configuration pane, under Check Behavior, select Allow incomplete or partial allocation of structures.
#include <stdlib.h> typedef struct { int length; int breadth; } rectangle; typedef struct { int length; int breadth; int height; } cuboid; void main() { cuboid *cuboidPtr = (cuboid*)malloc(sizeof(rectangle)); if(cuboidPtr!=NULL) { cuboidPtr->length = 10; cuboidPtr->breadth = 10; } }
Pointer to One Field of Structure Points to Another Field
#include <stdlib.h> typedef struct { int length; int breadth; } square; void main() { square mySquare; char* squarePtr = (char*)&mySquare.length; //Assign zero to mySquare.length byte by byte for(int byteIndex=1; byteIndex<=4; byteIndex++) { *squarePtr=0; squarePtr++; } //Assign zero to first byte of mySquare.breadth *squarePtr=0; }
In this example, although squarePtr
is a char
pointer,
it is assigned the address of the integer mySquare.length
. Because:
char
occupies 1 byte,int
occupies 4 bytes in a 32–bit architecture,
squarePtr
can access the four bytes of
mySquare.length
through pointer arithmetic. But when it
accesses the first byte of another field mySquare.breadth
, the
Illegally dereferenced pointer check shows a red
error.
Result Details: The check message confirms that the pointer points to 1 bytes at offset 4 in buffer of 4 bytes, so is outside bounds:
Points-to size is1 byte because the pointer
squarePtr
points tochar
.Buffer size is 4 bytes because the buffer size is based on the type of the variable pointed to, that is,
mySquare.length
. The type ofmySquare.length
isint
.Offset is 4 bytes because the pointer has been moved one
int
size away from the beginning of the buffer using the operationsquarePtr++
.
Note that the sizes of data types are target-dependent. The sizes in this example describe most common targets.
One possible correction is to assign squarePtr
the
address of the full structure mySquare
instead
of mySquare.length
. squarePtr
can
then access all the bytes of mySquare
through
pointer arithmetic.
#include <stdlib.h> typedef struct { int length; int breadth; } square; void main() { square mySquare; char* squarePtr = (char*)&mySquare; //Assign zero to mySquare.length byte by byte for(int byteIndex=1; byteIndex<=4; byteIndex++) { *squarePtr=0; squarePtr++; } //Assign zero to first byte of mySquare.breadth *squarePtr=0; }
You can use a pointer to navigate across the fields of a structure and not produce a red Illegally dereferenced pointer error. To allow such navigation, on the Configuration pane, under Check Behavior, select Enable pointer arithmetic across fields.
This option is not available for C++ projects. In C++, pointer arithmetic becomes nontrivial when dealing with concepts such as polymorphic types.
#include <stdlib.h> typedef struct { int length; int breadth; } square; void main() { square mySquare; char* squarePtr = (char*)&mySquare.length; //Assign zero to mySquare.length byte by byte for(int byteIndex=1; byteIndex<=4; byteIndex++) { *squarePtr=0; squarePtr++; } //Assign zero to first byte of mySquare.breadth *squarePtr=0; }
Function Returns Pointer to Local Variable
void func2(int *ptr) {
*ptr = 0;
}
int* func1(void) {
int ret = 0;
return &ret ;
}
void main(void) {
int* ptr = func1() ;
func2(ptr) ;
}
In the following code, ptr
points to ret
. Because the
scope of ret
is limited to func1
, when
ptr
is accessed in func2
, the access is
illegal. The verification shows a red Illegally dereferenced
pointer check on *ptr
.
By default, Polyspace
Code Prover™ does not detect functions returning pointers to local variables. To
detect such cases, use the option Detect stack pointer dereference outside scope (-detect-pointer-escape)
.
Result Details: The check message states that the pointer points to a local variable that is accessed outside its scope.
Use of freed memory (C only)
#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) {
free(pi);
}
j = *pi + shift;
return j;
}
In this example, if the argument shift
is negative, the pointer pi
is dereferenced after the allocated memory is freed using the free()
function. The Illegally dereferenced pointer check can detect this issue and report a possible run-time error (orange check).
Dereferencing of pointer alias that is conditionally reallocated
In this example, an alias of the pointer ptr1
is conditionally
reallocated. If randomVar
is true, the alias
ptr2
points to a new location. Otherwise, both
ptr1
and ptr2
points to the same location.
The dereferencing of ptr2
after the free
statement attempts to dereference an already freed pointer when
randomVar
is false. Polyspace reports an orange check of this run-time error.
int main() { volatile int randomVar; int *ptr1 = (int *)malloc(sizeof(int)); void *ptr2 = (void *)ptr1; if(randomVar) { ptr2 = malloc(sizeof(int)); assert(ptr2 != 0); } free(ptr1); *(int *)ptr2 = randomVar; // Potential IDP }
Check Information
Group: Static memory |
Language: C | C++ |
Acronym: IDP |
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.
Select a Web Site
Choose a web site to get translated content where available and see local events and offers. Based on your location, we recommend that you select: .
You can also select a web site from the following list
How to Get Best Site Performance
Select the China site (in Chinese or English) for best site performance. Other MathWorks country sites are not optimized for visits from your location.
Americas
- América Latina (Español)
- Canada (English)
- United States (English)
Europe
- 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)
Asia Pacific
- Australia (English)
- India (English)
- New Zealand (English)
- 中国
- 日本Japanese (日本語)
- 한국Korean (한국어)