Skip to content

AddressSanitizer can't report the issue of double free #5917

Description

@forchid

Context

  • Operating System & Odin Version: AlmaLinux 9.5 (Teal Serval),odin version dev-2025-11-nightly
  • Please paste odin report output:
    Odin: dev-2025-11-nightly
    OS: AlmaLinux 9.5 (Teal Serval), Linux 5.14.0-503.11.1.el9_5.x86_64
    CPU: Intel(R) Core(TM) i7-6500U CPU @ 2.50GHz
    RAM: 1774 MiB
    Backend: LLVM 20.1.8

Expected Behavior

Report the location of double free in odin source code.

Current Behavior

  • "==1765==ERROR: AddressSanitizer: SEGV on unknown address" if using the compiling options -debug -sanitize:address
  • But ok if using the compiling options -debug -sanitize:memory or -debug -sanitize:thread

Failure Information (for bugs)

  • When using the compiling options -debug -sanitize:address
# odin build double-free.odin -file -debug -sanitize:address
# ./double-free
My value = 100000, list size = 100000
My value = 200000, list size = 100000
My value = 300000, list size = 100000
My value = 400000, list size = 100000
My value = 500000, list size = 100000
My value = 600000, list size = 100000
My value = 700000, list size = 100000
My value = 800000, list size = 100000
My value = 900000, list size = 100000
My value = 999999, list size = 99999
Waiting for input ..

AddressSanitizer:DEADLYSIGNAL
=================================================================
==1765==ERROR: AddressSanitizer: SEGV on unknown address 0xfffffffffffffff6 (pc 0x00000042db46 bp 0x000000000000 sp 0x7ffdd7c55280 T0)
==1765==The signal is caused by a WRITE memory access.
    #0 0x42db46  (/root/test/sanitizer/double-free+0x42db46) (BuildId: 3dc8053cb968176277527e5e11e00440ad985ca1)
    #1 0x4c55af  (/root/test/sanitizer/double-free+0x4c55af) (BuildId: 3dc8053cb968176277527e5e11e00440ad985ca1)
    #2 0x592817  (/root/test/sanitizer/double-free+0x592817) (BuildId: 3dc8053cb968176277527e5e11e00440ad985ca1)
    #3 0x592087  (/root/test/sanitizer/double-free+0x592087) (BuildId: 3dc8053cb968176277527e5e11e00440ad985ca1)
    #4 0x59240d  (/root/test/sanitizer/double-free+0x59240d) (BuildId: 3dc8053cb968176277527e5e11e00440ad985ca1)
    #5 0x591edf  (/root/test/sanitizer/double-free+0x591edf) (BuildId: 3dc8053cb968176277527e5e11e00440ad985ca1)
    #6 0x580dfd  (/root/test/sanitizer/double-free+0x580dfd) (BuildId: 3dc8053cb968176277527e5e11e00440ad985ca1)
    #7 0x57c5e9  (/root/test/sanitizer/double-free+0x57c5e9) (BuildId: 3dc8053cb968176277527e5e11e00440ad985ca1)
    #8 0x587764  (/root/test/sanitizer/double-free+0x587764) (BuildId: 3dc8053cb968176277527e5e11e00440ad985ca1)
    #9 0x7f650fc295cf  (/lib64/libc.so.6+0x295cf) (BuildId: d78a44ae94f1d320342e0ff6c2315b2b589063f8)
    #10 0x7f650fc2967f  (/lib64/libc.so.6+0x2967f) (BuildId: d78a44ae94f1d320342e0ff6c2315b2b589063f8)
    #11 0x42a354  (/root/test/sanitizer/double-free+0x42a354) (BuildId: 3dc8053cb968176277527e5e11e00440ad985ca1)

AddressSanitizer can not provide additional info.
SUMMARY: AddressSanitizer: SEGV (/root/test/sanitizer/double-free+0x42db46) (BuildId: 3dc8053cb968176277527e5e11e00440ad985ca1)
==1765==ABORTING
  • When using the compiling options -debug -sanitize:memory or -debug -sanitize:thread
# odin build double-free.odin -file -debug -sanitize:memory
# ./double-free
My value = 100000, list size = 100000
My value = 200000, list size = 100000
My value = 300000, list size = 100000
My value = 400000, list size = 100000
My value = 500000, list size = 100000
My value = 600000, list size = 100000
My value = 700000, list size = 100000
My value = 800000, list size = 100000
My value = 900000, list size = 100000
My value = 999999, list size = 99999
Waiting for input ..

ok. 

Steps to Reproduce

  1. Using -sanitize:address
#odin build double-free.odin -file -debug -sanitize:address
# ./double-free
My value = 100000, list size = 100000
My value = 200000, list size = 100000
My value = 300000, list size = 100000
My value = 400000, list size = 100000
My value = 500000, list size = 100000
My value = 600000, list size = 100000
My value = 700000, list size = 100000
My value = 800000, list size = 100000
My value = 900000, list size = 100000
My value = 999999, list size = 99999
Waiting for input ..

AddressSanitizer:DEADLYSIGNAL
=================================================================
==1823==ERROR: AddressSanitizer: SEGV on unknown address 0xfffffffffffffff6 (pc 0x00000042db46 bp 0x000000000000 sp 0x7ffea82c9920 T0)
==1823==The signal is caused by a WRITE memory access.
    #0 0x42db46  (/root/test/sanitizer/double-free+0x42db46) (BuildId: 72d4298cca843cdfe975a5bd8a334bfa8a58b5b3) 
....
  1. Using -sanitize:memory or -sanitize:thread
#odin build double-free.odin -file -debug -sanitize:memory
# ./double-free
My value = 100000, list size = 100000
My value = 200000, list size = 100000
My value = 300000, list size = 100000
My value = 400000, list size = 100000
My value = 500000, list size = 100000
My value = 600000, list size = 100000
My value = 700000, list size = 100000
My value = 800000, list size = 100000
My value = 900000, list size = 100000
My value = 999999, list size = 99999
Waiting for input ..

ok.
  1. No -sanitize:XXX
# odin build double-free.odin -file -debug
# ./double-free
My value = 100000, list size = 100000
My value = 200000, list size = 100000
My value = 300000, list size = 100000
My value = 400000, list size = 100000
My value = 500000, list size = 100000
My value = 600000, list size = 100000
My value = 700000, list size = 100000
My value = 800000, list size = 100000
My value = 900000, list size = 100000
My value = 999999, list size = 99999
Waiting for input ..

Segmentation fault (core dumped)

The source code

double-free.odin

package main

import "core:fmt"
import "core:os"

main :: proc() {
    my := MyInt_new(0)
    {
        a : [dynamic](^MyInt)
        defer if(a != nil) {
            for e in a do free(e)
            clear(&a)
            delete(a)
            a = nil
        }
        free(my)
        my = nil
        
        for i in 1 ..< 100_0000 {
            my = MyInt_new(i)
            append(&a, my)
            if i % 10_0000 == 0 {
                fmt.printfln("My value = %v, list size = %v", my.value, len(a))
                for e in a { free(e) }
                my = nil
                delete(a)
                a = nil
            }
        }
        if my != nil {
            fmt.printfln("My value = %v, list size = %v", my.value, len(a))
        }
    }

    fmt.printfln("Waiting for input ..")
    c := [1]u8{}
    os.read(os.stdin, c[:])
    
    free(my) // Double free
    fmt.printfln("ok.")
}

MyInt :: struct {
    value: int,
}

MyInt_new :: proc(value: int) -> ^MyInt {
    result := new(MyInt)
    result.value = value
    return result
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions