passwd fields now have sentinels

This commit is contained in:
Motiejus Jakštys 2022-07-06 16:54:43 +03:00
parent 4a3d43561f
commit a63c60cc6f
4 changed files with 61 additions and 23 deletions

View File

@ -280,13 +280,13 @@ pub fn fromBytes(buf: []align(8) const u8) InvalidHeader!DB {
}
// dumps PackedGroup to []u8 and returns a CGroup.
fn getGroup(self: *const DB, group: PackedGroup, buf: []u8) error{OutOfMemory}!CGroup {
fn getGroup(self: *const DB, group: PackedGroup, buf: []u8) error{BufferTooSmall}!CGroup {
const members_slice = self.groupmembers[group.members_offset..];
var vit = compress.VarintSliceIteratorMust(members_slice);
const num_members = vit.remaining;
const ptr_end = @sizeOf(?[*:0]const u8) * (num_members + 1);
if (ptr_end > buf.len) return error.OutOfMemory;
if (ptr_end > buf.len) return error.BufferTooSmall;
var member_ptrs = mem.bytesAsSlice(?[*:0]const u8, buf[0..ptr_end]);
member_ptrs[member_ptrs.len - 1] = null;
var buf_offset: usize = ptr_end;
@ -297,7 +297,7 @@ fn getGroup(self: *const DB, group: PackedGroup, buf: []u8) error{OutOfMemory}!C
const entry = PackedUser.fromBytes(self.users[member_offset << 3 ..]);
const start = buf_offset;
const name = entry.user.name();
if (buf_offset + name.len + 1 > buf.len) return error.OutOfMemory;
if (buf_offset + name.len + 1 > buf.len) return error.BufferTooSmall;
mem.copy(u8, buf[buf_offset..], name);
buf_offset += name.len;
buf[buf_offset] = 0;
@ -309,7 +309,7 @@ fn getGroup(self: *const DB, group: PackedGroup, buf: []u8) error{OutOfMemory}!C
}
const name = group.name();
if (buf_offset + name.len + 1 > buf.len) return error.OutOfMemory;
if (buf_offset + name.len + 1 > buf.len) return error.BufferTooSmall;
mem.copy(u8, buf[buf_offset..], name);
buf[buf_offset + name.len] = 0;
@ -321,7 +321,7 @@ fn getGroup(self: *const DB, group: PackedGroup, buf: []u8) error{OutOfMemory}!C
}
// get a CGroup entry by name.
fn getgrnam(self: *const DB, name: []const u8, buf: []u8) error{OutOfMemory}!?CGroup {
fn getgrnam(self: *const DB, name: []const u8, buf: []u8) error{BufferTooSmall}!?CGroup {
const idx = bdz.search(self.bdz_groupname, name);
if (idx >= self.header.num_groups) return null;
const offset = self.idx_groupname2group[idx];
@ -332,7 +332,7 @@ fn getgrnam(self: *const DB, name: []const u8, buf: []u8) error{OutOfMemory}!?CG
}
// get a CGroup entry by it's gid.
fn getgrgid(self: *const DB, gid: u32, buf: []u8) error{OutOfMemory}!?CGroup {
fn getgrgid(self: *const DB, gid: u32, buf: []u8) error{BufferTooSmall}!?CGroup {
const idx = bdz.search_u32(self.bdz_gid, gid);
if (idx >= self.header.num_groups) return null;
const offset = self.idx_gid2group[idx];
@ -342,12 +342,12 @@ fn getgrgid(self: *const DB, gid: u32, buf: []u8) error{OutOfMemory}!?CGroup {
return try self.getGroup(group, buf);
}
fn pushStr(str: []const u8, buf: []u8, offset: *usize) [*]const u8 {
fn pushStr(str: []const u8, buf: []u8, offset: *usize) [*:0]const u8 {
const start = offset.*;
mem.copy(u8, buf[offset.*..], str);
buf[offset.* + str.len] = 0;
offset.* += str.len + 1;
return @ptrCast([*]const u8, &buf[start]);
return @ptrCast([*:0]const u8, &buf[start]);
}
fn getUser(self: *const DB, user: PackedUser, buf: []u8) error{BufferTooSmall}!CUser {
@ -725,7 +725,7 @@ test "getgrnam/getgrgid" {
_ = try db.getgrnam("all", buf);
buf.len -= 1;
try testing.expectError(error.OutOfMemory, db.getgrnam("all", buf));
try testing.expectError(error.BufferTooSmall, db.getgrnam("all", buf));
}
test "getpwnam/getpwuid" {

View File

@ -43,11 +43,12 @@ pub const TestDB = struct {
dir: testing.TmpDir,
path: [:0]const u8,
pub fn init(allocator: Allocator, errc: *ErrCtx) !TestDB {
pub fn init(allocator: Allocator) !TestDB {
var errc = ErrCtx{};
var corpus = try Corpus.testCorpus(allocator);
defer corpus.deinit();
var db = try DB.fromCorpus(allocator, &corpus, errc);
var db = try DB.fromCorpus(allocator, &corpus, &errc);
defer db.deinit(allocator);
var tmp = testing.tmpDir(.{});

View File

@ -145,13 +145,13 @@ pub fn fromReader(allocator: Allocator, err: *ErrCtx, reader: anytype) ![]User {
}
pub const CUser = extern struct {
pw_name: [*]const u8,
pw_passwd: [*]const u8 = pw_passwd,
pw_name: [*:0]const u8,
pw_passwd: [*:0]const u8 = pw_passwd,
pw_uid: u32,
pw_gid: u32,
pw_gecos: [*]const u8,
pw_dir: [*]const u8,
pw_shell: [*]const u8,
pw_gecos: [*:0]const u8,
pw_dir: [*:0]const u8,
pw_shell: [*:0]const u8,
};
const testing = std.testing;

View File

@ -127,7 +127,7 @@ export fn _nss_turbo_getpwuid_r(
}
export fn _nss_turbo_getpwnam_r(
name: [*:0]u8,
name: [*:0]const u8,
passwd: *CUser,
buffer: [*]u8,
buflen: usize,
@ -164,17 +164,54 @@ fn get_db(errnop: *c_int) ?DB {
const testing = std.testing;
test "nss_turbo_getpwuid_r" {
var errc = ErrCtx{};
var tf = try File.TestDB.init(testing.allocator, &errc);
test "getpwuid_r and getpwnam_r" {
var tf = try File.TestDB.init(testing.allocator);
defer tf.deinit();
const turbonss_db_path_old = turbonss_db_path;
turbonss_db_path = tf.path;
defer {
turbonss_db_path = turbonss_db_path_old;
}
var passwd: CUser = undefined;
var buffer: [1024]u8 = undefined;
var errno: c_int = 0;
const status = _nss_turbo_getpwuid_r(0, &passwd, &buffer, buffer.len, &errno);
var passwd: CUser = undefined;
try testing.expectEqual(
c.NSS_STATUS_SUCCESS,
_nss_turbo_getpwuid_r(128, &passwd, &buffer, buffer.len, &errno),
);
try testing.expectEqual(@as(c_int, 0), errno);
try testing.expectEqual(c.NSS_STATUS_SUCCESS, status);
try testVidmantas(passwd);
passwd = undefined;
try testing.expectEqual(
c.NSS_STATUS_SUCCESS,
_nss_turbo_getpwnam_r("vidmantas", &passwd, &buffer, buffer.len, &errno),
);
try testing.expectEqual(@as(c_int, 0), errno);
try testVidmantas(passwd);
passwd = undefined;
try testing.expectEqual(
c.NSS_STATUS_NOTFOUND,
_nss_turbo_getpwnam_r("does not exist", &passwd, &buffer, buffer.len, &errno),
);
try testing.expectEqual(@enumToInt(os.E.NOENT), @intCast(u16, errno));
passwd = undefined;
var small_buffer: [1]u8 = undefined;
try testing.expectEqual(
c.NSS_STATUS_TRYAGAIN,
_nss_turbo_getpwuid_r(0, &passwd, &small_buffer, small_buffer.len, &errno),
);
try testing.expectEqual(@enumToInt(os.E.RANGE), @intCast(u16, errno));
}
fn testVidmantas(u: CUser) !void {
try testing.expectEqualStrings("vidmantas", mem.sliceTo(u.pw_name, 0));
try testing.expectEqual(@as(u32, 128), u.pw_uid);
try testing.expectEqual(@as(u32, 128), u.pw_gid);
try testing.expectEqualStrings("Vidmantas Kaminskas", mem.sliceTo(u.pw_gecos, 0));
try testing.expectEqualStrings("/bin/bash", mem.sliceTo(u.pw_shell, 0));
}