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 "ArgumentDecoder.h" 28 29 #include "DataReference.h" 30 #include <stdio.h> 31 32 namespace CoreIPC { 33 34 ArgumentDecoder::ArgumentDecoder(const uint8_t* buffer, size_t bufferSize) 35 { 36 initialize(buffer, bufferSize); 37 } 38 39 ArgumentDecoder::ArgumentDecoder(const uint8_t* buffer, size_t bufferSize, Deque<Attachment>& attachments) 40 { 41 initialize(buffer, bufferSize); 42 43 m_attachments.swap(attachments); 44 } 45 46 ArgumentDecoder::~ArgumentDecoder() 47 { 48 ASSERT(m_buffer); 49 fastFree(m_buffer); 50 #if !PLATFORM(QT) && !PLATFORM(GTK) 51 // FIXME: We need to dispose of the mach ports in cases of failure. 52 #else 53 Deque<Attachment>::iterator end = m_attachments.end(); 54 for (Deque<Attachment>::iterator it = m_attachments.begin(); it != end; ++it) 55 it->dispose(); 56 #endif 57 } 58 59 void ArgumentDecoder::initialize(const uint8_t* buffer, size_t bufferSize) 60 { 61 m_buffer = static_cast<uint8_t*>(fastMalloc(bufferSize)); 62 m_bufferPos = m_buffer; 63 m_bufferEnd = m_buffer + bufferSize; 64 memcpy(m_buffer, buffer, bufferSize); 65 66 // Decode the destination ID. 67 decodeUInt64(m_destinationID); 68 } 69 70 static inline uint8_t* roundUpToAlignment(uint8_t* ptr, unsigned alignment) 71 { 72 ASSERT(alignment); 73 uintptr_t alignmentMask = alignment - 1; 74 return reinterpret_cast<uint8_t*>((reinterpret_cast<uintptr_t>(ptr) + alignmentMask) & ~alignmentMask); 75 } 76 77 bool ArgumentDecoder::alignBufferPosition(unsigned alignment, size_t size) 78 { 79 uint8_t* buffer = roundUpToAlignment(m_bufferPos, alignment); 80 if (static_cast<size_t>(m_bufferEnd - buffer) < size) { 81 // We've walked off the end of this buffer. 82 markInvalid(); 83 return false; 84 } 85 86 m_bufferPos = buffer; 87 return true; 88 } 89 90 bool ArgumentDecoder::bufferIsLargeEnoughToContain(unsigned alignment, size_t size) const 91 { 92 return static_cast<size_t>(m_bufferEnd - roundUpToAlignment(m_bufferPos, alignment)) >= size; 93 } 94 95 bool ArgumentDecoder::decodeBytes(Vector<uint8_t>& buffer) 96 { 97 uint64_t size; 98 if (!decodeUInt64(size)) 99 return false; 100 101 if (!alignBufferPosition(1, size)) 102 return false; 103 104 buffer.resize(size); 105 if (size > 0) 106 memcpy(&buffer[0], m_bufferPos, size); 107 m_bufferPos += size; 108 return true; 109 } 110 111 bool ArgumentDecoder::decodeBytes(DataReference& dataReference) 112 { 113 uint64_t size; 114 if (!decodeUInt64(size)) 115 return false; 116 117 if (!alignBufferPosition(1, size)) 118 return false; 119 120 uint8_t* data = m_bufferPos; 121 m_bufferPos += size; 122 123 dataReference = DataReference(data, size); 124 return true; 125 } 126 127 bool ArgumentDecoder::decodeBytes(uint8_t* buffer, size_t bufferSize) 128 { 129 // FIXME: Decoding the size is not strictly necessary here since we know the size upfront. 130 uint64_t size; 131 if (!decodeUInt64(size)) 132 return false; 133 134 ASSERT(size == bufferSize); 135 if (size != bufferSize) 136 return false; 137 138 if (!alignBufferPosition(1, size)) 139 return false; 140 141 memcpy(buffer, m_bufferPos, size); 142 m_bufferPos += size; 143 return true; 144 } 145 146 bool ArgumentDecoder::decodeBool(bool& result) 147 { 148 if (!alignBufferPosition(sizeof(result), sizeof(result))) 149 return false; 150 151 result = *reinterpret_cast<bool*>(m_bufferPos); 152 m_bufferPos += sizeof(result); 153 return true; 154 } 155 156 bool ArgumentDecoder::decodeUInt32(uint32_t& result) 157 { 158 if (!alignBufferPosition(sizeof(result), sizeof(result))) 159 return false; 160 161 result = *reinterpret_cast<uint32_t*>(m_bufferPos); 162 m_bufferPos += sizeof(result); 163 return true; 164 } 165 166 bool ArgumentDecoder::decodeUInt64(uint64_t& result) 167 { 168 if (!alignBufferPosition(sizeof(result), sizeof(result))) 169 return false; 170 171 result = *reinterpret_cast<uint64_t*>(m_bufferPos); 172 m_bufferPos += sizeof(result); 173 return true; 174 } 175 176 bool ArgumentDecoder::decodeInt32(int32_t& result) 177 { 178 if (!alignBufferPosition(sizeof(result), sizeof(result))) 179 return false; 180 181 result = *reinterpret_cast<uint32_t*>(m_bufferPos); 182 m_bufferPos += sizeof(result); 183 return true; 184 } 185 186 bool ArgumentDecoder::decodeInt64(int64_t& result) 187 { 188 if (!alignBufferPosition(sizeof(result), sizeof(result))) 189 return false; 190 191 result = *reinterpret_cast<uint64_t*>(m_bufferPos); 192 m_bufferPos += sizeof(result); 193 return true; 194 } 195 196 bool ArgumentDecoder::decodeFloat(float& result) 197 { 198 if (!alignBufferPosition(sizeof(result), sizeof(result))) 199 return false; 200 201 result = *reinterpret_cast<float*>(m_bufferPos); 202 m_bufferPos += sizeof(result); 203 return true; 204 } 205 206 bool ArgumentDecoder::decodeDouble(double& result) 207 { 208 if (!alignBufferPosition(sizeof(result), sizeof(result))) 209 return false; 210 211 result = *reinterpret_cast<double*>(m_bufferPos); 212 m_bufferPos += sizeof(result); 213 return true; 214 } 215 216 bool ArgumentDecoder::removeAttachment(Attachment& attachment) 217 { 218 if (m_attachments.isEmpty()) 219 return false; 220 221 attachment = m_attachments.takeFirst(); 222 return true; 223 } 224 225 #ifndef NDEBUG 226 void ArgumentDecoder::debug() 227 { 228 printf("ArgumentDecoder::debug()\n"); 229 printf("Number of Attachments: %d\n", (int)m_attachments.size()); 230 printf("Size of buffer: %d\n", (int)(m_bufferEnd - m_buffer)); 231 } 232 #endif 233 234 } // namespace CoreIPC 235