99
1010module Cardano.DbSync.Era.Shelley.Insert
1111 ( insertShelleyBlock
12+ , containsUnicodeNul
13+ , safeDecodeUtf8
1214 ) where
1315
1416import Cardano.Prelude
1517
16- import Cardano.BM.Trace (Trace , logDebug , logError , logInfo )
18+ import Cardano.BM.Trace (Trace , logDebug , logError , logInfo , logWarning )
1719
1820import Cardano.Db (DbWord64 (.. ))
1921
@@ -38,9 +40,12 @@ import Cardano.DbSync.Util
3840import Cardano.Slotting.Slot (EpochNo (.. ), EpochSize (.. ))
3941
4042import qualified Data.Aeson as Aeson
43+ import qualified Data.ByteString.Char8 as BS
4144import qualified Data.ByteString.Lazy.Char8 as LBS
4245import qualified Data.Map.Strict as Map
46+ import qualified Data.Text as Text
4347import qualified Data.Text.Encoding as Text
48+ import qualified Data.Text.Encoding.Error as Text
4449
4550import Database.Persist.Sql (SqlBackend )
4651
@@ -481,17 +486,39 @@ insertTxMetadata
481486 :: (MonadBaseControl IO m , MonadIO m )
482487 => Trace IO Text -> DB. TxId -> Shelley. MetaData
483488 -> ExceptT DbSyncNodeError (ReaderT SqlBackend m ) ()
484- insertTxMetadata _tracer txId (Shelley. MetaData mdmap) =
489+ insertTxMetadata tracer txId (Shelley. MetaData mdmap) =
485490 mapM_ insert $ Map. toList mdmap
486491 where
487492 insert
488493 :: (MonadBaseControl IO m , MonadIO m )
489494 => (Word64 , Shelley. MetaDatum )
490495 -> ExceptT DbSyncNodeError (ReaderT SqlBackend m ) ()
491- insert (key, md) =
492- void . lift . DB. insertTxMetadata $
493- DB. TxMetadata
494- { DB. txMetadataKey = DbWord64 key
495- , DB. txMetadataJson = Text. decodeUtf8 . LBS. toStrict $ Aeson. encode (jsonFromMetadataValue md)
496- , DB. txMetadataTxId = txId
497- }
496+ insert (key, md) = do
497+ let jsonbs = LBS. toStrict $ Aeson. encode (jsonFromMetadataValue md)
498+ ejson <- liftIO $ safeDecodeUtf8 jsonbs
499+ case ejson of
500+ Left err ->
501+ liftIO . logWarning tracer $ mconcat
502+ [ " insertTxMetadata: Could not decode to UTF8: " , textShow err ]
503+ Right json -> do
504+ -- See https://github.com/input-output-hk/cardano-db-sync/issues/297
505+ if containsUnicodeNul json
506+ then liftIO $ logWarning tracer " insertTxMetadata: dropped due to a Unicode NUL character."
507+ else
508+ void . lift . DB. insertTxMetadata $
509+ DB. TxMetadata
510+ { DB. txMetadataKey = DbWord64 key
511+ , DB. txMetadataJson = json
512+ , DB. txMetadataTxId = txId
513+ }
514+
515+ safeDecodeUtf8 :: ByteString -> IO (Either Text. UnicodeException Text )
516+ safeDecodeUtf8 bs
517+ | BS. any isNullChar bs = pure $ Left (Text. DecodeError (BS. unpack bs) (Just 0 ))
518+ | otherwise = try $ evaluate (Text. decodeUtf8With Text. strictDecode bs)
519+ where
520+ isNullChar :: Char -> Bool
521+ isNullChar ch = ord ch == 0
522+
523+ containsUnicodeNul :: Text -> Bool
524+ containsUnicodeNul = Text. isInfixOf " \\ u000"
0 commit comments