Skip to content

!!! project causes memory inconsistencies #38

Description

@Profpatsch

project (and potentially also inject, we haven’t verified`, will cause undefined behavior, which we noticed & verified in a production system.

The bug only appears with optimizations enabled (only tested -O2), not in ghci

I don’t have a minimal repro (yet), but I can describe what we did:

There was one function which loaded some data in IO, constructed a ist of rec, then before returning used project to reduce unnecessary fields in every list element:

loadData :: IO (Record '[ "foo" := Text ])
loadData = do
  listOfRes <- <fetch data>
  pure 
    $ map 
         (project @'["foo" := Text, "bar" := Int] @'["foo" := Text])
         listOfRes

And another function that pulled a subset of fields from the record, like this:

requestBody = do
  dat <- loadData
  
  let mapDat d = (Json.object [
         ("foo", get #foo d)
        ])
        
   pure $ Json.Array (map mapDat dat)

Let’s say the final data was

[ 
  { foo = "xx" },
  { foo = "yy" },
  { foo = "zz" },
]

Then what would be actually returned was (!!):

[ 
  { foo = "xx" },
  { foo = "xx" },
  { foo = "xx" },
]

now, if you rewrote the function to deeply evaluate the projected record:

loadData :: IO (Record '[ "foo" := Text ])
loadData = do
  listOfRes <- <fetch data>

  print listOfRes   -- <- deeply evaluate the record by printing it
 
  pure 
    $ map 
         (project @'["foo" := Text, "bar" := Int] @'["foo" := Text])
         listOfRes

It would again return

[ 
  { foo = "xx" },
  { foo = "yy" },
  { foo = "zz" },
]

When we rewrote the original function to construct a new record instead of projecting:

loadData :: IO (Record '[ "foo" := Text ])
loadData = do
  listOfRes <- <fetch data>
  pure 
    $ map 
         (\res -> rcons #foo (get #foo res) rnil)
         listOfRes

The problem went away.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions