From 3bd77259bf1ff2b8db800d46b1a3fe16a83a1e51 Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Thu, 31 Aug 2023 21:13:04 -0700 Subject: [PATCH] font: don't use intCast on index This is a weird one. By using intCast on the `idx` I am periodically getting a panic on index out of bounds where the index is larger than FontIndex can possibly be. Very strange! I tried to just remove intCasts and believe it or not that worked. Previously, `cat /dev/urandom` would trigger the issue in seconds and now I've had it running 20+ minutes without the issue. The additional `if` check is just a safety mechanism --- src/font/Group.zig | 29 +++++++++++++++++++++++++++-- 1 file changed, 27 insertions(+), 2 deletions(-) diff --git a/src/font/Group.zig b/src/font/Group.zig index ec1e18fbf..c338adaa4 100644 --- a/src/font/Group.zig +++ b/src/font/Group.zig @@ -303,7 +303,8 @@ fn indexForCodepointExact(self: Group, cp: u32, style: Style, p: ?Presentation) /// necessarily force the font to load. pub fn hasCodepoint(self: *Group, index: FontIndex, cp: u32, p: ?Presentation) bool { const list = self.faces.getPtr(index.style); - const item = list.items[@intCast(index.idx)]; + if (index.idx >= list.items.len) return false; + const item = list.items[index.idx]; return switch (item) { .deferred => |v| v.hasCodepoint(cp, p), .loaded => |face| loaded: { @@ -330,7 +331,7 @@ pub fn presentationFromIndex(self: *Group, index: FontIndex) !font.Presentation pub fn faceFromIndex(self: *Group, index: FontIndex) !*Face { if (index.special() != null) return error.SpecialHasNoFace; const list = self.faces.getPtr(index.style); - const item = &list.items[@intCast(index.idx)]; + const item = &list.items[index.idx]; return switch (item.*) { .deferred => |*d| deferred: { const face = try d.load(self.lib, self.size); @@ -553,6 +554,30 @@ test { } } +test "face count limit" { + const testing = std.testing; + const alloc = testing.allocator; + const testFont = @import("test.zig").fontRegular; + + var atlas_greyscale = try font.Atlas.init(alloc, 512, .greyscale); + defer atlas_greyscale.deinit(alloc); + + var lib = try Library.init(); + defer lib.deinit(); + + var group = try init(alloc, lib, .{ .points = 12 }); + defer group.deinit(); + + for (0..FontIndex.Special.start - 1) |_| { + try group.addFace(.regular, .{ .loaded = try Face.init(lib, testFont, .{ .points = 12 }) }); + } + + try testing.expectError(error.GroupFull, group.addFace( + .regular, + .{ .loaded = try Face.init(lib, testFont, .{ .points = 12 }) }, + )); +} + test "box glyph" { const testing = std.testing; const alloc = testing.allocator;