handle duplicate gid

This commit is contained in:
Motiejus Jakštys 2022-07-04 06:09:03 +03:00
parent e6b9d43646
commit eaccd00960
5 changed files with 57 additions and 20 deletions

View File

@ -5,6 +5,7 @@ const sort = std.sort;
const unicode = std.unicode; const unicode = std.unicode;
const Allocator = std.mem.Allocator; const Allocator = std.mem.Allocator;
const ArenaAllocator = std.heap.ArenaAllocator; const ArenaAllocator = std.heap.ArenaAllocator;
const AutoHashMap = std.AutoHashMap;
const StringHashMap = std.StringHashMap; const StringHashMap = std.StringHashMap;
const MultiArrayList = std.MultiArrayList; const MultiArrayList = std.MultiArrayList;
const ArrayListUnmanaged = std.ArrayListUnmanaged; const ArrayListUnmanaged = std.ArrayListUnmanaged;
@ -69,20 +70,43 @@ pub fn init(
for (groups_arr) |group| for (groups_arr) |group|
groups.appendAssumeCapacity(group); groups.appendAssumeCapacity(group);
// verify whatever comes to cmph are unique: user names
var name2user = StringHashMap(u32).init(allocator); var name2user = StringHashMap(u32).init(allocator);
var name2group = StringHashMap(u32).init(allocator);
for (users.items(.name)) |name, i| { for (users.items(.name)) |name, i| {
var res1 = try name2user.getOrPut(name); var result = try name2user.getOrPut(name);
if (res1.found_existing) if (result.found_existing)
return error.Duplicate; return error.Duplicate;
res1.value_ptr.* = @intCast(u32, i); result.value_ptr.* = @intCast(u32, i);
}
// verify whatever comes to cmph are unique: group names
var name2group = StringHashMap(u32).init(allocator);
for (groups.items(.name)) |name, i| {
var result = try name2group.getOrPut(name);
if (result.found_existing)
return error.Duplicate;
result.value_ptr.* = @intCast(u32, i);
} }
for (groups.items(.name)) |name, i| { // verify whatever comes to cmph are unique: gids
var res1 = try name2group.getOrPut(name); {
if (res1.found_existing) const gids = groups.items(.gid);
return error.Duplicate; var last_gid = gids[0];
res1.value_ptr.* = @intCast(u32, i); for (gids[1..]) |gid| {
if (gid == last_gid)
return err.returnf("duplicate gid {d}", .{gid}, error.Duplicate);
last_gid = gid;
}
}
// verify whatever comes to cmph are unique: uids
{
var uid_map = AutoHashMap(u32, void).init(allocator);
defer uid_map.deinit();
for (users.items(.uid)) |uid| {
const result = try uid_map.getOrPut(uid);
if (result.found_existing)
return err.returnf("duplicate uid {d}", .{uid}, error.Duplicate);
}
} }
var group2users = try allocator.alloc([]u32, groups.len); var group2users = try allocator.alloc([]u32, groups.len);
@ -236,9 +260,9 @@ pub fn testCorpus(allocator: Allocator) !Corpus {
const groups = [_]Group{ group0, group1, group2, group3 }; const groups = [_]Group{ group0, group1, group2, group3 };
var err_ctx = ErrCtx{}; var errc = ErrCtx{};
const result = try Corpus.init(allocator, users[0..], groups[0..], &err_ctx); const result = try Corpus.init(allocator, users[0..], groups[0..], &errc);
try testing.expectEqualStrings("", err_ctx.unwrap().constSlice()); try testing.expectEqualStrings("", errc.unwrap().constSlice());
return result; return result;
} }

View File

