#5453: Floating a non-exhaustive case can cause seg-faults
---------------------------------+------------------------------------------
    Reporter:  simonpj           |        Owner:              
        Type:  bug               |       Status:  new         
    Priority:  normal            |    Milestone:              
   Component:  Compiler          |      Version:  7.2.1       
    Keywords:                    |     Testcase:              
   Blockedby:                    |   Difficulty:              
          Os:  Unknown/Multiple  |     Blocking:              
Architecture:  Unknown/Multiple  |      Failure:  None/Unknown
---------------------------------+------------------------------------------
 Consider
 {{{
 {-# LANGUAGE MagicHash #-}
 module Main where

 import GHC.Exts

 data Var = TyVar !Int Bool Bool
          | TcTyVar Bool !Int Bool
          | Var Bool Bool !Int
          deriving (Show)

 scrut :: Var -> (Bool, String)
 scrut v = (True, case v of
     TcTyVar {} -> "OK"
     _ -> show v ++ show (case (case v of
                                  TyVar b _ _ -> b
                                  Var _ _ b -> b) of
                            I# x# -> if x# ==# 7#
                                     then show (I# (x# +# 1#))
                                     else show (I# (x# +# 2#))))

 main = putStrLn $ snd (scrut (TcTyVar True 1 False))
 }}}
 Try this:
 {{{
 ghc -O -fno-specialise Segfault.hs
 ./Segfault
 }}}
 The bug is in the new case-floating machinery. If you compile with
 `-dverbose-core2core` you'll see the following after the first float-out
 phase:
 {{{
 Main.scrut =
   \ (v_acT :: Main.Var) ->
     case case v_acT of _ {
            Main.TyVar b_acU ds_dw6 ds_dw7 -> b_acU;
            Main.Var ds_dw4 ds_dw5 b_acV -> b_acV
          }
     of _ { GHC.Types.I# x#_szn ->
     (GHC.Types.True,
      case v_acT of wild_Xh {
        __DEFAULT ->
          GHC.Base.augment
            @ GHC.Types.Char
            (\ (@ b_axY)
               (c_axZ [Lbv=OneShot] :: GHC.Types.Char -> b_axY -> b_axY)
               (n_ay0 [Lbv=OneShot] :: b_axY) ->
               GHC.Base.foldr
                 @ GHC.Types.Char @ b_axY c_axZ n_ay0 ($cshow_avj v_acT))
            (GHC.Show.$fShow[]_$cshow
               @ GHC.Types.Char
               GHC.Show.$fShowChar
               (case case x#_szn of _ {
                       __DEFAULT -> GHC.Types.False;
                       7 -> GHC.Types.True
                     }
                of _ {
                  GHC.Types.False ->
                    GHC.Show.$fShowInt_$cshow (GHC.Types.I# (GHC.Prim.+#
 x#_szn 2));
                  GHC.Types.True ->
                    GHC.Show.$fShowInt_$cshow (GHC.Types.I# (GHC.Prim.+#
 x#_szn 1))
                }));
        Main.TcTyVar ds_dwf ds_dwg ds_dwh -> lvl_szP
      })
     }
 }}}
 See the way that `case case v_acT` has gotten floated right out?  There
 are two separate bugs here:
  1. It's wrong from a strictness point of view, because it's made `scrut`
 strict in `v`
  2. It's wrong from a semantics point of view, because the floated-out
 case is non-exhaustive, and that's what ultimately leads to the seg fault.

 Problem (2) is with `CoreUtils.exprOkForSpeculation`. A non-exhaustive
 case is ''not'' ok for speculation!

 Problem (1) is with the `AnnCase` case of `SetLevels.lvlExpr`, where we're
 testing the wrong expression for ok-for-speculation-nes.  Both are quite
 easy to fix.

 Thanks to Max for identifying this bug.

-- 
Ticket URL: <http://hackage.haskell.org/trac/ghc/ticket/5453>
GHC <http://www.haskell.org/ghc/>
The Glasgow Haskell Compiler

_______________________________________________
Glasgow-haskell-bugs mailing list
[email protected]
http://www.haskell.org/mailman/listinfo/glasgow-haskell-bugs

Reply via email to