filamat: fix ubsan failure (#8461)
Enabling UBSan shows the following error: SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior filamat/src/eiff/Flattener.h:102:17 in filamat/src/eiff/Flattener.h:102:17: runtime error: applying non-zero offset 8 to null pointer We reference a placeholder byte on the heap when in DryRunner mode to workaround this issue.
This commit is contained in:
@@ -34,44 +34,54 @@
|
||||
|
||||
using namespace utils;
|
||||
|
||||
namespace {
|
||||
constexpr uint8_t FAKE_DRY_RUNNER_START_ADDR = 0x1;
|
||||
} // anonymous
|
||||
|
||||
namespace filamat {
|
||||
|
||||
class Flattener {
|
||||
public:
|
||||
explicit Flattener(uint8_t* dst) : mCursor(dst), mStart(dst){}
|
||||
|
||||
// DryRunner is used to compute the size of the flattened output but not actually carry out
|
||||
// flattening. If we set mStart = nullptr and mEnd=nullptr, we would hit an error about
|
||||
// offsetting on null when ubsan is enabled. Instead we point mStart to a fake address, and
|
||||
// mCursor is offset from that.
|
||||
static Flattener& getDryRunner() {
|
||||
static Flattener dryRunner = Flattener(nullptr);
|
||||
dryRunner.mStart = nullptr;
|
||||
dryRunner.mCursor = nullptr;
|
||||
dryRunner.mStart = (uint8_t*) FAKE_DRY_RUNNER_START_ADDR;
|
||||
dryRunner.mCursor = (uint8_t*) FAKE_DRY_RUNNER_START_ADDR;
|
||||
dryRunner.mOffsetPlaceholders.clear();
|
||||
dryRunner.mSizePlaceholders.clear();
|
||||
dryRunner.mValuePlaceholders.clear();
|
||||
return dryRunner;
|
||||
}
|
||||
|
||||
bool isDryRunner() { return mStart == nullptr;}
|
||||
bool isDryRunner() {
|
||||
return mStart == (uint8_t*) FAKE_DRY_RUNNER_START_ADDR;
|
||||
}
|
||||
|
||||
size_t getBytesWritten() {
|
||||
return mCursor - mStart;
|
||||
}
|
||||
|
||||
void writeBool(bool b) {
|
||||
if (mStart != nullptr) {
|
||||
if (!isDryRunner()) {
|
||||
mCursor[0] = static_cast<uint8_t>(b);
|
||||
}
|
||||
mCursor += 1;
|
||||
}
|
||||
|
||||
void writeUint8(uint8_t i) {
|
||||
if (mStart != nullptr) {
|
||||
if (!isDryRunner()) {
|
||||
mCursor[0] = i;
|
||||
}
|
||||
mCursor += 1;
|
||||
}
|
||||
|
||||
void writeUint16(uint16_t i) {
|
||||
if (mStart != nullptr) {
|
||||
if (!isDryRunner()) {
|
||||
mCursor[0] = static_cast<uint8_t>( i & 0xff);
|
||||
mCursor[1] = static_cast<uint8_t>((i >> 8) & 0xff);
|
||||
}
|
||||
@@ -79,7 +89,7 @@ public:
|
||||
}
|
||||
|
||||
void writeUint32(uint32_t i) {
|
||||
if (mStart != nullptr) {
|
||||
if (!isDryRunner()) {
|
||||
mCursor[0] = static_cast<uint8_t>( i & 0xff);
|
||||
mCursor[1] = static_cast<uint8_t>((i >> 8) & 0xff);
|
||||
mCursor[2] = static_cast<uint8_t>((i >> 16) & 0xff);
|
||||
@@ -89,7 +99,7 @@ public:
|
||||
}
|
||||
|
||||
void writeUint64(uint64_t i) {
|
||||
if (mStart != nullptr) {
|
||||
if (!isDryRunner()) {
|
||||
mCursor[0] = static_cast<uint8_t>( i & 0xff);
|
||||
mCursor[1] = static_cast<uint8_t>((i >> 8) & 0xff);
|
||||
mCursor[2] = static_cast<uint8_t>((i >> 16) & 0xff);
|
||||
@@ -104,7 +114,7 @@ public:
|
||||
|
||||
void writeString(const char* str) {
|
||||
size_t const len = strlen(str);
|
||||
if (mStart != nullptr) {
|
||||
if (!isDryRunner()) {
|
||||
strcpy(reinterpret_cast<char*>(mCursor), str);
|
||||
}
|
||||
mCursor += len + 1;
|
||||
@@ -112,7 +122,7 @@ public:
|
||||
|
||||
void writeString(std::string_view str) {
|
||||
size_t const len = str.length();
|
||||
if (mStart != nullptr) {
|
||||
if (!isDryRunner()) {
|
||||
memcpy(reinterpret_cast<char*>(mCursor), str.data(), len);
|
||||
mCursor[len] = 0;
|
||||
}
|
||||
@@ -121,14 +131,14 @@ public:
|
||||
|
||||
void writeBlob(const char* blob, size_t nbytes) {
|
||||
writeUint64(nbytes);
|
||||
if (mStart != nullptr) {
|
||||
if (!isDryRunner()) {
|
||||
memcpy(reinterpret_cast<char*>(mCursor), blob, nbytes);
|
||||
}
|
||||
mCursor += nbytes;
|
||||
}
|
||||
|
||||
void writeRaw(const char* raw, size_t nbytes) {
|
||||
if (mStart != nullptr) {
|
||||
if (!isDryRunner()) {
|
||||
memcpy(reinterpret_cast<char*>(mCursor), raw, nbytes);
|
||||
}
|
||||
mCursor += nbytes;
|
||||
@@ -136,7 +146,7 @@ public:
|
||||
|
||||
void writeSizePlaceholder() {
|
||||
mSizePlaceholders.push_back(mCursor);
|
||||
if (mStart != nullptr) {
|
||||
if (!isDryRunner()) {
|
||||
mCursor[0] = 0;
|
||||
mCursor[1] = 0;
|
||||
mCursor[2] = 0;
|
||||
@@ -164,7 +174,7 @@ public:
|
||||
mSizePlaceholders.pop_back();
|
||||
// -4 to account for the 4 bytes we are about to write.
|
||||
uint32_t const size = static_cast<uint32_t>(mCursor - dst - 4);
|
||||
if (mStart != nullptr) {
|
||||
if (!isDryRunner()) {
|
||||
dst[0] = static_cast<uint8_t>( size & 0xff);
|
||||
dst[1] = static_cast<uint8_t>((size >> 8) & 0xff);
|
||||
dst[2] = static_cast<uint8_t>((size >> 16) & 0xff);
|
||||
@@ -175,7 +185,7 @@ public:
|
||||
|
||||
void writeOffsetplaceholder(size_t index) {
|
||||
mOffsetPlaceholders.insert(std::pair<size_t, uint8_t*>(index, mCursor));
|
||||
if (mStart != nullptr) {
|
||||
if (!isDryRunner()) {
|
||||
mCursor[0] = 0x0;
|
||||
mCursor[1] = 0x0;
|
||||
mCursor[2] = 0x0;
|
||||
@@ -185,7 +195,7 @@ public:
|
||||
}
|
||||
|
||||
void writeOffsets(uint32_t forIndex) {
|
||||
if (mStart == nullptr) {
|
||||
if (isDryRunner()) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -209,7 +219,7 @@ public:
|
||||
|
||||
void writeValuePlaceholder() {
|
||||
mValuePlaceholders.push_back(mCursor);
|
||||
if (mStart != nullptr) {
|
||||
if (!isDryRunner()) {
|
||||
mCursor[0] = 0;
|
||||
mCursor[1] = 0;
|
||||
mCursor[2] = 0;
|
||||
@@ -228,7 +238,7 @@ public:
|
||||
|
||||
uint8_t* dst = mValuePlaceholders.back();
|
||||
mValuePlaceholders.pop_back();
|
||||
if (mStart != nullptr) {
|
||||
if (!isDryRunner()) {
|
||||
dst[0] = static_cast<uint8_t>( v & 0xff);
|
||||
dst[1] = static_cast<uint8_t>((v >> 8) & 0xff);
|
||||
dst[2] = static_cast<uint8_t>((v >> 16) & 0xff);
|
||||
|
||||
Reference in New Issue
Block a user