1 /* 2 * Copyright (C) 2010 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 "WOFFFileFormat.h" 28 #include <zlib.h> 29 30 #if !ENABLE(OPENTYPE_SANITIZER) 31 32 #include "SharedBuffer.h" 33 34 #if OS(UNIX) 35 #include <netinet/in.h> 36 #endif 37 38 #if PLATFORM(BREWMP) 39 #include <AEEstd.h> 40 #define htonl(x) std_htonl(x) 41 #define htons(x) std_htons(x) 42 #define ntohl(x) std_ntohl(x) 43 #define ntohs(x) std_ntohs(x) 44 #endif 45 46 #if OS(WINDOWS) 47 #if CPU(BIG_ENDIAN) 48 #define ntohs(x) ((uint16_t)(x)) 49 #define htons(x) ((uint16_t)(x)) 50 #define ntohl(x) ((uint32_t)(x)) 51 #define htonl(x) ((uint32_t)(x)) 52 #elif CPU(MIDDLE_ENDIAN) 53 #define ntohs(x) ((unit16_t)(x)) 54 #define htons(x) ((uint16_t)(x)) 55 #define ntohl(x) ((uint32_t)((((uint32_t)(x) & 0xffff0000) >> 16) | (((uint32_t)(x) & 0xffff) << 16)) 56 #define htonl(x) ntohl(x) 57 #else 58 #define ntohs(x) ((uint16_t)((((uint16_t)(x) & 0xff00) >> 8) | (((uint16_t)(x) & 0x00ff) << 8))) 59 #define htons(x) ntohs(x) 60 #define ntohl(x) ((uint32_t)((((uint32_t)(x) & 0xff000000) >> 24) | (((uint32_t)(x) & 0x00ff0000) >> 8) | \ 61 (((uint32_t)(x) & 0x0000ff00) << 8) | (((uint32_t)(x) & 0x000000ff) << 24))) 62 #define htonl(x) ntohl(x) 63 #endif 64 #endif // OS(WINDOWS) 65 66 namespace WebCore { 67 68 static bool readUInt32(SharedBuffer* buffer, size_t& offset, uint32_t& value) 69 { 70 ASSERT_ARG(offset, offset <= buffer->size()); 71 if (buffer->size() - offset < sizeof(value)) 72 return false; 73 74 value = ntohl(*reinterpret_cast<const uint32_t*>(buffer->data() + offset)); 75 offset += sizeof(value); 76 77 return true; 78 } 79 80 static bool readUInt16(SharedBuffer* buffer, size_t& offset, uint16_t& value) 81 { 82 ASSERT_ARG(offset, offset <= buffer->size()); 83 if (buffer->size() - offset < sizeof(value)) 84 return false; 85 86 value = ntohs(*reinterpret_cast<const uint16_t*>(buffer->data() + offset)); 87 offset += sizeof(value); 88 89 return true; 90 } 91 92 static bool writeUInt32(Vector<char>& vector, uint32_t value) 93 { 94 uint32_t bigEndianValue = htonl(value); 95 return vector.tryAppend(reinterpret_cast<char*>(&bigEndianValue), sizeof(bigEndianValue)); 96 } 97 98 static bool writeUInt16(Vector<char>& vector, uint16_t value) 99 { 100 uint16_t bigEndianValue = htons(value); 101 return vector.tryAppend(reinterpret_cast<char*>(&bigEndianValue), sizeof(bigEndianValue)); 102 } 103 104 static const uint32_t woffSignature = 0x774f4646; /* 'wOFF' */ 105 106 bool isWOFF(SharedBuffer* buffer) 107 { 108 size_t offset = 0; 109 uint32_t signature; 110 111 return readUInt32(buffer, offset, signature) && signature == woffSignature; 112 } 113 114 bool convertWOFFToSfnt(SharedBuffer* woff, Vector<char>& sfnt) 115 { 116 ASSERT_ARG(sfnt, sfnt.isEmpty()); 117 118 size_t offset = 0; 119 120 // Read the WOFF header. 121 uint32_t signature; 122 if (!readUInt32(woff, offset, signature) || signature != woffSignature) { 123 ASSERT_NOT_REACHED(); 124 return false; 125 } 126 127 uint32_t flavor; 128 if (!readUInt32(woff, offset, flavor)) 129 return false; 130 131 uint32_t length; 132 if (!readUInt32(woff, offset, length) || length != woff->size()) 133 return false; 134 135 uint16_t numTables; 136 if (!readUInt16(woff, offset, numTables)) 137 return false; 138 139 if (!numTables || numTables > 0x0fff) 140 return false; 141 142 uint16_t reserved; 143 if (!readUInt16(woff, offset, reserved) || reserved) 144 return false; 145 146 uint32_t totalSfntSize; 147 if (!readUInt32(woff, offset, totalSfntSize)) 148 return false; 149 150 if (woff->size() - offset < sizeof(uint16_t) + sizeof(uint16_t) + sizeof(uint32_t) + sizeof(uint32_t) + sizeof(uint32_t) + sizeof(uint32_t) + sizeof(uint32_t)) 151 return false; 152 153 offset += sizeof(uint16_t); // majorVersion 154 offset += sizeof(uint16_t); // minorVersion 155 offset += sizeof(uint32_t); // metaOffset 156 offset += sizeof(uint32_t); // metaLength 157 offset += sizeof(uint32_t); // metaOrigLength 158 offset += sizeof(uint32_t); // privOffset 159 offset += sizeof(uint32_t); // privLength 160 161 // Check if the WOFF can supply as many tables as it claims it has. 162 if (woff->size() - offset < numTables * 5 * sizeof(uint32_t)) 163 return false; 164 165 // Write the sfnt offset subtable. 166 uint16_t entrySelector = 0; 167 uint16_t searchRange = 1; 168 while (searchRange < numTables >> 1) { 169 entrySelector++; 170 searchRange <<= 1; 171 } 172 searchRange <<= 4; 173 uint16_t rangeShift = (numTables << 4) - searchRange; 174 175 if (!writeUInt32(sfnt, flavor) 176 || !writeUInt16(sfnt, numTables) 177 || !writeUInt16(sfnt, searchRange) 178 || !writeUInt16(sfnt, entrySelector) 179 || !writeUInt16(sfnt, rangeShift)) 180 return false; 181 182 if (sfnt.size() > totalSfntSize) 183 return false; 184 185 if (totalSfntSize - sfnt.size() < numTables * 4 * sizeof(uint32_t)) 186 return false; 187 188 size_t sfntTableDirectoryCursor = sfnt.size(); 189 sfnt.grow(sfnt.size() + numTables * 4 * sizeof(uint32_t)); 190 191 // Process tables. 192 for (uint16_t i = 0; i < numTables; ++i) { 193 // Read a WOFF table directory entry. 194 uint32_t tableTag; 195 if (!readUInt32(woff, offset, tableTag)) 196 return false; 197 198 uint32_t tableOffset; 199 if (!readUInt32(woff, offset, tableOffset)) 200 return false; 201 202 uint32_t tableCompLength; 203 if (!readUInt32(woff, offset, tableCompLength)) 204 return false; 205 206 if (tableOffset > woff->size() || tableCompLength > woff->size() - tableOffset) 207 return false; 208 209 uint32_t tableOrigLength; 210 if (!readUInt32(woff, offset, tableOrigLength) || tableCompLength > tableOrigLength) 211 return false; 212 213 if (tableOrigLength > totalSfntSize || sfnt.size() > totalSfntSize - tableOrigLength) 214 return false; 215 216 uint32_t tableOrigChecksum; 217 if (!readUInt32(woff, offset, tableOrigChecksum)) 218 return false; 219 220 // Write an sfnt table directory entry. 221 uint32_t* sfntTableDirectoryPtr = reinterpret_cast<uint32_t*>(sfnt.data() + sfntTableDirectoryCursor); 222 *sfntTableDirectoryPtr++ = htonl(tableTag); 223 *sfntTableDirectoryPtr++ = htonl(tableOrigChecksum); 224 *sfntTableDirectoryPtr++ = htonl(sfnt.size()); 225 *sfntTableDirectoryPtr++ = htonl(tableOrigLength); 226 sfntTableDirectoryCursor += 4 * sizeof(uint32_t); 227 228 if (tableCompLength == tableOrigLength) { 229 // The table is not compressed. 230 if (!sfnt.tryAppend(woff->data() + tableOffset, tableCompLength)) 231 return false; 232 } else { 233 uLongf destLen = tableOrigLength; 234 if (!sfnt.tryReserveCapacity(sfnt.size() + tableOrigLength)) 235 return false; 236 Bytef* dest = reinterpret_cast<Bytef*>(sfnt.end()); 237 sfnt.grow(sfnt.size() + tableOrigLength); 238 if (uncompress(dest, &destLen, reinterpret_cast<const Bytef*>(woff->data() + tableOffset), tableCompLength) != Z_OK) 239 return false; 240 if (destLen != tableOrigLength) 241 return false; 242 } 243 244 // Pad to a multiple of 4 bytes. 245 while (sfnt.size() % 4) 246 sfnt.append(0); 247 } 248 249 return sfnt.size() == totalSfntSize; 250 } 251 252 } // namespace WebCore 253 254 #endif // !ENABLE(OPENTYPE_SANITIZER) 255