@ -10,6 +10,7 @@ const ArrayList = std.ArrayList;
const AutoHashMap = std.AutoHashMap; const AutoHashMap = std.AutoHashMap;
const BoundedArray = std.BoundedArray; const BoundedArray = std.BoundedArray;
const ErrCtx = @import("ErrCtx.zig");
const Corpus = @import("Corpus.zig"); const Corpus = @import("Corpus.zig");
const pad = @import("padding.zig"); const pad = @import("padding.zig");
const compress = @import("compress.zig"); const compress = @import("compress.zig");
@ -54,7 +55,10 @@ additional_gids: []const u8,
pub fn fromCorpus( pub fn fromCorpus(
allocator: Allocator, allocator: Allocator,
corpus: *const Corpus, corpus: *const Corpus,
err: *ErrCtx,
) error{ OutOfMemory, InvalidRecord, TooMany }!DB { ) error{ OutOfMemory, InvalidRecord, TooMany }!DB {
_ = err;
const gids = corpus.groups.items(.gid); const gids = corpus.groups.items(.gid);
const gnames = corpus.groups.items(.name); const gnames = corpus.groups.items(.name);
const uids = corpus.users.items(.uid); const uids = corpus.users.items(.uid);
@ -630,7 +634,8 @@ test "read/write via iovec" {
var corpus = try Corpus.testCorpus(allocator); var corpus = try Corpus.testCorpus(allocator);
defer corpus.deinit(); defer corpus.deinit();
var db = try DB.fromCorpus(allocator, &corpus); var errc = ErrCtx{};
var db = try DB.fromCorpus(allocator, &corpus, &errc);
defer db.deinit(allocator); defer db.deinit(allocator);
const fd = try os.memfd_create("test_turbonss_db", 0); const fd = try os.memfd_create("test_turbonss_db", 0);
@ -648,12 +653,14 @@ test "read/write via iovec" {
try testing.expectEqualSlices(u32, db.idx_gid2group, db2.idx_gid2group[0..num_groups]); try testing.expectEqualSlices(u32, db.idx_gid2group, db2.idx_gid2group[0..num_groups]);
try testing.expectEqualSlices(u32, db.idx_uid2user, db2.idx_uid2user[0..num_users]); try testing.expectEqualSlices(u32, db.idx_uid2user, db2.idx_uid2user[0..num_users]);
try testing.expectEqualStrings("", errc.unwrap().constSlice());
} }
test "getgrnam/getgrgid" { test "getgrnam/getgrgid" {
var corpus = try Corpus.testCorpus(testing.allocator); var corpus = try Corpus.testCorpus(testing.allocator);
defer corpus.deinit(); defer corpus.deinit();
var db = try DB.fromCorpus(testing.allocator, &corpus); var errc = ErrCtx{};
var db = try DB.fromCorpus(testing.allocator, &corpus, &errc);
defer db.deinit(testing.allocator); defer db.deinit(testing.allocator);
var buf = try testing.allocator.alloc(u8, db.getgrBufsize()); var buf = try testing.allocator.alloc(u8, db.getgrBufsize());
defer testing.allocator.free(buf); defer testing.allocator.free(buf);
@ -677,6 +684,7 @@ test "getgrnam/getgrgid" {
try testing.expectEqual(all.gid, 9999); try testing.expectEqual(all.gid, 9999);
try testing.expectEqualStrings(all.name[0..3], "all"); try testing.expectEqualStrings(all.name[0..3], "all");
} }
try testing.expectEqualStrings("", errc.unwrap().constSlice());
_ = try db.getgrnam("all", buf); _ = try db.getgrnam("all", buf);
buf.len -= 1; buf.len -= 1;
@ -686,7 +694,8 @@ test "getgrnam/getgrgid" {
test "getpwnam/getpwuid" { test "getpwnam/getpwuid" {
var corpus = try Corpus.testCorpus(testing.allocator); var corpus = try Corpus.testCorpus(testing.allocator);
defer corpus.deinit(); defer corpus.deinit();
var db = try DB.fromCorpus(testing.allocator, &corpus); var errc = ErrCtx{};
var db = try DB.fromCorpus(testing.allocator, &corpus, &errc);
defer db.deinit(testing.allocator); defer db.deinit(testing.allocator);
var buf = try testing.allocator.alloc(u8, db.getpwBufsize()); var buf = try testing.allocator.alloc(u8, db.getpwBufsize());
defer testing.allocator.free(buf); defer testing.allocator.free(buf);
@ -708,6 +717,7 @@ test "getpwnam/getpwuid" {
try testing.expectEqual(vidmantas.pw_gid, 128); try testing.expectEqual(vidmantas.pw_gid, 128);
try testing.expectEqualStrings(vidmantas.pw_name[0..10], "vidmantas\x00"); try testing.expectEqualStrings(vidmantas.pw_name[0..10], "vidmantas\x00");
} }
try testing.expectEqualStrings("", errc.unwrap().constSlice());
const long = try db.getpwnam("Name" ** 8, buf); const long = try db.getpwnam("Name" ** 8, buf);
try testing.expectEqualStrings(long.?.pw_name[0..33], "Name" ** 8 ++ "\x00"); try testing.expectEqualStrings(long.?.pw_name[0..33], "Name" ** 8 ++ "\x00");

View File

@ -5,6 +5,7 @@ const Allocator = std.mem.Allocator;
const Corpus = @import("Corpus.zig"); const Corpus = @import("Corpus.zig");
const DB = @import("DB.zig"); const DB = @import("DB.zig");
const ErrCtx = @import("ErrCtx.zig");
const InvalidHeader = @import("header.zig").Invalid; const InvalidHeader = @import("header.zig").Invalid;
const File = @This(); const File = @This();
@ -42,11 +43,11 @@ pub const TestDB = struct {
dir: testing.TmpDir, dir: testing.TmpDir,
path: [:0]const u8, path: [:0]const u8,
pub fn init(allocator: Allocator) !TestDB { pub fn init(allocator: Allocator, errc: *ErrCtx) !TestDB {
var corpus = try Corpus.testCorpus(allocator); var corpus = try Corpus.testCorpus(allocator);
defer corpus.deinit(); defer corpus.deinit();
var db = try DB.fromCorpus(allocator, &corpus); var db = try DB.fromCorpus(allocator, &corpus, errc);
defer db.deinit(allocator); defer db.deinit(allocator);
var tmp = testing.tmpDir(.{}); var tmp = testing.tmpDir(.{});

View File

@ -6,6 +6,7 @@ const process = std.process;
const DB = @import("DB.zig"); const DB = @import("DB.zig");
const File = @import("File.zig"); const File = @import("File.zig");
const ErrCtx = @import("ErrCtx.zig");
const CGroup = @import("Group.zig").CGroup; const CGroup = @import("Group.zig").CGroup;
const PackedGroup = @import("PackedGroup.zig"); const PackedGroup = @import("PackedGroup.zig");
const CUser = @import("User.zig").CUser; const CUser = @import("User.zig").CUser;
@ -131,7 +132,8 @@ export fn _nss_turbo_getpwuid_r(
const testing = std.testing; const testing = std.testing;
test "nss_turbo_getpwuid_r" { test "nss_turbo_getpwuid_r" {
var tf = try File.TestDB.init(testing.allocator); var errc = ErrCtx{};
var tf = try File.TestDB.init(testing.allocator, &errc);
defer tf.deinit(); defer tf.deinit();
var env = try process.getEnvMap(testing.allocator); var env = try process.getEnvMap(testing.allocator);

View File

@ -97,8 +97,8 @@ fn execute(
return fail(errc.wrap("init corpus"), stderr, err); return fail(errc.wrap("init corpus"), stderr, err);
defer corpus.deinit(); defer corpus.deinit();
var db = DB.fromCorpus(allocator, &corpus) catch |err| var db = DB.fromCorpus(allocator, &corpus, &errc) catch |err|
return fail(errc.wrap("construct db from corpus"), stderr, err); return fail(errc.wrap("construct DB from corpus"), stderr, err);
defer db.deinit(allocator); defer db.deinit(allocator);
const fd = os.open(outFile, os.O.WRONLY | os.O.TRUNC | os.O.CREAT, 0644) catch |err| const fd = os.open(outFile, os.O.WRONLY | os.O.TRUNC | os.O.CREAT, 0644) catch |err|