Breaking Data.Set integrity without GeneralizedNewtypeDeriving

前端 未结 1 1912
旧时难觅i
旧时难觅i 2020-12-17 10:27

The code below uses an unsafe GeneralizedNewtypeDeriving extension to break Data.Set by inserting different elements with different Ord

相关标签:
1条回答
  • 2020-12-17 10:44

    I think that's an important question, so I'll repeat my answer from elsewhere: you can have multiple instances of the same class for the same type in Haskell98 without any extensions at all:

    $ cat A.hs
    module A where
    data U = X | Y deriving (Eq, Show)
    
    $ cat B.hs
    module B where
    import Data.Set
    import A
    instance Ord U where
        compare X X = EQ
        compare X Y = LT
        compare Y X = GT
        compare Y Y = EQ
    ins :: U -> Set U -> Set U
    ins = insert
    
    $ cat C.hs
    module C where
    import Data.Set
    import A
    instance Ord U where
        compare X X = EQ
        compare X Y = GT
        compare Y X = LT
        compare Y Y = EQ
    ins' :: U -> Set U -> Set U
    ins' = insert
    
    $ cat D.hs
    module D where
    import Data.Set
    import A
    import B
    import C
    test = ins' X $ ins X $ ins Y $ empty
    
    $ ghci D.hs
    Prelude D> test
    fromList [X,Y,X]
    

    And yes, you can prevent this kind of attacks by storing the dictionary internally:

    data MSet a where MSet :: Ord a => Set a -> MSet a
    
    0 讨论(0)
提交回复
热议问题