on master help sign in
Fix a crash reported by Michael Snoyman.

--HG-- extra : convert_revision : 57b826873d42656a950945fb118ffe6ac4d9e767

commit1b30a07102758dc535af21927aab1c8b6959cbd0 authorBryan O'Sullivan <bos@serpentine.com> dateFri 12 Mar 2010, 05:30 (17 years ago) parent08ae492
3 files changed+37−10
Data/Text/Lazy/Encoding/Fusion.hs+5−8 tests/Makefile+6−2 tests/Regressions.hs+26
Data/Text/Lazy/Encoding/Fusion.hs+5−8
@@ -100,19 +100,17 @@ streamUtf8 onErr bs0 = Stream next (T bs0 S0 0) unknownSize
100100unstreamChunks :: Int -> Stream Word8 -> ByteString
101101unstreamChunks chunkSize (Stream next s0 len0) = chunk s0 (upperBound 4 len0)
102102 where chunk s1 len1 = unsafePerformIO $ do
103− let len = min len1 chunkSize
103+ let len = max 4 (min len1 chunkSize)
104104 mallocByteString len >>= loop len 0 s1
105105 where
106106 loop !n !off !s fp = case next s of
107107 Done | off == 0 -> return Empty
108− | otherwise -> do
109− bs <- trimUp fp off
110− return $! Chunk bs Empty
108+ | otherwise -> return $! Chunk (trimUp fp off) Empty
111109 Skip s' -> loop n off s' fp
112110 Yield x s'
113111 | off == chunkSize -> do
114− bs <- trimUp fp off
115− return (Chunk bs (chunk s (n - B.length bs)))
112+ let !newLen = n - off
113+ return $! Chunk (trimUp fp off) (chunk s newLen)
116114 | off == n -> realloc fp n off s' x
117115 | otherwise -> do
118116 withForeignPtr fp $ \p -> pokeByteOff p off x
@@ -123,8 +121,7 @@ unstreamChunks chunkSize (Stream next s0 len0) = chunk s0 (upperBound 4 len0)
123121 fp' <- copy0 fp n n'
124122 withForeignPtr fp' $ \p -> pokeByteOff p off x
125123 loop n' (off+1) s fp'
126− {-# NOINLINE trimUp #-}
127− trimUp fp off = return $! B.PS fp 0 off
124+ trimUp fp off = B.PS fp 0 off
128125 copy0 :: ForeignPtr Word8 -> Int -> Int -> IO (ForeignPtr Word8)
129126 copy0 !src !srcLen !destLen = assert (srcLen <= destLen) $ do
130127 dest <- mallocByteString destLen
tests/Makefile+6−2
@@ -5,7 +5,8 @@ ghc-base-flags := -funbox-strict-fields -package criterion \
55 -package bytestring -ignore-package text \
66 -fno-ignore-asserts
77ghc-test-flags := -package QuickCheck -package test-framework \
8− -package test-framework-quickcheck
8+ -package test-framework-quickcheck -package test-framework-hunit \
9+ -package HUnit
910ghc-base-flags += -Wall -fno-warn-orphans -fno-warn-missing-signatures
1011ghc-flags := $(ghc-base-flags) -i../dist/build -package-name text-$(version)
1112ghc-hpc-flags := $(ghc-base-flags) -fhpc -fno-ignore-asserts -odir hpcdir \
@@ -16,7 +17,7 @@ lib-srcs := $(shell grep '^ *Data' ../text.cabal | \
1617
1718cabal := $(shell which cabal 2>/dev/null)
1819
19−all: bm qc coverage
20+all: bm qc coverage regressions
2021
2122lib: $(lib)
2223
@@ -46,6 +47,9 @@ qc-hpc: Properties.hs QuickCheckUtils.hs $(lib-srcs:%=../%)
4647 $(ghc) $(ghc-hpc-flags) $(ghc-opt-flags) -ihpcdir \
4748 --make -threaded -o $@ $<
4849
50+regressions: Regressions.o
51+ $(ghc) $(ghc-test-flags) -o $@ $^ $(lib)
52+
4953coverage: qc-hpc-html/hpc_index.html
5054
5155qc-hpc-html/hpc_index.html: qc-hpc
tests/Regressions.hsnew file+26
@@ -0,0 +1,26 @@
1+-- Regression tests for specific bugs.
2+
3+import Control.Exception (bracket)
4+import System.Directory (removeFile)
5+import System.IO (hClose, openTempFile)
6+import Test.HUnit (Assertion)
7+import qualified Data.ByteString.Lazy as LB
8+import qualified Data.Text.Lazy as LT
9+import qualified Data.Text.Lazy.Encoding as LE
10+import qualified Test.Framework as F
11+import qualified Test.Framework.Providers.HUnit as F
12+
13+-- Reported by Michael Snoyman: UTF-8 encoding a large lazy bytestring
14+-- caused either a segfault or attempt to allocate a negative number
15+-- of bytes.
16+lazy_encode_crash =
17+ bracket (openTempFile "." "crashy.txt")
18+ (\(path,h) -> hClose h >> removeFile path) $
19+ \(_,h) -> LB.hPut h . LE.encodeUtf8 . LT.pack . replicate 100000 $ 'a'
20+
21+tests :: F.Test
22+tests = F.testGroup "crashers" [
23+ F.testCase "lazy_encode_crash" lazy_encode_crash
24+ ]
25+
26+main = F.defaultMain [tests]