Найдите и объясните ошибку в этом фрагменте на C, указывая конкретные последствия (UB, утечка, крах) и предложите исправление:
char *f(){ char buf[10]; strcpy(buf, "this is too long"); return buf; }
Обсудите техники обнаружения таких ошибок (ASAN, valgrind), защитные приёмы (canary, ограждение) и архитектурные решения для избежания подобных классов ошибок

20 Окт в 10:34
3 +1
0
Ответы
1

Ошибка

В функции создаётся локальный массив char buf[101010];, затем делается strcpy(buf, "this is too long");. Строка литерал имеет длину (\;16\;) (символов без завершающего нуля), поэтому копируется (\;17\;) байт (включая \0). Это переписывает память за пределами буфера на (\;17-10=7\;) байт.

Последствия (конкретно)

UB (Undefined Behavior): чтение/запись за пределами стека — неопределённое поведение.Возможны крах (segfault) при перезаписи важной служебной информации стека.Возможна коррупция соседних локальных переменных или сохранённых адресов — уязвимость к RCE (удалённое исполнение кода).Утечки памяти здесь нет (нет динамического выделения), но есть потенциальная безопасность/стабильность проблемы.

Как исправить (варианты)
1) Вернуть литерал (если менять строку не нужно):
char *f(void){ return "this is too long"; }

2) Выделить память динамически и вернуть (проверять malloc):
char f(void){
const char s = "this is too long";
char *buf = malloc(strlen(s) + 1);
if (!buf) return NULL;
strcpy(buf, s);
return buf;
}

3) Использовать буфер достаточного размера (если статический допустим):
char *f(void){
static char buf[(17)]; // (\;16\;) символов + '\0'
strcpy(buf, "this is too long");
return buf;
}

4) Безопаснее — использовать ограничивающие функции:

snprintf(buf, sizeof buf, "%s", s);strlcpy (если доступна)
Никогда не полагаться на strcpy без гарантии достаточного размера.

Техники обнаружения ошибок

AddressSanitizer (ASAN): обнаруживает переполнения стека/кучи/ограничений — используйте флаги компилятора -fsanitize=address.Valgrind (memcheck): выявляет чтение/запись вне выделенной памяти, утечки (медленнее, не ловит всё, например переполнение стека не всегда).UndefinedBehaviorSanitizer (UBSAN): ловит некоторые UB-случаи.Компиляторные предупреждения: -Wstringop-overflow, -Wall -Wextra.Статический анализ (clang-tidy, Coverity, cppcheck), fuzzing (AFL, libFuzzer) и code review.

Защитные приёмы (runtime/OS)

Stack canaries (stack cookies): обнаруживают переполнение стека и инициируют аварийный выход.NX/DEP (non-executable stack) и ASLR — затрудняют эксплуатацию.Guard pages (страницы-ограждения) для стека: переполнение вызывает SIGSEGV.FORTIFY_SOURCE (glibc) — проверяет некоторые букопереполнения в libc при оптимизациях.Использовать безопасные библиотечные функции с проверкой длины.

Архитектурные решения для избежания таких ошибок

Использовать языки с управляемой памятью/безопасностью границ (Rust, Go, Java, etc.).Разработать API, где вызывающий явно предоставляет буфер и его размер или где функции возвращают безопасные управляемые строки (например, std::string в C++).Применять принцип минимальной привилегии и мемомодели с явной владением/жизненным циклом (RAII).Включать sanitizers и статический анализ в CI, проводить fuzz-тесты и ревью кода.Документировать и применять шаблоны безопасной работы со строками (не использовать strcpy, явно проверять размеры).

Кратко: причина — переполнение стека и возврат указателя на объект автоматической памяти (UB). Исправление — обеспечить корректную длительность жизни и достаточный размер буфера или использовать динамическую/безопасную альтернативу; применять обнаружение (ASAN/Valgrind), runtime-защиту (canary, guard pages) и архитектурно — безопасные языки и API.

20 Окт в 11:02
Не можешь разобраться в этой теме?
Обратись за помощью к экспертам
Гарантированные бесплатные доработки в течение 1 года
Быстрое выполнение от 2 часов
Проверка работы на плагиат
Поможем написать учебную работу
Прямой эфир