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 32namespace CoreIPC { 33 34ArgumentDecoder::ArgumentDecoder(const uint8_t* buffer, size_t bufferSize) 35{ 36 initialize(buffer, bufferSize); 37} 38 39ArgumentDecoder::ArgumentDecoder(const uint8_t* buffer, size_t bufferSize, Deque<Attachment>& attachments) 40{ 41 initialize(buffer, bufferSize); 42 43 m_attachments.swap(attachments); 44} 45 46ArgumentDecoder::~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 59void 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 70static 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 77bool 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 90bool ArgumentDecoder::bufferIsLargeEnoughToContain(unsigned alignment, size_t size) const 91{ 92 return static_cast<size_t>(m_bufferEnd - roundUpToAlignment(m_bufferPos, alignment)) >= size; 93} 94 95bool 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 111bool 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 127bool 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 146bool 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 156bool 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 166bool 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 176bool 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 186bool 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 196bool 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 206bool 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 216bool 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 226void 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