From 2707880f1b486f2a2f87d7e2de7baea12c6ca362 Mon Sep 17 00:00:00 2001 From: Ryan Macnak Date: Thu, 7 May 2020 19:40:18 +0000 Subject: [PATCH] [vm] Fix various UBSan failures. Bug: https://github.com/dart-lang/sdk/issues/39427 Change-Id: I74e0eee623d88005fb2893d03e284a87daa09260 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/146696 Reviewed-by: Alexander Markov Commit-Queue: Ryan Macnak --- runtime/bin/file_android.cc | 2 +- runtime/bin/file_fuchsia.cc | 2 +- runtime/bin/file_linux.cc | 2 +- runtime/bin/hashmap_test.cc | 8 +-- runtime/bin/process_test.cc | 11 +++- runtime/lib/double.cc | 4 +- runtime/platform/globals.h | 32 +---------- runtime/platform/growable_array.h | 3 + runtime/platform/safe_stack.h | 2 - runtime/platform/unaligned.h | 43 +++++++++++++++ .../platform/undefined_behavior_sanitizer.h | 20 +++++++ runtime/platform/unicode.h | 5 +- runtime/platform/utils.h | 14 ++--- runtime/vm/code_patcher_ia32.cc | 16 +++--- .../vm/compiler/assembler/assembler_base.cc | 2 +- .../vm/compiler/assembler/assembler_base.h | 19 +++++++ runtime/vm/compiler/assembler/disassembler.cc | 3 +- .../vm/compiler/assembler/disassembler_x86.cc | 55 +++++++++++-------- runtime/vm/compiler/backend/locations.cc | 3 +- runtime/vm/compiler/backend/locations.h | 2 +- runtime/vm/compiler/backend/range_analysis.cc | 2 +- .../frontend/kernel_translation_helper.h | 2 +- runtime/vm/dart_api_message.cc | 14 ++++- runtime/vm/dart_api_message.h | 2 - runtime/vm/datastream.h | 19 +++++-- runtime/vm/exceptions.h | 6 +- runtime/vm/flags.cc | 2 +- runtime/vm/heap/pages.cc | 14 +++-- runtime/vm/instructions_x64.cc | 6 +- runtime/vm/instructions_x64.h | 13 +++-- runtime/vm/kernel_binary.h | 6 +- runtime/vm/memory_region.h | 6 ++ runtime/vm/object.cc | 23 ++++---- runtime/vm/object.h | 4 +- runtime/vm/object_reload.cc | 3 +- runtime/vm/profiler.cc | 12 ++-- runtime/vm/raw_object.h | 8 +++ runtime/vm/snapshot.h | 2 +- runtime/vm/stack_frame.cc | 9 ++- tools/bots/test_matrix.json | 22 ++++---- tools/gn.py | 6 ++ 41 files changed, 278 insertions(+), 151 deletions(-) create mode 100644 runtime/platform/unaligned.h create mode 100644 runtime/platform/undefined_behavior_sanitizer.h diff --git a/runtime/bin/file_android.cc b/runtime/bin/file_android.cc index 51a7599ecbf..15352c0cb6f 100644 --- a/runtime/bin/file_android.cc +++ b/runtime/bin/file_android.cc @@ -484,7 +484,7 @@ int64_t File::LengthFromPath(Namespace* namespc, const char* name) { static void MillisecondsToTimespec(int64_t millis, struct timespec* t) { ASSERT(t != NULL); t->tv_sec = millis / kMillisecondsPerSecond; - t->tv_nsec = (millis - (t->tv_sec * kMillisecondsPerSecond)) * 1000L; + t->tv_nsec = (millis % kMillisecondsPerSecond) * 1000L; } void File::Stat(Namespace* namespc, const char* name, int64_t* data) { diff --git a/runtime/bin/file_fuchsia.cc b/runtime/bin/file_fuchsia.cc index 354dd65eb92..39d667b92b7 100644 --- a/runtime/bin/file_fuchsia.cc +++ b/runtime/bin/file_fuchsia.cc @@ -480,7 +480,7 @@ static int64_t TimespecToMilliseconds(const struct timespec& t) { static void MillisecondsToTimespec(int64_t millis, struct timespec* t) { ASSERT(t != NULL); t->tv_sec = millis / kMillisecondsPerSecond; - t->tv_nsec = (millis - (t->tv_sec * kMillisecondsPerSecond)) * 1000L; + t->tv_nsec = (millis % kMillisecondsPerSecond) * 1000L; } void File::Stat(Namespace* namespc, const char* name, int64_t* data) { diff --git a/runtime/bin/file_linux.cc b/runtime/bin/file_linux.cc index 16c17705dd3..dab296d3cfd 100644 --- a/runtime/bin/file_linux.cc +++ b/runtime/bin/file_linux.cc @@ -489,7 +489,7 @@ static int64_t TimespecToMilliseconds(const struct timespec& t) { static void MillisecondsToTimespec(int64_t millis, struct timespec* t) { ASSERT(t != NULL); t->tv_sec = millis / kMillisecondsPerSecond; - t->tv_nsec = (millis - (t->tv_sec * kMillisecondsPerSecond)) * 1000L; + t->tv_nsec = (millis % kMillisecondsPerSecond) * 1000L; } void File::Stat(Namespace* namespc, const char* name, int64_t* data) { diff --git a/runtime/bin/hashmap_test.cc b/runtime/bin/hashmap_test.cc index 307d21fe312..c30e87c2675 100644 --- a/runtime/bin/hashmap_test.cc +++ b/runtime/bin/hashmap_test.cc @@ -123,12 +123,12 @@ void TestSet(IntKeyHash hash, int size) { EXPECT_EQ(0u, set.occupancy()); // Insert a long series of values. - const int start = 453; - const int factor = 13; - const int offset = 7; + const uint32_t start = 453; + const uint32_t factor = 13; + const uint32_t offset = 7; const uint32_t n = size; - int x = start; + uint32_t x = start; for (uint32_t i = 0; i < n; i++) { EXPECT_EQ(i, set.occupancy()); set.Insert(x); diff --git a/runtime/bin/process_test.cc b/runtime/bin/process_test.cc index 3f4cd8fcfd6..f8fb36151df 100644 --- a/runtime/bin/process_test.cc +++ b/runtime/bin/process_test.cc @@ -6,6 +6,14 @@ #include #include +#if defined(__GNUC__) || defined(__Clang__) +__attribute__((no_sanitize("undefined"))) +#endif +void Crash() { + int* segfault = NULL; + *segfault = 1; +} + /* * Run ./process_test * : 0 = stdout, 1 = stderr, 2 = stdout and stderr @@ -32,8 +40,7 @@ int main(int argc, char* argv[]) { int crash = atoi(argv[4]); if (crash == 1) { - int* segfault = NULL; - *segfault = 1; + Crash(); } const int kLineSize = 128; diff --git a/runtime/lib/double.cc b/runtime/lib/double.cc index 471e41b250e..61b76a37d03 100644 --- a/runtime/lib/double.cc +++ b/runtime/lib/double.cc @@ -89,8 +89,8 @@ DEFINE_NATIVE_ENTRY(Double_hashCode, 0, 1) { if (FLAG_trace_intrinsified_natives) { OS::PrintErr("Double_hashCode %f\n", val); } - if (val >= static_cast(kMinInt64) && - val <= static_cast(kMaxInt64)) { + if ((val >= kMinInt64RepresentableAsDouble) && + (val <= kMaxInt64RepresentableAsDouble)) { int64_t ival = static_cast(val); if (static_cast(ival) == val) { return Integer::New(ival); diff --git a/runtime/platform/globals.h b/runtime/platform/globals.h index ac995f4ea1c..e11a833d637 100644 --- a/runtime/platform/globals.h +++ b/runtime/platform/globals.h @@ -459,6 +459,8 @@ const int32_t kMaxInt32 = 0x7FFFFFFF; const uint32_t kMaxUint32 = 0xFFFFFFFF; const int64_t kMinInt64 = DART_INT64_C(0x8000000000000000); const int64_t kMaxInt64 = DART_INT64_C(0x7FFFFFFFFFFFFFFF); +const int64_t kMinInt64RepresentableAsDouble = kMinInt64; +const int64_t kMaxInt64RepresentableAsDouble = DART_INT64_C(0x7FFFFFFFFFFFFC00); const uint64_t kMaxUint64 = DART_2PART_UINT64_C(0xFFFFFFFF, FFFFFFFF); const int64_t kSignBitDouble = DART_INT64_C(0x8000000000000000); @@ -636,36 +638,6 @@ inline D bit_copy(const S& source) { return destination; } -#if defined(HOST_ARCH_ARM) || defined(HOST_ARCH_ARM64) -// Similar to bit_copy and bit_cast, but does take the type from the argument. -template -static inline T ReadUnaligned(const T* ptr) { - T value; - memcpy(reinterpret_cast(&value), reinterpret_cast(ptr), - sizeof(value)); - return value; -} - -// Similar to bit_copy and bit_cast, but does take the type from the argument. -template -static inline void StoreUnaligned(T* ptr, T value) { - memcpy(reinterpret_cast(ptr), reinterpret_cast(&value), - sizeof(value)); -} -#else // !(HOST_ARCH_ARM || HOST_ARCH_ARM64) -// Similar to bit_copy and bit_cast, but does take the type from the argument. -template -static inline T ReadUnaligned(const T* ptr) { - return *ptr; -} - -// Similar to bit_copy and bit_cast, but does take the type from the argument. -template -static inline void StoreUnaligned(T* ptr, T value) { - *ptr = value; -} -#endif // !(HOST_ARCH_ARM || HOST_ARCH_ARM64) - // On Windows the reentrent version of strtok is called // strtok_s. Unify on the posix name strtok_r. #if defined(HOST_OS_WINDOWS) diff --git a/runtime/platform/growable_array.h b/runtime/platform/growable_array.h index 83deee8ece3..b604ea471b5 100644 --- a/runtime/platform/growable_array.h +++ b/runtime/platform/growable_array.h @@ -205,6 +205,9 @@ class BaseGrowableArray : public B { template inline void BaseGrowableArray::Sort(int compare(const T*, const T*)) { + // Avoid calling qsort with a null array. + if (length_ == 0) return; + typedef int (*CompareFunction)(const void*, const void*); qsort(data_, length_, sizeof(T), reinterpret_cast(compare)); } diff --git a/runtime/platform/safe_stack.h b/runtime/platform/safe_stack.h index 5a9bbebba7c..d6aa08f9344 100644 --- a/runtime/platform/safe_stack.h +++ b/runtime/platform/safe_stack.h @@ -5,8 +5,6 @@ #ifndef RUNTIME_PLATFORM_SAFE_STACK_H_ #define RUNTIME_PLATFORM_SAFE_STACK_H_ -#include "platform/globals.h" - #if defined(__has_feature) #if __has_feature(safe_stack) #define USING_SAFE_STACK diff --git a/runtime/platform/unaligned.h b/runtime/platform/unaligned.h new file mode 100644 index 00000000000..42f932b88ce --- /dev/null +++ b/runtime/platform/unaligned.h @@ -0,0 +1,43 @@ +// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +#ifndef RUNTIME_PLATFORM_UNALIGNED_H_ +#define RUNTIME_PLATFORM_UNALIGNED_H_ + +#include "platform/globals.h" +#include "platform/undefined_behavior_sanitizer.h" + +namespace dart { + +#if defined(HOST_ARCH_ARM) || defined(HOST_ARCH_ARM64) +template +static inline T LoadUnaligned(const T* ptr) { + T value; + memcpy(reinterpret_cast(&value), reinterpret_cast(ptr), + sizeof(value)); + return value; +} + +template +static inline void StoreUnaligned(T* ptr, T value) { + memcpy(reinterpret_cast(ptr), reinterpret_cast(&value), + sizeof(value)); +} +#else // !(HOST_ARCH_ARM || HOST_ARCH_ARM64) +template +NO_SANITIZE_UNDEFINED("alignment") +static inline T LoadUnaligned(const T* ptr) { + return *ptr; +} + +template +NO_SANITIZE_UNDEFINED("alignment") +static inline void StoreUnaligned(T* ptr, T value) { + *ptr = value; +} +#endif // !(HOST_ARCH_ARM || HOST_ARCH_ARM64) + +} // namespace dart + +#endif // RUNTIME_PLATFORM_UNALIGNED_H_ diff --git a/runtime/platform/undefined_behavior_sanitizer.h b/runtime/platform/undefined_behavior_sanitizer.h new file mode 100644 index 00000000000..68c6a92033c --- /dev/null +++ b/runtime/platform/undefined_behavior_sanitizer.h @@ -0,0 +1,20 @@ +// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +#ifndef RUNTIME_PLATFORM_UNDEFINED_BEHAVIOR_SANITIZER_H_ +#define RUNTIME_PLATFORM_UNDEFINED_BEHAVIOR_SANITIZER_H_ + +#if defined(__has_feature) +#if __has_feature(undefined_behavior_sanitizer) +#define USING_UNDEFINED_BEHAVIOR_SANITIZER +#endif +#endif + +#if defined(USING_UNDEFINED_BEHAVIOR_SANITIZER) +#define NO_SANITIZE_UNDEFINED(check) __attribute__((no_sanitize(check))) +#else +#define NO_SANITIZE_UNDEFINED(check) +#endif + +#endif // RUNTIME_PLATFORM_UNDEFINED_BEHAVIOR_SANITIZER_H_ diff --git a/runtime/platform/unicode.h b/runtime/platform/unicode.h index b784823e528..58338edb54a 100644 --- a/runtime/platform/unicode.h +++ b/runtime/platform/unicode.h @@ -7,6 +7,7 @@ #include "platform/allocation.h" #include "platform/globals.h" +#include "platform/unaligned.h" namespace dart { @@ -132,9 +133,9 @@ class Utf16 : AllStatic { // Returns the character at i and advances i to the next character // boundary. static int32_t Next(const uint16_t* characters, intptr_t* i, intptr_t len) { - int32_t ch = characters[*i]; + int32_t ch = LoadUnaligned(&characters[*i]); if (Utf16::IsLeadSurrogate(ch) && (*i < (len - 1))) { - int32_t ch2 = characters[*i + 1]; + int32_t ch2 = LoadUnaligned(&characters[*i + 1]); if (Utf16::IsTrailSurrogate(ch2)) { ch = Utf16::Decode(ch, ch2); *i += 1; diff --git a/runtime/platform/utils.h b/runtime/platform/utils.h index 6635fc34c5f..c64a062092e 100644 --- a/runtime/platform/utils.h +++ b/runtime/platform/utils.h @@ -215,7 +215,7 @@ class Utils { } static inline int64_t LowHighTo64Bits(uint32_t low, int32_t high) { - return (static_cast(high) << 32) | (low & 0x0ffffffffLL); + return (static_cast(high) << 32) | (low & 0x0ffffffffLL); } static inline constexpr bool IsAlphaNumeric(uint32_t c) { @@ -347,7 +347,7 @@ class Utils { "Unexpected uword size"); return std::numeric_limits::max(); } - return (1ll << n) - 1; + return (static_cast(1) << n) - 1; } static word SignedNBitMask(uint32_t n) { @@ -373,22 +373,22 @@ class Utils { static ValueType DecodeSLEB128(const uint8_t* data, const intptr_t data_length, intptr_t* byte_index) { + using Unsigned = typename std::make_unsigned::type; ASSERT(*byte_index < data_length); uword shift = 0; - ValueType value = 0; + Unsigned value = 0; uint8_t part = 0; do { part = data[(*byte_index)++]; - value |= static_cast(part & 0x7f) << shift; + value |= static_cast(part & 0x7f) << shift; shift += 7; } while ((part & 0x80) != 0); if ((shift < (sizeof(ValueType) * CHAR_BIT)) && ((part & 0x40) != 0)) { - using Unsigned = typename std::make_unsigned::type; const Unsigned kMax = std::numeric_limits::max(); - value |= static_cast(kMax << shift); + value |= static_cast(kMax << shift); } - return value; + return static_cast(value); } static char* StrError(int err, char* buffer, size_t bufsize); diff --git a/runtime/vm/code_patcher_ia32.cc b/runtime/vm/code_patcher_ia32.cc index 3c886ba9071..2c123dc96d5 100644 --- a/runtime/vm/code_patcher_ia32.cc +++ b/runtime/vm/code_patcher_ia32.cc @@ -5,6 +5,7 @@ #include "vm/globals.h" // Needed here to get TARGET_ARCH_IA32. #if defined(TARGET_ARCH_IA32) +#include "platform/unaligned.h" #include "vm/code_patcher.h" #include "vm/cpu.h" #include "vm/dart_entry.h" @@ -89,21 +90,18 @@ class InstanceCall : public UnoptimizedCall { #endif // DEBUG } - ObjectPtr data() const { return *reinterpret_cast(start_ + 1); } + ObjectPtr data() const { + return LoadUnaligned(reinterpret_cast(start_ + 1)); + } void set_data(const Object& data) const { - uword* cache_addr = reinterpret_cast(start_ + 1); - uword imm = static_cast(data.raw()); - *cache_addr = imm; + StoreUnaligned(reinterpret_cast(start_ + 1), data.raw()); } CodePtr target() const { - const uword imm = *reinterpret_cast(start_ + 6); - return static_cast(imm); + return LoadUnaligned(reinterpret_cast(start_ + 6)); } void set_target(const Code& target) const { - uword* target_addr = reinterpret_cast(start_ + 6); - uword imm = static_cast(target.raw()); - *target_addr = imm; + StoreUnaligned(reinterpret_cast(start_ + 6), target.raw()); } private: diff --git a/runtime/vm/compiler/assembler/assembler_base.cc b/runtime/vm/compiler/assembler/assembler_base.cc index 9f00096f04d..96d98a1e5f9 100644 --- a/runtime/vm/compiler/assembler/assembler_base.cc +++ b/runtime/vm/compiler/assembler/assembler_base.cc @@ -179,7 +179,7 @@ class PatchCodeWithHandle : public AssemblerFixup { // Patch the handle into the code. Once the instructions are installed into // a raw code object and the pointer offsets are setup, the handle is // resolved. - region.Store(position, &object_); + region.StoreUnaligned(position, &object_); pointer_offsets_->Add(position); } diff --git a/runtime/vm/compiler/assembler/assembler_base.h b/runtime/vm/compiler/assembler/assembler_base.h index 419ec7d1ea6..03f0cfc1cd1 100644 --- a/runtime/vm/compiler/assembler/assembler_base.h +++ b/runtime/vm/compiler/assembler/assembler_base.h @@ -10,6 +10,7 @@ #endif // defined(DART_PRECOMPILED_RUNTIME) #include "platform/assert.h" +#include "platform/unaligned.h" #include "vm/allocation.h" #include "vm/compiler/assembler/object_pool_builder.h" #include "vm/compiler/runtime_api.h" @@ -164,7 +165,13 @@ class AssemblerBuffer : public ValueObject { template void Emit(T value) { ASSERT(HasEnsuredCapacity()); +#if defined(TARGET_ARCH_IA32) || defined(TARGET_ARCH_X64) + // Variable-length instructions in ia32/x64 have unaligned immediates. + StoreUnaligned(reinterpret_cast(cursor_), value); +#else + // Other architecture have aligned, fixed-length instructions. *reinterpret_cast(cursor_) = value; +#endif cursor_ += sizeof(T); } @@ -181,14 +188,26 @@ class AssemblerBuffer : public ValueObject { T Load(intptr_t position) { ASSERT(position >= 0 && position <= (Size() - static_cast(sizeof(T)))); +#if defined(TARGET_ARCH_IA32) || defined(TARGET_ARCH_X64) + // Variable-length instructions in ia32/x64 have unaligned immediates. + return LoadUnaligned(reinterpret_cast(contents_ + position)); +#else + // Other architecture have aligned, fixed-length instructions. return *reinterpret_cast(contents_ + position); +#endif } template void Store(intptr_t position, T value) { ASSERT(position >= 0 && position <= (Size() - static_cast(sizeof(T)))); +#if defined(TARGET_ARCH_IA32) || defined(TARGET_ARCH_X64) + // Variable-length instructions in ia32/x64 have unaligned immediates. + StoreUnaligned(reinterpret_cast(contents_ + position), value); +#else + // Other architecture have aligned, fixed-length instructions. *reinterpret_cast(contents_ + position) = value; +#endif } const ZoneGrowableArray& pointer_offsets() const { diff --git a/runtime/vm/compiler/assembler/disassembler.cc b/runtime/vm/compiler/assembler/disassembler.cc index 00810729b6f..8af6086c245 100644 --- a/runtime/vm/compiler/assembler/disassembler.cc +++ b/runtime/vm/compiler/assembler/disassembler.cc @@ -4,6 +4,7 @@ #include "vm/compiler/assembler/disassembler.h" +#include "platform/unaligned.h" #include "vm/code_patcher.h" #include "vm/deopt_instructions.h" #include "vm/globals.h" @@ -232,7 +233,7 @@ void Disassembler::DisassembleCodeHelper(const char* function_fullname, Object& obj = Object::Handle(zone); for (intptr_t i = code.pointer_offsets_length() - 1; i >= 0; i--) { const uword addr = code.GetPointerOffsetAt(i) + code.PayloadStart(); - obj = *reinterpret_cast(addr); + obj = LoadUnaligned(reinterpret_cast(addr)); THR_Print(" %d : %#" Px " '%s'\n", code.GetPointerOffsetAt(i), addr, obj.ToCString()); } diff --git a/runtime/vm/compiler/assembler/disassembler_x86.cc b/runtime/vm/compiler/assembler/disassembler_x86.cc index 93f3129c836..78c9458dd53 100644 --- a/runtime/vm/compiler/assembler/disassembler_x86.cc +++ b/runtime/vm/compiler/assembler/disassembler_x86.cc @@ -9,6 +9,7 @@ #include "vm/compiler/assembler/disassembler.h" +#include "platform/unaligned.h" #include "platform/utils.h" #include "vm/allocation.h" #include "vm/constants_x86.h" @@ -403,7 +404,7 @@ int DisassemblerX64::PrintRightOperandHelper( switch (mod) { case 0: if ((rm & 7) == 5) { - int32_t disp = *reinterpret_cast(modrmp + 1); + int32_t disp = LoadUnaligned(reinterpret_cast(modrmp + 1)); Print("[rip"); PrintDisp(disp, "]"); return 5; @@ -419,7 +420,7 @@ int DisassemblerX64::PrintRightOperandHelper( return 2; } else if (base == 5) { // base == rbp means no base register (when mod == 0). - int32_t disp = *reinterpret_cast(modrmp + 2); + int32_t disp = LoadUnaligned(reinterpret_cast(modrmp + 2)); Print("[%s*%d", NameOfCPURegister(index), 1 << scale); PrintDisp(disp, "]"); return 6; @@ -444,8 +445,9 @@ int DisassemblerX64::PrintRightOperandHelper( uint8_t sib = *(modrmp + 1); int scale, index, base; get_sib(sib, &scale, &index, &base); - int disp = (mod == 2) ? *reinterpret_cast(modrmp + 2) - : *reinterpret_cast(modrmp + 2); + int disp = (mod == 2) + ? LoadUnaligned(reinterpret_cast(modrmp + 2)) + : *reinterpret_cast(modrmp + 2); if (index == 4 && (base & 7) == 4 && scale == 0 /*times_1*/) { Print("[%s", NameOfCPURegister(base)); PrintDisp(disp, "]"); @@ -457,8 +459,9 @@ int DisassemblerX64::PrintRightOperandHelper( return mod == 2 ? 6 : 3; } else { // No sib. - int disp = (mod == 2) ? *reinterpret_cast(modrmp + 1) - : *reinterpret_cast(modrmp + 1); + int disp = (mod == 2) + ? LoadUnaligned(reinterpret_cast(modrmp + 1)) + : *reinterpret_cast(modrmp + 1); Print("[%s", NameOfCPURegister(rm)); PrintDisp(disp, "]"); return (mod == 2) ? 5 : 2; @@ -490,18 +493,18 @@ int DisassemblerX64::PrintImmediate(uint8_t* data, break; case WORD_SIZE: if (sign_extend) { - value = *reinterpret_cast(data); + value = LoadUnaligned(reinterpret_cast(data)); } else { - value = *reinterpret_cast(data); + value = LoadUnaligned(reinterpret_cast(data)); } count = 2; break; case DOUBLEWORD_SIZE: case QUADWORD_SIZE: if (sign_extend) { - value = *reinterpret_cast(data); + value = LoadUnaligned(reinterpret_cast(data)); } else { - value = *reinterpret_cast(data); + value = LoadUnaligned(reinterpret_cast(data)); } count = 4; break; @@ -525,21 +528,21 @@ void DisassemblerX64::PrintImmediateValue(int64_t value, if (byte_count == 1) { int8_t v8 = static_cast(value); if (v8 < 0 && signed_value) { - Print("-%#" Px32, static_cast(-v8)); + Print("-%#" Px32, -static_cast(v8)); } else { Print("%#" Px32, static_cast(v8)); } } else if (byte_count == 2) { int16_t v16 = static_cast(value); if (v16 < 0 && signed_value) { - Print("-%#" Px32, static_cast(-v16)); + Print("-%#" Px32, -static_cast(v16)); } else { Print("%#" Px32, static_cast(v16)); } } else if (byte_count == 4) { int32_t v32 = static_cast(value); if (v32 < 0 && signed_value) { - Print("-%#010" Px32, static_cast(-v32)); + Print("-%#010" Px32, -static_cast(v32)); } else { if (v32 > 0xffff) { Print("%#010" Px32, v32); @@ -550,7 +553,7 @@ void DisassemblerX64::PrintImmediateValue(int64_t value, } else if (byte_count == 8) { int64_t v64 = static_cast(value); if (v64 < 0 && signed_value) { - Print("-%#018" Px64, static_cast(-v64)); + Print("-%#018" Px64, -static_cast(v64)); } else { if (v64 > 0xffffffffll) { Print("%#018" Px64, v64); @@ -778,7 +781,8 @@ void DisassemblerX64::PrintJump(uint8_t* pc, int32_t disp) { if (FLAG_disassemble_relative) { Print("%+d", disp); } else { - PrintAddress(pc + disp); + PrintAddress( + reinterpret_cast(reinterpret_cast(pc) + disp)); } } @@ -810,7 +814,7 @@ int DisassemblerX64::JumpShort(uint8_t* data) { int DisassemblerX64::JumpConditional(uint8_t* data) { ASSERT(0x0F == *data); uint8_t cond = *(data + 1) & 0x0F; - int32_t disp = *reinterpret_cast(data + 2) + 6; + int32_t disp = LoadUnaligned(reinterpret_cast(data + 2)) + 6; const char* mnem = conditional_code_suffix[cond]; Print("j%s ", mnem); PrintJump(data, disp); @@ -1178,15 +1182,15 @@ bool DisassemblerX64::DecodeInstructionType(uint8_t** data) { int imm_bytes = 0; switch (operand_size()) { case WORD_SIZE: - addr = *reinterpret_cast(*data + 1); + addr = LoadUnaligned(reinterpret_cast(*data + 1)); imm_bytes = 2; break; case DOUBLEWORD_SIZE: - addr = *reinterpret_cast(*data + 1); + addr = LoadUnaligned(reinterpret_cast(*data + 1)); imm_bytes = 4; break; case QUADWORD_SIZE: - addr = *reinterpret_cast(*data + 1); + addr = LoadUnaligned(reinterpret_cast(*data + 1)); imm_bytes = 8; break; default: @@ -1200,7 +1204,7 @@ bool DisassemblerX64::DecodeInstructionType(uint8_t** data) { } case CALL_JUMP_INSTR: { - int32_t disp = *reinterpret_cast(*data + 1) + 5; + int32_t disp = LoadUnaligned(reinterpret_cast(*data + 1)) + 5; Print("%s ", idesc.mnem); PrintJump(*data, disp); (*data) += 5; @@ -1635,8 +1639,9 @@ int DisassemblerX64::InstructionDecode(uword pc) { case 0x6B: { int mod, regop, rm; get_modrm(*(data + 1), &mod, ®op, &rm); - int32_t imm = - *data == 0x6B ? *(data + 2) : *reinterpret_cast(data + 2); + int32_t imm = *data == 0x6B + ? *(data + 2) + : LoadUnaligned(reinterpret_cast(data + 2)); Print("imul%s %s,%s,", operand_size_code(), NameOfCPURegister(regop), NameOfCPURegister(rm)); PrintImmediateValue(imm); @@ -1800,7 +1805,8 @@ int DisassemblerX64::InstructionDecode(uword pc) { } case 0x68: Print("push "); - PrintImmediateValue(*reinterpret_cast(data + 1)); + PrintImmediateValue( + LoadUnaligned(reinterpret_cast(data + 1))); data += 5; break; @@ -1995,7 +2001,8 @@ void Disassembler::DecodeInstruction(char* hex_buffer, for (intptr_t i = 0; i < offsets_length; i++) { uword addr = code.GetPointerOffsetAt(i) + code.PayloadStart(); if ((pc <= addr) && (addr < (pc + instruction_length))) { - *object = &Object::Handle(*reinterpret_cast(addr)); + *object = + &Object::Handle(LoadUnaligned(reinterpret_cast(addr))); break; } } diff --git a/runtime/vm/compiler/backend/locations.cc b/runtime/vm/compiler/backend/locations.cc index f5853c2774d..c9b0daca14f 100644 --- a/runtime/vm/compiler/backend/locations.cc +++ b/runtime/vm/compiler/backend/locations.cc @@ -41,7 +41,8 @@ intptr_t RegisterSet::RegisterCount(intptr_t registers) { intptr_t count = 0; while (registers != 0) { ++count; - registers &= (registers - 1); // Clear the least significant bit set. + // Clear the least significant bit set. + registers &= (static_cast(registers) - 1); } return count; } diff --git a/runtime/vm/compiler/backend/locations.h b/runtime/vm/compiler/backend/locations.h index a270ad82625..558767f7d64 100644 --- a/runtime/vm/compiler/backend/locations.h +++ b/runtime/vm/compiler/backend/locations.h @@ -97,7 +97,7 @@ class Location : public ValueObject { // Note that two locations with different kinds should never point to // the same place. For example kQuadStackSlot location should never intersect // with kDoubleStackSlot location. - enum Kind { + enum Kind : intptr_t { // This location is invalid. Payload must be zero. kInvalid = 0, diff --git a/runtime/vm/compiler/backend/range_analysis.cc b/runtime/vm/compiler/backend/range_analysis.cc index b960558348d..ff24226e3b2 100644 --- a/runtime/vm/compiler/backend/range_analysis.cc +++ b/runtime/vm/compiler/backend/range_analysis.cc @@ -1827,7 +1827,7 @@ RangeBoundary RangeBoundary::Shl(const RangeBoundary& value_boundary, } else if (shift_count == 0 || (limit > 0 && Utils::IsInt(static_cast(limit), value))) { // Result stays in 64 bit range. - const int64_t result = value << shift_count; + const int64_t result = static_cast(value) << shift_count; return RangeBoundary(result); } diff --git a/runtime/vm/compiler/frontend/kernel_translation_helper.h b/runtime/vm/compiler/frontend/kernel_translation_helper.h index e6f25bfbd05..23f3151eccd 100644 --- a/runtime/vm/compiler/frontend/kernel_translation_helper.h +++ b/runtime/vm/compiler/frontend/kernel_translation_helper.h @@ -277,7 +277,7 @@ class FunctionNodeHelper { kEnd, }; - enum AsyncMarker { + enum AsyncMarker : intptr_t { kSync = 0, kSyncStar = 1, kAsync = 2, diff --git a/runtime/vm/dart_api_message.cc b/runtime/vm/dart_api_message.cc index 639270c8db0..f5814c474ed 100644 --- a/runtime/vm/dart_api_message.cc +++ b/runtime/vm/dart_api_message.cc @@ -5,6 +5,8 @@ #include #include "vm/dart_api_message.h" + +#include "platform/undefined_behavior_sanitizer.h" #include "platform/unicode.h" #include "vm/object.h" #include "vm/snapshot_ids.h" @@ -102,8 +104,6 @@ Dart_CObject* ApiMessageReader::AllocateDartCObjectInt64(int64_t val) { return value; } -_Dart_CObject* ApiMessageReader::singleton_uint32_typed_data_ = NULL; - Dart_CObject* ApiMessageReader::AllocateDartCObjectDouble(double val) { Dart_CObject* value = AllocateDartCObject(Dart_CObject_kDouble); value->value.as_double = val; @@ -789,6 +789,8 @@ ApiMessageWriter::~ApiMessageWriter() { delete finalizable_data_; } +NO_SANITIZE_UNDEFINED( + "enum") // TODO(https://github.com/dart-lang/sdk/issues/39427) void ApiMessageWriter::MarkCObject(Dart_CObject* object, intptr_t object_id) { // Mark the object as serialized by adding the object id to the // upper bits of the type field in the Dart_CObject structure. Add @@ -799,16 +801,22 @@ void ApiMessageWriter::MarkCObject(Dart_CObject* object, intptr_t object_id) { ((mark_value) << kDartCObjectTypeBits) | object->type); } +NO_SANITIZE_UNDEFINED( + "enum") // TODO(https://github.com/dart-lang/sdk/issues/39427) void ApiMessageWriter::UnmarkCObject(Dart_CObject* object) { ASSERT(IsCObjectMarked(object)); object->type = static_cast(object->type & kDartCObjectTypeMask); } +NO_SANITIZE_UNDEFINED( + "enum") // TODO(https://github.com/dart-lang/sdk/issues/39427) bool ApiMessageWriter::IsCObjectMarked(Dart_CObject* object) { return (object->type & kDartCObjectMarkMask) != 0; } +NO_SANITIZE_UNDEFINED( + "enum") // TODO(https://github.com/dart-lang/sdk/issues/39427) intptr_t ApiMessageWriter::GetMarkedCObjectMark(Dart_CObject* object) { ASSERT(IsCObjectMarked(object)); intptr_t mark_value = @@ -954,6 +962,8 @@ bool ApiMessageWriter::WriteCObjectRef(Dart_CObject* object) { return WriteCObjectInlined(object, type); } +NO_SANITIZE_UNDEFINED( + "enum") // TODO(https://github.com/dart-lang/sdk/issues/39427) bool ApiMessageWriter::WriteForwardedCObject(Dart_CObject* object) { ASSERT(IsCObjectMarked(object)); Dart_CObject_Type type = diff --git a/runtime/vm/dart_api_message.h b/runtime/vm/dart_api_message.h index aa800313d95..ace7dd35c96 100644 --- a/runtime/vm/dart_api_message.h +++ b/runtime/vm/dart_api_message.h @@ -148,8 +148,6 @@ class ApiMessageReader : public BaseReader { Dart_CObject dynamic_type_marker; MessageFinalizableData* finalizable_data_; - - static _Dart_CObject* singleton_uint32_typed_data_; }; class ApiMessageWriter : public BaseWriter { diff --git a/runtime/vm/datastream.h b/runtime/vm/datastream.h index d34cdbe1740..89240d43c8e 100644 --- a/runtime/vm/datastream.h +++ b/runtime/vm/datastream.h @@ -68,7 +68,9 @@ class ReadStream : public ValueObject { // Reads 'len' bytes from the stream. void ReadBytes(uint8_t* addr, intptr_t len) { ASSERT((end_ - current_) >= len); - memmove(addr, current_, len); + if (len != 0) { + memmove(addr, current_, len); + } current_ += len; } @@ -128,23 +130,24 @@ class ReadStream : public ValueObject { template T Read(uint8_t end_byte_marker) { + using Unsigned = typename std::make_unsigned::type; const uint8_t* c = current_; ASSERT(c < end_); uint8_t b = *c++; if (b > kMaxUnsignedDataPerByte) { current_ = c; - return static_cast(b) - end_byte_marker; + return static_cast(b) - end_byte_marker; } T r = 0; uint8_t s = 0; do { - r |= static_cast(b) << s; + r |= static_cast(b) << s; s += kDataBitsPerByte; ASSERT(c < end_); b = *c++; } while (b <= kMaxUnsignedDataPerByte); current_ = c; - return r | ((static_cast(b) - end_byte_marker) << s); + return r | ((static_cast(b) - end_byte_marker) << s); } uint16_t Read16(uint8_t end_byte_marker) { @@ -406,7 +409,9 @@ class WriteStream : public ValueObject { Resize(len); } ASSERT((end_ - current_) >= len); - memmove(current_, addr, len); + if (len != 0) { + memmove(current_, addr, len); + } current_ += len; } @@ -550,7 +555,9 @@ class StreamingWriteStream : public ValueObject { void WriteBytes(const uint8_t* buffer, intptr_t size) { EnsureAvailable(size); - memmove(cursor_, buffer, size); + if (size != 0) { + memmove(cursor_, buffer, size); + } cursor_ += size; } diff --git a/runtime/vm/exceptions.h b/runtime/vm/exceptions.h index 430d7a9c347..7a44cd818f5 100644 --- a/runtime/vm/exceptions.h +++ b/runtime/vm/exceptions.h @@ -181,9 +181,9 @@ class CatchEntryMove { static CatchEntryMove FromSlot(SourceKind kind, intptr_t src_slot, intptr_t dest_slot) { - return CatchEntryMove(src_slot, - SourceKindField::encode(kind) | - (dest_slot << SourceKindField::bitsize())); + return CatchEntryMove(src_slot, SourceKindField::encode(kind) | + (static_cast(dest_slot) + << SourceKindField::bitsize())); } static intptr_t EncodePairSource(intptr_t src_lo_slot, intptr_t src_hi_slot) { diff --git a/runtime/vm/flags.cc b/runtime/vm/flags.cc index d3262355271..508a9ee1ec7 100644 --- a/runtime/vm/flags.cc +++ b/runtime/vm/flags.cc @@ -158,7 +158,7 @@ class Flag { OptionHandler option_handler_; }; FlagType type_; - bool changed_; + bool changed_ = false; }; Flag* Flags::Lookup(const char* name) { diff --git a/runtime/vm/heap/pages.cc b/runtime/vm/heap/pages.cc index 1c6444cc95a..ab0935716ea 100644 --- a/runtime/vm/heap/pages.cc +++ b/runtime/vm/heap/pages.cc @@ -1648,11 +1648,15 @@ void PageSpaceController::EvaluateGarbageCollection(SpaceUsage before, void PageSpaceController::EvaluateAfterLoading(SpaceUsage after) { // Number of pages we can allocate and still be within the desired growth // ratio. - intptr_t growth_in_pages = - (static_cast(after.CombinedUsedInWords() / - desired_utilization_) - - (after.CombinedUsedInWords())) / - kPageSizeInWords; + intptr_t growth_in_pages; + if (desired_utilization_ == 0.0) { + growth_in_pages = heap_growth_max_; + } else { + growth_in_pages = (static_cast(after.CombinedUsedInWords() / + desired_utilization_) - + (after.CombinedUsedInWords())) / + kPageSizeInWords; + } // Apply growth cap. growth_in_pages = diff --git a/runtime/vm/instructions_x64.cc b/runtime/vm/instructions_x64.cc index cbeba5f9c14..256faa98aa8 100644 --- a/runtime/vm/instructions_x64.cc +++ b/runtime/vm/instructions_x64.cc @@ -5,6 +5,8 @@ #include "vm/globals.h" // Needed here to get TARGET_ARCH_X64. #if defined(TARGET_ARCH_X64) +#include "platform/unaligned.h" + #include "vm/code_patcher.h" #include "vm/instructions.h" #include "vm/instructions_x64.h" @@ -22,7 +24,7 @@ intptr_t IndexFromPPLoadDisp8(uword start) { } intptr_t IndexFromPPLoadDisp32(uword start) { - int32_t offset = *reinterpret_cast(start); + int32_t offset = LoadUnaligned(reinterpret_cast(start)); return ObjectPool::IndexFromOffset(offset); } @@ -35,7 +37,7 @@ bool DecodeLoadObjectFromPoolOrThread(uword pc, const Code& code, Object* obj) { if ((bytes[0] == 0x49) || (bytes[0] == 0x4d)) { if ((bytes[1] == 0x8b) || (bytes[1] == 0x3b)) { // movq, cmpq if ((bytes[2] & 0xc7) == (0x80 | (THR & 7))) { // [r14+disp32] - int32_t offset = *reinterpret_cast(pc + 3); + int32_t offset = LoadUnaligned(reinterpret_cast(pc + 3)); return Thread::ObjectAtOffset(offset, obj); } if ((bytes[2] & 0xc7) == (0x40 | (THR & 7))) { // [r14+disp8] diff --git a/runtime/vm/instructions_x64.h b/runtime/vm/instructions_x64.h index 81e69c62d63..efc8abdecca 100644 --- a/runtime/vm/instructions_x64.h +++ b/runtime/vm/instructions_x64.h @@ -10,6 +10,7 @@ #error "Do not include instructions_x64.h directly; use instructions.h instead." #endif +#include "platform/unaligned.h" #include "vm/allocation.h" namespace dart { @@ -115,13 +116,15 @@ class PcRelativeCallPattern : public InstructionPattern { explicit PcRelativeCallPattern(uword pc) : InstructionPattern(pc) {} int32_t distance() { - return *reinterpret_cast(start() + 1) + kLengthInBytes; + return LoadUnaligned(reinterpret_cast(start() + 1)) + + kLengthInBytes; } void set_distance(int32_t distance) { // [distance] is relative to the start of the instruction, x64 considers the // offset relative to next PC. - *reinterpret_cast(start() + 1) = distance - kLengthInBytes; + StoreUnaligned(reinterpret_cast(start() + 1), + distance - kLengthInBytes); } static const int* pattern() { @@ -162,13 +165,15 @@ class PcRelativeTrampolineJumpPattern : public ValueObject { } int32_t distance() { - return *reinterpret_cast(pattern_start_ + 1) + kLengthInBytes; + return LoadUnaligned(reinterpret_cast(pattern_start_ + 1)) + + kLengthInBytes; } void set_distance(int32_t distance) { // [distance] is relative to the start of the instruction, x64 considers the // offset relative to next PC. - *reinterpret_cast(pattern_start_ + 1) = distance - kLengthInBytes; + StoreUnaligned(reinterpret_cast(pattern_start_ + 1), + distance - kLengthInBytes); } bool IsValid() const { diff --git a/runtime/vm/kernel_binary.h b/runtime/vm/kernel_binary.h index af2d8bac59c..11527eba3e4 100644 --- a/runtime/vm/kernel_binary.h +++ b/runtime/vm/kernel_binary.h @@ -7,6 +7,7 @@ #if !defined(DART_PRECOMPILED_RUNTIME) +#include "platform/unaligned.h" #include "vm/kernel.h" #include "vm/object.h" @@ -236,7 +237,8 @@ class Reader : public ValueObject { ASSERT((size_ >= 4) && (offset >= 0) && (offset <= size_ - 4)); uint32_t value; if (raw_buffer_ != NULL) { - value = *reinterpret_cast(raw_buffer_ + offset); + value = LoadUnaligned( + reinterpret_cast(raw_buffer_ + offset)); } else { value = typed_data_->GetUint32(offset); } @@ -259,7 +261,7 @@ class Reader : public ValueObject { double ReadDouble() { ASSERT((size_ >= 8) && (offset_ >= 0) && (offset_ <= size_ - 8)); - double value = ReadUnaligned( + double value = LoadUnaligned( reinterpret_cast(&this->buffer()[offset_])); offset_ += 8; return value; diff --git a/runtime/vm/memory_region.h b/runtime/vm/memory_region.h index 63cc44ae4e6..3432f6faf16 100644 --- a/runtime/vm/memory_region.h +++ b/runtime/vm/memory_region.h @@ -6,6 +6,7 @@ #define RUNTIME_VM_MEMORY_REGION_H_ #include "platform/assert.h" +#include "platform/unaligned.h" #include "vm/allocation.h" #include "vm/globals.h" @@ -42,6 +43,11 @@ class MemoryRegion : public ValueObject { *ComputeInternalPointer(offset) = value; } + template + void StoreUnaligned(uword offset, T value) const { + dart::StoreUnaligned(ComputeInternalPointer(offset), value); + } + template T* PointerTo(uword offset) const { return ComputeInternalPointer(offset); diff --git a/runtime/vm/object.cc b/runtime/vm/object.cc index 33aeba634a0..0cc1cfa948a 100644 --- a/runtime/vm/object.cc +++ b/runtime/vm/object.cc @@ -8,6 +8,7 @@ #include "include/dart_api.h" #include "platform/assert.h" +#include "platform/unaligned.h" #include "platform/unicode.h" #include "vm/bit_vector.h" #include "vm/bootstrap.h" @@ -555,6 +556,7 @@ void Object::InitNullAndBool(Isolate* isolate) { // Allocate a dummy bool object to give true the desired alignment. uword address = heap->Allocate(Bool::InstanceSize(), Heap::kOld); InitializeObject(address, kBoolCid, Bool::InstanceSize()); + static_cast(address + kHeapObjectTag)->ptr()->value_ = false; } { // Allocate true. @@ -8532,7 +8534,7 @@ InstancePtr Function::ImplicitInstanceClosure(const Instance& receiver) const { intptr_t Function::ComputeClosureHash() const { ASSERT(IsClosureFunction()); const Class& cls = Class::Handle(Owner()); - intptr_t result = String::Handle(name()).Hash(); + uintptr_t result = String::Handle(name()).Hash(); result += String::Handle(Signature()).Hash(); result += String::Handle(cls.Name()).Hash(); return result; @@ -15956,18 +15958,19 @@ CodePtr Code::FinalizeCode(FlowGraphCompiler* compiler, // Set pointer offsets list in Code object and resolve all handles in // the instruction stream to raw objects. + Thread* thread = Thread::Current(); for (intptr_t i = 0; i < pointer_offsets.length(); i++) { intptr_t offset_in_instrs = pointer_offsets[i]; code.SetPointerOffsetAt(i, offset_in_instrs); uword addr = region.start() + offset_in_instrs; ASSERT(instrs.PayloadStart() <= addr); ASSERT((instrs.PayloadStart() + instrs.Size()) > addr); - const Object* object = *reinterpret_cast(addr); + const Object* object = LoadUnaligned(reinterpret_cast(addr)); ASSERT(object->IsOld()); // N.B. The pointer is embedded in the Instructions object, but visited // through the Code object. - code.raw()->ptr()->StorePointer(reinterpret_cast(addr), - object->raw()); + code.raw()->ptr()->StorePointerUnaligned( + reinterpret_cast(addr), object->raw(), thread); } // Write protect instructions and, if supported by OS, use dual mapping @@ -20476,7 +20479,7 @@ const char* Integer::ToHexCString(Zone* zone) const { ASSERT(IsSmi() || IsMint()); int64_t value = AsInt64Value(); if (value < 0) { - return OS::SCreate(zone, "-0x%" PX64, static_cast(-value)); + return OS::SCreate(zone, "-0x%" PX64, -static_cast(value)); } else { return OS::SCreate(zone, "0x%" PX64, static_cast(value)); } @@ -21116,7 +21119,7 @@ bool String::Equals(const uint16_t* utf16_array, intptr_t len) const { } for (intptr_t i = 0; i < len; i++) { - if (this->CharAt(i) != utf16_array[i]) { + if (this->CharAt(i) != LoadUnaligned(&utf16_array[i])) { return false; } } @@ -21260,7 +21263,7 @@ StringPtr String::FromUTF16(const uint16_t* utf16_array, Heap::Space space) { bool is_one_byte_string = true; for (intptr_t i = 0; i < array_len; ++i) { - if (!Utf::IsLatin1(utf16_array[i])) { + if (!Utf::IsLatin1(LoadUnaligned(&utf16_array[i]))) { is_one_byte_string = false; break; } @@ -21357,7 +21360,7 @@ void String::Copy(const String& dst, if (dst.IsOneByteString()) { NoSafepointScope no_safepoint; for (intptr_t i = 0; i < array_len; ++i) { - ASSERT(Utf::IsLatin1(utf16_array[i])); + ASSERT(Utf::IsLatin1(LoadUnaligned(&utf16_array[i]))); *OneByteString::CharAddr(dst, i + dst_offset) = utf16_array[i]; } } else { @@ -22860,7 +22863,7 @@ Float32x4Ptr Float32x4::New(simd128_value_t value, Heap::Space space) { } simd128_value_t Float32x4::value() const { - return ReadUnaligned( + return LoadUnaligned( reinterpret_cast(&raw_ptr()->value_)); } @@ -22976,7 +22979,7 @@ int32_t Int32x4::w() const { } simd128_value_t Int32x4::value() const { - return ReadUnaligned( + return LoadUnaligned( reinterpret_cast(&raw_ptr()->value_)); } diff --git a/runtime/vm/object.h b/runtime/vm/object.h index b3cb5c5a98a..469f0279bdf 100644 --- a/runtime/vm/object.h +++ b/runtime/vm/object.h @@ -9796,7 +9796,7 @@ class TypedData : public TypedDataBase { ASSERT((byte_offset >= 0) && \ (byte_offset + static_cast(sizeof(type)) - 1) < \ LengthInBytes()); \ - return ReadUnaligned(ReadOnlyDataAddr(byte_offset)); \ + return LoadUnaligned(ReadOnlyDataAddr(byte_offset)); \ } \ void Set##name(intptr_t byte_offset, type value) const { \ NoSafepointScope no_safepoint; \ @@ -9931,7 +9931,7 @@ class ExternalTypedData : public TypedDataBase { #define TYPED_GETTER_SETTER(name, type) \ type Get##name(intptr_t byte_offset) const { \ - return ReadUnaligned(reinterpret_cast(DataAddr(byte_offset))); \ + return LoadUnaligned(reinterpret_cast(DataAddr(byte_offset))); \ } \ void Set##name(intptr_t byte_offset, type value) const { \ StoreUnaligned(reinterpret_cast(DataAddr(byte_offset)), value); \ diff --git a/runtime/vm/object_reload.cc b/runtime/vm/object_reload.cc index 669e44192e1..65677896917 100644 --- a/runtime/vm/object_reload.cc +++ b/runtime/vm/object_reload.cc @@ -4,6 +4,7 @@ #include "vm/object.h" +#include "platform/unaligned.h" #include "vm/code_patcher.h" #include "vm/hash_table.h" #include "vm/isolate_reload.h" @@ -74,7 +75,7 @@ void CallSiteResetter::ResetCaches(const Code& code) { for (intptr_t i = 0; i < offsets_length; i++) { int32_t offset = offsets[i]; ObjectPtr* object_ptr = reinterpret_cast(base_address + offset); - ObjectPtr raw_object = *object_ptr; + ObjectPtr raw_object = LoadUnaligned(object_ptr); if (!raw_object->IsHeapObject()) { continue; } diff --git a/runtime/vm/profiler.cc b/runtime/vm/profiler.cc index f4741fdf27b..5a01001a1ed 100644 --- a/runtime/vm/profiler.cc +++ b/runtime/vm/profiler.cc @@ -1175,11 +1175,13 @@ void Profiler::DumpStackTrace(uword sp, uword fp, uword pc, bool for_crash) { native_stack_walker.walk(); OS::PrintErr("-- End of DumpStackTrace\n"); - if (thread->execution_state() == Thread::kThreadInNative) { - TransitionNativeToVM transition(thread); - StackFrame::DumpCurrentTrace(); - } else if (thread->execution_state() == Thread::kThreadInVM) { - StackFrame::DumpCurrentTrace(); + if (thread != nullptr) { + if (thread->execution_state() == Thread::kThreadInNative) { + TransitionNativeToVM transition(thread); + StackFrame::DumpCurrentTrace(); + } else if (thread->execution_state() == Thread::kThreadInVM) { + StackFrame::DumpCurrentTrace(); + } } } diff --git a/runtime/vm/raw_object.h b/runtime/vm/raw_object.h index e61ecd000a1..6d6593e5d05 100644 --- a/runtime/vm/raw_object.h +++ b/runtime/vm/raw_object.h @@ -537,6 +537,14 @@ class ObjectLayout { } } + template + void StorePointerUnaligned(type const* addr, type value, Thread* thread) { + StoreUnaligned(const_cast(addr), value); + if (value->IsHeapObject()) { + CheckHeapPointerStore(value, thread); + } + } + DART_FORCE_INLINE void CheckHeapPointerStore(ObjectPtr value, Thread* thread) { uint32_t source_tags = this->tags_; diff --git a/runtime/vm/snapshot.h b/runtime/vm/snapshot.h index cb43fc25041..e78bd6ab003 100644 --- a/runtime/vm/snapshot.h +++ b/runtime/vm/snapshot.h @@ -155,7 +155,7 @@ class Snapshot { template T Read(intptr_t offset) const { - return ReadUnaligned( + return LoadUnaligned( reinterpret_cast(reinterpret_cast(this) + offset)); } diff --git a/runtime/vm/stack_frame.cc b/runtime/vm/stack_frame.cc index a0732592053..3c5b17bc0ab 100644 --- a/runtime/vm/stack_frame.cc +++ b/runtime/vm/stack_frame.cc @@ -114,9 +114,12 @@ IsolateGroup* StackFrame::IsolateGroupOfBareInstructionsFrame() const { } isolate_group = this->isolate_group(); - if (isolate_group->object_store()->code_order_table() != Object::null()) { - auto rct = isolate_group->reverse_pc_lookup_cache(); - if (rct->Contains(pc())) return isolate_group; + auto* object_store = isolate_group->object_store(); + if (object_store != nullptr) { + if (object_store->code_order_table() != Object::null()) { + auto rct = isolate_group->reverse_pc_lookup_cache(); + if (rct->Contains(pc())) return isolate_group; + } } return nullptr; diff --git a/tools/bots/test_matrix.json b/tools/bots/test_matrix.json index 9dc2f2fbc14..3f6ca8eb39e 100644 --- a/tools/bots/test_matrix.json +++ b/tools/bots/test_matrix.json @@ -553,61 +553,61 @@ "builder-tag": "analyzer_use_fasta" } }, - "dartk-asan-(linux|mac)-(debug|product|release)-(ia32|x64)": { + "dartk-asan-(linux|mac)-(debug|product|release)-(ia32|x64|simarm|simarm64)": { "options": { "builder-tag": "asan", "timeout": 240 } }, - "dartk-lsan-(linux|mac)-(debug|product|release)-(ia32|x64)": { + "dartk-lsan-(linux|mac)-(debug|product|release)-(ia32|x64|simarm|simarm64)": { "options": { "builder-tag": "lsan", "timeout": 240 } }, - "dartk-msan-linux-(debug|product|release)-x64": { + "dartk-msan-linux-(debug|product|release)-(x64|simarm64)": { "options": { "builder-tag": "msan", "timeout": 240 } }, - "dartk-tsan-(linux|mac)-(debug|product|release)-x64": { + "dartk-tsan-(linux|mac)-(debug|product|release)-(x64|simarm64)": { "options": { "builder-tag": "tsan", "timeout": 240 } }, - "dartk-ubsan-(linux|mac)-(debug|product|release)-(ia32|x64)": { + "dartk-ubsan-(linux|mac)-(debug|product|release)-(ia32|x64|simarm|simarm64)": { "options": { "builder-tag": "ubsan", "timeout": 240 } }, - "dartkp-asan-(linux|mac)-(debug|product|release)-x64": { + "dartkp-asan-(linux|mac)-(debug|product|release)-(x64|simarm|simarm64)": { "options": { "builder-tag": "asan", "timeout": 240 } }, - "dartkp-lsan-(linux|mac)-(debug|product|release)-x64": { + "dartkp-lsan-(linux|mac)-(debug|product|release)-(x64|simarm|simarm64)": { "options": { "builder-tag": "lsan", "timeout": 240 } }, - "dartkp-msan-linux-(debug|product|release)-x64": { + "dartkp-msan-linux-(debug|product|release)-(x64|simarm64)": { "options": { "builder-tag": "msan", "timeout": 240 } }, - "dartkp-tsan-(linux|mac)-(debug|product|release)-x64": { + "dartkp-tsan-(linux|mac)-(debug|product|release)-(x64|simarm64)": { "options": { "builder-tag": "tsan", "timeout": 240 } }, - "dartkp-ubsan-(linux|mac)-(debug|product|release)-x64": { + "dartkp-ubsan-(linux|mac)-(debug|product|release)-(x64|simarm|simarm64)": { "options": { "builder-tag": "ubsan", "timeout": 240 @@ -3820,7 +3820,7 @@ "LSAN_OPTIONS": "check_initialization_order=true:handle_segv=0:detect_leaks=1:detect_stack_use_after_return=0:disable_coredump=0:abort_on_error=1", "MSAN_OPTIONS": "check_initialization_order=true:handle_segv=0:detect_leaks=1:detect_stack_use_after_return=0:disable_coredump=0:abort_on_error=1", "TSAN_OPTIONS": "handle_segv=0:disable_coredump=0:abort_on_error=1", - "UBSAN_OPTIONS": "handle_segv=0:disable_coredump=0:abort_on_error=1" + "UBSAN_OPTIONS": "handle_segv=0:disable_coredump=0:halt_on_error=1:print_stacktrace=1" }, "sanitizer_symbolizer": { "linux": "buildtools/linux-x64/clang/bin/llvm-symbolizer", diff --git a/tools/gn.py b/tools/gn.py index 99a59cbd1e3..fdf9fe395d6 100755 --- a/tools/gn.py +++ b/tools/gn.py @@ -134,6 +134,12 @@ def UseSysroot(args, gn_args): # Don't use the sysroot if we're given another sysroot. if TargetSysroot(args): return False + # Our Debian Jesse sysroot doesn't work with GCC 9 + if not gn_args['is_clang']: + return False + # Our Debian Jesse sysroot has incorrect annotations on realloc. + if gn_args['is_ubsan']: + return False # Otherwise use the sysroot. return True