AG
Все записи

Как обнаружить переполнение стека

2 min read
EmbeddedстекотладкаMPU

Как обнаружить

Заполнение стека шаблонами. Стек заполняется известными значениями (например, 0xAA или 0xDEADBEEF) при инициализации. При обнаружении изменения шаблона фиксируется переполнение.

Пример:

// Заполнение стека шаблоном
memset(&stack_base, 0xAA, stack_size);
// Проверка целостности шаблона
for (uint8_t *ptr = &stack_base; ptr < &stack_top; ptr++) {
  if (*ptr != 0xAA) {
    error_handler();
  }
}

Проверка указателя стека. Регулярная проверка текущего значения указателя стека на соответствие границам выделенной области.

Использование аппаратных методов:

  • MPU (Memory Protection Unit). Конфигурируется для защиты области памяти, выделенной под стек, от записи за пределы. При нарушении генерируется исключение, которое можно обработать в обработчике ошибок. Пример: на Cortex-M процессорах MPU позволяет задать границы стека и сгенерировать HardFault при выходе за пределы.
  • Аппаратные watchpoints. Настройка CPU для отслеживания доступа к памяти в критической зоне (например, конец стека). При записи в защищённую область генерируется прерывание, позволяющее определить момент переполнения.
  • Регистры ограничения стека. Некоторые процессоры (например, ARMv8-M) имеют специальные регистры для установки максимального значения указателя стека. При превышении границы генерируется исключение.

Как исправить?

  1. Для критических систем:

    • используйте комбинацию аппаратных (MPU) и программных методов (canaries),
    • настройте watchpoints на запись в область ниже стека.
  2. Для RTOS-приложений:

    • регулярно проверяйте использование стека через uxTaskGetStackHighWaterMark(),
    • активируйте встроенные проверки стека (например, в FreeRTOS через configCHECK_FOR_STACK_OVERFLOW).
  3. Для bare-metal:

    • реализуйте ручное заполнение стека шаблонами и периодическую проверку,
    • используйте инструменты статического анализа (например, gcc -fstack-check).