xref: /aosp_15_r20/external/executorch/backends/vulkan/runtime/VulkanDelegateHeader.cpp (revision 523fa7a60841cd1ecfb9cc4201f1ca8b03ed023a)
1 /*
2  * Copyright (c) Meta Platforms, Inc. and affiliates.
3  * All rights reserved.
4  *
5  * This source code is licensed under the BSD-style license found in the
6  * LICENSE file in the root directory of this source tree.
7  */
8 
9 #include <executorch/backends/vulkan/runtime/VulkanDelegateHeader.h>
10 
11 #include <cstring>
12 
13 #include <executorch/runtime/core/error.h>
14 #include <executorch/runtime/core/result.h>
15 
16 #pragma clang diagnostic ignored "-Wdeprecated"
17 
18 namespace executorch {
19 namespace backends {
20 namespace vulkan {
21 
22 using executorch::runtime::Error;
23 using executorch::runtime::Result;
24 
25 namespace {
26 
27 struct ByteSlice {
28   size_t offset;
29   size_t size;
30 };
31 
32 constexpr size_t kExpectedSize = 30;
33 constexpr char kExpectedMagic[4] = {'V', 'H', '0', '0'};
34 
35 constexpr ByteSlice kMagic = {4, 4};
36 constexpr ByteSlice kHeaderSize = {8, 2};
37 constexpr ByteSlice kFlatbufferOffset = {10, 4};
38 constexpr ByteSlice kFlatbufferSize = {14, 4};
39 constexpr ByteSlice kBytesOffset = {18, 4};
40 constexpr ByteSlice kBytesSize = {22, 8};
41 
42 } // namespace
43 
44 /// Interprets the 8 bytes at `data` as a little-endian uint64_t.
getUInt64LE(const uint8_t * data)45 uint64_t getUInt64LE(const uint8_t* data) {
46   return (uint64_t)data[0] | ((uint64_t)data[1] << 8) |
47       ((uint64_t)data[2] << 16) | ((uint64_t)data[3] << 24) |
48       ((uint64_t)data[4] << 32) | ((uint64_t)data[5] << 40) |
49       ((uint64_t)data[6] << 48) | ((uint64_t)data[7] << 56);
50 }
51 
52 /// Interprets the 4 bytes at `data` as a little-endian uint32_t.
getUInt32LE(const uint8_t * data)53 uint32_t getUInt32LE(const uint8_t* data) {
54   return (uint32_t)data[0] | ((uint32_t)data[1] << 8) |
55       ((uint32_t)data[2] << 16) | ((uint32_t)data[3] << 24);
56 }
57 
58 /// Interprets the 2 bytes at `data` as a little-endian uint32_t.
getUInt16LE(const uint8_t * data)59 uint32_t getUInt16LE(const uint8_t* data) {
60   return (uint32_t)data[0] | ((uint32_t)data[1] << 8);
61 }
62 
is_valid() const63 bool VulkanDelegateHeader::is_valid() const {
64   if (header_size < kExpectedSize) {
65     return false;
66   }
67   if (flatbuffer_offset < header_size) {
68     return false;
69   }
70   if (flatbuffer_size == 0) {
71     return false;
72   }
73   if (bytes_offset < flatbuffer_offset + flatbuffer_size) {
74     return false;
75   }
76   if (bytes_size < 0) {
77     return false;
78   }
79 
80   return true;
81 }
82 
parse(const void * data)83 Result<VulkanDelegateHeader> VulkanDelegateHeader::parse(const void* data) {
84   const uint8_t* header_data = (const uint8_t*)data;
85 
86   const uint8_t* magic_start = header_data + kMagic.offset;
87   if (std::memcmp(magic_start, kExpectedMagic, kMagic.size) != 0) {
88     return Error::NotFound;
89   }
90 
91   VulkanDelegateHeader header = VulkanDelegateHeader{
92       getUInt16LE(header_data + kHeaderSize.offset),
93       getUInt32LE(header_data + kFlatbufferOffset.offset),
94       getUInt32LE(header_data + kFlatbufferSize.offset),
95       getUInt32LE(header_data + kBytesOffset.offset),
96       getUInt64LE(header_data + kBytesSize.offset),
97   };
98 
99   if (!header.is_valid()) {
100     return Error::InvalidArgument;
101   }
102 
103   return header;
104 }
105 
106 } // namespace vulkan
107 } // namespace backends
108 } // namespace executorch
109