exponenta event banner

ISO/IEC TS 17961 [libptr]

Формирование недопустимых указателей функцией библиотеки

Описание

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

Формирование недопустимых указателей функцией библиотеки. [1 ]

Внедрение Polyspace

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

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

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

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

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

Примеры

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

Проблема

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

Риск

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

Например, char *getwd(char *buf) копирует абсолютное имя пути текущей папки в ее аргумент. Если длина абсолютного пути больше, чем PATH_MAX байты, getwd прибыль NULL и содержание *buf не определен. Можно проверить возвращаемое значение getwd для NULL для проверки успешности вызова функции.

Однако, если разрешенный буфер для buf меньше, чем PATH_MAX байт, сбой может произойти для меньшего абсолютного имени пути. В этом случае getwd не возвращается NULL несмотря на то, что произошел сбой. Следовательно, разрешенный буфер для buf должно быть PATH_MAX в байтах.

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

Возможные исправления:

  • Использовать размер буфера PATH_MAX байт. Если буфер получен из неизвестного источника, перед использованием буфера в качестве аргумента getwd или realpath , убедитесь, что размер меньше PATH_MAX байт.

  • Используйте функцию управления путями, которая позволяет указать размер буфера.

    Например, если используется getwd чтобы получить абсолютный путь к текущей папке, используйте char *getcwd(char *buf, size_t size); вместо этого. Дополнительный аргумент size позволяет указать размер, больший или равный PATH_MAX.

  • Разрешить функции выделять дополнительную память динамически, если это возможно.

    Например, char *realpath(const char *path, char *resolved_path); динамически выделяет память, если resolved_path является NULL. Тем не менее, вы должны освободить эту память позже с помощью free функция.

Пример - Возможное переполнение буфера при использовании getwd Функция
#include <unistd.h>
#include <linux/limits.h>
#include <stdio.h>

void func(void) {
    char buf[PATH_MAX];
    if (getwd(buf+1)!= NULL)         {
        printf("cwd is %s\n", buf);
    }
}

В этом примере, хотя массив buf имеет PATH_MAX байт, аргумент getwd является buf + 1, разрешенный буфер которого меньше PATH_MAX байт.

Исправление - использовать массив размера PATH_MAX Байты

Одной из возможных корректировок является использование аргумента массива с размером, равным PATH_MAX байт.

#include <unistd.h>
#include <linux/limits.h>
#include <stdio.h>

void func(void) {
    char buf[PATH_MAX];
    if (getwd(buf)!= NULL)         {
        printf("cwd is %s\n", buf);
    }
}
Проблема

Недопустимое использование стандартной подпрограммы библиотечной памяти происходит при вызове функции библиотеки памяти с недопустимыми аргументами. Например, 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;
 }
Проблема

При вызове функции библиотеки строк с недопустимыми аргументами происходит недопустимое использование стандартной подпрограммы строк библиотеки.

Риск

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

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

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

char * strcpy(char * destination, const char* source);
пытается скопировать слишком много байт в целевой аргумент по сравнению с доступным буфером, ограничить исходный аргумент перед вызовом strcpy. В некоторых случаях можно использовать альтернативную функцию, чтобы избежать ошибки. Например, вместо strcpy, вы можете использовать strncpy для управления количеством скопированных байтов. См. также раздел Интерпретация результатов поиска ошибок в интерфейсе пользователя Polyspace Desktop.

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

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

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

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

Например, при вызове функции sprintf(char* buffer, const char* format), используется постоянная строка format большего размера, чем buffer.

Риск

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

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

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

  • Если вы используете sprintf для записи отформатированных данных в строку, используйте snprintf, _snprintf или sprintf_s вместо этого для обеспечения контроля длины. В качестве альтернативы можно использовать asprintf для автоматического выделения памяти, необходимой для целевого буфера.

  • Если вы используете vsprintf для записи форматированных данных из списка переменных аргументов в строку, используйте vsnprintf или vsprintf_s вместо этого для обеспечения контроля длины.

  • Если вы используете wcscpy для копирования широкой строки используйте wcsncpy, wcslcpy, или wcscpy_s вместо этого для обеспечения контроля длины.

Другим возможным решением является увеличение размера буфера.

Пример - Переполнение буфера в sprintf Использовать
#include <stdio.h>

void func(void) {
    char buffer[20];
    char *fmt_string = "This is a very long string, it does not fit in the buffer";

    sprintf(buffer, fmt_string);
}

В этом примере: buffer может содержать 20 char элементы, но fmt_string имеет больший размер.

Коррекция - использование snprintf Вместо sprintf

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

#include <stdio.h>

void func(void) {
    char buffer[20];
    char *fmt_string = "This is a very long string, it does not fit in the buffer";

    snprintf(buffer, 20, fmt_string);
}

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

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

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