exponenta event banner

ISO/IEC TS 17961 [nullref]

Отмена передачи указателя вне домена

Описание

Определение правила

Отмена передачи указателя вне домена. [1 ]

Внедрение Polyspace

Эта проверка проверяет наличие следующих проблем:

  • Небезопасная арифметика указателя.

  • Недопустимое использование стандартной подпрограммы библиотечной памяти.

  • Нулевой указатель.

  • Арифметическая операция с указателем NULL.

  • Недопустимое использование стандартной подпрограммы строки библиотеки.

Примеры

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

Проблема

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

При анализе Polyspace ® помечает это правило следующим образом:

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

Риск

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

Стандарт C определяет создание указателя на объект за пределами массива. Правило разрешает использование стандарта C. Отмена ссылки на указатель за пределами массива приводит к неопределенному поведению и является несоответствующим.

Проблема

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

Риск

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

Зафиксировать

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

См. примеры исправлений ниже.

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

Пример - Ошибка при использовании стандартной библиотечной памяти
#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 Desktop.

См. примеры исправлений ниже.

Пример - Ошибка нулевого указателя
#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 перед арифметическими операциями над указателем.

Если проблема возникает, несмотря на более раннюю проверку NULL, найдите промежуточные события между проверкой и последующим исключением. Часто детали результата показывают последовательность событий, которые привели к дефекту. Исправление может быть реализовано для любого события в последовательности. Если сведения о результатах не отображают историю событий, можно выполнить обратную трассировку, щелкнув правой кнопкой мыши параметры в исходном коде и просмотреть предыдущие связанные события. См. также раздел Интерпретация результатов поиска ошибок в интерфейсе пользователя Polyspace Desktop.

См. примеры исправлений ниже.

Пример - Арифметическая операция с ошибкой указателя NULL
#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 тело инструкции. Поэтому a 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 для управления количеством скопированных байтов.

См. примеры исправлений ниже.

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

Пример - Ошибка процедуры использования стандартной строки библиотеки
 #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);
 }

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

Разрешимость: неразрешимая
Представлен в R2019a

[1] Выдержки из стандарта «ISO/IEC TS 17961 Technical Specification - 2013-11-15» воспроизводятся с согласия AFNOR. Нормативную ценность имеет только оригинальный и полный текст стандарта, опубликованный изданиями AFNOR - доступный через веб-сайт www.boutique.afnor.org.