Home | History | Annotate | Download | only in CoreIPC
      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