@@ -406,12 +406,15 @@ chunkedSource ipair = do
406406 (src, mlen) <- liftIO $ I.readIORef ipair
407407 go src mlen
408408 where
409− go src NeedLen = do
410− (src', len) <- lift $ src C.$$+ getLen
411− go src' $ HaveLen len
412− go src NeedLenNewline = do
413− (src', len) <- lift $ src C.$$+ (CB.take 2 >> getLen)
414− go src' $ HaveLen len
409+ go' src front = do
410+ (src', (len, bs)) <- lift $ src C.$$+ front getLen
411+ let src''
412+ | S.null bs = src'
413+ | otherwise = C.yield bs >> src'
414+ go src'' $ HaveLen len
415+
416+ go src NeedLen = go' src id
417+ go src NeedLenNewline = go' src (CB.take 2 >>)
415418 go src (HaveLen 0) = liftIO $ I.writeIORef ipair (src, HaveLen 0)
416419 go src (HaveLen len) = do
417420 (src', mbs) <- lift $ src C.$$+ CL.head
@@ -433,14 +436,25 @@ chunkedSource ipair = do
433436 C.yield bs
434437 go src mlen
435438
436− getLen :: MonadIO m => C.Sink ByteString m Word
439+ getLen :: Monad m => C.Sink ByteString m (Word, ByteString)
437440 getLen = do
438− bss <- CB.takeWhile (/= 10) C.=$ CL.consume -- FIXME avoid attack
439− _ <- CB.take 1
440− return $
441− S.foldl' (\i c -> i * 16 + fromIntegral (hexToWord c)) 0
442− $ B.takeWhile isHexDigit
443− $ B.concat bss
441+ mbs <- CL.head
442+ case mbs of
443+ Nothing -> return (0, S.empty)
444+ Just bs -> do
445+ (x, y) <-
446+ case S.breakByte 10 bs of
447+ (x, y)
448+ | S.null y -> do
449+ mbs2 <- CL.head
450+ case mbs2 of
451+ Nothing -> return (x, y)
452+ Just bs2 -> return $ S.breakByte 10 $ bs `S.append` bs2
453+ | otherwise -> return (x, y)
454+ let w =
455+ S.foldl' (\i c -> i * 16 + fromIntegral (hexToWord c)) 0
456+ $ B.takeWhile isHexDigit x
457+ return (w, S.drop 1 y)
444458
445459 hexToWord w
446460 | w < 58 = w - 48