agrafix / agrafix/superrecord

!!! `project` causes memory inconsistencies

オープン
#38 コメント 10 件 リアクション 0 件 担当者 0 名 GitHub で見る
主要言語
Haskell
スター
83
フォーク
16
PR マージ指標
30日以内にマージされた PR はありません

説明

`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:

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

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

```haskell
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

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

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

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

now, if you rewrote the function to deeply evaluate the `project`ed record:

```haskell
loadData :: IO (Record '[ "foo" := Text ])
loadData = do
listOfRes <-

print listOfRes -- <- deeply evaluate the record by printing it

pure
$ map
(project @'["foo" := Text, "bar" := Int] @'["foo" := Text])
listOfRes
```

It would again return

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

When we rewrote the original function to construct a new record instead of `project`ing:

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

The problem went away.

コントリビューションガイド

このリポジトリのコントリビューションガイドは索引されていません

評価

この issue はまだ評価されていません。

新しい issue をメールで受け取る

初心者向けの GitHub issue を短くまとめたダイジェスト。