]> Projects (at) Tadryanom (dot) Me - AdrOS.git/commitdiff
fix: heap coalesce early-return, process_create_kernel leak, pipe double-free, path...
authorTulio A M Mendes <[email protected]>
Tue, 10 Feb 2026 02:35:38 +0000 (23:35 -0300)
committerTulio A M Mendes <[email protected]>
Tue, 10 Feb 2026 02:35:38 +0000 (23:35 -0300)
src/kernel/scheduler.c
src/kernel/syscall.c
src/mm/heap.c

index 5cf1fad600a0ddf08821dc741d08233a672c249f..95fe9a79e8ccf5bd78e2d43cc14e7756990d3498 100644 (file)
@@ -411,6 +411,7 @@ struct process* process_create_kernel(void (*entry_point)(void)) {
     
     void* stack = kmalloc(4096);
     if (!stack) {
+        kfree(proc);
         spin_unlock_irqrestore(&sched_lock, flags);
         return NULL;
     }
index c3429f2d56d2a305b275a70cead76a66c94033d9..48a3c9324be5c6f224469e73de6a43cd589b12d9 100644 (file)
@@ -415,13 +415,15 @@ static int pipe_create_kfds(int kfds[2]) {
 
     fs_node_t* rnode = NULL;
     fs_node_t* wnode = NULL;
-    if (pipe_node_create(ps, 1, &rnode) < 0 || pipe_node_create(ps, 0, &wnode) < 0) {
-        if (rnode) vfs_close(rnode);
-        if (wnode) vfs_close(wnode);
-        if (ps->buf) kfree(ps->buf);
+    if (pipe_node_create(ps, 1, &rnode) < 0) {
+        kfree(ps->buf);
         kfree(ps);
         return -ENOMEM;
     }
+    if (pipe_node_create(ps, 0, &wnode) < 0) {
+        vfs_close(rnode);
+        return -ENOMEM;
+    }
 
     struct file* rf = (struct file*)kmalloc(sizeof(*rf));
     struct file* wf = (struct file*)kmalloc(sizeof(*wf));
@@ -887,33 +889,72 @@ static int path_is_absolute(const char* p) {
 
 static void path_normalize_inplace(char* s) {
     if (!s) return;
-    // Collapse duplicate slashes and remove trailing slash (except for root).
-    char tmp[128];
-    size_t w = 0;
-    size_t r = 0;
     if (s[0] == 0) {
         strcpy(s, "/");
         return;
     }
 
-    while (s[r] != 0 && w + 1 < sizeof(tmp)) {
-        char c = s[r++];
-        if (c == '/') {
-            if (w == 0 || tmp[w - 1] != '/') {
-                tmp[w++] = '/';
+    // Phase 1: split into components, resolve '.' and '..'
+    char tmp[128];
+    // Stack of component start offsets within tmp
+    size_t comp_start[32];
+    int depth = 0;
+    size_t w = 0;
+
+    const char* p = s;
+    int absolute = (*p == '/');
+    if (absolute) {
+        tmp[w++] = '/';
+        while (*p == '/') p++;
+    }
+
+    while (*p != 0) {
+        // Extract next component
+        const char* seg = p;
+        while (*p != 0 && *p != '/') p++;
+        size_t seg_len = (size_t)(p - seg);
+        while (*p == '/') p++;
+
+        if (seg_len == 1 && seg[0] == '.') {
+            continue; // skip '.'
+        }
+
+        if (seg_len == 2 && seg[0] == '.' && seg[1] == '.') {
+            // Go up one level
+            if (depth > 0) {
+                depth--;
+                w = comp_start[depth];
             }
-        } else {
-            tmp[w++] = c;
+            continue;
+        }
+
+        // Record start of this component
+        if (depth < 32) {
+            comp_start[depth++] = w;
+        }
+
+        // Append separator if needed
+        if (w > 1 || (w == 1 && tmp[0] != '/')) {
+            if (w + 1 < sizeof(tmp)) tmp[w++] = '/';
+        }
+
+        // Append component
+        for (size_t i = 0; i < seg_len && w + 1 < sizeof(tmp); i++) {
+            tmp[w++] = seg[i];
         }
     }
-    tmp[w] = 0;
 
-    size_t l = strlen(tmp);
-    while (l > 1 && tmp[l - 1] == '/') {
-        tmp[l - 1] = 0;
-        l--;
+    // Handle empty result
+    if (w == 0) {
+        tmp[w++] = '/';
     }
 
+    // Remove trailing slash (except root)
+    while (w > 1 && tmp[w - 1] == '/') {
+        w--;
+    }
+
+    tmp[w] = 0;
     strcpy(s, tmp);
 }
 
index de38203c46ec22ff5aafe113c70e667cecfe92e6..9a66ec6ad61469277f371327e714270f3467ca5e 100644 (file)
@@ -182,18 +182,15 @@ void kfree(void* ptr) {
 
         // Only coalesce if physically adjacent.
         heap_header_t* expected_next = (heap_header_t*)((uint8_t*)header + sizeof(heap_header_t) + header->size);
-        if (next_block != expected_next) {
-            spin_unlock_irqrestore(&heap_lock, flags);
-            return;
-        }
-        
-        header->size += sizeof(heap_header_t) + next_block->size;
-        header->next = next_block->next;
-        
-        if (header->next) {
-            header->next->prev = header;
-        } else {
-            tail = header; // If next was tail, now current is tail
+        if (next_block == expected_next) {
+            header->size += sizeof(heap_header_t) + next_block->size;
+            header->next = next_block->next;
+
+            if (header->next) {
+                header->next->prev = header;
+            } else {
+                tail = header;
+            }
         }
     }
     
@@ -203,20 +200,16 @@ void kfree(void* ptr) {
 
         // Only coalesce if physically adjacent.
         heap_header_t* expected_hdr = (heap_header_t*)((uint8_t*)prev_block + sizeof(heap_header_t) + prev_block->size);
-        if (expected_hdr != header) {
-            spin_unlock_irqrestore(&heap_lock, flags);
-            return;
-        }
-        
-        prev_block->size += sizeof(heap_header_t) + header->size;
-        prev_block->next = header->next;
-        
-        if (header->next) {
-            header->next->prev = prev_block;
-        } else {
-            tail = prev_block;
+        if (expected_hdr == header) {
+            prev_block->size += sizeof(heap_header_t) + header->size;
+            prev_block->next = header->next;
+
+            if (header->next) {
+                header->next->prev = prev_block;
+            } else {
+                tail = prev_block;
+            }
         }
-        // No need to update 'header' anymore, prev_block is the merged one
     }
 
     spin_unlock_irqrestore(&heap_lock, flags);