[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 <alexmarkov@google.com>
Commit-Queue: Ryan Macnak <rmacnak@google.com>
This commit is contained in:
Ryan Macnak 2020-05-07 19:40:18 +00:00 committed by commit-bot@chromium.org
parent 8c79102889
commit 2707880f1b
41 changed files with 278 additions and 151 deletions

View file

@ -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) {

View file

@ -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) {

View file

@ -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) {

View file

@ -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);

View file

@ -6,6 +6,14 @@
#include <stdlib.h>
#include <string.h>
#if defined(__GNUC__) || defined(__Clang__)
__attribute__((no_sanitize("undefined")))
#endif
void Crash() {
int* segfault = NULL;
*segfault = 1;
}
/*
* Run ./process_test <outstream> <echocount> <exitcode> <crash>
* <outstream>: 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;

View file

@ -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<double>(kMinInt64) &&
val <= static_cast<double>(kMaxInt64)) {
if ((val >= kMinInt64RepresentableAsDouble) &&
(val <= kMaxInt64RepresentableAsDouble)) {
int64_t ival = static_cast<int64_t>(val);
if (static_cast<double>(ival) == val) {
return Integer::New(ival);

View file

@ -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 <typename T>
static inline T ReadUnaligned(const T* ptr) {
T value;
memcpy(reinterpret_cast<void*>(&value), reinterpret_cast<const void*>(ptr),
sizeof(value));
return value;
}
// Similar to bit_copy and bit_cast, but does take the type from the argument.
template <typename T>
static inline void StoreUnaligned(T* ptr, T value) {
memcpy(reinterpret_cast<void*>(ptr), reinterpret_cast<const void*>(&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 <typename T>
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 <typename T>
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)

View file

@ -205,6 +205,9 @@ class BaseGrowableArray : public B {
template <typename T, typename B, typename Allocator>
inline void BaseGrowableArray<T, B, Allocator>::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<CompareFunction>(compare));
}

View file

@ -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

View file

@ -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 <typename T>
static inline T LoadUnaligned(const T* ptr) {
T value;
memcpy(reinterpret_cast<void*>(&value), reinterpret_cast<const void*>(ptr),
sizeof(value));
return value;
}
template <typename T>
static inline void StoreUnaligned(T* ptr, T value) {
memcpy(reinterpret_cast<void*>(ptr), reinterpret_cast<const void*>(&value),
sizeof(value));
}
#else // !(HOST_ARCH_ARM || HOST_ARCH_ARM64)
template <typename T>
NO_SANITIZE_UNDEFINED("alignment")
static inline T LoadUnaligned(const T* ptr) {
return *ptr;
}
template <typename T>
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_

View file

@ -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_

View file

@ -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;

View file

@ -215,7 +215,7 @@ class Utils {
}
static inline int64_t LowHighTo64Bits(uint32_t low, int32_t high) {
return (static_cast<int64_t>(high) << 32) | (low & 0x0ffffffffLL);
return (static_cast<uint64_t>(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<uword>::max();
}
return (1ll << n) - 1;
return (static_cast<uword>(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<ValueType>::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<ValueType>(part & 0x7f) << shift;
value |= static_cast<Unsigned>(part & 0x7f) << shift;
shift += 7;
} while ((part & 0x80) != 0);
if ((shift < (sizeof(ValueType) * CHAR_BIT)) && ((part & 0x40) != 0)) {
using Unsigned = typename std::make_unsigned<ValueType>::type;
const Unsigned kMax = std::numeric_limits<Unsigned>::max();
value |= static_cast<ValueType>(kMax << shift);
value |= static_cast<Unsigned>(kMax << shift);
}
return value;
return static_cast<ValueType>(value);
}
static char* StrError(int err, char* buffer, size_t bufsize);

View file

@ -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<ObjectPtr*>(start_ + 1); }
ObjectPtr data() const {
return LoadUnaligned(reinterpret_cast<ObjectPtr*>(start_ + 1));
}
void set_data(const Object& data) const {
uword* cache_addr = reinterpret_cast<uword*>(start_ + 1);
uword imm = static_cast<uword>(data.raw());
*cache_addr = imm;
StoreUnaligned(reinterpret_cast<ObjectPtr*>(start_ + 1), data.raw());
}
CodePtr target() const {
const uword imm = *reinterpret_cast<uword*>(start_ + 6);
return static_cast<CodePtr>(imm);
return LoadUnaligned(reinterpret_cast<CodePtr*>(start_ + 6));
}
void set_target(const Code& target) const {
uword* target_addr = reinterpret_cast<uword*>(start_ + 6);
uword imm = static_cast<uword>(target.raw());
*target_addr = imm;
StoreUnaligned(reinterpret_cast<CodePtr*>(start_ + 6), target.raw());
}
private:

View file

@ -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<const Object*>(position, &object_);
region.StoreUnaligned<const Object*>(position, &object_);
pointer_offsets_->Add(position);
}

View file

@ -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 <typename T>
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<T*>(cursor_), value);
#else
// Other architecture have aligned, fixed-length instructions.
*reinterpret_cast<T*>(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<intptr_t>(sizeof(T))));
#if defined(TARGET_ARCH_IA32) || defined(TARGET_ARCH_X64)
// Variable-length instructions in ia32/x64 have unaligned immediates.
return LoadUnaligned(reinterpret_cast<T*>(contents_ + position));
#else
// Other architecture have aligned, fixed-length instructions.
return *reinterpret_cast<T*>(contents_ + position);
#endif
}
template <typename T>
void Store(intptr_t position, T value) {
ASSERT(position >= 0 &&
position <= (Size() - static_cast<intptr_t>(sizeof(T))));
#if defined(TARGET_ARCH_IA32) || defined(TARGET_ARCH_X64)
// Variable-length instructions in ia32/x64 have unaligned immediates.
StoreUnaligned(reinterpret_cast<T*>(contents_ + position), value);
#else
// Other architecture have aligned, fixed-length instructions.
*reinterpret_cast<T*>(contents_ + position) = value;
#endif
}
const ZoneGrowableArray<intptr_t>& pointer_offsets() const {

View file

@ -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<ObjectPtr*>(addr);
obj = LoadUnaligned(reinterpret_cast<ObjectPtr*>(addr));
THR_Print(" %d : %#" Px " '%s'\n", code.GetPointerOffsetAt(i), addr,
obj.ToCString());
}

View file

@ -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<int32_t*>(modrmp + 1);
int32_t disp = LoadUnaligned(reinterpret_cast<int32_t*>(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<int32_t*>(modrmp + 2);
int32_t disp = LoadUnaligned(reinterpret_cast<int32_t*>(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<int32_t*>(modrmp + 2)
: *reinterpret_cast<int8_t*>(modrmp + 2);
int disp = (mod == 2)
? LoadUnaligned(reinterpret_cast<int32_t*>(modrmp + 2))
: *reinterpret_cast<int8_t*>(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<int32_t*>(modrmp + 1)
: *reinterpret_cast<int8_t*>(modrmp + 1);
int disp = (mod == 2)
? LoadUnaligned(reinterpret_cast<int32_t*>(modrmp + 1))
: *reinterpret_cast<int8_t*>(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<int16_t*>(data);
value = LoadUnaligned(reinterpret_cast<int16_t*>(data));
} else {
value = *reinterpret_cast<uint16_t*>(data);
value = LoadUnaligned(reinterpret_cast<uint16_t*>(data));
}
count = 2;
break;
case DOUBLEWORD_SIZE:
case QUADWORD_SIZE:
if (sign_extend) {
value = *reinterpret_cast<int32_t*>(data);
value = LoadUnaligned(reinterpret_cast<int32_t*>(data));
} else {
value = *reinterpret_cast<uint32_t*>(data);
value = LoadUnaligned(reinterpret_cast<uint32_t*>(data));
}
count = 4;
break;
@ -525,21 +528,21 @@ void DisassemblerX64::PrintImmediateValue(int64_t value,
if (byte_count == 1) {
int8_t v8 = static_cast<int8_t>(value);
if (v8 < 0 && signed_value) {
Print("-%#" Px32, static_cast<int8_t>(-v8));
Print("-%#" Px32, -static_cast<uint8_t>(v8));
} else {
Print("%#" Px32, static_cast<uint8_t>(v8));
}
} else if (byte_count == 2) {
int16_t v16 = static_cast<int16_t>(value);
if (v16 < 0 && signed_value) {
Print("-%#" Px32, static_cast<int16_t>(-v16));
Print("-%#" Px32, -static_cast<uint16_t>(v16));
} else {
Print("%#" Px32, static_cast<uint16_t>(v16));
}
} else if (byte_count == 4) {
int32_t v32 = static_cast<int32_t>(value);
if (v32 < 0 && signed_value) {
Print("-%#010" Px32, static_cast<int32_t>(-v32));
Print("-%#010" Px32, -static_cast<uint32_t>(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<int64_t>(value);
if (v64 < 0 && signed_value) {
Print("-%#018" Px64, static_cast<int64_t>(-v64));
Print("-%#018" Px64, -static_cast<uint64_t>(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<uint8_t*>(reinterpret_cast<uintptr_t>(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<int32_t*>(data + 2) + 6;
int32_t disp = LoadUnaligned(reinterpret_cast<int32_t*>(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<int16_t*>(*data + 1);
addr = LoadUnaligned(reinterpret_cast<int16_t*>(*data + 1));
imm_bytes = 2;
break;
case DOUBLEWORD_SIZE:
addr = *reinterpret_cast<int32_t*>(*data + 1);
addr = LoadUnaligned(reinterpret_cast<int32_t*>(*data + 1));
imm_bytes = 4;
break;
case QUADWORD_SIZE:
addr = *reinterpret_cast<int64_t*>(*data + 1);
addr = LoadUnaligned(reinterpret_cast<int64_t*>(*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<int32_t*>(*data + 1) + 5;
int32_t disp = LoadUnaligned(reinterpret_cast<int32_t*>(*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, &regop, &rm);
int32_t imm =
*data == 0x6B ? *(data + 2) : *reinterpret_cast<int32_t*>(data + 2);
int32_t imm = *data == 0x6B
? *(data + 2)
: LoadUnaligned(reinterpret_cast<int32_t*>(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<int32_t*>(data + 1));
PrintImmediateValue(
LoadUnaligned(reinterpret_cast<int32_t*>(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<ObjectPtr*>(addr));
*object =
&Object::Handle(LoadUnaligned(reinterpret_cast<ObjectPtr*>(addr)));
break;
}
}

View file

@ -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<uintptr_t>(registers) - 1);
}
return count;
}

View file

@ -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,

View file

@ -1827,7 +1827,7 @@ RangeBoundary RangeBoundary::Shl(const RangeBoundary& value_boundary,
} else if (shift_count == 0 ||
(limit > 0 && Utils::IsInt(static_cast<int>(limit), value))) {
// Result stays in 64 bit range.
const int64_t result = value << shift_count;
const int64_t result = static_cast<uint64_t>(value) << shift_count;
return RangeBoundary(result);
}

View file

@ -277,7 +277,7 @@ class FunctionNodeHelper {
kEnd,
};
enum AsyncMarker {
enum AsyncMarker : intptr_t {
kSync = 0,
kSyncStar = 1,
kAsync = 2,

View file

@ -5,6 +5,8 @@
#include <memory>
#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<Dart_CObject_Type>(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 =

View file

@ -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 {

View file

@ -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 <typename T>
T Read(uint8_t end_byte_marker) {
using Unsigned = typename std::make_unsigned<T>::type;
const uint8_t* c = current_;
ASSERT(c < end_);
uint8_t b = *c++;
if (b > kMaxUnsignedDataPerByte) {
current_ = c;
return static_cast<T>(b) - end_byte_marker;
return static_cast<Unsigned>(b) - end_byte_marker;
}
T r = 0;
uint8_t s = 0;
do {
r |= static_cast<T>(b) << s;
r |= static_cast<Unsigned>(b) << s;
s += kDataBitsPerByte;
ASSERT(c < end_);
b = *c++;
} while (b <= kMaxUnsignedDataPerByte);
current_ = c;
return r | ((static_cast<T>(b) - end_byte_marker) << s);
return r | ((static_cast<Unsigned>(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;
}

View file

@ -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<uintptr_t>(dest_slot)
<< SourceKindField::bitsize()));
}
static intptr_t EncodePairSource(intptr_t src_lo_slot, intptr_t src_hi_slot) {

View file

@ -158,7 +158,7 @@ class Flag {
OptionHandler option_handler_;
};
FlagType type_;
bool changed_;
bool changed_ = false;
};
Flag* Flags::Lookup(const char* name) {

View file

@ -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<intptr_t>(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<intptr_t>(after.CombinedUsedInWords() /
desired_utilization_) -
(after.CombinedUsedInWords())) /
kPageSizeInWords;
}
// Apply growth cap.
growth_in_pages =

View file

@ -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<int32_t*>(start);
int32_t offset = LoadUnaligned(reinterpret_cast<int32_t*>(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<int32_t*>(pc + 3);
int32_t offset = LoadUnaligned(reinterpret_cast<int32_t*>(pc + 3));
return Thread::ObjectAtOffset(offset, obj);
}
if ((bytes[2] & 0xc7) == (0x40 | (THR & 7))) { // [r14+disp8]

View file

@ -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<PcRelativeCallPattern> {
explicit PcRelativeCallPattern(uword pc) : InstructionPattern(pc) {}
int32_t distance() {
return *reinterpret_cast<int32_t*>(start() + 1) + kLengthInBytes;
return LoadUnaligned(reinterpret_cast<int32_t*>(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<int32_t*>(start() + 1) = distance - kLengthInBytes;
StoreUnaligned(reinterpret_cast<int32_t*>(start() + 1),
distance - kLengthInBytes);
}
static const int* pattern() {
@ -162,13 +165,15 @@ class PcRelativeTrampolineJumpPattern : public ValueObject {
}
int32_t distance() {
return *reinterpret_cast<int32_t*>(pattern_start_ + 1) + kLengthInBytes;
return LoadUnaligned(reinterpret_cast<int32_t*>(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<int32_t*>(pattern_start_ + 1) = distance - kLengthInBytes;
StoreUnaligned(reinterpret_cast<int32_t*>(pattern_start_ + 1),
distance - kLengthInBytes);
}
bool IsValid() const {

View file

@ -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<const uint32_t*>(raw_buffer_ + offset);
value = LoadUnaligned(
reinterpret_cast<const uint32_t*>(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<const double*>(&this->buffer()[offset_]));
offset_ += 8;
return value;

View file

@ -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<T>(offset) = value;
}
template <typename T>
void StoreUnaligned(uword offset, T value) const {
dart::StoreUnaligned(ComputeInternalPointer<T>(offset), value);
}
template <typename T>
T* PointerTo(uword offset) const {
return ComputeInternalPointer<T>(offset);

View file

@ -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<BoolPtr>(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<Object**>(addr);
const Object* object = LoadUnaligned(reinterpret_cast<Object**>(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<ObjectPtr*>(addr),
object->raw());
code.raw()->ptr()->StorePointerUnaligned(
reinterpret_cast<ObjectPtr*>(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<uint64_t>(-value));
return OS::SCreate(zone, "-0x%" PX64, -static_cast<uint64_t>(value));
} else {
return OS::SCreate(zone, "0x%" PX64, static_cast<uint64_t>(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<const simd128_value_t*>(&raw_ptr()->value_));
}
@ -22976,7 +22979,7 @@ int32_t Int32x4::w() const {
}
simd128_value_t Int32x4::value() const {
return ReadUnaligned(
return LoadUnaligned(
reinterpret_cast<const simd128_value_t*>(&raw_ptr()->value_));
}

View file

@ -9796,7 +9796,7 @@ class TypedData : public TypedDataBase {
ASSERT((byte_offset >= 0) && \
(byte_offset + static_cast<intptr_t>(sizeof(type)) - 1) < \
LengthInBytes()); \
return ReadUnaligned(ReadOnlyDataAddr<type>(byte_offset)); \
return LoadUnaligned(ReadOnlyDataAddr<type>(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<type*>(DataAddr(byte_offset))); \
return LoadUnaligned(reinterpret_cast<type*>(DataAddr(byte_offset))); \
} \
void Set##name(intptr_t byte_offset, type value) const { \
StoreUnaligned(reinterpret_cast<type*>(DataAddr(byte_offset)), value); \

View file

@ -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<ObjectPtr*>(base_address + offset);
ObjectPtr raw_object = *object_ptr;
ObjectPtr raw_object = LoadUnaligned(object_ptr);
if (!raw_object->IsHeapObject()) {
continue;
}

View file

@ -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();
}
}
}

View file

@ -537,6 +537,14 @@ class ObjectLayout {
}
}
template <typename type>
void StorePointerUnaligned(type const* addr, type value, Thread* thread) {
StoreUnaligned(const_cast<type*>(addr), value);
if (value->IsHeapObject()) {
CheckHeapPointerStore(value, thread);
}
}
DART_FORCE_INLINE
void CheckHeapPointerStore(ObjectPtr value, Thread* thread) {
uint32_t source_tags = this->tags_;

View file

@ -155,7 +155,7 @@ class Snapshot {
template <typename T>
T Read(intptr_t offset) const {
return ReadUnaligned(
return LoadUnaligned(
reinterpret_cast<const T*>(reinterpret_cast<uword>(this) + offset));
}

View file

@ -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;

View file

@ -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",

View file

@ -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