/* * Copyright (C) 2020 Intel Corporation * * SPDX-License-Identifier: MIT * */ #include "shared/source/device_binary_format/ar/ar_decoder.h" #include namespace NEO { namespace Ar { Ar decodeAr(const ArrayRef binary, std::string &outErrReason, std::string &outWarnings) { if (false == isAr(binary)) { outErrReason = "Not an AR archive - mismatched file signature"; return {}; } Ar ret; ret.magic = reinterpret_cast(binary.begin()); const uint8_t *decodePos = binary.begin() + arMagic.size(); while (decodePos + sizeof(ArFileEntryHeader) <= binary.end()) { auto fileEntryHeader = reinterpret_cast(decodePos); auto fileEntryDataPos = decodePos + sizeof(ArFileEntryHeader); uint64_t fileSize = readDecimalfileSizeInBytes)>(fileEntryHeader->fileSizeInBytes); if (fileSize + (fileEntryDataPos - binary.begin()) > binary.size()) { outErrReason = "Corrupt AR archive - out of bounds data of file entry with idenfitier '" + std::string(fileEntryHeader->identifier, sizeof(fileEntryHeader->identifier)) + "'"; return {}; } if (ConstStringRef::fromArray(fileEntryHeader->trailingMagic) != arFileEntryTrailingMagic) { outWarnings.append("File entry header with identifier '" + std::string(fileEntryHeader->identifier, sizeof(fileEntryHeader->identifier)) + "' has invalid header trailing string"); } ArFileEntryHeaderAndData fileEntry = {}; fileEntry.fileName = readUnpaddedStringidentifier)>(fileEntryHeader->identifier); fileEntry.fullHeader = fileEntryHeader; fileEntry.fileData = ArrayRef(fileEntryDataPos, static_cast(fileSize)); if (fileEntry.fileName.empty()) { if (SpecialFileNames::longFileNamesFile == ConstStringRef(fileEntryHeader->identifier, 2U)) { fileEntry.fileName = SpecialFileNames::longFileNamesFile; ret.longFileNamesEntry = fileEntry; } else { outErrReason = "Corrupt AR archive - file entry does not have identifier : '" + std::string(fileEntryHeader->identifier, sizeof(fileEntryHeader->identifier)) + "'"; return {}; } } else { if (SpecialFileNames::longFileNamePrefix == fileEntry.fileName[0]) { auto longFileNamePos = readDecimalidentifier) - 1>(fileEntryHeader->identifier + 1); fileEntry.fileName = readLongFileName(ConstStringRef(reinterpret_cast(ret.longFileNamesEntry.fileData.begin()), ret.longFileNamesEntry.fileData.size()), static_cast(longFileNamePos)); if (fileEntry.fileName.empty()) { outErrReason = "Corrupt AR archive - long file name entry has broken identifier : '" + std::string(fileEntryHeader->identifier, sizeof(fileEntryHeader->identifier)) + "'"; return {}; } } ret.files.push_back(fileEntry); } decodePos = fileEntryDataPos + fileSize; decodePos += fileSize & 1U; // implicit 2-byte alignment } return ret; } } // namespace Ar } // namespace NEO