-
Notifications
You must be signed in to change notification settings - Fork 162
integer overflow in replace #81
Copy link
Copy link
Closed
Description
It's obvious that a lot of care went into properly handling integer overflow in this library. In the spirit of completeness, here is one spot that slipped through the cracks.
replace :: Text -> Text -> Text -> Text
replace needle@(Text _ _ neeLen)
(Text repArr repOff repLen)
haystack@(Text hayArr hayOff hayLen)
| neeLen == 0 = emptyError "replace"
| L.null ixs = haystack
| len > 0 = Text (A.run x) 0 len
| len < 0 = overflowError "replace"
| otherwise = empty
where
ixs = indices needle haystack
len = hayLen - (neeLen - repLen) * L.length ixs
x = do {- ... -}
The computation of len can overflow to a incorrect but positive value, whereupon the loop will write off the end of the allocated array. On a 64-bit system, you need to have already allocated quite a lot of memory to trigger this overflow (something like 60 GB):
import qualified Data.Text as T
main = print $ T.head $ T.replace
(T.singleton 'a')
(T.replicate (2^34+1) (T.singleton 'b'))
(T.replicate (2^30) (T.singleton 'a'))
On a 32-bit system, you can reduce both exponents above by 16 and then it is quite easy to reproduce the segmentation fault.
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
No labels