pointer size checker

This commit is contained in:
Motiejus Jakštys 2022-04-19 06:11:37 +03:00 committed by Motiejus Jakštys
parent 64bd5df633
commit 3c507ffe08
4 changed files with 28 additions and 20 deletions

View File

@ -154,8 +154,8 @@ OFFSET TYPE NAME DESCRIPTION
40 u64 nblocks_users
48 u64 nblocks_groupmembers
56 u64 nblocks_additional_gids
64 u64 getgr_max
72 u64 getpw_max
64 u64 getgr_bufsize
72 u64 getpw_bufsize
80 [48]u8 padding
```
@ -168,7 +168,7 @@ number of bytes. However, interpreting `[2]u6` with `xxd(1)` is harder than
interpreting `[2]u8`. Therefore we are using the space we have to make these
integers byte-wide.
`getgr_max` and `getpw_max` is a hint for the caller of `getgr*` and
`getgr_bufsize` and `getpw_bufsize` is a hint for the caller of `getgr*` and
`getpw*`-family calls. This is the recommended size of the buffer, so the
caller does not receive `ENOMEM`.

View File

@ -26,8 +26,8 @@ name2group: StringHashMap(u32),
group2users: []const []const u32,
user2groups: []const []const u32,
getgr_max: usize,
getpw_max: usize,
getgr_bufsize: usize,
getpw_bufsize: usize,
pub fn init(
baseAllocator: Allocator,
@ -43,15 +43,15 @@ pub fn init(
var groups_arr = try allocator.alloc(Group, groupsConst.len);
var users_arr = try allocator.alloc(User, usersConst.len);
var getgr_max: usize = 0;
var getgr_bufsize: usize = 0;
for (groupsConst) |*group, i| {
groups_arr[i] = try group.clone(allocator);
getgr_max = math.max(getgr_max, groups_arr[i].strlenZ());
getgr_bufsize = math.max(getgr_bufsize, groups_arr[i].strlenZ());
}
var getpw_max: usize = 0;
var getpw_bufsize: usize = 0;
for (usersConst) |*user, i| {
users_arr[i] = try user.clone(allocator);
getpw_max = math.max(getpw_max, users_arr[i].strlenZ());
getpw_bufsize = math.max(getpw_bufsize, users_arr[i].strlenZ());
}
sort.sort(User, users_arr, {}, cmpUser);
@ -123,8 +123,8 @@ pub fn init(
.name2group = name2group,
.group2users = group2users,
.user2groups = user2groups_final,
.getgr_max = getgr_max,
.getpw_max = getpw_max,
.getgr_bufsize = getgr_bufsize,
.getpw_bufsize = getpw_bufsize,
};
}

View File

@ -119,8 +119,8 @@ pub fn fromCorpus(
.nblocks_users = nblocks(u64, users.blob),
.nblocks_groupmembers = nblocks(u64, groupmembers.blob),
.nblocks_additional_gids = nblocks(u64, additional_gids.blob),
.getgr_max = corpus.getgr_max,
.getpw_max = corpus.getpw_max,
.getgr_bufsize = corpus.getgr_bufsize,
.getpw_bufsize = corpus.getpw_bufsize,
};
return DB{
@ -518,7 +518,7 @@ fn nblocks(comptime T: type, arr: []const u8) T {
fn assertDefinedLayout(comptime T: type) void {
return switch (T) {
u8, u16, u32, u64 => {},
u4, u8, u16, u32, u64 => {},
else => switch (@typeInfo(T)) {
.Array => assertDefinedLayout(meta.Elem(T)),
.Pointer => |info| assertDefinedLayout(info.child),
@ -599,7 +599,7 @@ test "high-level API" {
defer db.deinit(allocator);
// TODO: should accept a buffer instead of an allocator instead.
var buf = try allocator.alloc(u8, db.header.getgr_max);
var buf = try allocator.alloc(u8, db.header.getgr_bufsize);
defer allocator.free(buf);
const all = try db.getgrnam("all", &buf);
try testing.expect(all != null);

View File

@ -7,7 +7,7 @@ const max_shells = @import("shell.zig").max_shells;
const magic = [4]u8{ 0xf0, 0x9f, 0xa4, 0xb7 };
const version = 0;
const Endian = enum(u8) {
const Endian = enum(u4) {
big,
little,
@ -26,12 +26,14 @@ pub const Invalid = error{
InvalidMagic,
InvalidVersion,
InvalidEndianess,
InvalidPointerSize,
};
pub const Header = packed struct {
magic: [4]u8 = magic,
version: u8 = version,
endian: Endian = Endian.native(),
ptr_size: u4 = @sizeOf(?[*:0]const u8),
nblocks_shell_blob: u8,
num_shells: u8,
num_groups: u32,
@ -44,8 +46,8 @@ pub const Header = packed struct {
nblocks_users: u64,
nblocks_groupmembers: u64,
nblocks_additional_gids: u64,
getgr_max: u64,
getpw_max: u64,
getgr_bufsize: u64,
getpw_bufsize: u64,
padding: [48]u8 = [1]u8{0} ** 48,
pub fn fromBytes(blob: *const [@sizeOf(Header)]u8) Invalid!*const Header {
@ -60,6 +62,12 @@ pub const Header = packed struct {
if (self.endian != Endian.native())
return error.InvalidEndianess;
// when ptr size is larger than on the host that constructed it the DB,
// getgr_bufsize/getpw_bufsize may return insufficient values, causing
// OutOfMemory for getgr* and getpw* calls.
if (self.ptr_size < @sizeOf(?[*:0]const u8))
return error.InvalidPointerSize;
return self;
}
};
@ -92,8 +100,8 @@ test "header pack and unpack" {
.nblocks_users = 0,
.nblocks_groupmembers = 0,
.nblocks_additional_gids = 1,
.getgr_max = 16,
.getpw_max = 32,
.getgr_bufsize = 16,
.getpw_bufsize = 32,
};
const bytes = mem.asBytes(&header1);