diff options
| author | Zuhaitz Méndez Fernández de Aránguiz <zuhaitz@debian> | 2026-01-19 22:48:04 +0000 |
|---|---|---|
| committer | Zuhaitz Méndez Fernández de Aránguiz <zuhaitz@debian> | 2026-01-19 22:48:04 +0000 |
| commit | 23065ddf6ed0b3762dda5f5059888eb52b5c2415 (patch) | |
| tree | aec187b8211203081e8dacb07a5ce325eb348cc4 /std | |
| parent | 3af5dcf34d705cc52c1ffe5b85c2a90b5104e4c9 (diff) | |
Fixes related to memory safety. I will work more on this related to the stdlib.
Diffstat (limited to 'std')
| -rw-r--r-- | std/fs.zc | 18 | ||||
| -rw-r--r-- | std/option.zc | 16 | ||||
| -rw-r--r-- | std/path.zc | 4 | ||||
| -rw-r--r-- | std/result.zc | 8 | ||||
| -rw-r--r-- | std/string.zc | 34 | ||||
| -rw-r--r-- | std/vec.zc | 7 |
6 files changed, 70 insertions, 17 deletions
@@ -50,7 +50,7 @@ struct Metadata { is_file: bool; } -@derive(Eq) +// @derive(Eq) - Removed to avoid double-free on String field struct DirEntry { name: String; is_dir: bool; @@ -87,7 +87,11 @@ impl File { var s = String::new(buffer); free(buffer); - return Result<String>::Ok(s); + var res = Result<String>::Ok(s); + s.forget(); + var ret = res; + res.forget(); + return ret; } fn read_all(path: char*) -> Result<String> { @@ -97,7 +101,9 @@ impl File { var f: File = res.unwrap(); var s_res = f.read_to_string(); f.close(); - return s_res; + var ret = s_res; + s_res.forget(); + return ret; } fn write_string(self, content: char*) -> Result<bool> { @@ -157,6 +163,10 @@ impl File { free(name_buf); closedir(dir); - return Result< Vec<DirEntry> >::Ok(entries); + var res = Result< Vec<DirEntry> >::Ok(entries); + entries.forget(); + var ret = res; + res.forget(); + return ret; } } diff --git a/std/option.zc b/std/option.zc index 5652bd7..11b4428 100644 --- a/std/option.zc +++ b/std/option.zc @@ -23,12 +23,26 @@ impl Option<T> { return !self.is_some; } + fn forget(self) { + memset(&self.val, 0, sizeof(T)); + } + fn unwrap(self) -> T { if (!self.is_some) { !"Panic: unwrap called on None"; exit(1); } - return self.val; + var v = self.val; + memset(&self.val, 0, sizeof(T)); + return v; + } + + fn unwrap_ref(self) -> T* { + if (!self.is_some) { + !"Panic: unwrap_ref called on None"; + exit(1); + } + return &self.val; } fn unwrap_or(self, def_val: T) -> T { diff --git a/std/path.zc b/std/path.zc index 6a9531d..7055880 100644 --- a/std/path.zc +++ b/std/path.zc @@ -33,12 +33,12 @@ impl Path { var last = self.str.vec.get(base_len - 1); if (last != '/' && last != '\\') { var sep = String::new("/"); - new_s.append(sep); + new_s.append(&sep); } } var other_str = String::new(other); - new_s.append(other_str); + new_s.append(&other_str); return Path { str: new_s }; } diff --git a/std/result.zc b/std/result.zc index b043162..3794f1a 100644 --- a/std/result.zc +++ b/std/result.zc @@ -24,12 +24,18 @@ impl Result<T> { return !self.is_ok; } + fn forget(self) { + memset(&self.val, 0, sizeof(T)); + } + fn unwrap(self) -> T { if (!self.is_ok) { !"Panic: unwrap called on Err: {self.err}"; exit(1); } - return self.val; + var v = self.val; + memset(&self.val, 0, sizeof(T)); + return v; } fn expect(self, msg: char*) -> T { diff --git a/std/string.zc b/std/string.zc index 4e0ba03..2e59179 100644 --- a/std/string.zc +++ b/std/string.zc @@ -16,7 +16,11 @@ impl String { v.push(s[i]); } v.push(0); - return String { vec: v }; + var d = v.data; + var l = v.len; + var c = v.cap; + v.forget(); + return String { vec: Vec<char> { data: d, len: l, cap: c } }; } fn from(s: char*) -> String { @@ -30,23 +34,31 @@ impl String { fn destroy(self) { self.vec.free(); } + + fn forget(self) { + self.vec.forget(); + } - fn append(self, other: String) { + fn append(self, other: String*) { self.vec.len = self.vec.len - 1; - var other_len = other.vec.len; + var other_len = (*other).vec.len; for (var i = 0; i < other_len; i = i + 1) { - self.vec.push(other.vec.get(i)); + self.vec.push((*other).vec.get(i)); } } - fn add(self, other: String) -> String { + fn add(self, other: String*) -> String { var new_s = String::from(self.c_str()); new_s.append(other); - return new_s; + var d = new_s.vec.data; + var l = new_s.vec.len; + var c = new_s.vec.cap; + new_s.forget(); + return String { vec: Vec<char> { data: d, len: l, cap: c } }; } - fn eq(self, other: String) -> bool { - return strcmp(self.c_str(), other.c_str()) == 0; + fn eq(self, other: String*) -> bool { + return strcmp(self.c_str(), (*other).c_str()) == 0; } fn length(self) -> usize { @@ -66,7 +78,11 @@ impl String { v.push(self.vec.get(start + i)); } v.push(0); - return String { vec: v }; + var d = v.data; + var l = v.len; + var c = v.cap; + v.forget(); + return String { vec: Vec<char> { data: d, len: l, cap: c } }; } fn find(self, target: char) -> Option<usize> { @@ -244,6 +244,13 @@ impl Vec<T> { return true; } + // Prevent Drop from freeing memory (simulates move) + fn forget(self) { + self.data = 0; + self.len = 0; + self.cap = 0; + } + fn clone(self) -> Vec<T> { if (self.len == 0) { return Vec<T> { data: 0, len: 0, cap: 0 }; |
