1/* 2 * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. 3 * 4 * The contents of this file constitute Original Code as defined in and are 5 * subject to the Apple Public Source License Version 1.2 (the 'License'). 6 * You may not use this file except in compliance with the License. Please obtain 7 * a copy of the License at http://www.apple.com/publicsource and read it before 8 * using this file. 9 * 10 * This Original Code and all software distributed under the License are 11 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS 12 * OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, INCLUDING WITHOUT 13 * LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR 14 * PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. Please see the License for the 15 * specific language governing rights and limitations under the License. 16 */ 17 18 19// 20// ReadWriteSection.h 21// 22 23#ifndef _H_APPLEDL_READWRITESECTION 24#define _H_APPLEDL_READWRITESECTION 25 26#include <security_utilities/alloc.h> 27#include <security_filedb/AtomicFile.h> 28#include <security_utilities/endian.h> 29#include <security_cdsa_utilities/cssmerrors.h> 30#include <Security/cssm.h> 31#include "OverUnderflowCheck.h" 32 33namespace Security 34{ 35 36// 37// Atom -- An Atom is a 32-bit unsigned integer value that is always internally 38// represented using network byte order. 39// 40typedef Endian<uint32> Atom; 41 42enum { 43 AtomSize = sizeof(uint32) // XXX Why not just use sizeof(Atom)? 44}; 45 46// 47// Class representing a range (or subrange of a buffer). 48// 49class Range 50{ 51public: 52 Range(uint32 inOffset, uint32 inSize) : mOffset(inOffset), mSize(inSize) {} 53 uint32 mOffset; 54 uint32 mSize; 55}; 56 57// 58// Class representing a packed record. All the accessors on this class are const since the 59// underlying data is read-only 60// 61// XXX Should be replaced by Atom::Vector 62class ReadSection 63{ 64protected: 65 ReadSection(uint8 *inAddress, size_t inLength) : mAddress(inAddress), mLength(inLength) 66 { 67 if (mAddress == NULL) 68 CssmError::throwMe(CSSMERR_DL_DATABASE_CORRUPT); 69 } 70public: 71 ReadSection() : mAddress(NULL), mLength(0) {} 72 ReadSection(const uint8 *inAddress, size_t inLength) : 73 mAddress(const_cast<uint8 *>(inAddress)), mLength(inLength) {} 74 75 uint32 size() const { return (uint32)mLength; } 76 77 uint32 at(uint32 inOffset) const 78 { 79 if (inOffset > mLength) 80 { 81 CssmError::throwMe(CSSMERR_DL_DATABASE_CORRUPT); 82 } 83 84 return ntohl(*reinterpret_cast<const uint32 *>(mAddress + inOffset)); 85 } 86 87 uint32 operator[](uint32 inOffset) const 88 { 89 return at(inOffset); 90 } 91 92 // Return a subsection from inOffset to end of section. 93 ReadSection subsection(uint32 inOffset) const 94 { 95 if (inOffset > mLength) 96 CssmError::throwMe(CSSMERR_DL_DATABASE_CORRUPT); 97 return ReadSection(mAddress + inOffset, mLength - inOffset); 98 } 99 100 // Return a subsection from inOffset of inLength bytes. 101 ReadSection subsection(uint32 inOffset, uint32 inLength) const 102 { 103 if (CheckUInt32Add(inOffset, inLength) > mLength) 104 CssmError::throwMe(CSSMERR_DL_DATABASE_CORRUPT); 105 return ReadSection(mAddress + inOffset, inLength); 106 } 107 108 ReadSection subsection(const Range &inRange) const 109 { 110 return subsection(inRange.mOffset, inRange.mSize); 111 } 112 113 const uint8 *range(const Range &inRange) const 114 { 115 if (CheckUInt32Add(inRange.mOffset, inRange.mSize) > mLength) 116 CssmError::throwMe(CSSMERR_DL_DATABASE_CORRUPT); 117 return mAddress + inRange.mOffset; 118 } 119 120 uint8 *allocCopyRange(const Range &inRange, Allocator &inAllocator) const 121 { 122 uint8 *aData; 123 if (inRange.mSize == 0) 124 aData = NULL; 125 else 126 { 127 if (CheckUInt32Add(inRange.mOffset, inRange.mSize) > mLength) 128 CssmError::throwMe(CSSMERR_DL_DATABASE_CORRUPT); 129 130 aData = reinterpret_cast<uint8 *>(inAllocator.malloc(inRange.mSize)); 131 memcpy(aData, mAddress + inRange.mOffset, inRange.mSize); 132 } 133 134 return aData; 135 } 136 137 static uint32 align(uint32 offset) { return (CheckUInt32Subtract(CheckUInt32Add(offset, AtomSize), 1)) & ~(AtomSize - 1); } 138 139protected: 140 uint8 *mAddress; 141 size_t mLength; 142}; 143 144// 145// Class representing a packed record (or buffer) used for writing. 146// 147class WriteSection : public ReadSection 148{ 149public: 150 static const size_t DefaultCapacity = 64; 151 152 WriteSection(Allocator &inAllocator, size_t inCapacity) : 153 ReadSection(reinterpret_cast<uint8 *>(inAllocator.malloc(inCapacity)), 0), 154 mAllocator(inAllocator), 155 mCapacity(inCapacity) 156 { 157 if (mCapacity > 0) 158 memset(mAddress, 0, mCapacity); 159 } 160 161 WriteSection(Allocator &inAllocator = Allocator::standard()) : 162 ReadSection(reinterpret_cast<uint8 *>(inAllocator.malloc(DefaultCapacity)), 0), 163 mAllocator(inAllocator), 164 mCapacity(DefaultCapacity) 165 { 166 } 167 168 WriteSection(const WriteSection &ws, int length) : 169 ReadSection(reinterpret_cast<uint8 *>(ws.mAllocator.malloc(length)), length), 170 mAllocator(ws.mAllocator), 171 mCapacity(length) 172 { 173 memcpy(mAddress, ws.mAddress, length); 174 } 175 176 ~WriteSection() { mAllocator.free(mAddress); } 177 178private: 179 void grow(size_t inNewCapacity); 180 181public: 182#if BUG_GCC 183 uint32 size() const { return ReadSection::size(); } 184#else 185 // XXX This should work but egcs-2.95.2 doesn't like it. 186 using ReadSection::size; 187#endif 188 189 void size(uint32 inLength) { mLength = inLength; } 190 uint32 put(uint32 inOffset, uint32 inValue); 191 uint32 put(uint32 inOffset, uint32 inLength, const uint8 *inData); 192 193 const uint8 *address() const { return mAddress; } 194 uint8 *release() 195 { 196 uint8 *anAddress = mAddress; 197 mAddress = NULL; 198 mCapacity = 0; 199 return anAddress; 200 } 201 202private: 203 Allocator &mAllocator; 204 size_t mCapacity; 205}; 206 207} // end namespace Security 208 209#endif // _H_APPLEDL_READWRITESECTION 210