Illegally dereferenced pointer

Указатель разыменовывается вне границ

Описание

Это начинает работу, указатель разыменовывают, определяет, является ли указатель NULL или указывает вне его границ. Проверка происходит только, когда вы разыменовываете указатель и не, когда вы повторно присваиваете другому указателю или передаете указатель на функцию.

Сообщение проверки показывает вам смещение указателя и buffer size в байтах. Указатель указывает вне его границ, когда сумма смещения и размера указателя превышает buffer size.

  • Буфер: Когда вы присваиваете адрес указателю, блок памяти выделяется указателю. Вы не можете получить доступ к памяти, кроме того блокируют использование указателя. Размер этого блока является buffer size.

    Иногда, вместо определенного значения, размер может быть областью значений. Например, если вы создаете буфер динамически с помощью malloc с неизвестным входом для размера Polyspace® принимает, что размер массивов может взять полный спектр значений, позволенных типом входных данных.

  • Смещение: можно переместить указатель в позволенном блоке памяти при помощи адресной арифметики с указателями. Различием между начальным местоположением указателя и его текущим местоположением является смещение.

    Иногда, вместо определенного значения, смещение может быть областью значений. Например, если вы получаете доступ к массиву в цикле, значению изменений смещения в каждой итерации цикла, и берет область значений значений в цикле.

Например, если указатель указывает на массив:

  • Buffer size является размером массивов.

  • Смещение является различием между началом массива и текущим местоположением указателя.

Примеры

развернуть все

#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();
}

В этом примере:

  • Перед for цикл, p точки к началу массива arr.

  • После for цикл, p точки вне массива.

Illegally dereferenced pointer начинает работу, разыменовывают p после for цикл производит красную ошибку.

Коррекция — Удаляет недопустимый, разыменовывают

Одна возможная коррекция должна удалить нелегала, разыменовывают p после for цикл.

#define Size 1024

int input(void);

void main() {
    int arr[Size];
    int *p = arr;
 	
    for (int index = 0; index < Size ; index++, p++) {
        *p = input();
    }
}    
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);
}

В этом примере, в теле Initialize, ptr int указатель, который указывает на первое поле структуры. Когда вы пытаетесь получить доступ к второму полю через ptr, проверка Illegally dereferenced pointer производит красную ошибку.

Коррекция — Избегает доступа к памяти вне поля структуры

Одна возможная коррекция должна передать указатель на целую структуру к 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);
}
#include<stdlib.h>

void main() {
    int *ptr=NULL;
    *ptr=0;
}

В этом примере, ptr присвоен значение NULL. Поэтому, когда вы разыменовываете ptr, проверка Illegally dereferenced pointer производит красную ошибку.

Коррекция — Избегает, чтобы Нулевой указатель разыменовал

Одна возможная коррекция должна инициализировать ptr с адресом переменной вместо NULL.

void main() {
    int var;
    int *ptr=&var;
    *ptr=0;
}
int getOffset(void);

void main() {
    int *ptr = (int*) 0 + getOffset();
    if(ptr != (int*)0)
        *ptr = 0;
}

В этом примере, несмотря на то, что смещение добавляется к (int*) 0, Polyspace не обрабатывает результат как допустимый адрес. Поэтому, когда вы разыменовываете ptr, проверка Illegally dereferenced pointer производит красную ошибку.

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;
}

В этом примере:

  • Поля flagCollection имейте вводят unsigned int. Поэтому flagCollection структура требует 32 битов памяти в 32-битной архитектуре даже при том, что сами поля занимают 7 битов.

  • Когда вы бросаете char обратитесь к &myFlag к flagCollection указатель myFlagCollection, вы присваиваете только 8 битов памяти указателю. Поэтому Illegally dereferenced pointer начинает работу, разыменовывают myFlagCollection производит красную ошибку.

Коррекция — Использование корректирует тип для битовых полей

Одна возможная коррекция должна использовать unsigned char как тип поля flagCollection вместо unsigned int. В этом случае:

  • Структура flagCollection требует 8 битов памяти.

  • Когда вы бросаете char обратитесь к &myFlag к flagCollection указатель myFlagCollection, вы также присваиваете 8 битов памяти указателю. Поэтому Illegally dereferenced pointer начинает работу, разыменовывают myFlagCollection является зеленым.

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;
}
#include <stdlib.h>

void main(void)
{
    char *p = (char*)malloc(1);
    char *q = p;
    *q = 'a';
}

В этом примере, malloc может возвратить NULL к p. Поэтому, когда вы присваиваете p к q и разыменуйте q, проверка Illegally dereferenced pointer производит красную ошибку.

