Add data validation to Oar entries
continuous-integration/drone/push Build is passing Details
continuous-integration/drone/pr Build is passing Details

This commit is contained in:
kayomn 2022-10-11 01:03:02 +01:00
parent 52f4657872
commit e108486c17
2 changed files with 42 additions and 14 deletions

View File

@ -7,8 +7,42 @@ const sys = @import("./sys.zig");
/// Typically, following this block in memory is the file data it holds the meta-information for. /// Typically, following this block in memory is the file data it holds the meta-information for.
/// ///
pub const Entry = extern struct { pub const Entry = extern struct {
signature: [3]u8,
revision: u8,
name_length: u8, name_length: u8,
name_buffer: [255]u8 = std.mem.zeroes([255]u8), name_buffer: [255]u8 = std.mem.zeroes([255]u8),
file_size: u64, file_size: u64,
padding: [248]u8, padding: [244]u8,
///
/// Returns `true` if `entry` correctly identifies itself as a valid Oar entry, otherwise
/// `false`.
///
pub fn isValid(entry: Entry) bool {
return std.mem.eql(u8, &entry.signature, "oar");
}
///
/// Attempts to read an [Entry] from `file_access` at its current cursor position.
///
/// Returns the read [Entry] value or `null` if the end of file is reached before completing the
/// read.
///
pub fn read(file_access: *sys.FileAccess) sys.FileAccess.Error!?Entry {
var entry = std.mem.zeroes(Entry);
const origin = try file_access.queryCursor();
if ((try file_access.read(std.mem.asBytes(&entry))) != @sizeOf(Entry)) {
try file_access.seek(origin);
return null;
}
return entry;
}
///
/// Magic identifier used to validate [Entry] data.
///
const signature_magic = "oar";
}; };

View File

@ -459,22 +459,16 @@ pub const FileSystem = union(enum) {
const file_access = @ptrCast(*FileAccess, ext.SDL_RWFromFile( const file_access = @ptrCast(*FileAccess, ext.SDL_RWFromFile(
&path_buffer, "rb") orelse return error.FileNotFound); &path_buffer, "rb") orelse return error.FileNotFound);
while (true) { while (oar.Entry.read(file_access) catch return error.FileNotFound) |entry| {
var entry = std.mem.zeroes(oar.Entry); if (!entry.isValid()) break;
const entry_buffer = std.mem.asBytes(&entry);
if ((file_access.read(entry_buffer) catch return if (std.mem.eql(u8, entry.name_buffer[0 .. entry.name_length],
error.FileNotFound) != entry_buffer.len) return error.FileNotFound; path.buffer[0 .. path.length])) return file_access;
if (std.mem.eql(u8, entry.name_buffer[0 .. entry. file_access.seek(entry.file_size) catch break;
name_length], path.buffer[0 .. path.length])) {
return file_access;
}
file_access.seek(math.roundUp(u64, entry.file_size,
entry_buffer.len)) catch return error.FileNotFound;
} }
return error.FileNotFound;
}, },
.native => |native| { .native => |native| {