compute-runtime/shared/source/device_binary_format/ar/ar_decoder.cpp

72 lines
3.2 KiB
C++

/*
* Copyright (C) 2020 Intel Corporation
*
* SPDX-License-Identifier: MIT
*
*/
#include "device_binary_format/ar/ar_decoder.h"
#include <cstdint>
namespace NEO {
namespace Ar {
Ar decodeAr(const ArrayRef<const uint8_t> 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<const char *>(binary.begin());
const uint8_t *decodePos = binary.begin() + arMagic.size();
while (decodePos + sizeof(ArFileEntryHeader) <= binary.end()) {
auto fileEntryHeader = reinterpret_cast<const ArFileEntryHeader *>(decodePos);
auto fileEntryDataPos = decodePos + sizeof(ArFileEntryHeader);
uint64_t fileSize = readDecimal<sizeof(fileEntryHeader->fileSizeInBytes)>(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(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 = readUnpaddedString<sizeof(fileEntryHeader->identifier)>(fileEntryHeader->identifier);
fileEntry.fullHeader = fileEntryHeader;
fileEntry.fileData = ArrayRef<const uint8_t>(fileEntryDataPos, static_cast<size_t>(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 = readDecimal<sizeof(fileEntryHeader->identifier) - 1>(fileEntryHeader->identifier + 1);
fileEntry.fileName = readLongFileName(ConstStringRef(reinterpret_cast<const char *>(ret.longFileNamesEntry.fileData.begin()), ret.longFileNamesEntry.fileData.size()), static_cast<size_t>(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