From a5be027a0c05c8950bada14fa2f2e713ce7d6986 Mon Sep 17 00:00:00 2001 From: Gabriel Schneider Date: Tue, 29 Sep 2026 12:31:47 -0300 Subject: A look at a corrupt image fails with an err rather than open a blank pane An image stb_image could not read opened as an empty image pane, the look succeeding. The bytes' header is now checked at the look (stbi_info_from_memory), and one that is no image it reads fails the look, look: : not an image pardes can read, making no pane. Co-Authored-By: Claude Opus 5.5 --- src/image.zig | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) (limited to 'src/image.zig') diff --git a/src/image.zig b/src/image.zig index 071a2e2a..7b081ec6 100644 --- a/src/image.zig +++ b/src/image.zig @@ -732,11 +732,28 @@ test "native geometry is total at extreme accepted aspect ratios" { /// call once at startup / exit (stb_image's allocator shim) pub fn start(io: std.Io, gpa: std.mem.Allocator) void { zstbi.init(io, gpa); + started = true; } pub fn stop() void { + started = false; zstbi.deinit(); } +/// stb_image has its allocator (`start`): before, nothing of it may run. +var started = false; + +extern fn stbi_info_from_memory(buffer: [*]const u8, len: c_int, x: *c_int, y: *c_int, comp: *c_int) c_int; + +/// Whether `bytes` are an image `decode` can read, from its header alone. +pub fn readable(bytes: []const u8) bool { + if (bytes.len == 0 or bytes.len > std.math.maxInt(c_int)) return false; + var w: c_int = 0; + var h: c_int = 0; + var c: c_int = 0; + if (!started) return true; // ponytail: no stb_image yet (a unit test), so no judging + return stbi_info_from_memory(bytes.ptr, @intCast(bytes.len), &w, &h, &c) == 1; +} + /// decode + downscale to RGBA, gpa-owned. Returns null on any failure — the /// pane then simply shows a blank body. pub fn decode(gpa: std.mem.Allocator, bytes: []const u8) ?struct { rgba: []u8, w: usize, h: usize } { -- cgit v1.3