authorgravatar for rpkak@noreply.codeberg.orgrpkak <rpkak@noreply.codeberg.org> 2026-09-17 20:02:07+02:00
committergravatar for alex@alexrp.comAlex Rønne Petersen <alex@alexrp.com> 2026-09-18 01:25:17+02:00
log750006a823235d3757b40e1d169dac8bc86e9f1f
tree3e055b5c6d008b16c558c43f1479c08d03c2197d
parent955228b682dc48a3815707f318280af12a3daf00

libzigc: memchr, wmemchr: don't read past first occurence of value

Previously is was assumed, that all len bytes after ptr are readable.

2 files changed, 10 insertions(+), 3 deletions(-)

lib/c/string.zig+5-1
...@@ -68,8 +68,12 @@ comptime {...@@ -68,8 +68,12 @@ comptime {
68}68}
6969
70fn memchr(ptr: *const anyopaque, value: c_int, len: usize) callconv(.c) ?*anyopaque {70fn memchr(ptr: *const anyopaque, value: c_int, len: usize) callconv(.c) ?*anyopaque {
71 const b: u8 = @truncate(@as(c_uint, @bitCast(value)));
71 const bytes: [*]const u8 = @ptrCast(ptr);72 const bytes: [*]const u8 = @ptrCast(ptr);
72 return @constCast(bytes[std.mem.findScalar(u8, bytes[0..len], @truncate(@as(c_uint, @bitCast(value)))) orelse return null ..]);73 for (0..len) |i| {
74 if (bytes[i] == b) return @constCast(&bytes[i]);
75 }
76 return null;
73}77}
7478
75fn strcpy(noalias dst: [*]c_char, noalias src: [*:0]const c_char) callconv(.c) [*]c_char {79fn strcpy(noalias dst: [*]c_char, noalias src: [*:0]const c_char) callconv(.c) [*]c_char {
lib/c/wchar.zig+5-2
...@@ -46,8 +46,11 @@ comptime {...@@ -46,8 +46,11 @@ comptime {
46 }46 }
47}47}
4848
49fn wmemchr(ptr: [*]const wchar_t, value: wchar_t, len: usize) callconv(.c) ?[*]wchar_t {49fn wmemchr(ptr: [*]const wchar_t, value: wchar_t, len: usize) callconv(.c) ?*wchar_t {
50 return @constCast(ptr[std.mem.findScalar(wchar_t, ptr[0..len], value) orelse return null ..]);50 for (0..len) |i| {
51 if (ptr[i] == value) return @constCast(&ptr[i]);
52 }
53 return null;
51}54}
5255
53fn wmemcmp(a: [*]const wchar_t, b: [*]const wchar_t, len: usize) callconv(.c) c_int {56fn wmemcmp(a: [*]const wchar_t, b: [*]const wchar_t, len: usize) callconv(.c) c_int {