| 324 | } |
| 325 | |
| 326 | DartsDictPtr DartsDict::NewFromBuffer(const char* data, size_t size) { |
| 327 | DartsDictPtr dict(new DartsDict()); |
| 328 | auto internal = dict->internal; |
| 329 | |
| 330 | size_t headerLen = strlen(OCDHEADER); |
| 331 | if (size < headerLen || memcmp(data, OCDHEADER, headerLen) != 0) { |
| 332 | throw InvalidFormat("Invalid OpenCC dictionary header"); |
| 333 | } |
| 334 | size_t offset = headerLen; |
| 335 | |
| 336 | if (size - offset < 8) { |
| 337 | throw InvalidFormat("Invalid OpenCC dictionary header (dartsSize)"); |
| 338 | } |
| 339 | uint8_t probe[8]; |
| 340 | memcpy(probe, data + offset, 8); |
| 341 | offset += 8; |
| 342 | bool is64bit = |
| 343 | (probe[4] == 0 && probe[5] == 0 && probe[6] == 0 && probe[7] == 0); |
| 344 | |
| 345 | if (is64bit) { |
| 346 | uint64_t dartsSize64; |
| 347 | memcpy(&dartsSize64, probe, 8); |
| 348 | size_t dartsSize = static_cast<size_t>(dartsSize64); |
| 349 | if (dartsSize > size - offset) { |
| 350 | throw InvalidFormat( |
| 351 | "Invalid OpenCC dictionary (dartsSize exceeds file size)"); |
| 352 | } |
| 353 | if (dartsSize % sizeof(LegacyUnit64) != 0) { |
| 354 | throw InvalidFormat("Invalid legacy OCD dictionary unit alignment"); |
| 355 | } |
| 356 | std::unique_ptr<void, decltype(&free)> buffer(malloc(dartsSize), free); |
| 357 | if (!buffer) { |
| 358 | throw std::bad_alloc(); |
| 359 | } |
| 360 | memcpy(buffer.get(), data + offset, dartsSize); |
| 361 | offset += dartsSize; |
| 362 | |
| 363 | BinaryDictPtr binary = BinaryDict::NewFromBuffer(data + offset, size - offset); |
| 364 | |
| 365 | internal->buffer = buffer.release(); |
| 366 | internal->binary = std::move(binary); |
| 367 | internal->legacyArray64 = static_cast<const LegacyUnit64*>(internal->buffer); |
| 368 | |
| 369 | dict->lexicon = internal->binary->GetLexicon(); |
| 370 | dict->maxLength = internal->binary->KeyMaxLength(); |
| 371 | size_t numUnits = dartsSize / sizeof(LegacyUnit64); |
| 372 | if (!ValidateLegacy64(internal->legacyArray64, numUnits, |
| 373 | static_cast<int>(dict->lexicon->Length()))) { |
| 374 | throw InvalidFormat("Invalid legacy OCD dictionary darts data"); |
| 375 | } |
| 376 | return dict; |
| 377 | } |
| 378 | |
| 379 | // 32-bit: dartsSize is the first 4 bytes of probe; probe[4..7] belong to the |
| 380 | // darts array, so rewind 4 bytes before reading the array. |
| 381 | uint32_t dartsSize32; |
| 382 | memcpy(&dartsSize32, probe, 4); |
| 383 | size_t dartsSize = dartsSize32; |
nothing calls this directly
no test coverage detected