~alva/zig-bare

b06b45b4700c60a4868bd17644a5c0ec861885aa — ugla 4 months ago 3302303
Handle too-big HashMap capacity
3 files changed, 16 insertions(+), 5 deletions(-)

M README.md
M src/bare.zig
M src/test.zig
M README.md => README.md +2 -2
@@ 41,11 41,11 @@ const x = Bar{
var buf: [12]u8 = undefined;
var fbs = io.fixedBufferStream(&buf);

try Writer.init().write(x, fbs.outStream());
try Writer.init().write(x, fbs.writer());
try fbs.seekTo(0);
var r = Reader.init(allocator);
defer r.deinit();
const y = try r.read(Bar, fbs.inStream());
const y = try r.read(Bar, fbs.reader());
warn("x: {}\ny: {}\n", .{ x, y });
```


M src/bare.zig => src/bare.zig +6 -3
@@ 185,11 185,14 @@ pub const Reader = struct {
        if (comptime !isValidHashMapKeyType(K))
            @compileError("unsupported hashmap key type " ++ @typeName(K));

        var i = @intCast(u32, try self.readVarUint(reader));
        var i = try self.readVarUint(reader);
        var map = T.init(&self.arena.allocator);

        if (i != 0) {
            try map.ensureCapacity(i);
            if (std.math.maxInt(T.Size) < i)
                return ReadError.Overflow;

            try map.ensureCapacity(@intCast(T.Size, i));

            while (i != 0) : (i -= 1) {
                const key = try self.read(K, reader);


@@ 369,7 372,7 @@ fn isHashMap(comptime T: type) bool {
    // `HashMapKeyType` and `HashMapValueType` add further constraints.
    const has1 = @hasDecl(T, "iterator") or @hasDecl(T, "items");
    const has2 = @hasDecl(T, "putAssumeCapacity") and @hasDecl(T, "ensureCapacity");
    return has1 and has2;
    return has1 and has2 and @hasDecl(T, "Size");
}

fn HashMapKeyType(comptime T: type) type {

M src/test.zig => src/test.zig +8 -0
@@ 205,6 205,14 @@ test "read map[string]u8" {
    expectEqual(map.get("zomg") orelse unreachable, 4);
}

test "read map overflow" {
    var r = Reader.init(testing.allocator);
    defer r.deinit();
    const T = std.StringHashMap(u8);
    const map = r.read(T, io.fixedBufferStream("\xff\xff\xff\xff\xff\xff\xff\xff\xff\x00\x04zomg\x04\x03lol\x02").reader());
    expectError(error.Overflow, map);
}

test "read map[u8]void" {
    try testCompileError(
        \\pub fn main() void {