[GHC] #12523: Constructor info tables generated by GHCi don't return tagged pointers

#12523: Constructor info tables generated by GHCi don't return tagged pointers -------------------------------------+------------------------------------- Reporter: mniip | Owner: Type: bug | Status: new Priority: normal | Milestone: Component: GHCi | Version: 8.1 Keywords: | Operating System: Unknown/Multiple Architecture: | Type of failure: GHCi crash Unknown/Multiple | Test Case: | Blocked By: Blocking: | Related Tickets: Differential Rev(s): | Wiki Page: -------------------------------------+------------------------------------- If we have in a file: {{{#!hs data X = X String unX (X s) = s }}} And then load the file in ghci with `-fobject-code` and {{{
data Y = Y String unX (Unsafe.Coerce.unsafeCoerce (Y "foo")) "Segmentation fault (core dumped) }}}
Even though we are shooting ourselves in the foot there, the constructors `X` and `Y` are represented identically internally, so the code is supposed to work. And it does work if we either move `unX` into ghci'd code, or `Y` into compiled code. After a legthy debugging session with @rwbarton over IRC, we've identified the culprit of this. As [[Commentary/Rts/HaskellExecution/PointerTagging]] states, "In the continuation of an algebraic case, R1 is assumed tagged". And all compiled constructors tag the pointer when entered, e.g: {{{ Dump of assembler code for function ghczmprim_GHCziTypes_False_static_info: 0x00007fffef8dd018 <+0>: 48 ff c3 inc %rbx 0x00007fffef8dd01b <+3>: ff 65 00 jmpq *0x0(%rbp) Dump of assembler code for function base_GHCziBase_Just_static_info: 0x00007ffff03eb780 <+0>: 48 83 c3 02 add $0x2,%rbx 0x00007ffff03eb784 <+4>: ff 65 00 jmpq *0x0(%rbp) Dump of assembler code for function ghczmprim_GHCziTypes_GT_static_info: 0x00007fffef8dd1f8 <+0>: 48 83 c3 03 add $0x3,%rbx 0x00007fffef8dd1fc <+4>: ff 65 00 jmpq *0x0(%rbp) Dump of assembler code for function base_GHCziRTSziFlags_HeapByClosureType_static_info: 0x00007ffff057e768 <+0>: 48 ff c3 inc %rbx // more than 7 constructors so all tags are '1' 0x00007ffff057e76b <+3>: ff 65 00 jmpq *0x0(%rbp) }}} Whereas all ghci-bound data constructors share the `stg_interp_constr_entry` entry code (with an optional trampoline leading there): {{{ Dump of assembler code from 0x7ffff7ff3080 to 0x7ffff7ff3090: => 0x00007ffff7ff3080: jmpq *0x2(%rip) # 0x7ffff7ff3088 0x00007ffff7ff3088: 0x00007fffef4c9388 Dump of assembler code for function stg_interp_constr_entry: 0x00007fffef4c9388 <+0>: ff 65 00 jmpq *0x0(%rbp) }}} Relevant code: source:libraries/ghci/GHCi/InfoTable.hsc#L32 So in the end, compiled code relies on the assumption that the pointer is tagged, and ghci constructors produce untagged pointers. Even though it is currently impossible to have compiled code pattern match on a ghci constructor, I think this shouldn't happen. -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/12523 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#12523: Constructor info tables generated by GHCi don't return tagged pointers -------------------------------------+------------------------------------- Reporter: mniip | Owner: Type: bug | Status: new Priority: normal | Milestone: Component: GHCi | Version: 8.1 Resolution: | Keywords: Operating System: Unknown/Multiple | Architecture: | Unknown/Multiple Type of failure: GHCi crash | Test Case: Blocked By: | Blocking: Related Tickets: | Differential Rev(s): Wiki Page: | -------------------------------------+------------------------------------- Changes (by simonpj): * cc: simonmar (added) Comment: Yes, tagging really is part of the return convention for data constructors, so I'm a bit surprised that GHCi gets away without it. Is `unsafeCoerce` really part of this? What happens for {{{ unX (X "foo") }}} or {{{ unX (id (X "foo")) }}} ? Why would it be different to what happens with `unsafeCoerce`? I'm adding Simon Marlow (king of GHCi) in cc. -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/12523#comment:1 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#12523: Constructor info tables generated by GHCi don't return tagged pointers -------------------------------------+------------------------------------- Reporter: mniip | Owner: Type: bug | Status: new Priority: normal | Milestone: Component: GHCi | Version: 8.1 Resolution: | Keywords: Operating System: Unknown/Multiple | Architecture: | Unknown/Multiple Type of failure: GHCi crash | Test Case: Blocked By: | Blocking: Related Tickets: | Differential Rev(s): Wiki Page: | -------------------------------------+------------------------------------- Comment (by simonmar): Good catch. Simon, I think the answer to your question is that you can't construct that example, because compiled code cannot depend on interpreted code. Still, we should really respect the pointer tagging invariants both in compiled and interpreted code, so I agree this is a bug. -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/12523#comment:2 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#12523: Constructor info tables generated by GHCi don't return tagged pointers -------------------------------------+------------------------------------- Reporter: mniip | Owner: Type: bug | Status: new Priority: normal | Milestone: Component: GHCi | Version: 8.1 Resolution: | Keywords: Operating System: Unknown/Multiple | Architecture: | Unknown/Multiple Type of failure: GHCi crash | Test Case: Blocked By: | Blocking: Related Tickets: | Differential Rev(s): Wiki Page: | -------------------------------------+------------------------------------- Comment (by mniip): Replying to [comment:1 simonpj]: The whole problem lies in the code assigned to the `Y` constructor. When ghci uses `X` it uses the compiled info table and entry code so no problem arises. Indeed this bug is impossible to trigger without unsafeCoerce or other questionable functions. -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/12523#comment:3 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#12523: Constructor info tables generated by GHCi don't return tagged pointers -------------------------------------+------------------------------------- Reporter: mniip | Owner: Type: bug | Status: new Priority: normal | Milestone: Component: GHCi | Version: 8.1 Resolution: | Keywords: Operating System: Unknown/Multiple | Architecture: | Unknown/Multiple Type of failure: GHCi crash | Test Case: Blocked By: | Blocking: Related Tickets: | Differential Rev(s): Wiki Page: | -------------------------------------+------------------------------------- Comment (by simonpj):
The whole problem lies in the code assigned to the Y constructor. When ghci uses X it uses the compiled info table and entry code so no problem arises.
Ah, I see. Yes, if the `Y` constructor doesn't return a properly tagged result, any compiled code consuming `Y` values is going to seg-fault. Hence the need for `unsafeCoerce` to trigger the bug. Normally if `data Y = Y String` was interpreted then so is every function that consumes Y values. -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/12523#comment:4 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#12523: Constructor info tables generated by GHCi don't return tagged pointers -------------------------------------+------------------------------------- Reporter: mniip | Owner: Type: bug | Status: new Priority: normal | Milestone: Component: GHCi | Version: 8.1 Resolution: | Keywords: Operating System: Unknown/Multiple | Architecture: | Unknown/Multiple Type of failure: GHCi crash | Test Case: Blocked By: | Blocking: Related Tickets: | Differential Rev(s): Wiki Page: | -------------------------------------+------------------------------------- Comment (by osa1): Nice catch @mniip. Just to understand the problem here: Entry code for the constructor is correct, but the allocator should have marked the pointer, right? So the real problem is not InfoTable.hsc:32. -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/12523#comment:5 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#12523: Constructor info tables generated by GHCi don't return tagged pointers -------------------------------------+------------------------------------- Reporter: mniip | Owner: Type: bug | Status: new Priority: normal | Milestone: Component: GHCi | Version: 8.1 Resolution: | Keywords: Operating System: Unknown/Multiple | Architecture: | Unknown/Multiple Type of failure: GHCi crash | Test Case: Blocked By: | Blocking: Related Tickets: | Differential Rev(s): Wiki Page: | -------------------------------------+------------------------------------- Comment (by mniip): Replying to [comment:5 osa1]:
Just to understand the problem here: Entry code for the constructor is correct, but the allocator should have marked the pointer, right?
Nope, the problem is that the entry code should have marked the pointer but it did not. -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/12523#comment:6 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#12523: Constructor info tables generated by GHCi don't return tagged pointers -------------------------------------+------------------------------------- Reporter: mniip | Owner: mniip Type: bug | Status: new Priority: normal | Milestone: Component: GHCi | Version: 8.1 Resolution: | Keywords: Operating System: Unknown/Multiple | Architecture: | Unknown/Multiple Type of failure: GHCi crash | Test Case: Blocked By: | Blocking: Related Tickets: | Differential Rev(s): Wiki Page: | -------------------------------------+------------------------------------- Changes (by mniip): * owner: => mniip -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/12523#comment:7 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#12523: Constructor info tables generated by GHCi don't return tagged pointers -------------------------------------+------------------------------------- Reporter: mniip | Owner: mniip Type: bug | Status: patch Priority: normal | Milestone: Component: GHCi | Version: 8.1 Resolution: | Keywords: Operating System: Unknown/Multiple | Architecture: | Unknown/Multiple Type of failure: GHCi crash | Test Case: Blocked By: | Blocking: Related Tickets: | Differential Rev(s): Phab:D2473 Wiki Page: | -------------------------------------+------------------------------------- Changes (by mniip): * status: new => patch * differential: => Phab:D2473 -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/12523#comment:8 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#12523: Constructor info tables generated by GHCi don't return tagged pointers
-------------------------------------+-------------------------------------
Reporter: mniip | Owner: mniip
Type: bug | Status: patch
Priority: normal | Milestone:
Component: GHCi | Version: 8.1
Resolution: | Keywords:
Operating System: Unknown/Multiple | Architecture:
| Unknown/Multiple
Type of failure: GHCi crash | Test Case:
Blocked By: | Blocking:
Related Tickets: | Differential Rev(s): Phab:D2473
Wiki Page: |
-------------------------------------+-------------------------------------
Comment (by Ben Gamari

#12523: Constructor info tables generated by GHCi don't return tagged pointers -------------------------------------+------------------------------------- Reporter: mniip | Owner: mniip Type: bug | Status: merge Priority: normal | Milestone: 8.0.2 Component: GHCi | Version: 7.10.3 Resolution: | Keywords: Operating System: Unknown/Multiple | Architecture: | Unknown/Multiple Type of failure: GHCi crash | Test Case: Blocked By: | Blocking: Related Tickets: | Differential Rev(s): Phab:D2473 Wiki Page: | -------------------------------------+------------------------------------- Changes (by bgamari): * status: patch => merge * version: 8.1 => 7.10.3 * milestone: => 8.0.2 Comment: I suppose we should probably merge this for 8.0.2. -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/12523#comment:10 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#12523: Constructor info tables generated by GHCi don't return tagged pointers -------------------------------------+------------------------------------- Reporter: mniip | Owner: mniip Type: bug | Status: merge Priority: normal | Milestone: 8.0.2 Component: GHCi | Version: 7.10.3 Resolution: | Keywords: Operating System: Unknown/Multiple | Architecture: | Unknown/Multiple Type of failure: GHCi crash | Test Case: Blocked By: | Blocking: Related Tickets: | Differential Rev(s): Phab:D2473 Wiki Page: | -------------------------------------+------------------------------------- Comment (by simonmar): Given that it doesn't solve the whole problem, and the problem that it does solve needs `unsafeCoerce` to trigger it, I don't think we should merge it. -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/12523#comment:11 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#12523: Constructor info tables generated by GHCi don't return tagged pointers -------------------------------------+------------------------------------- Reporter: mniip | Owner: mniip Type: bug | Status: closed Priority: normal | Milestone: 8.0.2 Component: GHCi | Version: 7.10.3 Resolution: fixed | Keywords: Operating System: Unknown/Multiple | Architecture: | Unknown/Multiple Type of failure: GHCi crash | Test Case: Blocked By: | Blocking: Related Tickets: | Differential Rev(s): Phab:D2473 Wiki Page: | -------------------------------------+------------------------------------- Changes (by bgamari): * status: merge => closed * resolution: => fixed Comment: Oh dear, that boat may have already sailed as I just merged it in 062b462ba88a493fa12377a11960e8bed2f56781 ;) Simonmar, do you think think this warrants a revert or should we just leave it be? -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/12523#comment:12 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#12523: Constructor info tables generated by GHCi don't return tagged pointers -------------------------------------+------------------------------------- Reporter: mniip | Owner: mniip Type: bug | Status: closed Priority: normal | Milestone: 8.0.2 Component: GHCi | Version: 7.10.3 Resolution: fixed | Keywords: Operating System: Unknown/Multiple | Architecture: | Unknown/Multiple Type of failure: GHCi crash | Test Case: Blocked By: | Blocking: Related Tickets: | Differential Rev(s): Phab:D2473 Wiki Page: | -------------------------------------+------------------------------------- Comment (by simonmar): Ok, let's leave it. -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/12523#comment:13 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler
participants (1)
-
GHC