`std.posix.mprotect` remove memory length assertion
Zig's wrapper functions over mmap and munmap abstract over the system pages' lengths: std.posix.mmap returns (if successful) a slice of the exact requested length (rather than error, or rounded up to a multiple of the page size). std.posix.munmap accepts the slice produced by std.posix.mmap - so the length here too isn't page aligned.
std.posix.mprotect should also adhere to the abstraction, and accept any slice produced by std.posix.mmap, without need to fiddle with the data.
the change is simply to remove the assertion, as it seems like Linux, Plan9, and Windows' VirtualProtect all cope with lengths which aren't a multiple of a page (as I understand it, all other OSs require using the libc function, which also allows for lengths not divisible by the page size).
mprotect() changes the access protections for the calling process's memory pages containing any part of the address range in the interval [addr, addr+len-1].
The mprotect() function shall change the access protections to be that specified by prot for those whole pages containing any part of the address space of the process starting at address addr and continuing for len bytes.
The size of the region whose access protection attributes are to be changed, in bytes. The region of affected pages includes all pages containing one or more bytes in the range from the lpAddress parameter to
(lpAddress+dwSize).
with the change we do nice things like:
const flags: std.os.linux.MAP = .{
.TYPE = .PRIVATE,
.ANONYMOUS = true,
};
const mem = try std.posix.mmap(
null,
len,
0b011, // read, write
flags,
-1,
0,
);
defer std.posix.munmap(mem);
// write stuff to `mem`...
try std.posix.mprotect(
mem,
0b001, // just read
);
// read from `mem`...
whereas currently we need to do lie to the function:
comptime std.debug.assert(std.mem.page_size & std.mem.page_size - 1 == 0); // power of two
const page_bits: usize = std.mem.page_size - 1;
try std.posix.mprotect(mem.ptr[0 .. (mem.len + page_bits) & ~page_bits], 0b001);