From 3b2f135d5c21a43e8185e98a84e374448a1560ed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Motiejus=20Jak=C5=A1tys?= Date: Thu, 10 Mar 2022 19:19:50 +0200 Subject: [PATCH] refactor ShellReader, so it can be included --- src/sections.zig | 6 +++--- src/shell.zig | 46 +++++++++++++++++++++++----------------------- src/user.zig | 29 +++++++++++++++-------------- 3 files changed, 41 insertions(+), 40 deletions(-) diff --git a/src/sections.zig b/src/sections.zig index 9348cc4..42944db 100644 --- a/src/sections.zig +++ b/src/sections.zig @@ -248,9 +248,9 @@ pub fn usersSection( var blob = try ArrayList(u8).initCapacity(allocator, 24 * corpus.users.len); errdefer blob.deinit(); for (corpus.users) |user, i| { - const userOffset = try math.cast(u32, blob.items.len); - std.debug.assert(userOffset & 7 == 0); - idx2offset[i] = userOffset; + const user_offset = try math.cast(u32, blob.items.len); + std.debug.assert(user_offset & 7 == 0); + idx2offset[i] = user_offset; try userImport.PackedUser.packTo( &blob, user, diff --git a/src/shell.zig b/src/shell.zig index 186b036..ecdc116 100644 --- a/src/shell.zig +++ b/src/shell.zig @@ -10,7 +10,7 @@ const StringContext = std.hash_map.StringContext; // maxShells is the maximum number of "popular" shells. pub const max_shells = 63; pub const max_shell_len = 64; -const ShellAlignment = 2; // bits +pub const shell_alignment_bits = 2; // bits // 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 @@ -18,29 +18,29 @@ const ShellAlignment = 2; // bits // to 4 bytes. // The actual shell length is len+1: we don't allow empty shells, and the real // length of the shell is 1-64 bytes. -const ShellIndex = packed struct { +pub const ShellIndex = packed struct { offset: u10, len: u6, }; // ShellReader interprets "Shell Index" and "Shell Blob" sections. pub const ShellReader = struct { - sectionIndex: []const ShellIndex, - sectionBlob: []const u8, + section_index: []const ShellIndex, + section_blob: []const u8, pub fn init(index: []const u8, blob: []const u8) ShellReader { return ShellReader{ - .sectionIndex = std.mem.bytesAsSlice(ShellIndex, index), - .sectionBlob = blob, + .section_index = std.mem.bytesAsSlice(ShellIndex, index), + .section_blob = blob, }; } // get returns a shell at the given index. pub fn get(self: *const ShellReader, idx: u6) []const u8 { - const shellIndex = self.sectionIndex[idx]; - const start = shellIndex.offset << 2; - const end = start + shellIndex.len + 1; - return self.sectionBlob[start..end]; + const shell_index = self.section_index[idx]; + const start = shell_index.offset << 2; + const end = start + shell_index.len + 1; + return self.section_blob[start..end]; } }; @@ -72,31 +72,31 @@ pub const ShellWriter = struct { .indices = StringHashMap(u6).init(allocator), }; errdefer self.indices.deinit(); - var fullOffset: u12 = 0; + var full_offset: u12 = 0; var idx: u6 = 0; while (idx < shells.len) : (idx += 1) { const len = try std.math.cast(u6, shells.get(idx).len); try self.blob.appendSlice(shells.get(idx)); - const ourShell = self.blob.constSlice()[fullOffset .. fullOffset + len]; - try self.indices.put(ourShell, idx); + const our_shell = self.blob.constSlice()[full_offset .. full_offset + len]; + try self.indices.put(our_shell, idx); self.index.set(idx, ShellIndex{ - .offset = try std.math.cast(u10, fullOffset >> 2), + .offset = try std.math.cast(u10, full_offset >> 2), .len = len - 1, }); - fullOffset += len; - const padding = pad.roundUpPadding(u12, ShellAlignment, fullOffset); - fullOffset += padding; + full_offset += len; + const padding = pad.roundUpPadding(u12, shell_alignment_bits, full_offset); + full_offset += padding; try self.blob.appendNTimes(0, padding); } return self; } - pub fn sectionIndex(self: *const ShellSections) []const u8 { + pub fn section_index(self: *const ShellSections) []const u8 { return std.mem.sliceAsBytes(self.index.constSlice()); } - pub fn sectionBlob(self: *const ShellSections) []const u8 { + pub fn section_blob(self: *const ShellSections) []const u8 { return self.blob.constSlice(); } @@ -198,17 +198,17 @@ test "basic shellpopcon" { try testing.expectEqual(sections.getIndex(bash).?, 2); try testing.expectEqual(sections.getIndex(nobody), null); try testing.expectEqual( - sections.sectionBlob().len, + sections.section_blob().len, pad.roundUp(u12, 2, bash.len) + pad.roundUp(u12, 2, zsh.len) + pad.roundUp(u12, 2, long.len), ); const shellReader = ShellReader.init( - sections.sectionIndex(), - sections.sectionBlob(), + sections.section_index(), + sections.section_blob(), ); try testing.expectEqualStrings(shellReader.get(0), long); try testing.expectEqualStrings(shellReader.get(1), zsh); try testing.expectEqualStrings(shellReader.get(2), bash); - try testing.expectEqual(shellReader.sectionIndex.len, 3); + try testing.expectEqual(shellReader.section_index.len, 3); } diff --git a/src/user.zig b/src/user.zig index 3dd374f..4da4621 100644 --- a/src/user.zig +++ b/src/user.zig @@ -3,6 +3,7 @@ const std = @import("std"); const pad = @import("padding.zig"); const validate = @import("validate.zig"); const compress = @import("compress.zig"); +const shellImport = @import("shell.zig"); const InvalidRecord = validate.InvalidRecord; const assert = std.debug.assert; @@ -180,7 +181,7 @@ pub const PackedUser = struct { pub const Iterator = struct { section: ?[]const u8, - shellIndex: Idx2ShellProto, + shell_reader: shellImport.ShellReader, pub fn next(it: *Iterator) error{Overflow}!?Self { if (it.section) |section| { @@ -192,8 +193,8 @@ pub const PackedUser = struct { } }; - pub fn iterator(section: []const u8, idxFn: Idx2ShellProto) Iterator { - return Iterator{ .section = section, .shellIndex = idxFn }; + pub fn iterator(section: []const u8, shell_reader: shellImport.ShellReader) Iterator { + return Iterator{ .section = section, .shell_reader = shell_reader }; } // packTo packs the User record and copies it to the given byte slice. @@ -269,13 +270,13 @@ pub const PackedUser = struct { return self.bytes[gecos_pos .. gecos_pos + gecos_len]; } - pub fn shell(self: Self, idxFn: Idx2ShellProto) []const u8 { + pub fn shell(self: Self, shell_reader: shellImport.ShellReader) []const u8 { if (self.inner.shell_here) { const shell_pos = self.inner.maybeShellStart(); const shell_len = self.inner.shellLen(); return self.bytes[shell_pos .. shell_pos + shell_len]; } - return idxFn(self.inner.shell_len_or_idx); + return shell_reader.get(self.inner.shell_len_or_idx); } }; @@ -295,13 +296,13 @@ fn testShellIndex(allocator: Allocator) StringHashMap(u6) { return result; } -fn testShell(index: u6) []const u8 { - return switch (index) { - 0 => "/bin/bash", - 1 => "/bin/zsh", - else => unreachable, - }; -} +const test_shell_reader = shellImport.ShellReader{ + .section_blob = "/bin/bash000/bin/zsh", + .section_index = &[_]shellImport.ShellIndex{ + shellImport.ShellIndex{ .offset = 0, .len = 9 - 1 }, + shellImport.ShellIndex{ .offset = 12 >> 2, .len = 8 - 1 }, + }, +}; test "construct PackedUser section" { var buf = ArrayList(u8).init(testing.allocator); @@ -344,7 +345,7 @@ test "construct PackedUser section" { } var i: u29 = 0; - var it1 = PackedUser.iterator(buf.items, testShell); + var it1 = PackedUser.iterator(buf.items, test_shell_reader); while (try it1.next()) |user| : (i += 1) { try testing.expectEqual(users[i].uid, user.uid()); try testing.expectEqual(users[i].gid, user.gid()); @@ -355,7 +356,7 @@ test "construct PackedUser section" { try testing.expectEqualStrings(users[i].name, user.name()); try testing.expectEqualStrings(users[i].gecos, user.gecos()); try testing.expectEqualStrings(users[i].home, user.home()); - try testing.expectEqualStrings(users[i].shell, user.shell(testShell)); + try testing.expectEqualStrings(users[i].shell, user.shell(test_shell_reader)); } try testing.expectEqual(users.len, i); }