summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Mathieu Chartier <mathieuc@google.com> 2016-02-16 14:06:35 -0800
committer Mathieu Chartier <mathieuc@google.com> 2016-02-16 15:02:22 -0800
commit361e04aaa5d3eca9f978a802ee44b1213f31da58 (patch)
treed7dc0fb40c2fedbb9aad37fd8f9aba48fc4a6a26
parent88f38e9b4e9ba0aca3d6fd4823be3a7226c87f33 (diff)
Add custom arena deleter for RegisterLine
Previously it protected by using sizeof(RegisterLine) but this was not accurate due to register lines being variable sized. Bug: 27156726 Change-Id: Ia4b134b85a2e61993d17bd4f0eff60c89c164dc3
-rw-r--r--runtime/base/scoped_arena_containers.h18
-rw-r--r--runtime/verifier/method_verifier.cc6
-rw-r--r--runtime/verifier/method_verifier.h8
-rw-r--r--runtime/verifier/register_line-inl.h13
-rw-r--r--runtime/verifier/register_line.h10
5 files changed, 41 insertions, 14 deletions
diff --git a/runtime/base/scoped_arena_containers.h b/runtime/base/scoped_arena_containers.h
index 1236585afd..9b56856f11 100644
--- a/runtime/base/scoped_arena_containers.h
+++ b/runtime/base/scoped_arena_containers.h
@@ -201,22 +201,28 @@ inline ScopedArenaAllocatorAdapter<void> ScopedArenaAllocator::Adapter(ArenaAllo
template <typename T>
class ArenaDelete {
static constexpr uint8_t kMagicFill = 0xCE;
- public:
- void operator()(T* ptr) const {
- ptr->~T();
+ protected:
+ // Used for variable sized objects such as RegisterLine.
+ ALWAYS_INLINE void ProtectMemory(T* ptr, size_t size) const {
if (RUNNING_ON_MEMORY_TOOL > 0) {
// Writing to the memory will fail if it we already destroyed the pointer with
// DestroyOnlyDelete since we make it no access.
- memset(ptr, kMagicFill, sizeof(T));
- MEMORY_TOOL_MAKE_NOACCESS(ptr, sizeof(T));
+ memset(ptr, kMagicFill, size);
+ MEMORY_TOOL_MAKE_NOACCESS(ptr, size);
} else if (kIsDebugBuild) {
CHECK(ArenaStack::ArenaTagForAllocation(reinterpret_cast<void*>(ptr)) == ArenaFreeTag::kUsed)
<< "Freeing invalid object " << ptr;
ArenaStack::ArenaTagForAllocation(reinterpret_cast<void*>(ptr)) = ArenaFreeTag::kFree;
// Write a magic value to try and catch use after free error.
- memset(ptr, kMagicFill, sizeof(T));
+ memset(ptr, kMagicFill, size);
}
}
+
+ public:
+ void operator()(T* ptr) const {
+ ptr->~T();
+ ProtectMemory(ptr, sizeof(T));
+ }
};
// In general we lack support for arrays. We would need to call the destructor on each element,
diff --git a/runtime/verifier/method_verifier.cc b/runtime/verifier/method_verifier.cc
index 1d31408cf0..a6cf9eaf86 100644
--- a/runtime/verifier/method_verifier.cc
+++ b/runtime/verifier/method_verifier.cc
@@ -1960,8 +1960,8 @@ bool MethodVerifier::CodeFlowVerifyInstruction(uint32_t* start_guess) {
// We need to ensure the work line is consistent while performing validation. When we spot a
// peephole pattern we compute a new line for either the fallthrough instruction or the
// branch target.
- ArenaUniquePtr<RegisterLine> branch_line;
- ArenaUniquePtr<RegisterLine> fallthrough_line;
+ RegisterLineArenaUniquePtr branch_line;
+ RegisterLineArenaUniquePtr fallthrough_line;
switch (inst->Opcode()) {
case Instruction::NOP:
@@ -4824,7 +4824,7 @@ bool MethodVerifier::UpdateRegisters(uint32_t next_insn, RegisterLine* merge_lin
AdjustReturnLine(this, ret_inst, target_line);
}
} else {
- ArenaUniquePtr<RegisterLine> copy;
+ RegisterLineArenaUniquePtr copy;
if (kDebugVerify) {
copy.reset(RegisterLine::Create(target_line->NumRegs(), this));
copy->CopyFromLine(target_line);
diff --git a/runtime/verifier/method_verifier.h b/runtime/verifier/method_verifier.h
index c7d1e6bc90..b53a45cf41 100644
--- a/runtime/verifier/method_verifier.h
+++ b/runtime/verifier/method_verifier.h
@@ -30,6 +30,7 @@
#include "handle.h"
#include "instruction_flags.h"
#include "method_reference.h"
+#include "register_line.h"
#include "reg_type_cache.h"
namespace art {
@@ -45,6 +46,7 @@ namespace verifier {
class DexPcToReferenceMap;
class MethodVerifier;
class RegisterLine;
+using RegisterLineArenaUniquePtr = std::unique_ptr<RegisterLine, RegisterLineArenaDelete>;
class RegType;
/*
@@ -127,7 +129,7 @@ class PcToRegisterLineTable {
}
private:
- ScopedArenaVector<ArenaUniquePtr<RegisterLine>> register_lines_;
+ ScopedArenaVector<RegisterLineArenaUniquePtr> register_lines_;
DISALLOW_COPY_AND_ASSIGN(PcToRegisterLineTable);
};
@@ -771,14 +773,14 @@ class MethodVerifier {
PcToRegisterLineTable reg_table_;
// Storage for the register status we're currently working on.
- ArenaUniquePtr<RegisterLine> work_line_;
+ RegisterLineArenaUniquePtr work_line_;
// The address of the instruction we're currently working on, note that this is in 2 byte
// quantities
uint32_t work_insn_idx_;
// Storage for the register status we're saving for later.
- ArenaUniquePtr<RegisterLine> saved_line_;
+ RegisterLineArenaUniquePtr saved_line_;
const uint32_t dex_method_idx_; // The method we're working on.
// Its object representation if known.
diff --git a/runtime/verifier/register_line-inl.h b/runtime/verifier/register_line-inl.h
index 330c06ab46..bfbb78f58a 100644
--- a/runtime/verifier/register_line-inl.h
+++ b/runtime/verifier/register_line-inl.h
@@ -185,9 +185,12 @@ inline void RegisterLine::VerifyMonitorStackEmpty(MethodVerifier* verifier) cons
}
}
+inline size_t RegisterLine::ComputeSize(size_t num_regs) {
+ return OFFSETOF_MEMBER(RegisterLine, line_) + num_regs * sizeof(uint16_t);
+}
+
inline RegisterLine* RegisterLine::Create(size_t num_regs, MethodVerifier* verifier) {
- void* memory = verifier->GetArena().Alloc(OFFSETOF_MEMBER(RegisterLine, line_) +
- (num_regs * sizeof(uint16_t)));
+ void* memory = verifier->GetArena().Alloc(ComputeSize(num_regs));
return new (memory) RegisterLine(num_regs, verifier);
}
@@ -200,6 +203,12 @@ inline RegisterLine::RegisterLine(size_t num_regs, MethodVerifier* verifier)
SetResultTypeToUnknown(verifier);
}
+inline void RegisterLineArenaDelete::operator()(RegisterLine* ptr) const {
+ const size_t size = ptr != nullptr ? RegisterLine::ComputeSize(ptr->NumRegs()) : 0u;
+ ptr->~RegisterLine();
+ ProtectMemory(ptr, size);
+}
+
} // namespace verifier
} // namespace art
diff --git a/runtime/verifier/register_line.h b/runtime/verifier/register_line.h
index b2f5555d8b..d50845421f 100644
--- a/runtime/verifier/register_line.h
+++ b/runtime/verifier/register_line.h
@@ -197,6 +197,9 @@ class RegisterLine {
return num_regs_;
}
+ // Return how many bytes of memory a register line uses.
+ ALWAYS_INLINE static size_t ComputeSize(size_t num_regs);
+
/*
* Get the "this" pointer from a non-static method invocation. This returns the RegType so the
* caller can decide whether it needs the reference to be initialized or not. (Can also return
@@ -401,6 +404,13 @@ class RegisterLine {
DISALLOW_COPY_AND_ASSIGN(RegisterLine);
};
+class RegisterLineArenaDelete : public ArenaDelete<RegisterLine> {
+ public:
+ void operator()(RegisterLine* ptr) const;
+};
+
+
+
} // namespace verifier
} // namespace art