on master help sign in
Ensure that an encoding error handler's result is safe

--HG-- extra : amend_source : c4036e7a53a663f37b2379806739b48c65a9c014

commit1780bd7940fe5beed86c071536ec38317345f314 authorBryan O'Sullivan <bos@serpentine.com> dateMon 14 Jan 2013, 19:20 (14 years ago) parent0d5fc85
2 files changed+13−3
Data/Text/Encoding.hs+2−2 tests/Tests/Regressions.hs+11−1
Data/Text/Encoding.hs+2−2
@@ -61,7 +61,7 @@ import Data.Bits ((.&.))
6161import Data.ByteString as B
6262import Data.ByteString.Internal as B
6363import Data.Text.Encoding.Error (OnDecodeError, UnicodeException, strictDecode)
64−import Data.Text.Internal (Text(..), textP)
64+import Data.Text.Internal (Text(..), safe, textP)
6565import Data.Text.Private (runText)
6666import Data.Text.UnsafeChar (ord, unsafeWrite)
6767import Data.Text.UnsafeShift (shiftL, shiftR)
@@ -130,7 +130,7 @@ decodeUtf8With onErr (PS fp off len) = runText $ \done -> do
130130 Just c -> do
131131 destOff <- peek destOffPtr
132132 w <- unsafeSTToIO $
133− unsafeWrite dest (fromIntegral destOff) c
133+ unsafeWrite dest (fromIntegral destOff) (safe c)
134134 poke destOffPtr (destOff + fromIntegral w)
135135 loop $ curPtr' `plusPtr` 1
136136 loop (ptr `plusPtr` off)
tests/Tests/Regressions.hs+11−1
@@ -8,10 +8,11 @@ module Tests.Regressions
88
99import Control.Exception (SomeException, handle)
1010import System.IO
11−import Test.HUnit (assertFailure)
11+import Test.HUnit (assertBool, assertFailure)
1212import qualified Data.ByteString as B
1313import qualified Data.ByteString.Lazy as LB
1414import qualified Data.Text as T
15+import qualified Data.Text.Encoding as TE
1516import qualified Data.Text.IO as T
1617import qualified Data.Text.Lazy as LT
1718import qualified Data.Text.Lazy.Encoding as LE
@@ -49,9 +50,18 @@ replicate_crash = handle (\(_::SomeException) -> return ()) $
4950 power | maxBound == (2147483647::Int) = 28
5051 | otherwise = 60 :: Int
5152
53+-- Reported by John Millikin: a UTF-8 decode error handler could
54+-- return a bogus substitution character, which we would write without
55+-- checking.
56+utf8_decode_unsafe :: IO ()
57+utf8_decode_unsafe = do
58+ let t = TE.decodeUtf8With (\_ _ -> Just '\xdc00') "\x80"
59+ assertBool "broken error recovery shouldn't break us" (t == "\xfffd")
60+
5261tests :: F.Test
5362tests = F.testGroup "Regressions"
5463 [ F.testCase "hGetContents_crash" hGetContents_crash
5564 , F.testCase "lazy_encode_crash" lazy_encode_crash
5665 , F.testCase "replicate_crash" replicate_crash
66+ , F.testCase "utf8_decode_unsafe" utf8_decode_unsafe
5767 ]