security/sandbox/chromium/base/win/scoped_handle.h

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

michael@0 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
michael@0 2 // Use of this source code is governed by a BSD-style license that can be
michael@0 3 // found in the LICENSE file.
michael@0 4
michael@0 5 #ifndef BASE_WIN_SCOPED_HANDLE_H_
michael@0 6 #define BASE_WIN_SCOPED_HANDLE_H_
michael@0 7
michael@0 8 #include <windows.h>
michael@0 9
michael@0 10 #include "base/base_export.h"
michael@0 11 #include "base/basictypes.h"
michael@0 12 #include "base/location.h"
michael@0 13 #include "base/logging.h"
michael@0 14 #include "base/move.h"
michael@0 15
michael@0 16 namespace base {
michael@0 17 namespace win {
michael@0 18
michael@0 19 // TODO(rvargas): remove this with the rest of the verifier.
michael@0 20 #if defined(COMPILER_MSVC)
michael@0 21 // MSDN says to #include <intrin.h>, but that breaks the VS2005 build.
michael@0 22 extern "C" {
michael@0 23 void* _ReturnAddress();
michael@0 24 }
michael@0 25 #define BASE_WIN_GET_CALLER _ReturnAddress()
michael@0 26 #elif defined(COMPILER_GCC)
michael@0 27 #define BASE_WIN_GET_CALLER __builtin_extract_return_addr(\\
michael@0 28 __builtin_return_address(0))
michael@0 29 #endif
michael@0 30
michael@0 31 // Generic wrapper for raw handles that takes care of closing handles
michael@0 32 // automatically. The class interface follows the style of
michael@0 33 // the ScopedStdioHandle class with a few additions:
michael@0 34 // - IsValid() method can tolerate multiple invalid handle values such as NULL
michael@0 35 // and INVALID_HANDLE_VALUE (-1) for Win32 handles.
michael@0 36 // - Receive() method allows to receive a handle value from a function that
michael@0 37 // takes a raw handle pointer only.
michael@0 38 template <class Traits, class Verifier>
michael@0 39 class GenericScopedHandle {
michael@0 40 MOVE_ONLY_TYPE_FOR_CPP_03(GenericScopedHandle, RValue)
michael@0 41
michael@0 42 public:
michael@0 43 typedef typename Traits::Handle Handle;
michael@0 44
michael@0 45 // Helper object to contain the effect of Receive() to the function that needs
michael@0 46 // a pointer, and allow proper tracking of the handle.
michael@0 47 class Receiver {
michael@0 48 public:
michael@0 49 explicit Receiver(GenericScopedHandle* owner)
michael@0 50 : handle_(Traits::NullHandle()),
michael@0 51 owner_(owner) {}
michael@0 52 ~Receiver() { owner_->Set(handle_); }
michael@0 53
michael@0 54 operator Handle*() { return &handle_; }
michael@0 55
michael@0 56 private:
michael@0 57 Handle handle_;
michael@0 58 GenericScopedHandle* owner_;
michael@0 59 };
michael@0 60
michael@0 61 GenericScopedHandle() : handle_(Traits::NullHandle()) {}
michael@0 62
michael@0 63 explicit GenericScopedHandle(Handle handle) : handle_(Traits::NullHandle()) {
michael@0 64 Set(handle);
michael@0 65 }
michael@0 66
michael@0 67 // Move constructor for C++03 move emulation of this type.
michael@0 68 GenericScopedHandle(RValue other) : handle_(Traits::NullHandle()) {
michael@0 69 Set(other.object->Take());
michael@0 70 }
michael@0 71
michael@0 72 ~GenericScopedHandle() {
michael@0 73 Close();
michael@0 74 }
michael@0 75
michael@0 76 bool IsValid() const {
michael@0 77 return Traits::IsHandleValid(handle_);
michael@0 78 }
michael@0 79
michael@0 80 // Move operator= for C++03 move emulation of this type.
michael@0 81 GenericScopedHandle& operator=(RValue other) {
michael@0 82 if (this != other.object) {
michael@0 83 Set(other.object->Take());
michael@0 84 }
michael@0 85 return *this;
michael@0 86 }
michael@0 87
michael@0 88 void Set(Handle handle) {
michael@0 89 if (handle_ != handle) {
michael@0 90 Close();
michael@0 91
michael@0 92 if (Traits::IsHandleValid(handle)) {
michael@0 93 handle_ = handle;
michael@0 94 Verifier::StartTracking(handle, this, BASE_WIN_GET_CALLER,
michael@0 95 tracked_objects::GetProgramCounter());
michael@0 96 }
michael@0 97 }
michael@0 98 }
michael@0 99
michael@0 100 Handle Get() const {
michael@0 101 return handle_;
michael@0 102 }
michael@0 103
michael@0 104 operator Handle() const {
michael@0 105 return handle_;
michael@0 106 }
michael@0 107
michael@0 108 // This method is intended to be used with functions that require a pointer to
michael@0 109 // a destination handle, like so:
michael@0 110 // void CreateRequiredHandle(Handle* out_handle);
michael@0 111 // ScopedHandle a;
michael@0 112 // CreateRequiredHandle(a.Receive());
michael@0 113 Receiver Receive() {
michael@0 114 DCHECK(!Traits::IsHandleValid(handle_)) << "Handle must be NULL";
michael@0 115 return Receiver(this);
michael@0 116 }
michael@0 117
michael@0 118 // Transfers ownership away from this object.
michael@0 119 Handle Take() {
michael@0 120 Handle temp = handle_;
michael@0 121 handle_ = Traits::NullHandle();
michael@0 122 if (Traits::IsHandleValid(temp)) {
michael@0 123 Verifier::StopTracking(temp, this, BASE_WIN_GET_CALLER,
michael@0 124 tracked_objects::GetProgramCounter());
michael@0 125 }
michael@0 126 return temp;
michael@0 127 }
michael@0 128
michael@0 129 // Explicitly closes the owned handle.
michael@0 130 void Close() {
michael@0 131 if (Traits::IsHandleValid(handle_)) {
michael@0 132 Verifier::StopTracking(handle_, this, BASE_WIN_GET_CALLER,
michael@0 133 tracked_objects::GetProgramCounter());
michael@0 134
michael@0 135 if (!Traits::CloseHandle(handle_))
michael@0 136 CHECK(false);
michael@0 137
michael@0 138 handle_ = Traits::NullHandle();
michael@0 139 }
michael@0 140 }
michael@0 141
michael@0 142 private:
michael@0 143 Handle handle_;
michael@0 144 };
michael@0 145
michael@0 146 #undef BASE_WIN_GET_CALLER
michael@0 147
michael@0 148 // The traits class for Win32 handles that can be closed via CloseHandle() API.
michael@0 149 class HandleTraits {
michael@0 150 public:
michael@0 151 typedef HANDLE Handle;
michael@0 152
michael@0 153 // Closes the handle.
michael@0 154 static bool CloseHandle(HANDLE handle) {
michael@0 155 return ::CloseHandle(handle) != FALSE;
michael@0 156 }
michael@0 157
michael@0 158 // Returns true if the handle value is valid.
michael@0 159 static bool IsHandleValid(HANDLE handle) {
michael@0 160 return handle != NULL && handle != INVALID_HANDLE_VALUE;
michael@0 161 }
michael@0 162
michael@0 163 // Returns NULL handle value.
michael@0 164 static HANDLE NullHandle() {
michael@0 165 return NULL;
michael@0 166 }
michael@0 167
michael@0 168 private:
michael@0 169 DISALLOW_IMPLICIT_CONSTRUCTORS(HandleTraits);
michael@0 170 };
michael@0 171
michael@0 172 // Do-nothing verifier.
michael@0 173 class DummyVerifierTraits {
michael@0 174 public:
michael@0 175 typedef HANDLE Handle;
michael@0 176
michael@0 177 static void StartTracking(HANDLE handle, const void* owner,
michael@0 178 const void* pc1, const void* pc2) {}
michael@0 179 static void StopTracking(HANDLE handle, const void* owner,
michael@0 180 const void* pc1, const void* pc2) {}
michael@0 181
michael@0 182 private:
michael@0 183 DISALLOW_IMPLICIT_CONSTRUCTORS(DummyVerifierTraits);
michael@0 184 };
michael@0 185
michael@0 186 // Performs actual run-time tracking.
michael@0 187 class BASE_EXPORT VerifierTraits {
michael@0 188 public:
michael@0 189 typedef HANDLE Handle;
michael@0 190
michael@0 191 static void StartTracking(HANDLE handle, const void* owner,
michael@0 192 const void* pc1, const void* pc2);
michael@0 193 static void StopTracking(HANDLE handle, const void* owner,
michael@0 194 const void* pc1, const void* pc2);
michael@0 195
michael@0 196 private:
michael@0 197 DISALLOW_IMPLICIT_CONSTRUCTORS(VerifierTraits);
michael@0 198 };
michael@0 199
michael@0 200 typedef GenericScopedHandle<HandleTraits, VerifierTraits> ScopedHandle;
michael@0 201
michael@0 202 } // namespace win
michael@0 203 } // namespace base
michael@0 204
michael@0 205 #endif // BASE_SCOPED_HANDLE_WIN_H_

mercurial