登録: 8年前

完了: 8年前

#3486 closed bug (fixed)

Data.ByteString.elemIndices causes SEGV

報告者: nwn 担当者: duncan
優先度: high マイルストーン: 6.12.1
コンポーネント: libraries/base バージョン: 6.10.4
キーワード: 関係者:
Operating System: MacOS X Architecture: x86
Type of failure: None/Unknown Test Case:
Blocked By: Blocking:
Related Tickets: Differential Rev(s):
Wiki Page:

詳細

The elemIndices for strict ByteString causes SEGV in some situation.

import Data.Int
import qualified Data.ByteString as S

main = do
 cs <- S.getContents
 let ps = S.elemIndices 10 cs
 putStrLn $ "S.length cs = " ++ show (S.length cs)
 putStrLn $ "length ps = " ++ show (length ps)

If above program gets some large input, it crashes.

$ ghc --make ei
[1 of 1] Compiling Main             ( ei.hs, ei.o )
Linking ei ...
$ yes | head -10000 | ./ei
S.length cs = 20000
Segmentation fault

By the way, there might be a border of SEGV or not.

$ yes | head -4096 | ./ei
S.length cs = 8192
Segmentation fault
$ yes | head -4095 | ./ei
S.length cs = 8190
length ps = 4095

And this script works fine.

import qualified Data.ByteString as S
import qualified Data.ByteString.Lazy as L

main = do
 let cs = S.pack . take 8192 . cycle $ [48,10]
     ps = S.elemIndices 10 cs
 putStrLn $ "length cs = " ++ show (S.length cs)
 putStrLn $ "length ps = " ++ show (length ps)

I think there is causes about the bug in S.getContents or S.elemIndices or both. But I cannot figure out it.

添付ファイル (1)

split-elems-fix.dpatch (37.1 KB) - duncan8年前に追加。
Fix elemIndices and split

すべての添付ファイルをダウンロード: .zip

更新履歴 (7)

comment:1 更新者: igloo (8年前)

difficulty: Unknown
マイルストーン: 6.12.1
担当者: igloo に設定

Thanks for the report. I'll try to reproduce this with 6.10.4 and the HEAD.

comment:2 更新者: igloo (8年前)

Reproducible with both.

comment:3 更新者: igloo (8年前)

優先度: normalhigh
担当者: igloo から duncan に変更

The problem is in elemIndices:

elemIndices :: Word8 -> ByteString -> [Int]
elemIndices w (PS x s l) = inlinePerformIO $ withForeignPtr x $ \p -> do
    let ptr = p `plusPtr` s

        STRICT1(loop)
        loop n = let q = inlinePerformIO $ memchr (ptr `plusPtr` n)
                                                w (fromIntegral (l - n))
                 in if q == nullPtr
                        then []
                        else let i = q `minusPtr` ptr
                             in i : loop (i+1)
    return $! loop 0

The lazy thunk using p escapes from the withForeignPtr, so x can be freed. Replacing [] with:

                             inlinePerformIO $ do touchForeignPtr x
                                                  return []

makes the segfault go away.

I'm assigning this to duncan so that he or Don can fix it in the upstream repo, and also check if any other functions have the same problem.

I assume that this will also fix #3487.

更新者: duncan (8年前)

添付ファイル: split-elems-fix.dpatch を追加

Fix elemIndices and split

comment:4 更新者: duncan (8年前)

Attached patch should fix it (and #3487). Just awaiting further review.

comment:5 更新者: simonmar (8年前)

Duncan, can this be closed now?

comment:6 親コメント:  5 更新者: duncan (8年前)

ステータス: newclosed
解決方法: fixed

Replying to simonmar:

Duncan, can this be closed now?

Yes, the fix is in bytestring-0.9.1.5 which is included with ghc-6.12

詳しい使い方は TracTickets を参照してください。