yaze 0.3.2
Link to the Past ROM Editor
 
Loading...
Searching...
No Matches
zsprite_validation.h
Go to the documentation of this file.
1#ifndef YAZE_APP_EDITOR_SPRITE_ZSPRITE_VALIDATION_H_
2#define YAZE_APP_EDITOR_SPRITE_ZSPRITE_VALIDATION_H_
3
4#include <cstdint>
5#include <string_view>
6
7#include "absl/status/status.h"
8
9namespace yaze::editor::zsprite {
10// Check the same byte snapshot subsequently decoded by ZSprite::Load. Counts
11// and .NET string lengths are bounded before allocating any frame or routine.
12inline absl::Status ValidateZsmBytes(std::string_view data) {
13 size_t cursor = 0;
14 auto bytes = [&](size_t count) {
15 if (count > data.size() - cursor)
16 return false;
17 cursor += count;
18 return true;
19 };
20 auto count32 = [&](uint32_t limit, uint32_t& value) {
21 if (!bytes(4))
22 return false;
23 value = 0;
24 for (int i = 0; i < 4; ++i)
25 value |= uint32_t(static_cast<uint8_t>(data[cursor - 4 + i])) << (8 * i);
26 return value <= limit;
27 };
28 auto boolean = [&] {
29 if (!bytes(1))
30 return false;
31 return static_cast<uint8_t>(data[cursor - 1]) <= 1;
32 };
33 auto string = [&] {
34 uint32_t length = 0;
35 for (int i = 0; i < 5; ++i) {
36 if (!bytes(1))
37 return false;
38 const auto value = static_cast<uint8_t>(data[cursor - 1]);
39 if (i == 4 && (value & 0xf0))
40 return false;
41 length |= uint32_t(value & 127) << (7 * i);
42 if (!(value & 128))
43 return length <= 1024 * 1024 && bytes(length);
44 }
45 return false;
46 };
47 auto invalid = [] {
48 return absl::DataLossError("Malformed or oversized ZSM asset");
49 };
50 if (data.size() > 8 * 1024 * 1024)
51 return invalid();
52 uint32_t count = 0;
53 if (!count32(256, count))
54 return invalid();
55 for (uint32_t i = 0; i < count; ++i)
56 if (!string() || !bytes(3))
57 return invalid();
58 if (!count32(256, count))
59 return invalid();
60 for (uint32_t i = 0; i < count; ++i) {
61 uint32_t tiles = 0;
62 if (!count32(128, tiles))
63 return invalid();
64 for (uint32_t j = 0; j < tiles; ++j)
65 if (!bytes(3) || !boolean() || !boolean() || !bytes(1) || !boolean() ||
66 !bytes(3))
67 return invalid();
68 }
69 for (int i = 0; i < 20; ++i)
70 if (!boolean())
71 return invalid();
72 if (!bytes(6))
73 return invalid();
74 if (cursor < data.size()) {
75 if (!string() || !count32(1024, count))
76 return invalid();
77 for (uint32_t i = 0; i < count; ++i)
78 if (!string() || !string())
79 return invalid();
80 }
81 if (cursor < data.size() && !string())
82 return invalid();
83 return cursor == data.size() ? absl::OkStatus() : invalid();
84}
85} // namespace yaze::editor::zsprite
86#endif
Namespace for the ZSprite format from Zarby's ZSpriteMaker.
absl::Status ValidateZsmBytes(std::string_view data)