mirror of
https://github.com/ghostty-org/ghostty.git
synced 2025-07-15 00:06:09 +03:00
Merge pull request #2070 from ghostty-org/kitty-shm
terminal/kitty: shared memory size may be larger than expected for pages
This commit is contained in:
@ -368,6 +368,15 @@ pub const Transmission = struct {
|
|||||||
// but they are formats that a png may decode to that we
|
// but they are formats that a png may decode to that we
|
||||||
// support.
|
// support.
|
||||||
grey_alpha,
|
grey_alpha,
|
||||||
|
|
||||||
|
pub fn bpp(self: Format) u8 {
|
||||||
|
return switch (self) {
|
||||||
|
.grey_alpha => 2,
|
||||||
|
.rgb => 3,
|
||||||
|
.rgba => 4,
|
||||||
|
.png => unreachable, // Must be validated before
|
||||||
|
};
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
pub const Medium = enum {
|
pub const Medium = enum {
|
||||||
|
@ -128,17 +128,42 @@ pub const LoadingImage = struct {
|
|||||||
defer _ = std.c.close(fd);
|
defer _ = std.c.close(fd);
|
||||||
defer _ = std.c.shm_unlink(pathz);
|
defer _ = std.c.shm_unlink(pathz);
|
||||||
|
|
||||||
const stat = std.posix.fstat(fd) catch |err| {
|
// The size from stat on may be larger than our expected size because
|
||||||
log.warn("unable to fstat shared memory {s}: {}", .{ path, err });
|
// shared memory has to be a multiple of the page size.
|
||||||
return error.InvalidData;
|
const stat_size: usize = stat: {
|
||||||
|
const stat = std.posix.fstat(fd) catch |err| {
|
||||||
|
log.warn("unable to fstat shared memory {s}: {}", .{ path, err });
|
||||||
|
return error.InvalidData;
|
||||||
|
};
|
||||||
|
if (stat.size <= 0) return error.InvalidData;
|
||||||
|
break :stat @intCast(stat.size);
|
||||||
};
|
};
|
||||||
if (stat.size <= 0) return error.InvalidData;
|
|
||||||
|
|
||||||
const size: usize = @intCast(stat.size);
|
const expected_size: usize = switch (self.image.format) {
|
||||||
|
// Png we decode the full data size because later decoding will
|
||||||
|
// get the proper dimensions and assert validity.
|
||||||
|
.png => stat_size,
|
||||||
|
|
||||||
|
// For these formats we have a size we must have.
|
||||||
|
.grey_alpha, .rgb, .rgba => |f| size: {
|
||||||
|
const bpp = f.bpp();
|
||||||
|
break :size self.image.width * self.image.height * bpp;
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
// Our stat size must be at least the expected size otherwise
|
||||||
|
// the shared memory data is invalid.
|
||||||
|
if (stat_size < expected_size) {
|
||||||
|
log.warn(
|
||||||
|
"shared memory size too small expected={} actual={}",
|
||||||
|
.{ expected_size, stat_size },
|
||||||
|
);
|
||||||
|
return error.InvalidData;
|
||||||
|
}
|
||||||
|
|
||||||
const map = std.posix.mmap(
|
const map = std.posix.mmap(
|
||||||
null,
|
null,
|
||||||
size,
|
stat_size, // mmap always uses the stat size
|
||||||
std.c.PROT.READ,
|
std.c.PROT.READ,
|
||||||
std.c.MAP{ .TYPE = .SHARED },
|
std.c.MAP{ .TYPE = .SHARED },
|
||||||
fd,
|
fd,
|
||||||
@ -149,11 +174,13 @@ pub const LoadingImage = struct {
|
|||||||
};
|
};
|
||||||
defer std.posix.munmap(map);
|
defer std.posix.munmap(map);
|
||||||
|
|
||||||
|
// Our end size always uses the expected size so we cut off the
|
||||||
|
// padding for mmap alignment.
|
||||||
const start: usize = @intCast(t.offset);
|
const start: usize = @intCast(t.offset);
|
||||||
const end: usize = if (t.size > 0) @min(
|
const end: usize = if (t.size > 0) @min(
|
||||||
@as(usize, @intCast(t.offset)) + @as(usize, @intCast(t.size)),
|
@as(usize, @intCast(t.offset)) + @as(usize, @intCast(t.size)),
|
||||||
size,
|
expected_size,
|
||||||
) else size;
|
) else expected_size;
|
||||||
|
|
||||||
assert(self.data.items.len == 0);
|
assert(self.data.items.len == 0);
|
||||||
try self.data.appendSlice(alloc, map[start..end]);
|
try self.data.appendSlice(alloc, map[start..end]);
|
||||||
@ -302,12 +329,7 @@ pub const LoadingImage = struct {
|
|||||||
if (img.width > max_dimension or img.height > max_dimension) return error.DimensionsTooLarge;
|
if (img.width > max_dimension or img.height > max_dimension) return error.DimensionsTooLarge;
|
||||||
|
|
||||||
// Data length must be what we expect
|
// Data length must be what we expect
|
||||||
const bpp: u32 = switch (img.format) {
|
const bpp = img.format.bpp();
|
||||||
.grey_alpha => 2,
|
|
||||||
.rgb => 3,
|
|
||||||
.rgba => 4,
|
|
||||||
.png => unreachable, // png should be decoded by here
|
|
||||||
};
|
|
||||||
const expected_len = img.width * img.height * bpp;
|
const expected_len = img.width * img.height * bpp;
|
||||||
const actual_len = self.data.items.len;
|
const actual_len = self.data.items.len;
|
||||||
if (actual_len != expected_len) {
|
if (actual_len != expected_len) {
|
||||||
|
Reference in New Issue
Block a user