Erro: dynamic-stack-buffer-overflow

Erro na limpeza de endereço: dynamic-stack-buffer-overflow

Este exemplo mostra o erro resultante de um acesso de buffer fora dos limites de um objeto alocado em pilha.

Exemplo – alloca estouro (à direita)

// example1.cpp
// dynamic-stack-buffer-overflow error
#include <malloc.h>

__declspec(noinline)
void foo(int index, int len) {

    volatile char *str = (volatile char *)_alloca(len);

    //    reinterpret_cast<long>(str) & 31L;

    str[index] = '1'; // Boom !
}

int main(int argc, char **argv) {

    foo(33, 10);
    return 0;
}

Para compilar e testar esse exemplo, execute estes comandos em um prompt de comando do desenvolvedor do Visual Studio 2019 versão 16.9 ou posterior:

cl example1.cpp /fsanitize=address /Zi
devenv /debugexe example1.exe

Erro resultante

Captura de tela do depurador exibindo erro de dynamic-stack-buffer-overflow no exemplo 1.

Exemplo – alloca overflow (à direita)

// example2.cpp
// dynamic-stack-buffer-overflow error
#include <malloc.h>

__declspec(noinline)
void foo(int index, int len) {

    volatile char *str = (volatile char *)_alloca(len);

    str[index] = '1';  // Boom!
}

int main(int argc, char **argv) {
    foo(-1, 10);
    return 0;
}

Para compilar e testar esse exemplo, execute estes comandos em um prompt de comando do desenvolvedor do Visual Studio 2019 versão 16.9 ou posterior:

cl example2.cpp /fsanitize=address /Zi
devenv /debugexe example2.exe

Erro resultante – alloca overflow (à esquerda)

Captura de tela do depurador exibindo erro de dynamic-stack-buffer-overflow no exemplo 2.

Exemplo – várias chamadas para alloca

// example3.cpp
// dynamic-stack-buffer-overflow error
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>

#define SIZE 7
extern void nothing();
int x=13,*aa,*bb,y=0;
int fail = 0;
int tmp;

int main()
{
    int* cc;
    int i;
    int k = 17;
    __try {
        tmp = k;
        aa = (int*)_alloca(SIZE * sizeof(int));
        if (((int)aa) & 0x3)
            fail = 1;
        for (i = 0; i < SIZE; i++) {
            aa[i] = x + 1 + i;
        }
        bb = (int*)_alloca(x * sizeof(int));
        if (((int)bb) & 0x3)
            fail = 1;

        for (i = 0; i < x; i++) {
            bb[i] = 7;
            bb[i] = bb[i] + i;
        }
        {
            int s = 112728283;
            int ar[8];
            for (i = 0; i < 8; i++)
                ar[i] = s * 17 * i;
        }

        cc = (int*)_alloca(x);
        if (((int)cc) & 0x3)
            fail = 1;

        cc[0] = 0;
        cc[1] = 1;
        cc[2] = 2;
        cc[3] = 3;             // <--- Boom!
        for (i = 0; i < x; i++)
            if (bb[i] != (7 + i))
                fail = 1;
        if (tmp != k)
            fail = 1;
        if (fail) {
            printf("fail\n");
            exit(7);
        }
        printf("%d\n", (*cc) / y);
        printf("fail\n");
        exit(7);
    }
    __except (1)
    {
        for (i = 0; i < SIZE; i++)
            if (aa[i] != (x + i + 1))
                fail = 1;
        if (fail) {
            printf("fail\n");
            exit(7);
        }
        printf("pass\n");
        exit(0);
    }
}

Para compilar e testar esse exemplo, execute estes comandos em um prompt de comando do desenvolvedor do Visual Studio 2019 versão 16.9 ou posterior:

cl example3.cpp /fsanitize=address /Zi
devenv /debugexe example3.exe

Erro resultante – várias chamadas para a alloca

Captura de tela do depurador exibindo erro de dynamic-stack-buffer-overflow no exemplo 3.

Confira também

Visão geral do AddressSanitizer
Problemas conhecidos do AddressSanitizer
Referência de linguagem e build do AddressSanitizer
Referência de runtime do AddressSanitizer
Bytes de sombra de AddressSanitizer
Nuvem do AddressSanitizer ou teste distribuído
Integração do depurador do AddressSanitizer
Exemplos de erro do AddressSanitizer