adding simple header validation
This commit is contained in:
parent
ed1e464305
commit
44107bac51
|
@ -1,4 +1,5 @@
|
||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
|
const shells = @import("shell.zig");
|
||||||
|
|
||||||
const HeaderSize = @sizeOf(Header);
|
const HeaderSize = @sizeOf(Header);
|
||||||
const Magic = [4]u8{ 0xf0, 0x9f, 0xa4, 0xb7 };
|
const Magic = [4]u8{ 0xf0, 0x9f, 0xa4, 0xb7 };
|
||||||
|
@ -10,6 +11,7 @@ const HeaderError = error{
|
||||||
InvalidVersion,
|
InvalidVersion,
|
||||||
InvalidBom,
|
InvalidBom,
|
||||||
TooManyShells,
|
TooManyShells,
|
||||||
|
InvalidOffset,
|
||||||
};
|
};
|
||||||
|
|
||||||
const Header = packed struct {
|
const Header = packed struct {
|
||||||
|
@ -29,7 +31,37 @@ const Header = packed struct {
|
||||||
offset_additional_gids: u32,
|
offset_additional_gids: u32,
|
||||||
|
|
||||||
pub fn init(blob: [HeaderSize]u8) HeaderError!Header {
|
pub fn init(blob: [HeaderSize]u8) HeaderError!Header {
|
||||||
return @bitCast(Header, blob);
|
const self = @bitCast(Header, blob);
|
||||||
|
for (Magic) |item, index| {
|
||||||
|
if (self.magic[index] != item) return error.InvalidMagic;
|
||||||
|
}
|
||||||
|
if (self.version != 0) {
|
||||||
|
return error.InvalidVersion;
|
||||||
|
}
|
||||||
|
if (self.bom != Bom) {
|
||||||
|
return error.InvalidBom;
|
||||||
|
}
|
||||||
|
if (self.num_shells > shells.MaxShells) {
|
||||||
|
return error.TooManyShells;
|
||||||
|
}
|
||||||
|
|
||||||
|
const offsets = [_]u32{
|
||||||
|
self.offset_cmph_uid2user,
|
||||||
|
self.offset_cmph_groupname2group,
|
||||||
|
self.offset_cmph_username2user,
|
||||||
|
self.offset_idx,
|
||||||
|
self.offset_groups,
|
||||||
|
self.offset_users,
|
||||||
|
self.offset_groupmembers,
|
||||||
|
self.offset_additional_gids,
|
||||||
|
};
|
||||||
|
for (offsets) |offset| {
|
||||||
|
if (offset & @intCast(u32, 63) != 0) {
|
||||||
|
return error.InvalidOffset;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn asArray(self: *const Header) [HeaderSize]u8 {
|
pub fn asArray(self: *const Header) [HeaderSize]u8 {
|
||||||
|
@ -44,7 +76,7 @@ test "header size is byte-aligned" {
|
||||||
}
|
}
|
||||||
|
|
||||||
test "header pack and unpack" {
|
test "header pack and unpack" {
|
||||||
const header = Header{
|
const goodHeader = Header{
|
||||||
.magic = Magic,
|
.magic = Magic,
|
||||||
.version = Version,
|
.version = Version,
|
||||||
.bom = Bom,
|
.bom = Bom,
|
||||||
|
@ -61,7 +93,31 @@ test "header pack and unpack" {
|
||||||
.offset_additional_gids = 0,
|
.offset_additional_gids = 0,
|
||||||
};
|
};
|
||||||
|
|
||||||
const blob = header.asArray();
|
const blob = goodHeader.asArray();
|
||||||
const header2 = try Header.init(blob);
|
const gotHeader = try Header.init(blob);
|
||||||
try testing.expectEqual(header, header2);
|
try testing.expectEqual(goodHeader, gotHeader);
|
||||||
|
|
||||||
|
{
|
||||||
|
var header = goodHeader;
|
||||||
|
header.magic[0] = 0;
|
||||||
|
try testing.expectError(error.InvalidMagic, Header.init(header.asArray()));
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
var header = goodHeader;
|
||||||
|
header.bom = 0x3412;
|
||||||
|
try testing.expectError(error.InvalidBom, Header.init(header.asArray()));
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
var header = goodHeader;
|
||||||
|
header.num_shells = shells.MaxShells + 1;
|
||||||
|
try testing.expectError(error.TooManyShells, Header.init(header.asArray()));
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
var header = goodHeader;
|
||||||
|
header.offset_cmph_uid2user = 128;
|
||||||
|
try testing.expectError(error.InvalidOffset, Header.init(header.asArray()));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,8 +7,8 @@ const BoundedArray = std.BoundedArray;
|
||||||
const StringContext = std.hash_map.StringContext;
|
const StringContext = std.hash_map.StringContext;
|
||||||
|
|
||||||
// MaxShells is the maximum number of "popular" shells.
|
// MaxShells is the maximum number of "popular" shells.
|
||||||
const MaxShells = 63;
|
pub const MaxShells = 63;
|
||||||
const MaxShellLen = 64;
|
pub const MaxShellLen = 64;
|
||||||
|
|
||||||
// ShellIndex is an index to the shell strings. As shell can be up to 64 bytes
|
// ShellIndex is an index to the shell strings. As shell can be up to 64 bytes
|
||||||
// (1<<6), maximum number of shells is 63 (1<<6-1), the maximum location offset
|
// (1<<6), maximum number of shells is 63 (1<<6-1), the maximum location offset
|
||||||
|
@ -22,7 +22,7 @@ const ShellIndex = struct {
|
||||||
};
|
};
|
||||||
|
|
||||||
// ShellReader interprets "Shell Index" and "Shell Blob" sections.
|
// ShellReader interprets "Shell Index" and "Shell Blob" sections.
|
||||||
const ShellReader = struct {
|
pub const ShellReader = struct {
|
||||||
sectionIndex: []const ShellIndex,
|
sectionIndex: []const ShellIndex,
|
||||||
sectionBlob: []const u8,
|
sectionBlob: []const u8,
|
||||||
|
|
||||||
|
@ -44,7 +44,7 @@ const ShellReader = struct {
|
||||||
|
|
||||||
// ShellWriter is a shell popularity contest: collect shells and return the
|
// ShellWriter is a shell popularity contest: collect shells and return the
|
||||||
// popular ones, sorted by score. score := len(shell) * number_of_shells.
|
// popular ones, sorted by score. score := len(shell) * number_of_shells.
|
||||||
const ShellWriter = struct {
|
pub const ShellWriter = struct {
|
||||||
counts: std.StringHashMap(u32),
|
counts: std.StringHashMap(u32),
|
||||||
allocator: Allocator,
|
allocator: Allocator,
|
||||||
const KV = struct { shell: []const u8, score: u32 };
|
const KV = struct { shell: []const u8, score: u32 };
|
||||||
|
|
Loading…
Reference in New Issue