on master help sign in
Merge pull request #477 from vshabanov/master

Fix for "Invalid UTF-8 stream" error on valid characters (#476).

commitf664f508c07474302eb416e5d20eff689a52a941 authorAdam Bergmark <adam@bergmark.nl> dateSat 22 Oct 2016, 15:03 (10 years ago) parentd9f0374f6030ee
3 files changed+25−3
aeson.cabal+1 cbits/unescape_string.c+1−2 tests/UnitTests.hs+23−1
aeson.cabal+1
@@ -180,6 +180,7 @@ test-suite tests
180180 base,
181181 base-compat,
182182 base-orphans >= 0.5.3 && <0.6,
183+ base16-bytestring,
183184 containers,
184185 dlist,
185186 generic-deriving >= 1.10 && < 1.12,
cbits/unescape_string.c+1−2
@@ -130,7 +130,7 @@ int _js_decode_string(uint16_t *const dest, size_t *destoff,
130130 *d++ = (uint16_t) unidata;
131131
132132 if (surrogate) {
133− if (unidata <= 0xDC00 || unidata >= 0xDFFF) // is not low surrogate
133+ if (unidata < 0xDC00 || unidata > 0xDFFF) // is not low surrogate
134134 return -1;
135135 surrogate = 0;
136136 } else if (unidata >= 0xD800 && unidata <= 0xDBFF ) { // is high surrogate
@@ -147,4 +147,3 @@ int _js_decode_string(uint16_t *const dest, size_t *destoff,
147147 if (codepoint != 'u') { return -1; }
148148 DISPATCH_ASCII(unicode1)
149149}
150−
tests/UnitTests.hs+23−1
@@ -21,7 +21,7 @@ import Prelude ()
2121import Prelude.Compat
2222
2323import Control.Applicative (Const(..))
24−import Control.Monad (forM)
24+import Control.Monad (forM, forM_)
2525import Data.Aeson ((.=), (.:), (.:?), (.:!), FromJSON(..), FromJSONKeyFunction(..), FromJSONKey(..), ToJSON1(..), decode, eitherDecode, encode, genericParseJSON, genericToEncoding, genericToJSON, object, withObject)
2626import Data.Aeson.Internal (JSONPathElement(..), formatError)
2727import Data.Aeson.TH (deriveJSON, deriveToJSON, deriveToJSON1)
@@ -50,8 +50,10 @@ import Instances ()
5050import Test.Framework (Test, testGroup)
5151import Test.Framework.Providers.HUnit (testCase)
5252import Test.HUnit (Assertion, assertFailure, assertEqual)
53+import Text.Printf (printf)
5354import Types (Approx(..), Compose3, Compose3', I)
5455import UnitTests.NullaryConstructors (nullaryConstructors)
56+import qualified Data.ByteString.Base16.Lazy as LBase16
5557import qualified Data.ByteString.Lazy.Char8 as L
5658import qualified Data.DList as DList
5759import qualified Data.HashMap.Strict as HM
@@ -104,6 +106,7 @@ tests = testGroup "unit" [
104106 , testGroup "Nullary constructors" $ fmap (testCase "-") nullaryConstructors
105107 , testGroup "FromJSONKey" $ fmap (testCase "-") fromJSONKeyAssertions
106108 , testCase "PR #455" pr455
109+ , testCase "Unescape string (PR #477)" unescapeString
107110 ]
108111
109112roundTripCamel :: String -> Assertion
@@ -574,6 +577,25 @@ data MyRecord2 = MyRecord2 {_field3 :: Maybe Int, _field4 :: Maybe Bool}
574577instance ToJSON MyRecord2
575578instance FromJSON MyRecord2
576579
580+-- A regression test for: https://github.com/bos/aeson/pull/477
581+unescapeString :: Assertion
582+unescapeString = do
583+ assertEqual "Basic escaping"
584+ (Right ("\" / \\ \b \f \n \r \t" :: String))
585+ (eitherDecode "\"\\\" \\/ \\\\ \\b \\f \\n \\r \\t\"")
586+
587+ forM_ [minBound .. maxBound :: Char] $ \ c ->
588+ let s = LT.pack [c] in
589+ assertEqual (printf "UTF-16 encoded '\\x%X'" c)
590+ (Right s) (eitherDecode $ utf16Char s)
591+ where
592+ utf16Char = formatString . LBase16.encode . LT.encodeUtf16BE
593+ formatString s
594+ | L.length s == 4 = L.concat ["\"\\u", s, "\""]
595+ | L.length s == 8 =
596+ L.concat ["\"\\u", L.take 4 s, "\\u", L.drop 4 s, "\""]
597+ | otherwise = error "unescapeString: can't happen"
598+
577599-- A regression test for: https://github.com/bos/aeson/pull/455
578600data Foo a = FooNil | FooCons (Foo Int)
579601