Skip to content
This repository was archived by the owner on Aug 18, 2020. It is now read-only.

Commit 1d6d9f7

Browse files
author
Michael Hueschen
committed
[CO-354] Fix SafeCopy instance for AddrAttributes
From @dcoutts: > The uncheckedLookAhead is actually a bit dangerous > and rather misleading. It only does what you expect > if all the input is supplied in one chunk, since it > only looks up to the end of the chunk. If acid-state > uses the incremental interface to deserialise in e.g. > 4k chunks then this can fail at a chunk boundary. I switch to using `Alternative` to run the non-legacy parser first, and if it fails, to run the legacy parser. This seems to leverage Cereal's `fail` mechanism the way it is intended - when the first parser fails, no input is consumed, and the second parser is run.
1 parent 036f1b9 commit 1d6d9f7

File tree

1 file changed

+14
-25
lines changed

1 file changed

+14
-25
lines changed

lib/src/Pos/SafeCopy.hs

Lines changed: 14 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ import qualified Cardano.Crypto.Wallet as CC
1212
import qualified Cardano.Crypto.Wallet.Encrypted as CC
1313
import qualified Crypto.Math.Edwards25519 as ED25519
1414
import qualified Crypto.Sign.Ed25519 as EDS25519
15-
import qualified Data.ByteString.Lazy as BSL
1615
import Data.SafeCopy (Contained, SafeCopy (..), base, contain, deriveSafeCopySimple,
1716
safeGet, safePut)
1817
import qualified Data.Serialize as Cereal
@@ -147,31 +146,21 @@ instance SafeCopy AddrAttributes where
147146
let bs = Bi.serialize (mkAttributes aa)
148147
safePut bs
149148

150-
getCopy = contain $ do
151-
let label = Cereal.label "Pos.Core.Common.AddrAttributes.AddrAttributes:"
152-
153-
let getLegacy =
154-
(\apdp asd -> AddrAttributes apdp asd NMNothing)
155-
<$> safeGet
156-
<*> safeGet
157-
158-
-- ByteStrings are prefixed with a Int64 length. We cheat here and read the length as
159-
-- thought it were a safePut-encoded Int64, so we know how long the ByteString will be.
149+
-- Try decoding as a BSL.ByteString containing the new format, but if that
150+
-- fails go for the legacy format.
151+
getCopy = contain $ label $ getNonLegacy <|> getLegacy
152+
where
153+
label = Cereal.label "Pos.Core.Common.AddrAttributes.AddrAttributes:"
154+
--
155+
getNonLegacy = do
156+
eAAA <- Bi.decodeFull <$> safeGet
157+
case eAAA of
158+
Left err -> fail (show err)
159+
Right aaa -> pure (attrData aaa)
160160
--
161-
-- 4[version] + 8[Int64] + <bytesLen>
162-
-- bytesLen == length of AddrAttributes bytestring
163-
bytesLen <- Cereal.lookAhead safeGet
164-
bytes <- BSL.fromStrict <$> Cereal.uncheckedLookAhead (fromIntegral bytesLen + 12)
165-
let _aaaVersionBytes = BSL.take 4 bytes
166-
attrAddrAttrBytes = BSL.drop 12 bytes
167-
label $ if BSL.length attrAddrAttrBytes /= bytesLen
168-
then getLegacy
169-
else case Bi.decodeFull attrAddrAttrBytes of
170-
Left _ -> getLegacy
171-
Right attrAddrAttrs -> do
172-
-- seek ahead since we passed our bytes
173-
Cereal.uncheckedSkip (12 + fromIntegral bytesLen)
174-
pure (attrData attrAddrAttrs)
161+
getLegacy = AddrAttributes <$> safeGet
162+
<*> safeGet
163+
<*> pure NMNothing
175164

176165
deriveSafeCopySimple 0 'base ''Address'
177166
deriveSafeCopySimple 0 'base ''Address

0 commit comments

Comments
 (0)