Skip to content

Commit

Permalink
Merge pull request #73 from kaitai-io/fix-strict-aliasing-violations
Browse files Browse the repository at this point in the history
read_f{4,8}{be,le}(): fix violations of strict aliasing rules
  • Loading branch information
GreyCat authored Jun 3, 2024
2 parents 25ea924 + c01f530 commit 2831b0e
Show file tree
Hide file tree
Showing 3 changed files with 66 additions and 5 deletions.
11 changes: 10 additions & 1 deletion Common.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -13,5 +13,14 @@ endif()
# This method was taken from https://www.pragmaticlinux.com/2022/07/enable-compiler-warnings-with-cmake/
target_compile_options(${PROJECT_NAME} PRIVATE
$<$<CXX_COMPILER_ID:MSVC>:/W4 /WX>
$<$<NOT:$<CXX_COMPILER_ID:MSVC>>:-Wall -Wextra -Wpedantic -Werror>
$<$<NOT:$<CXX_COMPILER_ID:MSVC>>:
-Wall -Wextra -Wpedantic -Werror
# See <https://gcc.gnu.org/onlinedocs/gcc/Warning-Options.html#index-Wstrict-aliasing_003dn>:
#
# > Level 1: (...) it has very few false negatives. However, it has many false positives.
#
# If we encounter into false positives in the future, we can increase the level, but let's
# start with the most aggressive option to make sure we don't miss anything.
-fstrict-aliasing -Wstrict-aliasing=1
>
)
55 changes: 51 additions & 4 deletions kaitai/kaitaistream.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,57 @@
#include <byteswap.h>
#endif

#include <cstring> // std::memcpy
#include <iostream>
#include <vector>
#include <stdexcept>

#ifdef KAITAI_STREAM_H_CPP11_SUPPORT
#include <type_traits> // std::enable_if, std::is_trivially_copyable, std::is_trivially_constructible

// Taken from https://en.cppreference.com/w/cpp/numeric/bit_cast#Possible_implementation
// (only adjusted for C++11 compatibility)
template<class To, class From>
typename std::enable_if<
sizeof(To) == sizeof(From) &&
std::is_trivially_copyable<From>::value &&
std::is_trivially_copyable<To>::value,
To
>::type
// constexpr support needs compiler magic
static bit_cast(const From &src) noexcept
{
static_assert(std::is_trivially_constructible<To>::value,
"This implementation additionally requires "
"destination type to be trivially constructible");

To dst;
std::memcpy(&dst, &src, sizeof(To));
return dst;
}
#else
// The following implementation of `StaticAssert` was inspired by https://stackoverflow.com/a/6765840

// empty default template
template <bool b>
struct StaticAssert;

// template specialized on true
template <>
struct StaticAssert<true> {};

template<class To, class From>
To
static bit_cast(const From &src)
{
StaticAssert<sizeof(To) == sizeof(From)>();

To dst;
std::memcpy(&dst, &src, sizeof(To));
return dst;
}
#endif

kaitai::kstream::kstream(std::istream *io) {
m_io = io;
init();
Expand Down Expand Up @@ -263,7 +310,7 @@ float kaitai::kstream::read_f4be() {
#if __BYTE_ORDER == __LITTLE_ENDIAN
t = bswap_32(t);
#endif
return reinterpret_cast<float &>(t);
return bit_cast<float>(t);
}

double kaitai::kstream::read_f8be() {
Expand All @@ -272,7 +319,7 @@ double kaitai::kstream::read_f8be() {
#if __BYTE_ORDER == __LITTLE_ENDIAN
t = bswap_64(t);
#endif
return reinterpret_cast<double &>(t);
return bit_cast<double>(t);
}

// ........................................................................
Expand All @@ -285,7 +332,7 @@ float kaitai::kstream::read_f4le() {
#if __BYTE_ORDER == __BIG_ENDIAN
t = bswap_32(t);
#endif
return reinterpret_cast<float &>(t);
return bit_cast<float>(t);
}

double kaitai::kstream::read_f8le() {
Expand All @@ -294,7 +341,7 @@ double kaitai::kstream::read_f8le() {
#if __BYTE_ORDER == __BIG_ENDIAN
t = bswap_64(t);
#endif
return reinterpret_cast<double &>(t);
return bit_cast<double>(t);
}

// ========================================================================
Expand Down
5 changes: 5 additions & 0 deletions kaitai/kaitaistream.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,11 @@
// Kaitai Struct runtime API version: x.y.z = 'xxxyyyzzz' decimal
#define KAITAI_STRUCT_VERSION 11000L

// check for C++11 support - https://stackoverflow.com/a/40512515
#if __cplusplus >= 201103L || (defined(_MSC_VER) && _MSC_VER >= 1900)
#define KAITAI_STREAM_H_CPP11_SUPPORT
#endif

#include <istream>
#include <sstream>
#include <stdint.h>
Expand Down

0 comments on commit 2831b0e

Please sign in to comment.