Skip to content

Commit 545818a

Browse files
committed
manyLength fail early if not enough bytes
parseLenDel fail early if not enough bytes. Improve generation speed for large inputs? Actually no.
1 parent 2bdbfd1 commit 545818a

File tree

1 file changed

+31
-16
lines changed

1 file changed

+31
-16
lines changed

library/src/Protobuf/Internal/Runtime.purs

Lines changed: 31 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import Control.Monad.Trans.Class (lift)
2424
import Data.Array (snoc, foldRecM)
2525
import Data.Array as Array
2626
import Data.ArrayBuffer.Builder (DataBuff(..), PutM, subBuilder)
27+
import Data.ArrayBuffer.DataView (byteLength)
2728
import Data.ArrayBuffer.Types (DataView, ByteLength)
2829
import Data.Enum (class BoundedEnum, fromEnum, toEnum)
2930
import Data.Foldable (foldl)
@@ -39,7 +40,8 @@ import Data.UInt64 (UInt64)
3940
import Data.UInt64 as UInt64
4041
import Effect.Class (class MonadEffect)
4142
import Parsing (ParserT, Position(..), fail, position)
42-
import Parsing.DataView (takeN)
43+
import Parsing.Combinators (lookAhead)
44+
import Parsing.DataView (takeN, takeRest)
4345
import Protobuf.Internal.Common (Bytes(..), FieldNumber, WireType(..), label)
4446
import Protobuf.Internal.Decode as Decode
4547
import Protobuf.Internal.Encode as Encode
@@ -76,6 +78,7 @@ type FieldNumberInt
7678
= Int
7779

7880
-- | Call a parser repeatedly until exactly *N* bytes have been consumed.
81+
-- | Will fail if not enough bytes remain in the DataView.
7982
-- | Will fail if too many bytes are consumed.
8083
manyLength ::
8184
forall m a.
@@ -85,19 +88,24 @@ manyLength ::
8588
ByteLength ->
8689
ParserT DataView m (Array a)
8790
manyLength p len = do
88-
Position { index: posBegin } <- position
89-
let
90-
go :: List a -> ParserT DataView m (Step (List a) (List a))
91-
go accum = do
92-
Position { index: pos } <- position
93-
case compare (pos - posBegin) len of
94-
GT -> fail "manyLength consumed too many bytes."
95-
EQ -> lift $ pure (Done accum)
96-
LT -> do
97-
x <- p
98-
pure (Loop (x : accum))
99-
-- https://github.com/purescript-contrib/purescript-parsing/pull/199#issuecomment-1145956271
100-
Array.reverse <$> Array.fromFoldable <$> tailRecM go List.Nil
91+
remaining_bytes :: Int <- byteLength <$> lookAhead takeRest
92+
if remaining_bytes < len
93+
then do
94+
fail $ "manyLength " <> show len <> " not enough bytes of input " <> show remaining_bytes <> " remaining"
95+
else do
96+
Position { index: posBegin } <- position
97+
let
98+
go :: List a -> ParserT DataView m (Step (List a) (List a))
99+
go accum = do
100+
Position { index: pos } <- position
101+
case compare (pos - posBegin) len of
102+
GT -> fail $ "manyLength " <> show len <> " consumed too many bytes " <> (show $ pos - posBegin)
103+
EQ -> lift $ pure (Done accum)
104+
LT -> do
105+
x <- p
106+
pure (Loop (x : accum))
107+
-- https://github.com/purescript-contrib/purescript-parsing/pull/199#issuecomment-1145956271
108+
Array.reverse <$> Array.fromFoldable <$> tailRecM go List.Nil
101109

102110
-- | A message field value from an unknown `.proto` definition.
103111
-- |
@@ -174,13 +182,20 @@ putFieldUnknown (UnknownLenDel fieldNumber x) = Encode.encodeBytesField fieldNum
174182

175183
putFieldUnknown (UnknownBits32 fieldNumber x) = Encode.encodeBytesField fieldNumber x
176184

177-
-- | Parse a length, then call a parser which takes one length as its argument.
185+
-- | Parse a bytelength, then call a parser which takes one bytelength as its argument.
178186
parseLenDel ::
179187
forall m a.
180188
MonadEffect m =>
181189
(Int -> ParserT DataView m a) ->
182190
ParserT DataView m a
183-
parseLenDel p = p <<< UInt.toInt =<< Decode.decodeVarint32
191+
parseLenDel p = do
192+
len <- UInt.toInt <$> Decode.decodeVarint32
193+
remaining_bytes :: Int <- byteLength <$> lookAhead takeRest
194+
if remaining_bytes < len
195+
then do
196+
fail $ "parseLenDel " <> show len <> " not enough bytes of input " <> show remaining_bytes <> " remaining"
197+
else do
198+
p len
184199

185200
putLenDel ::
186201
forall m a.

0 commit comments

Comments
 (0)