GCC генерирует Canary или нет?

Моя версия gcc - 4.8.2, а операционная система - ubuntu 14.04 (64 бит). Я обнаружил, что иногда gcc автоматически генерирует канарейку для защиты от переполнения буфера, иногда нет, почему?

для генерации канарейки: когда SIZE кратно четырем

#include<stdio.h>
#define SIZE 4

int main()
{
    char s[SIZE];
    scanf("%s", s);
    return 0;
}

asm после gcc -c -g-Wa, -a, -ad

...
   4:a.c           **** int main()
   5:a.c           **** {
  13                    .loc 1 5 0
  14                    .cfi_startproc
  15 0000 55            pushq   %rbp
  16                    .cfi_def_cfa_offset 16
  17                    .cfi_offset 6, -16
  18 0001 4889E5        movq    %rsp, %rbp
  19                    .cfi_def_cfa_register 6
  20 0004 4883EC10      subq    $16, %rsp
  21                    .loc 1 5 0
  22 0008 64488B04      movq    %fs:40, %rax
  22      25280000 
  22      00
  23 0011 488945F8      movq    %rax, -8(%rbp)
  24 0015 31C0          xorl    %eax, %eax
   6:a.c           ****     char s[SIZE];
   7:a.c           ****     scanf("%s", s);
...

случай не создавать канарейку: не кратное четырем

#include<stdio.h>
#define SIZE 2

int main()
{
    char s[SIZE];
    scanf("%s", s);
    return 0;
}

asm после gcc -c -g-Wa, -a, -ad

...
   4:a.c           **** int main()
   5:a.c           **** {
  13                    .loc 1 5 0
  14                    .cfi_startproc
  15 0000 55            pushq   %rbp
  16                    .cfi_def_cfa_offset 16
  17                    .cfi_offset 6, -16
  18 0001 4889E5        movq    %rsp, %rbp
  19                    .cfi_def_cfa_register 6
  20 0004 4883EC10      subq    $16, %rsp
   6:a.c           ****     char s[SIZE];
   7:a.c           ****     scanf("%s", s);
...

Ответ 1

ОК, я думаю, мы знаем ответ из комментариев, поэтому я отправлю его здесь, чтобы указать его явно.

Включение канарейки во множество функций может привести к ухудшению производительности. Вот почему есть несколько способов сказать GCC, что мы хотим их использовать, которые описаны здесь здесь. Основные идеи:

  • Канары не используются по умолчанию, нужно передать один из флагов, которые их активируют.
  • Чтобы сохранить время выполнения, GCC использует простую эвристику с флагом -fstack-protector: добавляет канавари для функций, которые используют alloca или локальные буферы, превышающие 8 байты (по умолчанию).
  • Эвристика может быть изменена с помощью параметра ssp-buffer-size: --param ssp-buffer-size=4.

Очевидно, Ubuntu отправляет версию GCC с размером буфера, измененным на 4, поэтому буферы меньше, чем это не вызывает генерацию канарейки. Я подтверждаю (и кто-то еще должен повторять), что, компилируя два примера с --param ssp-buffer-size=4, который создает сборку с канареями только для одного из них.