Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SIGSEGV when accessing tuple element from partial function #2609

Closed
king1600 opened this issue Mar 21, 2018 · 6 comments · Fixed by #3723
Closed

SIGSEGV when accessing tuple element from partial function #2609

king1600 opened this issue Mar 21, 2018 · 6 comments · Fixed by #3723
Labels
needs investigation This needs to be looked into before its "ready for work" triggers release Major issue that when fixed, results in an "emergency" release

Comments

@king1600
Copy link

The segfault occurs regardless of the --debug flag.
Compiler version: 0.21.3-98ce091 [release]

  • (native windows binary) llvm 3.9.1 -- msvc-15-x64
  • (windows 10 WSL) llvm 3.9.1 -- gcc (Ubuntu/Linaro 6.3.0-18ubuntu2~14.04) 6.3.0 20170519

The bugged code:

actor Main
  new create(env: Env) =>
    try _bug()?._2 as Bool end

  fun _bug(): (USize, (Bool | None)) ? =>
    match "bug"
    | "bug" => (0, true)
    | "anything" => (0, None)
    else error end 

The segfault

0x000000000040441e in Main_tag_create_oo (this=0x7ffffe7ce400, env=0x7ffffe7cdc00) at main.pony:3
3           try _bug()?._2 as Bool end

gdb backtrace:

#0  0x000000000040441e in Main_tag_create_oo (this=0x7ffffe7ce400, env=0x7ffffe7cdc00) at main.pony:3
#1  0x0000000000402760 in Main_Dispatch ()
#2  0x000000000040ec72 in ponyint_actor_run ()
#3  0x00000000004070ad in run_thread ()
#4  0x00007fffff1e76ba in start_thread (arg=0x7ffff5fb0700) at pthread_create.c:333
#5  0x00007ffffeae741d in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:109

I do not currently have a proposed solution but the bug itself seems simple to reproduce.

@Praetonus
Copy link
Member

This is a bug in the union-to-tuple cast code generation.

@mfelsche
Copy link
Contributor

mfelsche commented Apr 6, 2018

FYI, i am hitting the same issue, when calling a method like:

fun generate_and_shrink(): ((U8^ | Bool^), Iterator[(U8^ | Bool^)])

@mfelsche
Copy link
Contributor

mfelsche commented Apr 6, 2018

I was able to reproduce the issue with the following snippet:

actor Main
  new create(env: Env) =>
    try
      match _bug(env.args(0)?)?
      | (let u: USize, let bn: Bool) => env.out.print("bool")
      | (let u: USize, let bn: None) => env.out.print("none")
      end
    end

  fun _bug(s: String): (USize, (Bool | None)) ? =>
    match s
    | "./scratch" => (0, true)
    | "anything" => (0, None)
    else
      error
    end

This one seems to show that it is both the match that tries to get a tuple element and the direct tuple element access being executed on the tuple of unions result (USize, (Bool | None)) causing the segfault.

The segfault does not happen, when using no primitive types (i.e. replacing USize and Bool with String). Looking at the faulty address it seems to interpret the USize value of 0 as a memory address. I don't know if this is the problem or the fact that the USize does not seem to be a pointer but a plain machine word as tuple element.

@SeanTAllen
Copy link
Member

With the 0.22.4 on OSX, I get this error for @king1600's example but not @mfelsche's. @mfelsche can you test your's again?

@jemc jemc added the triggers release Major issue that when fixed, results in an "emergency" release label Nov 20, 2018
@aturley
Copy link
Member

aturley commented Nov 20, 2018

@malthe can you test this again to see if you're still having the issue?

@SeanTAllen SeanTAllen added needs investigation This needs to be looked into before its "ready for work" bug and removed bug: 1 - needs investigation labels May 12, 2020
Trundle added a commit to Trundle/ponyc that referenced this issue Feb 26, 2021
It's possible that the method body returns a subtype of the return type.
For example, a return value with type `((U32, U32) | (U32, None))` is
legal for a method with return type `(U32, (U32 | None))`, but it
requires a cast.

Fixes ponylang#2609, ponylang#2808
@Trundle
Copy link
Contributor

Trundle commented Feb 27, 2021

In the first example, the match's inferred type is ((USize, Bool) | (USize, None)). That type is a subtype of (USize, (Bool | None)), but the code generator doesn't insert the correct cast.

The crash goes away if one changes it to something like:

actor Main
  new create(env: Env) =>
    try _bug()?._2 as Bool end

  fun _bug(): (USize, (Bool | None)) ? =>
    let x: (USize, (Bool | None)) = match "bug"
    | "bug" => (0, true)
    | "anything" => (0, None)
    else error end
    x

SeanTAllen pushed a commit that referenced this issue Feb 27, 2021
It's possible that the method body returns a subtype of the return type.
For example, a return value with type `((U32, U32) | (U32, None))` is
legal for a method with return type `(U32, (U32 | None))`, but it
requires a cast.

Fixes #2609, #2808
@SeanTAllen SeanTAllen removed the bug label Jan 22, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
needs investigation This needs to be looked into before its "ready for work" triggers release Major issue that when fixed, results in an "emergency" release
Projects
None yet
Development

Successfully merging a pull request may close this issue.

7 participants