1 | /* |
2 | * Copyright (C) 2010, 2011 Apple Inc. All rights reserved. |
3 | * |
4 | * Redistribution and use in source and binary forms, with or without |
5 | * modification, are permitted provided that the following conditions |
6 | * are met: |
7 | * 1. Redistributions of source code must retain the above copyright |
8 | * notice, this list of conditions and the following disclaimer. |
9 | * 2. Redistributions in binary form must reproduce the above copyright |
10 | * notice, this list of conditions and the following disclaimer in the |
11 | * documentation and/or other materials provided with the distribution. |
12 | * |
13 | * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' |
14 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, |
15 | * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
16 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS |
17 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
18 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
19 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
20 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
21 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
22 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF |
23 | * THE POSSIBILITY OF SUCH DAMAGE. |
24 | */ |
25 | |
26 | #include "config.h" |
27 | #include "Decoder.h" |
28 | |
29 | #include "DataReference.h" |
30 | #include "MessageFlags.h" |
31 | #include <stdio.h> |
32 | |
33 | #if PLATFORM(MAC) |
34 | #include "ImportanceAssertion.h" |
35 | #endif |
36 | |
37 | namespace IPC { |
38 | |
39 | static const uint8_t* copyBuffer(const uint8_t* buffer, size_t bufferSize) |
40 | { |
41 | auto bufferCopy = static_cast<uint8_t*>(fastMalloc(bufferSize)); |
42 | memcpy(bufferCopy, buffer, bufferSize); |
43 | |
44 | return bufferCopy; |
45 | } |
46 | |
47 | Decoder::Decoder(const uint8_t* buffer, size_t bufferSize, void (*bufferDeallocator)(const uint8_t*, size_t), Vector<Attachment>&& attachments) |
48 | : m_buffer { bufferDeallocator ? buffer : copyBuffer(buffer, bufferSize) } |
49 | , m_bufferPos { m_buffer } |
50 | , m_bufferEnd { m_buffer + bufferSize } |
51 | , m_bufferDeallocator { bufferDeallocator } |
52 | , m_attachments { WTFMove(attachments) } |
53 | { |
54 | ASSERT(!(reinterpret_cast<uintptr_t>(m_buffer) % alignof(uint64_t))); |
55 | |
56 | if (!decode(m_messageFlags)) |
57 | return; |
58 | |
59 | if (!decode(m_messageReceiverName)) |
60 | return; |
61 | |
62 | if (!decode(m_messageName)) |
63 | return; |
64 | |
65 | if (!decode(m_destinationID)) |
66 | return; |
67 | } |
68 | |
69 | Decoder::~Decoder() |
70 | { |
71 | ASSERT(m_buffer); |
72 | |
73 | if (m_bufferDeallocator) |
74 | m_bufferDeallocator(m_buffer, m_bufferEnd - m_buffer); |
75 | else |
76 | fastFree(const_cast<uint8_t*>(m_buffer)); |
77 | |
78 | // FIXME: We need to dispose of the mach ports in cases of failure. |
79 | |
80 | #if HAVE(QOS_CLASSES) |
81 | if (m_qosClassOverride) |
82 | pthread_override_qos_class_end_np(m_qosClassOverride); |
83 | #endif |
84 | } |
85 | |
86 | bool Decoder::isSyncMessage() const |
87 | { |
88 | return m_messageFlags & SyncMessage; |
89 | } |
90 | |
91 | bool Decoder::shouldDispatchMessageWhenWaitingForSyncReply() const |
92 | { |
93 | return m_messageFlags & DispatchMessageWhenWaitingForSyncReply; |
94 | } |
95 | |
96 | bool Decoder::shouldUseFullySynchronousModeForTesting() const |
97 | { |
98 | return m_messageFlags & UseFullySynchronousModeForTesting; |
99 | } |
100 | |
101 | #if PLATFORM(MAC) |
102 | void Decoder::setImportanceAssertion(std::unique_ptr<ImportanceAssertion> assertion) |
103 | { |
104 | m_importanceAssertion = WTFMove(assertion); |
105 | } |
106 | #endif |
107 | |
108 | std::unique_ptr<Decoder> Decoder::unwrapForTesting(Decoder& decoder) |
109 | { |
110 | ASSERT(decoder.isSyncMessage()); |
111 | |
112 | Vector<Attachment> attachments; |
113 | Attachment attachment; |
114 | while (decoder.removeAttachment(attachment)) |
115 | attachments.append(WTFMove(attachment)); |
116 | attachments.reverse(); |
117 | |
118 | DataReference wrappedMessage; |
119 | if (!decoder.decode(wrappedMessage)) |
120 | return nullptr; |
121 | |
122 | return std::make_unique<Decoder>(wrappedMessage.data(), wrappedMessage.size(), nullptr, WTFMove(attachments)); |
123 | } |
124 | |
125 | static inline const uint8_t* roundUpToAlignment(const uint8_t* ptr, unsigned alignment) |
126 | { |
127 | // Assert that the alignment is a power of 2. |
128 | ASSERT(alignment && !(alignment & (alignment - 1))); |
129 | |
130 | uintptr_t alignmentMask = alignment - 1; |
131 | return reinterpret_cast<uint8_t*>((reinterpret_cast<uintptr_t>(ptr) + alignmentMask) & ~alignmentMask); |
132 | } |
133 | |
134 | static inline bool alignedBufferIsLargeEnoughToContain(const uint8_t* alignedPosition, const uint8_t* bufferEnd, size_t size) |
135 | { |
136 | return bufferEnd >= alignedPosition && static_cast<size_t>(bufferEnd - alignedPosition) >= size; |
137 | } |
138 | |
139 | bool Decoder::alignBufferPosition(unsigned alignment, size_t size) |
140 | { |
141 | const uint8_t* alignedPosition = roundUpToAlignment(m_bufferPos, alignment); |
142 | if (!alignedBufferIsLargeEnoughToContain(alignedPosition, m_bufferEnd, size)) { |
143 | // We've walked off the end of this buffer. |
144 | markInvalid(); |
145 | return false; |
146 | } |
147 | |
148 | m_bufferPos = alignedPosition; |
149 | return true; |
150 | } |
151 | |
152 | bool Decoder::bufferIsLargeEnoughToContain(unsigned alignment, size_t size) const |
153 | { |
154 | return alignedBufferIsLargeEnoughToContain(roundUpToAlignment(m_bufferPos, alignment), m_bufferEnd, size); |
155 | } |
156 | |
157 | bool Decoder::decodeFixedLengthData(uint8_t* data, size_t size, unsigned alignment) |
158 | { |
159 | if (!alignBufferPosition(alignment, size)) |
160 | return false; |
161 | |
162 | memcpy(data, m_bufferPos, size); |
163 | m_bufferPos += size; |
164 | |
165 | return true; |
166 | } |
167 | |
168 | bool Decoder::decodeVariableLengthByteArray(DataReference& dataReference) |
169 | { |
170 | uint64_t size; |
171 | if (!decode(size)) |
172 | return false; |
173 | |
174 | if (!alignBufferPosition(1, size)) |
175 | return false; |
176 | |
177 | const uint8_t* data = m_bufferPos; |
178 | m_bufferPos += size; |
179 | |
180 | dataReference = DataReference(data, size); |
181 | return true; |
182 | } |
183 | |
184 | template<typename Type> |
185 | static void decodeValueFromBuffer(Type& value, const uint8_t*& bufferPosition) |
186 | { |
187 | memcpy(&value, bufferPosition, sizeof(value)); |
188 | bufferPosition += sizeof(Type); |
189 | } |
190 | |
191 | template<typename Type> |
192 | Decoder& Decoder::getOptional(Optional<Type>& optional) |
193 | { |
194 | Type result; |
195 | if (!alignBufferPosition(sizeof(result), sizeof(result))) |
196 | return *this; |
197 | |
198 | decodeValueFromBuffer(result, m_bufferPos); |
199 | optional = result; |
200 | return *this; |
201 | } |
202 | |
203 | Decoder& Decoder::operator>>(Optional<bool>& optional) |
204 | { |
205 | return getOptional(optional); |
206 | } |
207 | |
208 | Decoder& Decoder::operator>>(Optional<uint8_t>& optional) |
209 | { |
210 | return getOptional(optional); |
211 | } |
212 | |
213 | Decoder& Decoder::operator>>(Optional<uint16_t>& optional) |
214 | { |
215 | return getOptional(optional); |
216 | } |
217 | |
218 | Decoder& Decoder::operator>>(Optional<uint32_t>& optional) |
219 | { |
220 | return getOptional(optional); |
221 | } |
222 | |
223 | Decoder& Decoder::operator>>(Optional<uint64_t>& optional) |
224 | { |
225 | return getOptional(optional); |
226 | } |
227 | |
228 | Decoder& Decoder::operator>>(Optional<int16_t>& optional) |
229 | { |
230 | return getOptional(optional); |
231 | } |
232 | |
233 | Decoder& Decoder::operator>>(Optional<int32_t>& optional) |
234 | { |
235 | return getOptional(optional); |
236 | } |
237 | |
238 | Decoder& Decoder::operator>>(Optional<int64_t>& optional) |
239 | { |
240 | return getOptional(optional); |
241 | } |
242 | |
243 | Decoder& Decoder::operator>>(Optional<float>& optional) |
244 | { |
245 | return getOptional(optional); |
246 | } |
247 | |
248 | Decoder& Decoder::operator>>(Optional<double>& optional) |
249 | { |
250 | return getOptional(optional); |
251 | } |
252 | |
253 | bool Decoder::decode(bool& result) |
254 | { |
255 | if (!alignBufferPosition(sizeof(result), sizeof(result))) |
256 | return false; |
257 | |
258 | decodeValueFromBuffer(result, m_bufferPos); |
259 | return true; |
260 | } |
261 | |
262 | bool Decoder::decode(uint8_t& result) |
263 | { |
264 | if (!alignBufferPosition(sizeof(result), sizeof(result))) |
265 | return false; |
266 | |
267 | decodeValueFromBuffer(result, m_bufferPos); |
268 | return true; |
269 | } |
270 | |
271 | bool Decoder::decode(uint16_t& result) |
272 | { |
273 | if (!alignBufferPosition(sizeof(result), sizeof(result))) |
274 | return false; |
275 | |
276 | decodeValueFromBuffer(result, m_bufferPos); |
277 | return true; |
278 | } |
279 | |
280 | bool Decoder::decode(uint32_t& result) |
281 | { |
282 | if (!alignBufferPosition(sizeof(result), sizeof(result))) |
283 | return false; |
284 | |
285 | decodeValueFromBuffer(result, m_bufferPos); |
286 | return true; |
287 | } |
288 | |
289 | bool Decoder::decode(uint64_t& result) |
290 | { |
291 | if (!alignBufferPosition(sizeof(result), sizeof(result))) |
292 | return false; |
293 | |
294 | decodeValueFromBuffer(result, m_bufferPos); |
295 | return true; |
296 | } |
297 | |
298 | bool Decoder::decode(int16_t& result) |
299 | { |
300 | if (!alignBufferPosition(sizeof(result), sizeof(result))) |
301 | return false; |
302 | |
303 | decodeValueFromBuffer(result, m_bufferPos); |
304 | return true; |
305 | } |
306 | |
307 | bool Decoder::decode(int32_t& result) |
308 | { |
309 | if (!alignBufferPosition(sizeof(result), sizeof(result))) |
310 | return false; |
311 | |
312 | decodeValueFromBuffer(result, m_bufferPos); |
313 | return true; |
314 | } |
315 | |
316 | bool Decoder::decode(int64_t& result) |
317 | { |
318 | if (!alignBufferPosition(sizeof(result), sizeof(result))) |
319 | return false; |
320 | |
321 | decodeValueFromBuffer(result, m_bufferPos); |
322 | return true; |
323 | } |
324 | |
325 | bool Decoder::decode(float& result) |
326 | { |
327 | if (!alignBufferPosition(sizeof(result), sizeof(result))) |
328 | return false; |
329 | |
330 | decodeValueFromBuffer(result, m_bufferPos); |
331 | return true; |
332 | } |
333 | |
334 | bool Decoder::decode(double& result) |
335 | { |
336 | if (!alignBufferPosition(sizeof(result), sizeof(result))) |
337 | return false; |
338 | |
339 | decodeValueFromBuffer(result, m_bufferPos); |
340 | return true; |
341 | } |
342 | |
343 | bool Decoder::removeAttachment(Attachment& attachment) |
344 | { |
345 | if (m_attachments.isEmpty()) |
346 | return false; |
347 | |
348 | attachment = m_attachments.takeLast(); |
349 | return true; |
350 | } |
351 | |
352 | } // namespace IPC |
353 | |