Commit ea6a076065

Andrew Kelley <andrew@ziglang.org>
2020-08-25 22:36:15
stage2: fix use-after-free in elf linker code
1 parent 84d50c8
Changed files (1)
src-self-hosted
link
src-self-hosted/link/Elf.zig
@@ -1348,6 +1348,7 @@ fn freeTextBlock(self: *Elf, text_block: *TextBlock) void {
     var already_have_free_list_node = false;
     {
         var i: usize = 0;
+        // TODO turn text_block_free_list into a hash map
         while (i < self.text_block_free_list.items.len) {
             if (self.text_block_free_list.items[i] == text_block) {
                 _ = self.text_block_free_list.swapRemove(i);
@@ -1359,11 +1360,19 @@ fn freeTextBlock(self: *Elf, text_block: *TextBlock) void {
             i += 1;
         }
     }
+    // TODO process free list for dbg info just like we do above for vaddrs
 
     if (self.last_text_block == text_block) {
         // TODO shrink the .text section size here
         self.last_text_block = text_block.prev;
     }
+    if (self.dbg_info_decl_first == text_block) {
+        self.dbg_info_decl_first = text_block.dbg_info_next;
+    }
+    if (self.dbg_info_decl_last == text_block) {
+        // TODO shrink the .debug_info section size here
+        self.dbg_info_decl_last = text_block.dbg_info_prev;
+    }
 
     if (text_block.prev) |prev| {
         prev.next = text_block.next;
@@ -1382,6 +1391,20 @@ fn freeTextBlock(self: *Elf, text_block: *TextBlock) void {
     } else {
         text_block.next = null;
     }
+
+    if (text_block.dbg_info_prev) |prev| {
+        prev.dbg_info_next = text_block.dbg_info_next;
+
+        // TODO the free list logic like we do for text blocks above
+    } else {
+        text_block.dbg_info_prev = null;
+    }
+
+    if (text_block.dbg_info_next) |next| {
+        next.dbg_info_prev = text_block.dbg_info_prev;
+    } else {
+        text_block.dbg_info_next = null;
+    }
 }
 
 fn shrinkTextBlock(self: *Elf, text_block: *TextBlock, new_block_size: u64) void {
@@ -1583,10 +1606,10 @@ pub fn freeDecl(self: *Elf, decl: *Module.Decl) void {
         next.prev = null;
     }
     if (self.dbg_line_fn_first == &decl.fn_link.elf) {
-        self.dbg_line_fn_first = null;
+        self.dbg_line_fn_first = decl.fn_link.elf.next;
     }
     if (self.dbg_line_fn_last == &decl.fn_link.elf) {
-        self.dbg_line_fn_last = null;
+        self.dbg_line_fn_last = decl.fn_link.elf.prev;
     }
 }