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

    <tr>
        <th>Summary</th>
        <td>
            [Clang] Mixed use of VLAs and alloca leads to miscompilation (early pop of alloca memory)
        </td>
    </tr>

    <tr>
      <th>Labels</th>
      <td>
            clang
      </td>
    </tr>

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

    <tr>
      <th>Reporter</th>
      <td>
          kkofler
      </td>
    </tr>
</table>

<pre>
    In this (minimized, not linkable, use `clang -O2 -S allocatest.c` and look at the output to test) testcase:
```c
#include <alloca.h>

struct nlopt;

extern int n;
struct nlopt *create(void);
void f(struct nlopt *opt, double *x, void *userdata);
void solve(struct nlopt *opt);

int main(void)
{
  struct nlopt *opt = create();
  int i;
  {
    double x[n];
    for (i = 0; i < n; i++) {
      void *p = alloca(8);
 f(opt, x, p);
    }
  }
  solve(opt);
  return 0;
}
```
the `alloca` needs to live until the end of the function, but (as evidenced by the assembly output), Clang actually emits code to restore `rsp` to its value before the VLA creation at the point where the VLA goes out of scope, and that also ends up destroying the arrays from `alloca`.

In the real (much longer) code, the `solve` function (actually called `nlopt_optimize`) ends up using the pointers that were recorded in the `opt` structure by the function `f` (actually called `nlopt_add_inequality_constraint`), but due to the early pop, they will have been overwritten, leading to a crash.

I can reproduce this both with the latest clang version 18.1.8 and with the ancient clang version 13.0.1, so this is a longstanding bug.

GCC gets this right: `gcc -O2 -S allocatest.c` shows that `rsp` is **not** restored until after `solve` is called (so the lifetime of the VLA also has to be extended, but there is not really a way around that in this case), and in fact, the real program also does not crash when compiled with GCC as it does when compiled with Clang.
</pre>
<img width="1" height="1" alt="" src="http://email.email.llvm.org/o/eJx8Vs2O4zYTfBr60hhDpiyPffDB4_nmQ4ANcgiw1wVFtiRmKFLhjz3O0wdNSl5PshvAgESp1ayuqmZbhKB7i3hkzQtrXlcixcH54_u76wz6VevU7fiLhTjoAIzvR231qP9CxfgZrItgtH0XrUFap4DAdpU0wvbw9BuHp99BGOOkiBjiWrJdBcIqMM69g4gQBwSX4pQiRAcUw_ghX6UIyOoTq05sV5WfpAWvtZUmKQRWn0vq9cDq_9G76hSiTzKCNW6KrH4pD_EjoregbQRbHj6GAeMn6VFEZHx_cVoxfihRtICO8f0_wyk5P4NyqTVIDz5omcMZP6WAXokoPucJzlzwZ7kOd6wEchTaPmCpTuyZ3gL84Ftg9Svc4d8zQa5WL4slASyYP1jzYlnzugQAdM6TujonrFj9AnR7zoyBZvwl_w4PqeBe8ZQ_KmIwvn-AQezNbGWOpgeEBOt1hleuC0ePnAB4jMnbjClz8froCVadyENsV83b7yqwiCqQn4y-ICQbtclGQ6vAdfm2S1ZG7SxhahORuRcB8KIVWokK2lsOEyHg2Jrb7FECxc9wzu4WMiZhzA1w1DGAdAppT48hOp8R-TARnOiAAi7CJIQWO3pLyb9-ORXltLNLL0yOdLsO-BDTOwwEgLAH6abcaNREcRARhAmOKguQJlAYonc3bfsC33txC9B5N35iaF28lpsawaMwubGTHMA426Mnoakg2mmmt2izq-7UZc4WDqQwBhXFZXN-c1PMhwQpxA93fCks0HKh6EMp4kr1epTOK1Sg7bIpGWFXzb5PHhddvmPYVR1F_BcWodQ3bfHPJIyOt2_S2RC90DYWcIsFVMr6ZaMIb24wuWmu_wZXbQwM4kICogV3QX_1OkbMDjIoVC7MgQDpRRgWhkEKCx4n71SSWM7Q1sUBrjoOeS-TT0YoJ-YFfaCyNvv1Zr3PIt8DhZUa7b8i63W13hCI4Ep6HUBkGUMUNsNqUz_j-f_5DD3GUCK97ofI6hNR1Uv5s_M6DO466_Td1HkWnBg_WRfLzeJ8NXec6CL6T87R4a4N34dCtdEdRj3i0phk-GzpQeQWbhHo-LaqzBsSKubu0CEPHzKvuYGAq7iB8C4tfaHniZXnSFGZ6NQWOiHjYuzs_cm73oux7Kuo2yhz1pFa0YJ046QJdxaDSBQBdCyxP4jIB8R6pY61OtQHscLj5rmp9ofqwJ9Xw1F2squ7523btJuuelZNo_Z1zWuxFbtGVN1KH3nFm2rHG87rhj-vt1uplNjIpj7gvuKcbSschTZrYy7j2vl-pUNIeNxsm321WRnRogl5nnOe_cI4p9Huj_TBU5v6wLaV0SGG7ymijib_CcjwWfMKv-oPkjNkdb5-OYVMYfFHNn2WaNShlC-WY-HeP_TdHD7i6PyN8cMqeXMcYpwCjXf-xvhbr-OQ2rV0I-NvhGe-PE3e_YGk1luuLzD-Npd4OfK_AwAA___xhs8p">