Skip to content

Segfault when accessing a union in a tuple via Any #4507

@nisanharamati

Description

@nisanharamati

Repro

Minimal version

actor Main
  let env: Env
  new create(env': Env) =>
    env = env'
    let x = ("hello", USize(123))
    match_x(x)            // segfault

  fun match_x(x: Any val) =>
    env.out.print("match_x(x: Any val): ")
    // segfault
    match x
    | let s: Stringable => env.out.print("\t" + s.string())
    | (let a: Stringable, let b: (USize | U64)) =>
      env.out.print("\t(" + a.string() + ", " + b.string() +")")
    else
      env.out.print("\tno-match")
    end

Some more cases

actor Main
  let env: Env
  new create(env': Env) =>
    env = env'
    let str = "string"

    env.out.print("param is String: " + str)
    // works fine
    env.out.print("inline match")
    match str
    | let s: Stringable => env.out.print("\t" + s.string())
    end

    match_usize(str)        // fine
    match_number(str)       // fine
    match_stringable(str)   // fine

    let x = ("hello", USize(123))
    env.out.print("\n\nparam is (String, USize): (" + x._1 + ", " + x._2.string()
                  + ")")
    // works fine
    env.out.print("inline match")
    match x
    | (let a: Stringable, let b: Stringable) =>
      env.out.print("\t(" + a.string() + ", " + b.string() +")")
    end

    match_usize(x)        // fine
    match_number(x)       // segfault
    match_stringable(x)   // segfault

  fun match_stringable(p: Any val) =>
    env.out.print("match_stringable(p: Any): ")
    match p
    | let s: Stringable => env.out.print("\t" + s.string())
    | (let a: Stringable, let b: Stringable) =>
      env.out.print("\t(" + a.string() + ", " + b.string() + ")")
    else
      env.out.print("\tno-match")
    end

  fun match_number(p: Any val) =>
    env.out.print("match_number(p: Any): ")
    match p
    | let s: Stringable => env.out.print("\t" + s.string())
    | (let a: Stringable, let b: Number) =>
      env.out.print("\t(" + a.string() + ", " + b.string() + ")")
    else
      env.out.print("\tno-match")
    end

  fun match_usize(p: Any val) =>
    env.out.print("match_usize(p: Any): ")
    match p
    | let s: Stringable => env.out.print("\t" + s.string())
    | (let a: Stringable, let b: USize) =>
      env.out.print("\t(" + a.string() + ", " + b.string() + ")")
    else
      env.out.print("\tno-match")
    end

OS: MacOS, M3
Pony version

% ponyc -v
0.58.3-cb2f814b [debug]
Compiled with: LLVM 15.0.7 -- AppleClang-15.0.0.15000309-arm64
Defaults: pic=true

Backtrace (of the minimal version)

% lldb -- ./12_segfault_tuple
(lldb) target create "./12_segfault_tuple"
Current executable set to 'scratch/pony/12_segfault_tuple/12_segfault_tuple' (arm64).
(lldb) r
Process 21124 launched: 'scratch/pony/12_segfault_tuple/12_segfault_tuple' (arm64)
match_x(x: Any val):
Process 21124 stopped
* thread #4, stop reason = EXC_BAD_ACCESS (code=1, address=0x7b)
    frame #0: 0x000000010000537c 12_segfault_tuple`___lldb_unnamed_symbol3694 + 372
12_segfault_tuple`___lldb_unnamed_symbol3694:
->  0x10000537c <+372>: ldr    x8, [x0]
    0x100005380 <+376>: b      0x100005418               ; <+528>
    0x100005384 <+380>: ldr    x0, [x8, x10]
    0x100005388 <+384>: ldr    x8, [x0]
Target 0: (12_segfault_tuple) stopped.
(lldb) bt
* thread #4, stop reason = EXC_BAD_ACCESS (code=1, address=0x7b)
  * frame #0: 0x000000010000537c 12_segfault_tuple`___lldb_unnamed_symbol3694 + 372
    frame #1: 0x0000000100009518 12_segfault_tuple`handle_message(ctx=0x00000001084e9e08, actor=0x00000001084e8c00, msg=0x00000001084e9300) at actor.c:507:7
    frame #2: 0x0000000100008b20 12_segfault_tuple`ponyint_actor_run(ctx=0x00000001084e9e08, actor=0x00000001084e8c00, polling=false) at actor.c:592:20
    frame #3: 0x00000001000230c8 12_segfault_tuple`run(sched=0x00000001084e9dc0) at scheduler.c:1075:23
    frame #4: 0x0000000100022500 12_segfault_tuple`run_thread(arg=0x00000001084e9dc0) at scheduler.c:1127:3
    frame #5: 0x00000001804e6f94 libsystem_pthread.dylib`_pthread_start + 136

Metadata

Metadata

Assignees

Labels

triggers releaseMajor issue that when fixed, results in an "emergency" release

Type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions