commit ea1a6a7c2e5c3cfd7573ee4988aaa6bed7e71586
parent 507af14c14be9fbaa27992357aa25e40c443daee
Author: Jared Tobin <jared@jtobin.io>
Date: Sat, 10 Oct 2026 13:02:13 +0400
lib: compare TLV lengths in Word64
A length of 2^63 or more wrapped to a negative Int, passed the bounds
check, and was accepted with an empty value; parsing then resumed
inside the claimed value. Compare in Word64 before converting.
Diffstat:
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/lib/Lightning/Protocol/BOLT1/TLV.hs b/lib/Lightning/Protocol/BOLT1/TLV.hs
@@ -136,8 +136,8 @@ decodeTlvStreamRaw = go Nothing []
Nothing -> pure ()
(len, rest2) <- maybe (Left TlvNonMinimalEncoding) Right
(decodeBigSize rest1)
- -- Length bounds check
- when (fromIntegral len > BS.length rest2) $
+ -- Length bounds check (in Word64, so huge lengths can't wrap)
+ when (len > fromIntegral (BS.length rest2)) $
Left TlvLengthExceedsBounds
let !val = BS.take (fromIntegral len) rest2
!rest3 = BS.drop (fromIntegral len) rest2
@@ -172,8 +172,8 @@ decodeTlvStreamWith isKnown = go Nothing []
Nothing -> pure ()
(len, rest2) <- maybe (Left TlvNonMinimalEncoding) Right
(decodeBigSize rest1)
- -- Length bounds check
- when (fromIntegral len > BS.length rest2) $
+ -- Length bounds check (in Word64, so huge lengths can't wrap)
+ when (len > fromIntegral (BS.length rest2)) $
Left TlvLengthExceedsBounds
let !val = BS.take (fromIntegral len) rest2
!rest3 = BS.drop (fromIntegral len) rest2