Skip to content

Don't read bytes beyond the end pointer in consOpen #26

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

Merged
merged 1 commit into from
May 1, 2022

Conversation

lagunoff
Copy link
Contributor

@lagunoff lagunoff commented Jan 4, 2022

In some cases consOpen reads one byte after the end pointer. I discovered it using ghcjs where in the implementation of ByteString there are runtime checks whether accessed bytes are inside the boundaries, this seem to fix the issue.

@tittoassini
Copy link
Collaborator

Thanks for this, I am working on a new release of 'flat' and will incorporate your changes.

Do you have any simple test that shows this issue?

@lagunoff
Copy link
Contributor Author

No, it's very hard to show this problem in ghc, you have to allocate a ByteString at the end of memory segment so that reading next byte will cause a SEGFAULT, and maybe that won't even work I can only reproduce this probelm in GHCJS

@tittoassini
Copy link
Collaborator

tittoassini commented Jan 12, 2022 via email

@lagunoff
Copy link
Contributor Author

lagunoff commented Jan 16, 2022

Not a test but I managed to get a minimal example that reliable reproduces this problem (using GHCJS). And problem only occurs when the input ByteString is constructed using createFromArrayBuffer, parsing a ByteString with same contents but constructed with Data.ByteString.pack won't raise this error (apparently in this case bounds check is not performed). Last fact I found about this problem is that the datatype has to have three or more constructors otherwise problem also doesn't happen.

{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE DeriveAnyClass #-}
{-# LANGUAGE TypeApplications #-}
import Data.ByteString as BS
import Data.JSString
import Flat
import GHC.Generics
import JavaScript.TypedArray.ArrayBuffer
import qualified GHCJS.Buffer as Buffer

data Foo
  = Foo
  | Bar
  | Baz
  deriving (Show, Generic, Flat)

main :: IO ()
main = do
  -- >>> [1]
  print $ BS.unpack $ flat Foo
  -- >>> Right Foo
  print $ unflat @Foo $ flat Foo
  -- >>> Right Foo
  print $ unflat @Foo $ BS.pack [1]
  -- >>> RangeError: Offset is outside the bounds of the DataView
  -- at DataView.getUint16
  print $ unflat @Foo $ fromSingleByte 1

fromSingleByte :: Int -> ByteString
fromSingleByte = Buffer.toByteString 0 Nothing .
  Buffer.createFromArrayBuffer . fromSingleByte_js

foreign import javascript unsafe
  "var buf = new ArrayBuffer(1);\
  \var view = new Int8Array(buf);\
  \view[0] = $1;\
  \$r = buf;"
  fromSingleByte_js :: Int -> ArrayBuffer

consopen-counterexample.tar.gz

@tittoassini tittoassini merged commit 559617e into Quid2:master May 1, 2022
@tittoassini
Copy link
Collaborator

First of all, many thanks for your help in this matter and apologies for taking so long in addressing it.

Maybe you should have been a bit more forceful.

Rather than wasting time in writing a test case you should have simply told me:

"Bloody fool, can't you see that you are guilty of a classic one-off bug? I therefore direct and command you to immediately merge this fix and afterwards go hide your head in shame under the nearest rock!"

I am sure that I would have complied expeditiously :-)

best

@lagunoff
Copy link
Contributor Author

lagunoff commented May 8, 2022

Haha, Ok) I'm really happy to contribute to this library, I'm using it a lot as transport in fullstack haskell apps, it's a great tool. Thanks to you and other people who develops and maintains flat 👍!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants