diff options
author | Kieran Bingham <kieran.bingham@ideasonboard.com> | 2020-02-18 12:51:14 +0000 |
---|---|---|
committer | Kieran Bingham <kieran.bingham@ideasonboard.com> | 2020-02-19 10:21:21 +0000 |
commit | 90240a79506a3c400f3af4cb0b08746ae87c79e2 (patch) | |
tree | f71cf819bb96187e5ddb2aaed7d8da71ce02e674 /include/linux/media-bus-format.h | |
parent | b5eff18f1aef980fa7eb55184996710a6fc9523e (diff) |
libcamera: media_device: prevent sign extension on casts
The conversion of pointers to integers is implementation defined and
differs between g++ and clang++ when utilising a uint64_t type.
#include <iostream>
int main(int argc, char **argv)
{
void *ptr = reinterpret_cast<void *>(0xf1234567);
uint64_t u64 = reinterpret_cast<uint64_t>(ptr);
uint64_t uint64 = reinterpret_cast<uintptr_t>(ptr);
std::cout << "ptr " << ptr
<< " ptr -> u64 0x" << std::hex << u64
<< " ptr -> uintptr_t -> u64 0x" << std::hex << uint64
<< std::endl;
return 0;
}
When compiled with g++ for a 32-bit platform produces the following
unexpected output:
ptr 0xf1234567 ptr -> u64 0xfffffffff1234567 ptr -> uintptr_t -> u64 0xf1234567
The standards states:
"A pointer can be explicitly converted to any integral type large enough
to hold all values of its type. The mapping function is
implementation-defined. [Note: It is intended to be unsurprising to
those who know the addressing structure of the underlying machine. — end
note]"
And as such the g++ implementation appears to be little more surprising
than expected in this situation.
The MediaDevice passes pointers to the kernel via the struct
media_v2_topology in which pointers are cast using a uint64 type (__u64),
which is affected by the sign extension described above when BIT(32) is
set and causes an invalid address to be given to the kernel.
Ensure that we cast using uintptr_t which is not affected by the sign
extension issue.
Signed-off-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
Diffstat (limited to 'include/linux/media-bus-format.h')
0 files changed, 0 insertions, 0 deletions