summaryrefslogtreecommitdiff
path: root/std
diff options
context:
space:
mode:
authorZuhaitz Méndez Fernández de Aránguiz <zuhaitz@debian>2026-01-19 22:48:04 +0000
committerZuhaitz Méndez Fernández de Aránguiz <zuhaitz@debian>2026-01-19 22:48:04 +0000
commit23065ddf6ed0b3762dda5f5059888eb52b5c2415 (patch)
treeaec187b8211203081e8dacb07a5ce325eb348cc4 /std
parent3af5dcf34d705cc52c1ffe5b85c2a90b5104e4c9 (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.zc18
-rw-r--r--std/option.zc16
-rw-r--r--std/path.zc4
-rw-r--r--std/result.zc8
-rw-r--r--std/string.zc34
-rw-r--r--std/vec.zc7
6 files changed, 70 insertions, 17 deletions
diff --git a/std/fs.zc b/std/fs.zc
index 4223054..d35a1fa 100644
--- a/std/fs.zc
+++ b/std/fs.zc
@@ -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> {
diff --git a/std/vec.zc b/std/vec.zc
index be4dc05..fe16ac8 100644
--- a/std/vec.zc
+++ b/std/vec.zc
@@ -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 };