Undefined behavior in ClientWithAsyncTemplateMethods constructor
- Dominant language
- C++
- Stars
- 2.2k
- Forks
- 1.2k
- Avg merge
- 3d 14h
- Merged PRs (30d)
- 12
Description
### Describe the bug
`ClientWithAsyncTemplateMethods` has the following constructor:
https://github.com/aws/aws-sdk-cpp/blob/08f5335f43eabe4a3d7fb5454c655e7b86630b4d/src/aws-cpp-sdk-core/include/aws/core/client/AWSClientAsyncCRTP.h#L47-L56
The `static_cast(this)` is meant to cast the base `this` pointer to the corresponding derived `this` pointer (which can have a different address when multiple inheritance is involved).
The problem, though, is that it happens in the base class *constructor*, so the derived object is not yet constructed yet. And, therefore, the `static_cast` to the derived `this` is undefined behavior.
This is flagged by some of the UBSan builds in Apache Arrow:
https://github.com/apache/arrow/issues/46863
```
Start test: S3FileSystem
/var/folders/x7/ch5v91h56_zbvbd1y2f600dm0000gn/T/RtmpjRMkwO/file8951246f6d2e/_deps/aws-sdk-cpp-src/src/aws-cpp-sdk-core/include/aws/core/client/AWSClientAsyncCRTP.h:51:40: runtime error: downcast of address 0x61b00011cd98 which does not point to an object of type 'Aws::S3::S3Client'
0x61b00011cd98: note: object is of type 'Aws::Client::AWSXMLClient'
00 00 00 00 b0 eb b9 28 01 00 00 00 75 73 2d 65 61 73 74 2d 31 00 e6 8b 01 00 00 00 00 00 00 00
^~~~~~~~~~~~~~~~~~~~~~~
vptr for 'Aws::Client::AWSXMLClient'
#0 0x0001245e7770 in Aws::Client::ClientWithAsyncTemplateMethods::ClientWithAsyncTemplateMethods()+0x1f0 (arrow.so:arm64+0x701f770)
#1 0x0001245ebe10 in Aws::S3::S3Client::S3Client(std::__1::shared_ptr const&, std::__1::shared_ptr>, Aws::S3::S3ClientConfiguration const&)+0x310 (arrow.so:arm64+0x7023e10)
```
### Regression Issue
- [ ] Select this option if this issue appears to be a regression.
### Expected Behavior
Undefined behavior should not occur when constructing S3Client.
### Current Behavior
Undefined behavior is detected when constructing S3Client. See detailed messages above.
### Reproduction Steps
The Apache Arrow CI job is too complicated to describe here, sorry.
### Possible Solution
A possible solution would be to pass the derived pointer explicitly to the `ClientWithAsyncTemplateMethods` constructor, so that no `static_cast` is required.
```c++
ClientWithAsyncTemplateMethods(AwsServiceClientT* derived)
: m_isInitialized(true),
m_operationsProcessed(0)
{
Aws::Utils::ComponentRegistry::RegisterComponent(AwsServiceClientT::GetServiceName(),
derived,
&AwsServiceClientT::ShutdownSdkClient);
}
```
### Additional Information/Context
_No response_
### AWS CPP SDK version used
1.11.594
### Compiler and Version used
-
### Operating System and version
-
Contributor guide
Assessment
This issue has not been assessed yet.