11_mingw_offsetof.patch (7294B)
1 # HG changeset patch 2 # User Tom Ritter <tom@mozilla.com> 3 # Date 1528394907 18000 4 # Thu Jun 07 13:08:27 2018 -0500 5 # Node ID ffb6c5c06905538fb887464e9553e7b47cdf7575 6 # Parent 1987e062f1e5bf2998bb8e9d96353c5ccb0cc281 7 Bug 1461421 Use OffsetOf to calculate the location of parameters_ rather than making assumptions about the parent class r?bobowen 8 9 MozReview-Commit-ID: D7REZiAIMpN 10 11 diff --git a/sandbox/win/src/crosscall_params.h b/sandbox/win/src/crosscall_params.h 12 --- a/sandbox/win/src/crosscall_params.h 13 +++ b/sandbox/win/src/crosscall_params.h 14 @@ -78,16 +78,17 @@ union MultiType { 15 ULONG_PTR ulong_ptr; 16 }; 17 18 // Maximum number of IPC parameters currently supported. 19 // To increase this value, we have to: 20 // - Add another Callback typedef to Dispatcher. 21 // - Add another case to the switch on SharedMemIPCServer::InvokeCallback. 22 // - Add another case to the switch in GetActualAndMaxBufferSize 23 +// - Add another case to the switch in GetMinDeclaredActualCallParamsSize 24 const int kMaxIpcParams = 9; 25 26 // Contains the information about a parameter in the ipc buffer. 27 struct ParamInfo { 28 ArgType type_; 29 uint32_t offset_; 30 uint32_t size_; 31 }; 32 @@ -287,16 +288,18 @@ class ActualCallParams : public CrossCal 33 34 protected: 35 ActualCallParams() : CrossCallParams(IpcTag::UNUSED, NUMBER_PARAMS) {} 36 37 private: 38 ParamInfo param_info_[NUMBER_PARAMS + 1]; 39 char parameters_[BLOCK_SIZE - sizeof(CrossCallParams) - 40 sizeof(ParamInfo) * (NUMBER_PARAMS + 1)]; 41 + 42 + friend uint32_t GetMinDeclaredActualCallParamsSize(uint32_t param_count); 43 }; 44 45 static_assert(sizeof(ActualCallParams<1, 1024>) == 1024, "bad size buffer"); 46 static_assert(sizeof(ActualCallParams<2, 1024>) == 1024, "bad size buffer"); 47 static_assert(sizeof(ActualCallParams<3, 1024>) == 1024, "bad size buffer"); 48 49 } // namespace sandbox 50 51 diff --git a/sandbox/win/src/crosscall_server.cc b/sandbox/win/src/crosscall_server.cc 52 --- a/sandbox/win/src/crosscall_server.cc 53 +++ b/sandbox/win/src/crosscall_server.cc 54 @@ -28,30 +28,31 @@ namespace { 55 56 // The buffer for a message must match the max channel size. 57 const size_t kMaxBufferSize = sandbox::kIPCChannelSize; 58 59 } // namespace 60 61 namespace sandbox { 62 63 +// The template types are used to calculate the maximum expected size. 64 +typedef ActualCallParams<0, kMaxBufferSize> ActualCP0; 65 +typedef ActualCallParams<1, kMaxBufferSize> ActualCP1; 66 +typedef ActualCallParams<2, kMaxBufferSize> ActualCP2; 67 +typedef ActualCallParams<3, kMaxBufferSize> ActualCP3; 68 +typedef ActualCallParams<4, kMaxBufferSize> ActualCP4; 69 +typedef ActualCallParams<5, kMaxBufferSize> ActualCP5; 70 +typedef ActualCallParams<6, kMaxBufferSize> ActualCP6; 71 +typedef ActualCallParams<7, kMaxBufferSize> ActualCP7; 72 +typedef ActualCallParams<8, kMaxBufferSize> ActualCP8; 73 +typedef ActualCallParams<9, kMaxBufferSize> ActualCP9; 74 + 75 // Returns the actual size for the parameters in an IPC buffer. Returns 76 // zero if the |param_count| is zero or too big. 77 uint32_t GetActualBufferSize(uint32_t param_count, void* buffer_base) { 78 - // The template types are used to calculate the maximum expected size. 79 - typedef ActualCallParams<1, kMaxBufferSize> ActualCP1; 80 - typedef ActualCallParams<2, kMaxBufferSize> ActualCP2; 81 - typedef ActualCallParams<3, kMaxBufferSize> ActualCP3; 82 - typedef ActualCallParams<4, kMaxBufferSize> ActualCP4; 83 - typedef ActualCallParams<5, kMaxBufferSize> ActualCP5; 84 - typedef ActualCallParams<6, kMaxBufferSize> ActualCP6; 85 - typedef ActualCallParams<7, kMaxBufferSize> ActualCP7; 86 - typedef ActualCallParams<8, kMaxBufferSize> ActualCP8; 87 - typedef ActualCallParams<9, kMaxBufferSize> ActualCP9; 88 - 89 // Retrieve the actual size and the maximum size of the params buffer. 90 switch (param_count) { 91 case 0: 92 return 0; 93 case 1: 94 return reinterpret_cast<ActualCP1*>(buffer_base)->GetSize(); 95 case 2: 96 return reinterpret_cast<ActualCP2*>(buffer_base)->GetSize(); 97 @@ -69,16 +70,45 @@ uint32_t GetActualBufferSize(uint32_t pa 98 return reinterpret_cast<ActualCP8*>(buffer_base)->GetSize(); 99 case 9: 100 return reinterpret_cast<ActualCP9*>(buffer_base)->GetSize(); 101 default: 102 return 0; 103 } 104 } 105 106 +// Returns the minimum size for the parameters in an IPC buffer. Returns 107 +// zero if the |param_count| is less than zero or too big. 108 +uint32_t GetMinDeclaredActualCallParamsSize(uint32_t param_count) { 109 + switch (param_count) { 110 + case 0: 111 + return offsetof(ActualCP0, parameters_); 112 + case 1: 113 + return offsetof(ActualCP1, parameters_); 114 + case 2: 115 + return offsetof(ActualCP2, parameters_); 116 + case 3: 117 + return offsetof(ActualCP3, parameters_); 118 + case 4: 119 + return offsetof(ActualCP4, parameters_); 120 + case 5: 121 + return offsetof(ActualCP5, parameters_); 122 + case 6: 123 + return offsetof(ActualCP6, parameters_); 124 + case 7: 125 + return offsetof(ActualCP7, parameters_); 126 + case 8: 127 + return offsetof(ActualCP8, parameters_); 128 + case 9: 129 + return offsetof(ActualCP9, parameters_); 130 + default: 131 + return 0; 132 + } 133 +} 134 + 135 // Verifies that the declared sizes of an IPC buffer are within range. 136 bool IsSizeWithinRange(uint32_t buffer_size, 137 uint32_t min_declared_size, 138 uint32_t declared_size) { 139 if ((buffer_size < min_declared_size) || 140 (sizeof(CrossCallParamsEx) > min_declared_size)) { 141 // Minimal computed size bigger than existing buffer or param_count 142 // integer overflow. 143 @@ -133,18 +163,17 @@ CrossCallParamsEx* CrossCallParamsEx::Cr 144 // will catch memory access violations so we don't crash. 145 __try { 146 CrossCallParams* call_params = 147 reinterpret_cast<CrossCallParams*>(buffer_base); 148 149 // Check against the minimum size given the number of stated params 150 // if too small we bail out. 151 param_count = call_params->GetParamsCount(); 152 - min_declared_size = 153 - sizeof(CrossCallParams) + ((param_count + 1) * sizeof(ParamInfo)); 154 + min_declared_size = GetMinDeclaredActualCallParamsSize(param_count); 155 156 // Initial check for the buffer being big enough to determine the actual 157 // buffer size. 158 if (buffer_size < min_declared_size) 159 return nullptr; 160 161 // Retrieve the declared size which if it fails returns 0. 162 declared_size = GetActualBufferSize(param_count, buffer_base); 163 @@ -158,18 +187,17 @@ CrossCallParamsEx* CrossCallParamsEx::Cr 164 copied_params = reinterpret_cast<CrossCallParamsEx*>(backing_mem); 165 memcpy(backing_mem, call_params, declared_size); 166 167 // Avoid compiler optimizations across this point. Any value stored in 168 // memory should be stored for real, and values previously read from memory 169 // should be actually read. 170 std::atomic_thread_fence(std::memory_order_seq_cst); 171 172 - min_declared_size = 173 - sizeof(CrossCallParams) + ((param_count + 1) * sizeof(ParamInfo)); 174 + min_declared_size = GetMinDeclaredActualCallParamsSize(param_count); 175 176 // Check that the copied buffer is still valid. 177 if (copied_params->GetParamsCount() != param_count || 178 GetActualBufferSize(param_count, backing_mem) != declared_size || 179 !IsSizeWithinRange(buffer_size, min_declared_size, declared_size)) { 180 delete[] backing_mem; 181 return nullptr; 182 }