<table border="1" cellspacing="0" cellpadding="8">
    <tr>
        <th>Issue</th>
        <td>
            <a href=https://github.com/llvm/llvm-project/issues/54804>54804</a>
        </td>
    </tr>

    <tr>
        <th>Summary</th>
        <td>
            [ASAN] [x86] Thrown exceptions corrupt stack near catch site
        </td>
    </tr>

    <tr>
      <th>Labels</th>
      <td>
            new issue
      </td>
    </tr>

    <tr>
      <th>Assignees</th>
      <td>
      </td>
    </tr>

    <tr>
      <th>Reporter</th>
      <td>
          stwish-msft
      </td>
    </tr>
</table>

<pre>
    When an exception is thrown with AddressSanitizer in use, the x86 compiler fails to take into account stack red-zones added for catch bodies when determining variable addresses. Below are five examples.

```
>clang --version
clang version 14.0.0
Target: i686-pc-windows-msvc
Thread model: posix
InstalledDir: C:\Program Files (x86)\LLVM\bin
```

`> clang -m32 test.cpp -fsanitize=address`
``` C++
#include <stdio.h>

void one() {
    // Set variables before and after caught exception.
    // Variable set after thrown exception is corrupted.
    puts("one");
    int test = 5;

    try {
        throw 42;
    } catch (...) {
    }

    int test2 = 10;

    printf("%p : %d\n", &test, test);
    printf("%p : %d\n", &test2, test2);
    // 014FFA10 : 5
    // 014FFA30 : 7213915 <-- should be 10
}

void two() {
    puts("two");
    // Expanding amount of stack variables show that the next 16 bytes are corrupted.
    int test = 5;

    try {
        throw 42;
    } catch (...) {
    }

    int vars[5] = {10, 15, 20, 25, 30};

    printf("%p : %d\n", &test, test);
    for (int& x : vars) {
        printf("%p : %d\n", &x, x);
    }
    // 014FF9F0 : 5
    // 014FFA00 : 67108874 <-- should be 10
    // 014FFA04 : 0        <-- should be 15 (always 0)
    // 014FFA08 : 22018464 <-- should be 20
    // 014FFA0C : 0        <-- should be 25 (always 0)
    // 014FFA10 : 30
}

void three() {
    puts("three");
    // Without the first variable set prior to exception throw, only 4 bytes are corrupted.
    try {
        throw 42;
    } catch (...) {
    }

    int vars[5] = {10, 15, 20, 25, 30};

    for (int& x : vars) {
        printf("%p : %d\n", &x, x);
    }

    // 014FFA00 : 10
    // 014FFA04 : 22018464 <-- should be 15
    // 014FFA08 : 20
    // 014FFA0C : 25
    // 014FFA10 : 30
}

void four() {
    puts("four");
    // Moving all variables before thrown exception corrupt in a different pattern.

    int vars[5] = {10, 15, 20, 25, 30};

    try {
        throw 42;
    } catch (...) {
    }

    for (int& x : vars) {
        printf("%p : %d\n", &x, x);
    }
    // 014FF9F0 : 10
    // 014FF9F4 : 0        <-- should be 15 (always 0)
    // 014FF9F8 : 22018464 <-- should be 20
    // 014FF9FC : 0        <-- should be 25 (always 0)
    // 014FFA00 : 30
}

void five() {
    puts("five");
    // Before and after also corrupt in a unique pattern.

    int vars[5] = {10, 15, 20, 25, 30};

    try {
        throw 42;
    } catch (...) {
    }

    int vars2[5] = {35, 40, 45, 50, 55};

    for (int& x : vars) {
        printf("%p : %d\n", &x, x);
    }

    for (int& x : vars2) {
        printf("%p : %d\n", &x, x);
    }
    // 014FF990 : 10
    // 014FF994 : 15
    // 014FF998 : 20
    // 014FF99C : 0        <-- should be 25 (always 0)
    // 014FF9A0 : 30
    // 014FF9E0 : 35
    // 014FF9E4 : 22018432 <-- should be 40
    // 014FF9E8 : 20       <-- should be 45 (always 20)
    // 014FF9EC : 50
    // 014FF9F0 : 55
}

int main() {
    one();
    two();
    three();
    four();
    five();
}
```
</pre>
<img width="1px" height="1px" alt="" src="http://email.email.llvm.org/o/eJzVWN-PmzgQ_mvIixUEBpLwkIdsspFOak8nbdU-G2wSXx3M2SbJ9q-_sYH8Jrutdu-2EQLHY4-_mflmsMkkfZ5-W7MSkRKxfc4qw2WJuEZmreSuRDtu1mhGqWJaP5GSG_6DKcRLVGvm4TkMY2g_GaFcbiouQFQQLmC2RIZ8ZzAQWiTPZV0apA3JvyPF6PCHLJlGhFJGUSEVyonJ1yiTlEP3zsKhzDC14SUvV2hLFCeZYHaCxcG0jx6YkDtEFEMF3zKATjaVAIEXLLxg1t5HQXs1f6PHXBDQNxxumdJgZ9PfdLZdKIz9wG9nfCFqxYwXzRAfTUbDKh_ueEnlTg83epu3Y9aKEYo2kjJhR1ZS830j-qMEi4VgdMGVFc3h5iXzv5RcKbJBS_CXRh6egP88nILk06evn-GR8fK2AYfO6BG1pmwijAzTxs-rCg0L3YbIixats46zO2WAAz_Yq-nGES9zUVOGvGiuDeXSX8MCp0tuJacIQgZYASjyxu1cBD8PL-FCT8wc4qRRxiCqEK-SIlJAICHA9WptjgzzrxR87YKsQVMzqaXgGS1zqVRdGUZPNFS10Q4adhixdWZ0AhFI6HwEBi5QchAdBxj1fG6U67SroxifqfLGi5assKDv-9fuGC8utXfLY7d-GNwAUCkYVDQ2eDipkKULNCiwoXR9c_g7slpc0rnnuZE_oQJ3Oq481cYiCOPlchYGTkfSI44a8RiHURomljzDIdJrWQsK8bd2NkaeO8RRyezkLSod4-gG9KF73FdALFsYyMbVFVm0peVIQMCxgwgS4wpUyfYGhSOUPRtbdoCZt2j0AWgCBmgveUi8ZOFQwBzwI0QrTOwduzZ27SiwOt6FSrYigwLQAwPR3mlwyC6t-In19va5v4po54ZLdqXL--QLGvFoHAaTyTjuZd_1xNhNDDr4VxMTazoRO_KsUWDx9uiZOD0YB-EkHl0DwL0A5vcB4FcCaLMzupdm8Gq6WbNPEq0Z0pdq3-DtL-smiQqu9LHGuzINsQeqwBv-WKJdOthYy1I8o_iFlPstMup_SIf7rH-J3L2kDHvTqWXzC6TFffNfQcZC1uo-F5sRfVT8LLeu5Atxvc-42ii0XLP7VIIoLwqmGJChIgb2FaX_TkR5XzZ_oKrcR8B0-TbVNV3-YnVNl29UXYNXEBrOHS8Q2o3oI_TD5R6ZCC3PmVuX_J-a_d607UDiC5SRwxQ7fLFrJ66dJB-wCvctjv_L5EtfSL60Sb6-Ip-m94t8mr5N7qSz89y5kj-28j6cj6dvsQhf4Yh7FXcG9hgQnxqA71jw2Hgi6a0y7eY0uVkdLOM3BM7wN4rD4RB9FvPDeei897h9u9ied2_S8-5DPTpmzwFYd_Yf0GlE0yglA8ONYFNIytnT7E-Xl8mD_RABrS8Xr9PDqbs9ZpWMdJ9sNDdsUCsxXRtTaft9w_lpBfvGOvNzuYE_Qmy7x7BS8m-WQxYtudY1g-xdJvEkiAfrKc0ncTAOAhKPKSYp3IowieJxwMawzc_YQJCMCW0hQw6VbIecCptPyWLApzgAxoAGHAUBVKdRnjKcxRkp4oCwEfbigEFUhG9x-FKtBmrqIGX1SoNQcG30UUi05quSOQ9Z_aSGnbCaarPjej3c6MIM3PJTB_9fTUXkRQ">