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

    <tr>
        <th>Summary</th>
        <td>
            [clang] KCFI hash mismatches with anonymous structs and qualified typedefs
        </td>
    </tr>

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

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

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

<pre>
    Compiling the following files with `-fsanitize=kcfi` enabled incorrectly causes a KCFI violation, on current `main` as well as llvm16:

`kcfi_anon_struct.h`:
```c
typedef volatile struct { int a; int b; } A;
```

`kcfi_anon_struct_a.c`:
```c
typedef volatile struct { int a; int b; } B;
#include "kcfi_anon_struct.h"

B getB() { B v = { 0, 0 }; return v; }

extern void (*callee)(A *a);

int main(int argc, char *argv[]) {
  A a;
  callee(&a);
  B b = getB();
  b.a = a.a;
  return 0;
}
```

`kcfi_anon_struct_b.c`:
```c
#include "kcfi_anon_struct.h"
void f(A *a) {
        a->b = a->a + 8;
}
void (*callee)(A *a) = f;
```

Compiling with
```sh
clang -fsanitize=kcfi kcfi_anon_struct_a.c kcfi_anon_struct_b.c
```

will produce an executable that fails with a KCFI hash mismatch.


This happens because the name mangling used to create the KCFI typeid hash uses '$_*id*' with a compilation-unique integer identifier in place of the anonymous struct. In compiling `kcfi_anon_struct_a.c`, `B` gets the identified `$_0` and `A` gets the identifier `$_1` so mangling the type for `callee` gets the string `_ZTSFvPV3$_1E`. In compiling `kcfi_anon_struct_b.c` there's no definition of `B` so `A` gets theidentified `$_0` and so the mangled type for `callee` is `_ZTSFvPV3$_0E`, the typeid hashes differ between `main()` and `f()` and a trap is hit when it's executed.

When there's an *unqualified* typedef of an anonymous struct, say
```c
typedef struct { int a; int b; } A;
```
the type name is used in the mangled name, retrieved by `TagDecl::getTypedefNameForAnonDecl()`. Qualified types fail the hasExtInfo() check here and so return `nullptr`.

Presumably the same issue exists if anonymous structs are used without any typedef.
</pre>
<img width="1px" height="1px" alt="" src="http://email.email.llvm.org/o/eJysVt1u4zYTfRr6ZhCDofynC1_IcQwsPuDDFg1aoDcBRY0kdinSS1JO3KcvhpJiZ5Nmg6KAIVPiaOacMz-UDEE3FnHLlju23M9kH1vnt6rDWemq8_bOdUdttG0gtgi1M8Y90V2tDQZ40rEFtuI3dZBWR_0Xsmz_TdWarTiglaXBCrRVzntU0ZxByT5gAAn_uzt8gZN2RkbtLBN34Cyo3nu0kTx2UltyIgM8oTH0b8ypu12xrGB8z_h0XXGK9yits48h-l7FectW_GK24sNPDffxfMQKazil0AZheAnYegfaRpAsGxYlLdh6DwXLdj_4-gmCRzlX_y2G3QWDyLRVpq8QmBDvcBfiGt0OGow7JjZM5Mn_Dk7Asn1ac9KdUwCK4zH23sJpjHntBZ8j0pbTFSRfhZLGIDKRM7EpgIlC0voFZLoSg5RHsUmsfKMooGqlT2_45jRU3YhteAugSAJMd1OkDROrV0EAdlAmLheKV5vlXKZNOb_2NpLkF6gvTD-b3PLj5H46QUnN-lq_iwiM5_KGZfcDv7SUwMQONm-B_ywryUX9cRFf2pxa-gfDMD5QRtoG3vQ6vFf-bx-SbP8M4EkbA0fvql4hSAv4jKqPNEAgtjJCLbUZ5804PFoZWuh06GRU7fxV0tL1odUBWnk8og1QYpo8aYhZ2SF00jaJbx-wguhAeZRxMEjuqUd1NURJM4uJNROLRyYKXTFRMLGe4KgkXhpkN73V33uk5sUGPegKbdS1pqWFo5EKwdUpCmlz7lwfxu6fwxc7uiJcH4wVcUe7OxqPDcaQvL0EqiCZLB55Gp823Rfv2_rJ9pb2g7uoQmakANQuGY2Fde0lRD_ifPzj4dfD6etvWXJ1z1b8E1yGLiJPHplYB7AOKqw1lZazJNLEMbg3FD5gG1xCl5hQZt8locMb3Px-lHaiPiYfA1S6rtFDifEJ0b6cTsPAuYhcv34iIXp5pFCtjvDUogUdE9OhtrF6VbS_k8FFDWmpfXv7vZcmEWWigOnccDXt_1hABD7I88dHzr8_7V5KIvWPDkPnaPtKbtojHB6j13jCCsozafMgmz0qQ0MzKxqMDwOc_8sOD84X1tm0PQk4h18m3ilmSP2fIrUy3D_HL7Z246GmWlTfgISb8j_OeLbitjfmGD15vNb6q8fQd7I056GSB0KhR8BnHWIAXb9RN4D0OHCmtnd9BGnPU0rms2qbVXmWyxlub9dikS-zJc9m7Vbydc5xvdnIepFhna1Q8KXKq8UiW_B6iTO9FVws-Ebkt-vFkt_OpahKtc6zLK-XG1wgW3DspDZz-gCaO9_MEtbtLV8t82xmZIkmpO83IdKIphNmuZ_5Lb1wU_ZNYAtuiNjFRdTRpI--4Y3l_p2hOn3gvSOFreD7qwxVWIdZ7822jfEYKM_iwMSh0bHty7lyHRMHCj7-3Ry9-xOpZg-JTGDiMPI5bcXfAQAA__-6yzn0">