Разыменование указателя вне основной области
Проблема происходит, когда указатель, следующий из арифметики на операнде указателя, не обращается к элементу того же массива как тот операнд указателя.
Polyspace® отмечает это правило во время анализа как:
Средство поиска ошибки — Array access out-of-bounds
и Pointer access out-of-bounds
Программа автоматического доказательства кода — и
Средство поиска ошибки и Программа автоматического доказательства Кода проверяют это правило по-другому и могут показать различные результаты для этого правила. В Программе автоматического доказательства Кода можно также видеть различие в результатах на основе выбора для опции Verification level (-to)
. Смотрите проверку на кодирование стандартных нарушений.
Используя неверный массив индекс может привести к ошибочному поведению программы. Выведенные индексы времени выполнения массивов особенно неприятны, потому что они не могут легко проверяться ручным анализом или статическим анализом.
Стандарт C задает создание указателя на один вне конца массива. Правило разрешает Стандарт C. Разыменование указателя на один вне конца массива вызывает неопределенное поведение и несовместимо.
Недопустимое использование стандартной стандартной программы библиотеки memory происходит, когда библиотечная функция памяти вызвана недействительными аргументами. Например, memcpy
функционируйте копирует в массив, который не может разместить количество скопированных байтов.
Использование библиотечной функции памяти с недействительными аргументами может привести к проблемам, таким как переполнение буфера.
Фиксация зависит от первопричины дефекта. Часто детали результата показывают последовательность событий, которые привели к дефекту. Можно реализовать закрепление на любом событии в последовательности. Если детали результата не показывают историю события, можно проследить использование, щелкните правой кнопкой по опциям по исходному коду и смотрите предыдущие связанные события. См. также Интерпретируют Результаты Polyspace Bug Finder.
Смотрите примеры мер ниже.
Если вы не хотите устранять проблему, добавьте комментарии в свой результат или код, чтобы избежать другого анализа. Смотрите Результаты Polyspace Адреса Через Исправления ошибок или Выравнивания.
#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);
/* Defect: Arguments of memcpy invalid: str2 has size < 6 */
return str2;
}
Размер строки str2
5, но шесть символов строки str1
копируются в str2
использование memcpy
функция.
Одна возможная коррекция должна настроить размер str2
так, чтобы это разместило символы, скопированные с memcpy
функция.
#include <string.h> #include <stdio.h> char* Copy_First_Six_Letters(void) { /* Fix: Declare str2 with size 6 */ char str1[10],str2[6]; printf("Enter string:\n"); scanf("%s",str1); memcpy(str2,str1,6); return str2; }
Нулевой указатель происходит, когда вы используете указатель со значением NULL
как будто это указывает на допустимую ячейку памяти.
Разыменование нулевого указателя является неопределенным поведением. В большинстве реализаций разыменовывание может заставить вашу программу отказывать.
Проверяйте указатель на NULL
прежде разыменовывают.
Если проблема происходит несмотря на более раннюю проверку на NULL
, ищите промежуточные события между проверкой, и последующие разыменовывают. Часто детали результата показывают последовательность событий, которые привели к дефекту. Можно реализовать закрепление на любом событии в последовательности. Если детали результата не показывают историю события, можно проследить использование, щелкните правой кнопкой по опциям по исходному коду и смотрите предыдущие связанные события. См. также Интерпретируют Результаты Polyspace Bug Finder.
Смотрите примеры мер ниже.
#include <stdlib.h>
int FindMax(int *arr, int Size)
{
int* p=NULL;
*p=arr[0];
/* Defect: Null pointer dereference */
for(int i=0;i<Size;i++)
{
if(arr[i] > (*p))
*p=arr[i];
}
return *p;
}
Указатель p
инициализируется со значением NULL
. Однако, когда значение arr[0]
записан в *p
P
принят, чтобы указать на допустимую ячейку памяти.
Одна возможная коррекция должна инициализировать p
с действительным адресом памяти прежде разыменовывают.
#include <stdlib.h> int FindMax(int *arr, int Size) { /* Fix: Assign address to null pointer */ int* p=&arr[0]; for(int i=0;i<Size;i++) { if(arr[i] > (*p)) *p=arr[i]; } return *p; }
Арифметическая операция с Нулевым указателем происходит, когда арифметическая операция включает указатель, значением которого является NULL
.
Выполнение адресной арифметики с указателями на нулевом указателе и разыменование получившегося указателя являются неопределенным поведением. В большинстве реализаций разыменовывание может заставить вашу программу отказывать.
Проверяйте указатель на NULL
перед арифметическими операциями на указателе.
Если проблема происходит несмотря на более раннюю проверку на NULL
, ищите промежуточные события между проверкой, и последующие разыменовывают. Часто детали результата показывают последовательность событий, которые привели к дефекту. Можно реализовать закрепление на любом событии в последовательности. Если детали результата не показывают историю события, можно проследить использование, щелкните правой кнопкой по опциям по исходному коду и смотрите предыдущие связанные события. См. также Интерпретируют Результаты Polyspace Bug Finder.
Смотрите примеры мер ниже.
#include<stdlib.h>
int Check_Next_Value(int *loc, int val)
{
int *ptr = loc, found = 0;
if (ptr==NULL)
{
ptr++;
/* Defect: NULL pointer shifted */
if (*ptr==val) found=1;
}
return(found);
}
Когда ptr
NULL
указатель, код вводит if
тело оператора. Поэтому NULL
указатель смещен в операторе ptr++
.
Одна возможная коррекция должна выполнить арифметическую операцию когда ptr
не NULL
.
#include<stdlib.h> int Check_Next_Value(int *loc, int val) { int *ptr = loc, found = 0; /* Fix: Perform operation when ptr is not NULL */ if (ptr!=NULL) { ptr++; if (*ptr==val) found=1; } return(found); }
Недопустимое использование стандартной стандартной программы строки библиотеки происходит, когда библиотечная функция строки вызвана недействительными аргументами.
Риск зависит от типа недействительных аргументов. Например, использование strcpy
функция с исходным аргументом, больше, чем целевой аргумент, может привести к переполнению буфера.
Фиксация зависит от стандартной библиотечной функции, вовлеченной в дефект. В некоторых случаях можно ограничить аргументы функции перед вызовом функции. Например, если strcpy
функция:
char * strcpy(char * destination, const char* source)
strcpy
. В некоторых случаях можно использовать альтернативную функцию, чтобы избежать ошибки. Например, вместо strcpy
, можно использовать strncpy
управлять количеством скопированных байтов.Смотрите примеры мер ниже.
Если вы не хотите устранять проблему, добавьте комментарии в свой результат или код, чтобы избежать другого анализа. Смотрите Результаты Polyspace Адреса Через Исправления ошибок или Выравнивания.
#include <string.h>
#include <stdio.h>
char* Copy_String(void)
{
char *res;
char gbuffer[5],text[20]="ABCDEFGHIJKL";
res=strcpy(gbuffer,text);
/* Error: Size of text is less than gbuffer */
return(res);
}
Строка text
больше в размере, чем gbuffer
. Поэтому функциональный strcpy
не может скопировать text
в gbuffer
.
Одна возможная коррекция должна объявить целевую строку gbuffer
с равным или большим размером, чем исходная строка text
.
#include <string.h> #include <stdio.h> char* Copy_String(void) { char *res; /*Fix: gbuffer has equal or larger size than text */ char gbuffer[20],text[20]="ABCDEFGHIJKL"; res=strcpy(gbuffer,text); return(res); }
Использование испорченного дефекта указателя повышено когда:
Испорченный Нулевой указатель — указатель не подтвержден против NULL.
Испорченный указатель размера — размер зоны памяти, на которую указывает указатель, не подтвержден.
На одном указателе ваш код может иметь экземпляры Использования испорченного указателя, Указатель разыменовывают с испорченным смещением, и Испорченным NULL или не пустой отключенной строкой. Средство поиска ошибки повышает только первый испорченный дефект указателя, который оно находит.
Атакующий может дать вашей программе подсказку, которая указывает на неожиданные ячейки памяти. Если указатель разыменовывается, чтобы записать, атакующий может:
Измените переменные состояния критической программы.
Заставьте свою программу отказывать.
Выполните нежелательный код.
Если указатель разыменовывается, чтобы читать, атакующий может:
Считайте уязвимые данные.
Заставьте свою программу отказывать.
Измените переменную программы к неожиданному значению.
Избегайте использования указателей из внешних источников.
В качестве альтернативы, если вы доверяете внешнему источнику, санируете указатель, прежде чем разыменуют. В отдельной функции санитизации:
Проверяйте, что указатель не является ПУСТЫМ.
Проверяйте размер ячейки памяти (если возможный). Эта вторая проверка подтверждает, ожидает ли размер данных, указатель указывает на соответствия размеру вашу программу.
Дефект все еще появляется в теле функции санитизации. Однако, если вы используете функцию санитизации вместо нескольких случаев, дефект появляется только однажды. Можно выровнять по ширине дефект и скрыть его в более поздних отзывах при помощи аннотаций кода. Смотрите Результаты Polyspace Адреса Через Исправления ошибок или Выравнивания.
void taintedptr(int* p, int i) {
*p = i;
}
В этом примере, указатель *p
передается в качестве аргумента, и значение изменяется. Указатель может быть пустым или указать на неизвестную память, которая может быть уязвимой.
Одна возможная коррекция должна избежать указателей из внешних источников.
int *taintedptr(int i) { /* Use heap memory allocated in the application */ int *p = (int *)malloc(sizeof (int)); if (p != NULL) { /* Check for success */ *p = i; } return p; }
Другая возможная коррекция должна санировать указатель перед использованием его. Этот пример использует вторую функцию, чтобы проверять, является ли указатель пустым и может быть разыменован.
#include <stdlib.h>
int* sanitize_ptr(int* p) {
int* res = NULL;
if (p && *p) { /* Tainted pointer detected here, used as "firewall" */
/* Pointer is not null and dereference ok */
res = p;
}
return res;
}
void taintedptr(int* p, int i) {
p = sanitize_ptr(p);
if (p) {
*p = i;
}
}
Разрешимость: неразрешимый |
[1] Выписки из стандарта "Техническая характеристика ISO/IEC TS 17961 - 2013-11-15" воспроизводятся с соглашением о AFNOR. Только исходный и полный текст стандарта, как опубликовано Выпусками AFNOR - доступный через веб-сайт www.boutique.afnor.org - имеет нормативное значение.
1. Если смысл перевода понятен, то лучше оставьте как есть и не придирайтесь к словам, синонимам и тому подобному. О вкусах не спорим.
2. Не дополняйте перевод комментариями “от себя”. В исправлении не должно появляться дополнительных смыслов и комментариев, отсутствующих в оригинале. Такие правки не получится интегрировать в алгоритме автоматического перевода.
3. Сохраняйте структуру оригинального текста - например, не разбивайте одно предложение на два.
4. Не имеет смысла однотипное исправление перевода какого-то термина во всех предложениях. Исправляйте только в одном месте. Когда Вашу правку одобрят, это исправление будет алгоритмически распространено и на другие части документации.
5. По иным вопросам, например если надо исправить заблокированное для перевода слово, обратитесь к редакторам через форму технической поддержки.