ISO/IEC TS 17961 [nullref]

Разыменование указателя вне основной области

Описание

Управляйте определением

Разыменование указателя вне основной области. [1]

Примеры

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

Описание

Проблема происходит, когда указатель, следующий из арифметики на операнде указателя, не обращается к элементу того же массива как тот операнд указателя.

Polyspace® отмечает это правило во время анализа как:

Средство поиска ошибки и Программа автоматического доказательства Кода проверяют это правило по-другому и могут показать различные результаты для этого правила. В Программе автоматического доказательства Кода можно также видеть различие в результатах на основе выбора для опции Verification level (-to). Смотрите Проверку на Кодирование Стандартных Нарушений.

Риск

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

Стандарт C задает создание указателя на один вне конца массива. Правило разрешает Стандарт C. Разыменование указателя на один вне конца массива вызывает неопределенное поведение и несовместимо.

Описание

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

Риск

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

Фиксация

Фиксация зависит от первопричины дефекта. Часто детали результата показывают последовательность событий, которые привели к дефекту. Можно реализовать закрепление на любом событии в последовательности. Если детали результата не показывают историю события, можно проследить использование, щелкните правой кнопкой по опциям по исходному коду и смотрите предыдущие связанные события. См. также Интерпретируют Результаты Polyspace Bug Finder.

Смотрите примеры мер ниже.

Если вы не хотите устранять проблему, добавьте комментарии в свой результат или код, чтобы избежать другого анализа. Смотрите Результаты Polyspace Адреса Через Исправления ошибок или Комментарии.

Пример - недопустимое использование стандартной ошибки стандартной программы библиотеки Memory

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

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

Разрешимость: неразрешимый

Введенный в R2019a


[1]  Выписки из стандарта "Техническая характеристика ISO/IEC TS 17961 - 2013-11-15" воспроизводятся с соглашением о AFNOR. Только исходный и полный текст стандарта, как опубликовано Выпусками AFNOR - доступный через веб-сайт www.boutique.afnor.org - имеет нормативное значение.