<table border="1" cellspacing="0" cellpadding="8">
<tr>
<th>Issue</th>
<td>
<a href=https://github.com/llvm/llvm-project/issues/86647>86647</a>
</td>
</tr>
<tr>
<th>Summary</th>
<td>
Undefined behavior in `CastInfo::castFailed` with `From=<MLIR interface>`
</td>
</tr>
<tr>
<th>Labels</th>
<td>
mlir
</td>
</tr>
<tr>
<th>Assignees</th>
<td>
</td>
</tr>
<tr>
<th>Reporter</th>
<td>
ingomueller-net
</td>
</tr>
</table>
<pre>
I observed a `TypeSwitch` taking the "wrong" case in the snippet below:
```cpp
llvm::TypeSwitch<ExpressionOpInterface, int>(op)
.Case<FieldReferenceOp, LiteralOp>([&](auto op) {
llvm::errs() << __PRETTY_FUNCTION__ << "\n";
op.dump();
return 42;
})
```
which produced the following output during [CI on Github](https://github.com/iree-org/iree-llvm-sandbox/actions/runs/8374812356/job/22930857368):
```cpp
int (anonymous namespace)::exportOperation(mlir::substrait::FieldReferenceOp)
%2 = substrait.literal -1 : si1
```
The line with `__PRETTY_FUNCTION__` shows that we are in the `FieldReferenceOp` case but the op printed is actually a `literal`/`LiteralOp`, so the `TypeSwitch` entered the wrong case.
Curiously, this works fine on my local machine (using Clang 14, 15, and 17) but fails consistently on CI (using Clang 14, 15, and 17).
After a lot of printf debugging, I think that I found what the problem is: Eventually, `CastInfo::castFailed` is called when we try a case that doesn't correspond to the runtime type of the argument.
```cpp
static inline CastReturnType castFailed() {
return CastReturnType(nullptr);
}
```
The problem is that `CastReturnType` at this point is `const ExpressionOpInterface &`. Notice the `&`! So we seem to create a *reference* to `nullptr` and then return that. Indeed, if I compile with ASan and UBsan, I get this in CI:
```
==21930==ERROR: AddressSanitizer: stack-use-after-return on address 0x7fef0de7fb20 at pc 0x7fef2d7c165c bp 0x7fffb4ebd190 sp 0x7fffb4ebd188
READ of size 8 at 0x7fef0de7fb20 thread T0
#0 0x7fef2d7c165b in llvm::TypeSwitch<mlir::substrait::ExpressionOpInterface, mlir::FailureOr<std::unique_ptr<substrait::proto::Expression, std::default_delete<substrait::proto::Expression>>>>& llvm::TypeSwitch<mlir::substrait::ExpressionOpInterface, mlir::FailureOr<std::unique_ptr<substrait::proto::Expression, std::default_delete<substrait::proto::Expression>>>>::Case<mlir::substrait::FieldReferenceOp, (anonymous namespace)::exportOperation(mlir::substrait::ExpressionOpInterface)::$_0&>((anonymous namespace)::exportOperation(mlir::substrait::ExpressionOpInterface)::$_0&) /home/runner/work/iree-llvm-sandbox/iree-llvm-sandbox/sandbox/third_party/llvm-project/llvm/include/llvm/ADT/TypeSwitch.h:151:[26](https://github.com/iree-org/iree-llvm-sandbox/actions/runs/8391967477/job/22983497415#step:13:27)
...
```
Curiously, again, the sanitizers don't complain on my local machine.
I am not 100% sure whether my understanding of the code above returning a local reference is actually correct, but in the following, less templated code, I do get a warning:
```cpp
using CastReturnType = const ExpressionOpInterface &;
auto castFailed = []() -> CastReturnType {
return CastReturnType(nullptr);
// ^~~~~~~
// warning: returning reference to local temporary object [-Wreturn-stack-address]
};
```
As a simple work-around, I changed the original code to use `TypeSwitch<Operation *, int>` instead of `TypeSwitch<ExpressionOpInterface, int>`, for which `CastReturnType` is a pointer type that is value constructed from `nullptr`, which works fine.
However, I find the current behavior extremely dangerous. If using `TypeSwitch<ExpressionOpInterface, int>` isn't expected to work, I think there should be a mechanism that prevents compilation with those arguments.
</pre>
<img width="1px" height="1px" alt="" src="http://email.email.llvm.org/o/eJzkWEtv47oV_jXM5iCGRFl-LLzwKHFr4HZSZDIougoo6cjiHYpUSSqO76K_vTik_MokM_cWF93UCBKL4jk87-9jhHNypxFXLP_E8rsbMfjW2JXUO9MNqBTaW43-pjT1YbUFUzq0L1iDADZLng49ftlLX7VsloAX36TegW8RGOd7a_SOcQ6VcAhSh3WnZd-jhxKV2bNszZI7lhx_z5L4U_V9XFHqpaNN2frioKy4f-0tOieNfui32qNtRIWMFyC1Z9k94wvTM76MOmBSCIcsKzYSVf2IDVrUFT70JPCL9GiFeuijGEWAz1h-x_hCDN5A0ANs_mnUFT5nq9BaR2K0JytYVsDz898f75-e_vm8-fq5eNo-fH5-Pr5inLO80PQnu9Jn-kk9dH1U9OadRT9YDdMLGTa_Ozl3CtllHPetrFroramHCusQ9sYoZfaUHDP4fvBQD5aeWP6p2ILR8Bfp26GMnrfe944c5BvGN7vwZlKZjvGNtIi3xu6OXykUt07oujSvjG9E5aXRjvGNHcKfRTafLlKe5TPGN7-akvEN58ssWeTzbBbd_UkJSO2BsqGNPnRmcKBFh64PCV-OWXjtjfUPPVpBxzO-6JS08Z0bSuetkD4-fl8Dx0DynAPL7uAkMFGxNuA2BZatwcn0BzF_ahGU1Ah76VvqjHcKgVrEtWbvwLfCwx5B2FNjsFnynXGzJPZOOfiwx_TQW6k91iAdiMoPQqlD7MTRWjKLb9gsOVc2rRTgzPGY655F6p-xSkLHhiMnl74Vg5VmcOpAenwrHeyN_eagIX-Nhu4AylRCQSeqltYYXwyOyqtQQu8gnZJgmtNvoWtI59Qw5FQjpHJQGe2k86i9OpC-Yvu7NFzZuG48WhCgjAfTxDA1UGM57HaSxlABW7Jdf4vB30JjBl3Dnh7I996aUmEHkiof7l9Qx-iSJJslhXB-qxsTy6gSzm-EVFhTCKWDSiiFpA015dVbykrIXTitNug043MPlbEWXW90DT5mxA7ayw7BH3ok02lN2N3QofaTH_eG88LLCqQOlUcmPoZxQRmGCxvHCXWaYuNQuRZgfKEHpXpvL6cQDZsfV_05cNHXMVgXimcJhCBLB72hfpaOdlHaPbw7y4Gm8CyZwGfjZYXHyo2rjKfwxVCYHWJHYawsCo_UB3xtj_3D-JresVlydIvs0KHS9TEEZPEEtrpGClMBsoEtVKbrpRpbef1F6CD29ZMTOtbRDkd3JBXrRyNsfMzuWHbH02WWxK_3j48Pj1Rj67omz78ILb38DW0YMl5U324Hh7eCCvp2NNNoEHE3JK_zBpukxnlT8hDYvhoXeT2v0lleQdmHlaYpp1jW6TIBd72yWETjHu_Xd1RzTv6GsCBlb9T71qKo4Sk5YxLjWXJ9YElx-ACqP5zEH2L4WYKqd7D4YFlWOF_HxUHLfw34TPnMijc6e2u8eas-DL-jdI2NGJR_rlGhx9-rIbs___DZ_42r4d1Inv4AohZ_Il5_ELpREePT5zAUInn7X59KM5VvWtNhJDwaLeMbwsYP6NF7a-dvvpW2fu6F9QfGN2Fbb82vWPnxkTToSg01nhfWd0-Mb851OGlZtk7zlOzMPx257J_K6JbpcjafzueXjG6RTZfzKQF05jz2ZEPGsjWfnwjWZDL5AZBcUQyxE1JHroHgjuPRQW2OGNr1Skj9Hve4QswtiA608ZAmCeM5uMEiYbRv0ZLkoGu0zgtdB2YcsbcyNYIozQuOIEHvxHjKCV2uCFgAdUpTEVjNyOhOnJvWFc1uj2Q40Tc6JGJJbQKcCNiLcNRPCfHIi67Bnpjrz_D0COnhYnNmB0E2Xv1GonDLsvvvDvivyEMoN3j3w_L7f4fP1dZzEC6Cfw66N2MeKJLGCnsAU1KHkAO3_4gitxFER8Akt05M5mTYezW4diDAya4n6Df2262wRBFjmqpW6N1Ik42VO6mFiqXiDQzuLbHOitOgIVJycTclvqidJ1Q1zXdSP7vZRi7fGAvxkvcu2aLSjEwLbaSVgZhJBy9CDRgLxQ4VFWJjTXfNkeiAqPzM8q-66q9mjy806igujYyMCqrBWtR0sW_FizQW8NVb7FAdoKbQWTO4CWwbiPX7xx0HOVJofO0x2O4NxGF7ye3RIl2yBlVDSZSwQ0qddF0MQm-RqL0bSV7MUCB6vjXuzLzd6PJNvcrqZbYUN7hK52k6nc6n6fKmXWX1YprkecPzNBV5tUzLRTavUt7M6nJei-pGrnjCp0nGZ2mSZNlykizzLM-bplrmTT7PkE0T7IRUExq5E2N3N9K5AVeL2Ww6v1GiROXC_2Q4D0jFOcvvbuwqTOhy2Dk2TZR03p0VeOkVrr7qGilr9TkZUv_sEnO8t26s6QJRLf72y_YR5CkXIQk3g1WrH6DJiEpvwCv4FcCDXPtPAAAA__-SetSh">