错误:stack-use-after-return

地址擦除器错误:在返回后使用堆栈内存

此检查需要通过额外的编译器选项 /fsanitize-address-use-after-return 并通过设置环境变量 ASAN_OPTIONS=detect_stack_use_after_return=1 激活的代码生成。

此检查会大幅降低应用程序速度。 请考虑支持返回后使用的算法的 Clang 摘要,以及更大的性能成本。

重要

如果使用额外的编译器选项 /fsanitize-address-use-after-return 创建对象文件,编译器生成的代码会关于如何分配堆栈帧做出运行时决策。 如果环境变量 ASAN_OPTIONS 未设置为 detect_stack_use_after_return,则代码的速度仍然比单独使用 /fsanitize=address 慢。 速度较慢是因为某些堆栈帧仍会产生额外的开销,这些帧通过使用 alloca() 为帧的某些部分分配空间。 在处理完 use-after-return 错误时,最好删除这些对象文件。

示例 - 简单 C

// example1.cpp
// stack-use-after-return error
volatile char* x;

void foo() {
    char stack_buffer[42];
    x = &stack_buffer[13];
}

int main() {

    foo();
    *x = 42; // Boom!

    return (*x == 42);
}

若要生成并测试此示例,请在 Visual Studio 2019 版本 16.9 或更高版本的开发人员命令提示符中运行以下命令:

cl example1.cpp /fsanitize=address /fsanitize-address-use-after-return /Zi
set ASAN_OPTIONS=detect_stack_use_after_return=1
devenv /debugexe example1.exe

生成的错误 - 简单 C

示例 1 中显示 stack-use-after-return 错误的调试程序的屏幕截图。

示例 - C++ 和模板

// example2.cpp
// stack-use-after-return error
#include <stdlib.h>

enum ReadOrWrite { Read = 0, Write = 1 };

struct S32 {
    char x[32];
};

template<class T>
T* LeakStack() {
    T t[100];
    static volatile T* x;
    x = &t[0];
    return (T*)x;
}

template<class T>
void StackUseAfterReturn(int Idx, ReadOrWrite w) {
    static T sink;
    T* t = LeakStack<T>();
    if (w)
        t[100 + Idx] = T();
    else
        sink = t[100 + Idx];
}

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

    if (argc != 2) return 1;
    int kind = atoi(argv[1]);

    switch (kind) {
    case 1: StackUseAfterReturn<char>(0, Read); break;
    case 2: StackUseAfterReturn<S32>(0, Write); break;
    }
    return 0;
}

若要生成并测试此示例,请在 Visual Studio 2019 版本 16.9 或更高版本的开发人员命令提示符中运行以下命令:

cl example2.cpp /fsanitize=address /fsanitize-address-use-after-return /Zi /Od
set ASAN_OPTIONS=detect_stack_use_after_return=1
devenv /debugexe example2.exe 1

ASAN 是动态分析的一种形式,这意味着它只能检测实际执行的错误代码。 优化器可以确定从未使用过 t[100 + Idx]sink 的值,并省略赋值。 因此,此示例需要 /Od 标志。

生成的错误 - C++ 和模板

示例 2 中显示 stack-use-after-return 错误的调试程序的屏幕截图。

另请参阅

AddressSanitizer 概述
AddressSanitizer 已知问题
AddressSanitizer 生成和语言参考
AddressSanitizer 运行时参考
AddressSanitizer 阴影字节
AddressSanitizer 云或分布式测试
AddressSanitizer 调试程序集成
AddressSanitizer 错误示例