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
37namespace IPC {
38
39static 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
47Decoder::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
69Decoder::~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
86bool Decoder::isSyncMessage() const
87{
88 return m_messageFlags & SyncMessage;
89}
90
91bool Decoder::shouldDispatchMessageWhenWaitingForSyncReply() const
92{
93 return m_messageFlags & DispatchMessageWhenWaitingForSyncReply;
94}
95
96bool Decoder::shouldUseFullySynchronousModeForTesting() const
97{
98 return m_messageFlags & UseFullySynchronousModeForTesting;
99}
100
101#if PLATFORM(MAC)
102void Decoder::setImportanceAssertion(std::unique_ptr<ImportanceAssertion> assertion)
103{
104 m_importanceAssertion = WTFMove(assertion);
105}
106#endif
107
108std::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
125static 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
134static 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
139bool 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
152bool Decoder::bufferIsLargeEnoughToContain(unsigned alignment, size_t size) const
153{
154 return alignedBufferIsLargeEnoughToContain(roundUpToAlignment(m_bufferPos, alignment), m_bufferEnd, size);
155}
156
157bool 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
168bool 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
184template<typename Type>
185static void decodeValueFromBuffer(Type& value, const uint8_t*& bufferPosition)
186{
187 memcpy(&value, bufferPosition, sizeof(value));
188 bufferPosition += sizeof(Type);
189}
190
191template<typename Type>
192Decoder& 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
203Decoder& Decoder::operator>>(Optional<bool>& optional)
204{
205 return getOptional(optional);
206}
207
208Decoder& Decoder::operator>>(Optional<uint8_t>& optional)
209{
210 return getOptional(optional);
211}
212
213Decoder& Decoder::operator>>(Optional<uint16_t>& optional)
214{
215 return getOptional(optional);
216}
217
218Decoder& Decoder::operator>>(Optional<uint32_t>& optional)
219{
220 return getOptional(optional);
221}
222
223Decoder& Decoder::operator>>(Optional<uint64_t>& optional)
224{
225 return getOptional(optional);
226}
227
228Decoder& Decoder::operator>>(Optional<int16_t>& optional)
229{
230 return getOptional(optional);
231}
232
233Decoder& Decoder::operator>>(Optional<int32_t>& optional)
234{
235 return getOptional(optional);
236}
237
238Decoder& Decoder::operator>>(Optional<int64_t>& optional)
239{
240 return getOptional(optional);
241}
242
243Decoder& Decoder::operator>>(Optional<float>& optional)
244{
245 return getOptional(optional);
246}
247
248Decoder& Decoder::operator>>(Optional<double>& optional)
249{
250 return getOptional(optional);
251}
252
253bool 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
262bool 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
271bool 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
280bool 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
289bool 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
298bool 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
307bool 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
316bool 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
325bool 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
334bool 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
343bool 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