Коррекция — возвращаемое значение Проверки malloc для NULL

Одна возможная коррекция должна проверять p для NULL прежде, чем разыменовать q.

#include <stdlib.h>
void main(void)
{
    char *p = (char*)malloc(1);
    char *q = p;
    if(p!=NULL) *q = 'a';
}
#include <stdlib.h>

enum typeName {CHAR,INT};

typedef struct {
    enum typeName myTypeName;
    union {
        char myChar;
        int myInt;
    } myVar;
} myType;

void main() {
    myType* myTypePtr;
    myTypePtr = (myType*)malloc(sizeof(int) + sizeof(char));
    if(myTypePtr != NULL) {
        myTypePtr->myTypeName = INT;
    }
}

В этом примере:

  • Поскольку объединение myVar имеет int переменная как поле, это должно быть присвоено 4 байта в 32-битной архитектуре. Поэтому структура myType должен быть присвоен 4+4 = 8 байтов.

  • malloc возвращает sizeof(int) + sizeof(char)Байты =4+1=5 памяти myTypePtr, указатель на myType структура. Поэтому, когда вы разыменовываете myTypePtr, проверка Illegally dereferenced pointer возвращает красную ошибку.

Коррекция — достаточная память Присвоения к указателю

Одна возможная коррекция должна присвоить 8 байтов памяти myTypePtr прежде разыменовывают.

#include <stdlib.h>

enum typeName {CHAR,INT};

typedef struct {
    enum typeName myTypeName;
    union {
        char myChar;
        int myInt;
    } myVar;
} myType;

void main() {
    myType* myTypePtr;
    myTypePtr = (myType*)malloc(sizeof(int) + sizeof(int));
    if(myTypePtr != NULL) {
        myTypePtr->myTypeName = INT;
    }
}
#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;
    }
}

В этом примере, cuboidPtr получает достаточную память, чтобы вместить два из ее полей. Поскольку стандарты ANSI® C не позволяют такие частичные выделения памяти, Illegally dereferenced pointer проверяют разыменовывание cuboidPtr производит красную ошибку.

Коррекция — Выделяет полную память

Наблюдать ANSI C стандарты, cuboidPtr должен быть выделен полная память.

#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;
    }
}
Коррекция — опция анализа Polyspace Использования

Можно позволить частичное выделение памяти для структур, все же не иметь красную ошибку Illegally dereferenced pointer. Чтобы позволить частичное выделение памяти, на панели Configuration, под Check Behavior, выбирают 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;
    }
}
#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;
}

В этом примере, несмотря на то, что squarePtr char указатель, это присвоено адрес целочисленного mySquare.length. Поскольку:

  • char занимает 1 байт,

  • int занимает 4 байта в 32-битной архитектуре,

squarePtr может получить доступ к четырем байтам mySquare.length через адресную арифметику с указателями. Но когда это получает доступ к первому байту другого поля mySquare.breadth, проверка Illegally dereferenced pointer производит красную ошибку.

Коррекция — адрес Присвоения структуры вместо поля

Одна возможная коррекция должна присвоить squarePtr адрес полной структуры mySquare вместо mySquare.length. squarePtr может затем получить доступ ко всем байтам mySquare через адресную арифметику с указателями.

#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;
}
Коррекция — опция анализа Polyspace Использования (не доступный на C++)

Можно использовать указатель, чтобы перейти через поля структуры и не произвести красную ошибку Illegally dereferenced pointer. Чтобы позволить такую навигацию, на панели Configuration, под Check Behavior, выбирают Enable pointer arithmetic across fields.

Эта опция не доступна для проектов C++. На C++ адресная арифметика с указателями становится нетривиальной при контакте с концепциями, такими как полиморфные типы.


#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;
}
void func2(int *ptr) {
    *ptr = 0; 
}

int* func1(void) {
    int ret = 0;
    return &ret ;
}
void main(void) {
    int* ptr = func1() ;
    func2(ptr) ;
}

В следующем коде, ptr точки к ret. Поскольку осциллограф ret ограничивается func1, когда ptr получен доступ в func2, доступ недопустим. Верификация производит красный Illegally dereferenced pointer, проверяют *ptr.

По умолчанию Polyspace Code Prover™ не обнаруживает функции, возвращающие указатели на локальные переменные. Чтобы обнаружить такие случаи, используйте опцию Detect stack pointer dereference outside scope (-detect-pointer-escape).

Проверяйте информацию

Группа: Статическая память
Язык: C | C++
Акроним: IDP