Для получения триального ключа
заполните форму ниже
Team License (базовая версия)
Enterprise License (расширенная версия)
* Нажимая на кнопку, вы даете согласие на обработку
своих персональных данных. См. Политику конфиденциальности

Запросите информацию о ценах
Новая лицензия
Продление лицензии
--Выберите валюту--
USD
EUR
RUB
* Нажимая на кнопку, вы даете согласие на обработку
своих персональных данных. См. Политику конфиденциальности

Бесплатная лицензия PVS-Studio для специалистов Microsoft MVP
* Нажимая на кнопку, вы даете согласие на обработку
своих персональных данных. См. Политику конфиденциальности

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

Мне интересно попробовать плагин на:
* Нажимая на кнопку, вы даете согласие на обработку
своих персональных данных. См. Политику конфиденциальности

Ваше сообщение отправлено.

Мы ответим вам на


Если вы так и не получили ответ, пожалуйста, проверьте папку
Spam/Junk и нажмите на письме кнопку "Не спам".
Так Вы не пропустите ответы от нашей команды.

>
>
>
Про разницу между strlcat и strncat

Про разницу между strlcat и strncat

16 Июл 2019

Пока идёт активная подготовка больших статей про проверку кода операционной системы Haiku OS, я хочу привести один пример популярной ошибки с функцией strncat из этого проекта. Освежить знания по этой теме будет полезно для всех C и C++ разработчиков.

0640_strncat_strlcat_ru/image1.png

Описание функций

Функция strncat служит для конкатенации строк и имеет следующую сигнатуру:

char *strncat(char *dest, const char *src, size_t n);

Она добавляет не более n символов из строки src к строке dest, при этом строка src может не заканчиваться терминальным нулём. В строке dest должно быть достаточно места, иначе поведение программы становится непредсказуемым из-за переполнения буфера, т.к. функция не производит контроля границ.

Функция strlcat служит для конкатенации строк и делает это более безопасно, чем функция strncat. strlcat имеет следующую сигнатуру:

size_t strlcat(char *dst, const char *src, size_t size)

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

Ошибка в Haiku OS

V645 The 'strncat' function call could lead to the 'output' buffer overflow. The bounds should not contain the size of the buffer, but a number of characters it can hold. NamespaceDump.cpp 101

static void
dump_acpi_namespace(acpi_ns_device_info *device, char *root, int indenting)
{
  char result[255];
  char output[320];
  char tabs[255] = "";
  char hid[16] = "";
  int i;
  size_t written = 0;
  for (i = 0; i < indenting; i++)
    strlcat(tabs, "|    ", sizeof(tabs));

  strlcat(tabs, "|--- ", sizeof(tabs));
  ....
  void *counter = NULL;
  while (....) {
    uint32 type = device->acpi->get_object_type(result);
    snprintf(output, sizeof(output), "%s%s", tabs, result + depth);
    switch(type) {
      case ACPI_TYPE_INTEGER:
        strncat(output, "     INTEGER", sizeof(output));
        break;
      case ACPI_TYPE_STRING:
        strncat(output, "     STRING", sizeof(output));
        break;
      case ACPI_TYPE_BUFFER:
        strncat(output, "     BUFFER", sizeof(output));
        break;
      case ACPI_TYPE_PACKAGE:
        strncat(output, "     PACKAGE", sizeof(output));
        break;
      ....
      case ACPI_TYPE_MUTEX:
        strncat(output, "     MUTEX", sizeof(output));
        break;
      case ACPI_TYPE_REGION:
        strncat(output, "     REGION", sizeof(output));
        break;
      case ACPI_TYPE_POWER:
        strncat(output, "     POWER", sizeof(output));
        break;
      case ACPI_TYPE_PROCESSOR:
        strncat(output, "     PROCESSOR", sizeof(output));
        break;
      case ACPI_TYPE_THERMAL:
        strncat(output, "     THERMAL", sizeof(output));
        break;
      case ACPI_TYPE_BUFFER_FIELD:
        strncat(output, "     BUFFER_FIELD", sizeof(output));
        break;
      case ACPI_TYPE_ANY:
      default:
        break;
    }
    ....
  }
  ....
}

Анализатор обнаружил смешанный код, состоящий из вызовов функций strlcat и strncat. Причём, вызовы функции strlcat являются корректными:

char tabs[255] = "";
....
strlcat(tabs, "|--- ", sizeof(tabs));

в них передаётся нультерминальная строка и размер всего буфера.

В то же время, многочисленные вызовы strncat в цикле являются ошибочными и могут привести к ошибке:

char output[320];
....
strncat(output, "     INTEGER", sizeof(output));

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

Заключение

Полезные ссылки по теме:

P.S.

Не дожидаясь публикации основных больших статей , мы отправили отчёт разработчикам Haiku OS, и они уже приступили к исправлению ошибок: https://git.haiku-os.org/haiku/log/?qt=grep&q=pvs

Популярные статьи по теме
Четыре причины проверять, что вернула функция malloc

Дата: 20 Апр 2022

Автор: Андрей Карпов

Некоторые разработчики пренебрежительно относятся к проверкам: удалось ли выделить память с помощью функции malloc или нет. Их логика проста – памяти всегда должно хватить. А если не хватит, всё равн…
Атака Trojan Source: скрытые уязвимости

Дата: 15 Апр 2022

Автор: Гость

Мы представляем новый тип атаки для внедрения в исходный код вредоносных изменений, по-разному выглядящих для компилятора и человека. Такая атака эксплуатирует тонкости стандартов кодирования символо…
Дизайн и эволюция constexpr в C++

Дата: 13 Янв 2022

Автор: Гость

constexpr - одно из самых магических ключевых слов в современном C++. Оно дает возможность создать код, который будет выполнен еще до окончания процесса компиляции, что является абсолютным пределом д…
C++20 Ranges — Полное руководство

Дата: 07 Дек 2021

Автор: Гость

C++20 Ranges, также известные как STL v2, эффективно заменяют существующие возможности и алгоритмы STL. В этой статье я расскажу вам о нововведениях, которые внесли собой Ranges. Также мы поговорим о…
Вызов виртуальных функций в конструкторах и деструкторах (C++)

Дата: 26 Ноя 2021

Автор: Андрей Карпов

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

Комментарии (0)

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