commit e9803624ac9e1966a58f22c69bdf4190bdb21c53
parent 97c191b4f4243c11285cd324956fc39de751cf33
Author: Bor Grošelj Simić <bgs@turminal.net>
Date: Tue, 19 Apr 2022 19:30:27 +0200
path: fix dangling pointer to a stack resource
path::init initialized buf.cur to point into a stack-allocated buffer,
which caused memory corruption after path::init returned.
Signed-off-by: Bor Grošelj Simić <bgs@turminal.net>
Diffstat:
2 files changed, 14 insertions(+), 11 deletions(-)
diff --git a/path/buffer.ha b/path/buffer.ha
@@ -7,7 +7,7 @@ use strings;
export type buffer = struct {
buf: [PATH_MAX]u8,
- cur: []u8,
+ end: size,
};
// Initializes a new path buffer.
@@ -19,7 +19,7 @@ export fn init() buffer = {
// Resets a path buffer to its initial state.
export fn reset(buf: *buffer) void = {
- buf.cur = buf.buf[..0];
+ buf.end = 0;
};
// Sets the value of a path buffer to a list of components, overwriting any
@@ -34,7 +34,7 @@ export fn set(buf: *buffer, items: str...) (str | errors::overflow) = {
export fn dup(buf: *buffer) buffer = {
let new = buffer { ... };
new.buf[..] = buf.buf[..];
- new.cur = new.buf[..0];
+ new.end = 0;
return new;
};
@@ -59,7 +59,7 @@ export fn dup(buf: *buffer) buffer = {
// path::set(&buf, "foo", "bar", "/")!;
// assert(path::string(&buf) == "foo/bar/");
export fn string(buf: *buffer) str = {
- const value = strings::fromutf8_unsafe(buf.cur);
+ const value = strings::fromutf8_unsafe(buf.buf[..buf.end]);
if (value == "") {
return ".";
};
@@ -88,8 +88,9 @@ fn appendnorm(buf: *buffer, elem: (str | []u8)) (void | errors::overflow) = {
yield strings::toutf8(string);
};
if (len(elem) == 1 && elem[0] == PATHSEP) {
- if (len(buf.cur) == 0) {
- static append(buf.cur, PATHSEP);
+ if (buf.end == 0) {
+ buf.buf[0] = PATHSEP;
+ buf.end += 1;
return;
};
return;
@@ -129,13 +130,15 @@ fn parent(buf: *buffer) (void | errors::overflow) = {
};
fn doappend(buf: *buffer, elem: []u8) (void | errors::overflow) = {
- if (len(buf.cur) + len(elem) + 1 >= PATH_MAX) {
+ if (buf.end + len(elem) + 1 >= PATH_MAX) {
return errors::overflow;
};
- if (len(buf.cur) > 0 && buf.cur[len(buf.cur) - 1] != PATHSEP) {
- static append(buf.cur, PATHSEP);
+ if (buf.end > 0 && buf.buf[buf.end - 1] != PATHSEP) {
+ buf.buf[buf.end] = PATHSEP;
+ buf.end += 1;
};
- static append(buf.cur, elem...);
+ buf.buf[buf.end..buf.end + len(elem)] = elem;
+ buf.end += len(elem);
};
@test fn appendnorm() void = {
diff --git a/path/util.ha b/path/util.ha
@@ -7,7 +7,7 @@ fn getbytes(in: (str | *buffer)) []u8 = {
case let st: str =>
return strings::toutf8(st);
case let buf: *buffer =>
- return buf.cur;
+ return buf.buf[..buf.end];
};
};