safety checks in group parsing

This commit is contained in:
Motiejus Jakštys 2023-06-06 20:37:53 +03:00
parent e1cae43d08
commit a447e7fdf4
4 changed files with 24 additions and 20 deletions

View File

@ -368,21 +368,25 @@ pub fn packCGroup(self: *const DB, group: *const PackedGroup, buf: []u8) error{
};
}
pub fn getGroupByName(self: *const DB, name: []const u8) ?PackedGroup {
pub fn getGroupByName(self: *const DB, name: []const u8) error{Overflow}!?PackedGroup {
const idx = bdz.search(self.bdz_groupname, name);
if (idx >= self.header.num_groups) return null;
if (idx >= self.header.num_groups)
return null;
const offset = self.idx_groupname2group[idx];
const group = PackedGroup.fromBytes(@alignCast(8, self.groups[offset << 3 ..])).group;
if (!mem.eql(u8, name, group.name())) return null;
const group = (try PackedGroup.fromBytes(@alignCast(8, self.groups[offset << 3 ..]))).group;
if (!mem.eql(u8, name, group.name()))
return null;
return group;
}
pub fn getGroupByGid(self: *const DB, gid: u32) ?PackedGroup {
pub fn getGroupByGid(self: *const DB, gid: u32) error{Overflow}!?PackedGroup {
const idx = bdz.search_u32(self.bdz_gid, gid);
if (idx >= self.header.num_groups) return null;
if (idx >= self.header.num_groups)
return null;
const offset = self.idx_gid2group[idx];
const group = PackedGroup.fromBytes(@alignCast(8, self.groups[offset << 3 ..])).group;
if (gid != group.gid()) return null;
const group = (try PackedGroup.fromBytes(@alignCast(8, self.groups[offset << 3 ..]))).group;
if (gid != group.gid())
return null;
return group;
}
@ -393,7 +397,7 @@ pub fn getgrnam(
buf: []u8,
omit_members: bool,
) error{ Overflow, BufferTooSmall }!?CGroup {
const group = self.getGroupByName(name) orelse return null;
const group = try self.getGroupByName(name) orelse return null;
if (omit_members)
return try packCGroupNoMembers(&group, buf)
else
@ -407,7 +411,7 @@ pub fn getgrgid(
buf: []u8,
omit_members: bool,
) error{ Overflow, BufferTooSmall }!?CGroup {
const group = self.getGroupByGid(gid) orelse return null;
const group = try self.getGroupByGid(gid) orelse return null;
if (omit_members)
return try packCGroupNoMembers(&group, buf)
else

View File

@ -39,13 +39,11 @@ pub const Entry = struct {
end: usize,
};
pub fn fromBytes(bytes: []align(8) const u8) Entry {
pub fn fromBytes(bytes: []align(8) const u8) error{Overflow}!Entry {
const inner = mem.bytesAsValue(Inner, bytes[0..@sizeOf(Inner)]);
const start_blob = @sizeOf(Inner);
const end_strings = @sizeOf(Inner) + inner.groupnameLen();
const members_offset = compress.uvarint(bytes[end_strings..]) catch |err| switch (err) {
error.Overflow => unreachable,
};
const members_offset = try compress.uvarint(bytes[end_strings..]);
const end_blob = end_strings + members_offset.bytes_read;
return Entry{
@ -70,9 +68,9 @@ pub const Iterator = struct {
total: u32,
advanced_by: usize = 0,
pub fn next(it: *Iterator) ?PackedGroup {
pub fn next(it: *Iterator) error{Overflow}!?PackedGroup {
if (it.idx == it.total) return null;
const entry = fromBytes(@alignCast(8, it.section[it.next_start..]));
const entry = try fromBytes(@alignCast(8, it.section[it.next_start..]));
it.idx += 1;
it.next_start += entry.end;
it.advanced_by = entry.end;
@ -149,7 +147,7 @@ test "PackedGroup construct" {
var i: u29 = 0;
var it = PackedGroup.iterator(buf.items, groups.len);
while (it.next()) |group| : (i += 1) {
while (try it.next()) |group| : (i += 1) {
try testing.expectEqual(groups[i].gid, group.gid());
try testing.expectEqualStrings(groups[i].name, group.name());
try testing.expectEqual(groups[i].members_offset, group.membersOffset());

View File

@ -369,7 +369,9 @@ fn getgrent_r(
return c.NSS_STATUS_UNAVAIL;
});
const group = it.next() orelse {
const group = it.next() catch |err| switch (err) {
error.Overflow => return badFile(errnop),
} orelse {
errnop.* = 0;
return c.NSS_STATUS_NOTFOUND;
};

View File

@ -159,7 +159,7 @@ fn group(stdout: anytype, db: *const DB, keys: []const [*:0]const u8) error{Over
for (keys) |key| {
const keyZ = mem.span(key);
const maybe_packed_group = if (fmt.parseUnsigned(u32, keyZ, 10)) |gid|
const maybe_packed_group = try if (fmt.parseUnsigned(u32, keyZ, 10)) |gid|
db.getGroupByGid(gid)
else |_|
db.getGroupByName(keyZ);
@ -178,7 +178,7 @@ fn group(stdout: anytype, db: *const DB, keys: []const [*:0]const u8) error{Over
fn groupAll(stdout: anytype, db: *const DB) error{Overflow}!u8 {
var it = PackedGroup.iterator(db.groups, db.header.num_groups);
while (it.next()) |g|
while (try it.next()) |g|
if (try printGroup(stdout, db, &g)) |exit_code|
return exit_code;