diff --git a/ruby-marshal.cabal b/ruby-marshal.cabal
--- a/ruby-marshal.cabal
+++ b/ruby-marshal.cabal
@@ -1,5 +1,5 @@
 name: ruby-marshal
-version: 0.2.0
+version: 0.2.1
 synopsis: Parse a subset of Ruby objects serialised with Marshal.dump.
 description: Parse a subset of Ruby objects serialised with Marshal.dump.
 homepage: https://github.com/filib/ruby-marshal
@@ -10,7 +10,7 @@
 category: Data
 build-type: Simple
 tested-with: GHC == 7.8.4, GHC == 7.10.3, GHC == 8.6.5, GHC == 8.8.3
-cabal-version: >= 1.10
+cabal-version: 2.0
 extra-source-files: CHANGELOG.md
 
 Source-repository head
@@ -31,7 +31,7 @@
     , fail        >= 4.9.0.0 && < 4.10
     , string-conv >= 0.1     && <= 0.2
     , mtl         >= 2.1.0   && <= 2.3.0
-    , vector      >= 0.10.0  && <= 0.12.1.2
+    , vector      >= 0.10.0  && <  0.13
   default-language:
     Haskell2010
   exposed-modules:
@@ -59,6 +59,8 @@
     , mtl
     , string-conv
     , vector
+  build-tool-depends:
+    hspec-discover:hspec-discover >= 2.9 && < 2.10
   default-language:
     Haskell2010
   other-modules:
diff --git a/src/Data/Ruby/Marshal/Get.hs b/src/Data/Ruby/Marshal/Get.hs
--- a/src/Data/Ruby/Marshal/Get.hs
+++ b/src/Data/Ruby/Marshal/Get.hs
@@ -24,7 +24,8 @@
 ) where
 
 import           Control.Applicative
-import           Control.Monad              (liftM2)
+import           Control.Monad              (liftM2, when)
+import           Data.Monoid                ((<>))
 import qualified Data.ByteString            as BS
 import           Data.Ruby.Marshal.Encoding (toEnc)
 import           Data.Ruby.Marshal.Int
@@ -60,10 +61,16 @@
            FloatChar      -> RFloat <$> getFloat
            StringChar     -> RString <$> getString
            SymbolChar     -> RSymbol <$> getSymbol
-           ObjectLinkChar -> RIVar <$> getObjectLink
+           ObjectLinkChar -> getObjectLink
            SymlinkChar    -> RSymbol <$> getSymlink
-           ArrayChar      -> RArray <$> getArray go
-           HashChar       -> RHash <$> getHash go go
+           ArrayChar      -> do
+             result <- RArray <$> getArray go
+             writeCache result
+             pure result
+           HashChar       -> do
+             result <- RHash <$> getHash go go
+             writeCache result
+             pure result
            IVarChar       -> RIVar <$> getIVar go
            _              -> return Unsupported
 
@@ -140,13 +147,14 @@
       return result
 
 -- | Pulls an Instance Variable out of the object cache.
-getObjectLink :: Marshal (RubyObject, RubyStringEncoding)
+getObjectLink :: Marshal RubyObject
 getObjectLink = marshalLabel "ObjectLink" $ do
   index <- getFixnum
-  maybeObject <- readObject index
+  when (index == 0) $ fail $ "invalid object link (index=0)"
+  maybeObject <- readObject (index - 1)
   case maybeObject of
-    Just (RIVar x) -> return x
-    _              -> fail "invalid object link"
+    Just x -> return x
+    x      -> fail $ "invalid object link (index=" <> show index <> ", target=" <> show x <> ")"
 
 -- | Parses <http://ruby-doc.org/core-2.2.0/String.html String>.
 getString :: Marshal BS.ByteString
diff --git a/src/Data/Ruby/Marshal/Monad.hs b/src/Data/Ruby/Marshal/Monad.hs
--- a/src/Data/Ruby/Marshal/Monad.hs
+++ b/src/Data/Ruby/Marshal/Monad.hs
@@ -77,6 +77,12 @@
 writeCache object = do
   cache <- get
   case object of
-    RIVar _   -> put $ cache { objects = V.snoc (objects cache) object }
-    RSymbol _ -> put $ cache { symbols = V.snoc (symbols cache) object }
+    RSymbol _ -> do
+      put $ cache { symbols = V.snoc (symbols cache) object }
+    RIVar _   -> do
+      put $ cache { objects = V.snoc (objects cache) object }
+    RArray _   -> do
+      put $ cache { objects = V.snoc (objects cache) object }
+    RHash _   -> do
+      put $ cache { objects = V.snoc (objects cache) object }
     _         -> return ()
diff --git a/test/MarshalSpec.hs b/test/MarshalSpec.hs
--- a/test/MarshalSpec.hs
+++ b/test/MarshalSpec.hs
@@ -13,6 +13,11 @@
     bs <- BS.readFile path
     return $ decode bs
 
+loadBinEither :: FilePath -> IO (Either String RubyObject)
+loadBinEither path = do
+    bs <- BS.readFile path
+    return $ decodeEither bs
+
 spec :: Spec
 spec = describe "load" $ do
   context "when we have nil" $
@@ -109,3 +114,10 @@
     it "should parse" $ do
       object <- loadBin "test/bin/symbol.bin"
       object `shouldBe` Just (RSymbol "hello_haskell")
+
+  context "when we have hashes, arrays and object links" $
+    it "should parse" $ do
+      object <- loadBinEither "test/bin/objectsAndStringReferences.bin"
+      object `shouldBe` Right (RArray $ V.fromList
+        [ RHash mempty, RArray mempty, RIVar (RString "hello", UTF_8), RIVar (RString "haskell", UTF_8)
+        , RHash mempty, RArray mempty, RIVar (RString "hello", UTF_8), RIVar (RString "haskell", UTF_8)])
