diff --git a/aeson.cabal b/aeson.cabal
--- a/aeson.cabal
+++ b/aeson.cabal
@@ -1,5 +1,5 @@
 name:            aeson
-version:         1.0.2.0
+version:         1.0.2.1
 license:         BSD3
 license-file:    LICENSE
 category:        Text, Web, JSON
@@ -180,6 +180,7 @@
     base,
     base-compat,
     base-orphans >= 0.5.3 && <0.6,
+    base16-bytestring,
     containers,
     dlist,
     generic-deriving >= 1.10 && < 1.12,
diff --git a/cbits/unescape_string.c b/cbits/unescape_string.c
--- a/cbits/unescape_string.c
+++ b/cbits/unescape_string.c
@@ -130,7 +130,7 @@
     *d++ = (uint16_t) unidata;
 
     if (surrogate) {
-      if (unidata <= 0xDC00 || unidata >= 0xDFFF) // is not low surrogate
+      if (unidata < 0xDC00 || unidata > 0xDFFF) // is not low surrogate
         return -1;
       surrogate = 0;
     } else if (unidata >= 0xD800 && unidata <= 0xDBFF ) { // is high surrogate
@@ -147,4 +147,3 @@
     if (codepoint != 'u') { return -1; }
     DISPATCH_ASCII(unicode1)
 }
-
diff --git a/changelog.md b/changelog.md
--- a/changelog.md
+++ b/changelog.md
@@ -1,21 +1,29 @@
 For the latest version of this document, please see [https://github.com/bos/aeson/blob/master/changelog.md](https://github.com/bos/aeson/blob/master/changelog.md).
 
+#### 1.0.2.1
+
+* Fixes a regression where a bunch of valid characters caused an
+  "Invalid UTF8-Stream" error when decoding. Thanks to Vladimir
+  Shabanov who investigated and fixed this.
+
 ### 1.0.2.0
 
 * Fixes a regression where it was no longer possible to derive
-  instances for types such as `data T a = T { f1 :: a, f2 :: Maybe a }`.
-  The fix is available on GHC >= 7.10.
+  instances for types such as `data T a = T { f1 :: a, f2 :: Maybe a
+  }`.
 
+Thanks to Sean Leather for fixing this, and to Ryan Scott for helping out.
+
 ### 1.0.1.0
 
 * Decoding performance has been significantly improved (see
-  https://github.com/bos/aeson/pull/452).
+  https://github.com/bos/aeson/pull/452). Thanks to @winterland1989.
 
 * Add `ToJSON`/`FromJSON` instances for newtypes from
   `Data.Semigroup`: `Min`, `Max`, `First`, `Last`, `WrappedMonoid`,
-  `Option`.
+  `Option`. Thanks to Lennart Spitzner.
 
-* Make the documentation for `.:!` more accurate.
+* Make the documentation for `.:!` more accurate. Thanks to Ian Jeffries.
 
 # 1.0.0.0
 
diff --git a/tests/UnitTests.hs b/tests/UnitTests.hs
--- a/tests/UnitTests.hs
+++ b/tests/UnitTests.hs
@@ -21,7 +21,7 @@
 import Prelude.Compat
 
 import Control.Applicative (Const(..))
-import Control.Monad (forM)
+import Control.Monad (forM, forM_)
 import Data.Aeson ((.=), (.:), (.:?), (.:!), FromJSON(..), FromJSONKeyFunction(..), FromJSONKey(..), ToJSON1(..), decode, eitherDecode, encode, genericParseJSON, genericToEncoding, genericToJSON, object, withObject)
 import Data.Aeson.Internal (JSONPathElement(..), formatError)
 import Data.Aeson.TH (deriveJSON, deriveToJSON, deriveToJSON1)
@@ -50,8 +50,10 @@
 import Test.Framework (Test, testGroup)
 import Test.Framework.Providers.HUnit (testCase)
 import Test.HUnit (Assertion, assertFailure, assertEqual)
+import Text.Printf (printf)
 import Types (Approx(..), Compose3, Compose3', I)
 import UnitTests.NullaryConstructors (nullaryConstructors)
+import qualified Data.ByteString.Base16.Lazy as LBase16
 import qualified Data.ByteString.Lazy.Char8 as L
 import qualified Data.DList as DList
 import qualified Data.HashMap.Strict as HM
@@ -104,6 +106,7 @@
   , testGroup "Nullary constructors" $ fmap (testCase "-") nullaryConstructors
   , testGroup "FromJSONKey" $ fmap (testCase "-") fromJSONKeyAssertions
   , testCase "PR #455" pr455
+  , testCase "Unescape string (PR #477)" unescapeString
   ]
 
 roundTripCamel :: String -> Assertion
@@ -573,6 +576,25 @@
 
 instance ToJSON   MyRecord2
 instance FromJSON MyRecord2
+
+-- A regression test for: https://github.com/bos/aeson/pull/477
+unescapeString :: Assertion
+unescapeString = do
+  assertEqual "Basic escaping"
+     (Right ("\" / \\ \b \f \n \r \t" :: String))
+     (eitherDecode "\"\\\" \\/ \\\\ \\b \\f \\n \\r \\t\"")
+
+  forM_ [minBound .. maxBound :: Char] $ \ c ->
+    let s = LT.pack [c] in
+    assertEqual (printf "UTF-16 encoded '\\x%X'" c)
+      (Right s) (eitherDecode $ utf16Char s)
+  where
+    utf16Char = formatString . LBase16.encode . LT.encodeUtf16BE
+    formatString s
+      | L.length s == 4 = L.concat ["\"\\u", s, "\""]
+      | L.length s == 8 =
+          L.concat ["\"\\u", L.take 4 s, "\\u", L.drop 4 s, "\""]
+      | otherwise = error "unescapeString: can't happen"
 
 -- A regression test for: https://github.com/bos/aeson/pull/455
 data Foo a = FooNil | FooCons (Foo Int)
