summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorÖmer Sinan Ağacan <omeragacan@gmail.com>2020-03-17 13:55:39 +0300
committerBen Gamari <ben@smart-cactus.org>2020-05-30 10:20:52 -0400
commitbc05d3599545ddca50dbd8a557fd71785f6cb6fd (patch)
treec4041a25bbadbd543c23936c85c1c99f4e4988f8
parent9037a2b64ec78cc6d6946aae118622517c8163e2 (diff)
downloadhaskell-bc05d3599545ddca50dbd8a557fd71785f6cb6fd.tar.gz
FastString: fix eager reading of string ptr in hashStr
This read causes NULL dereferencing when len is 0. Fixes #17909 In the reproducer in #17909 this bug is triggered as follows: - SimplOpt.dealWithStringLiteral is called with a single-char string ("=" in #17909) - tailFS gets called on the FastString of the single-char string. - tailFS checks the length of the string, which is 1, and calls mkFastStringByteString on the tail of the ByteString, which is an empty ByteString as the original ByteString has only one char. - ByteString's unsafeUseAsCStringLen returns (NULL, 0) for the empty ByteString, which is passed to mkFastStringWith. - mkFastStringWith gets hash of the NULL pointer via hashStr, which fails on empty strings because of this bug. (cherry picked from commit cb1785d9f839e34a3a4892f354f0c51cc6553c0e)
-rw-r--r--compiler/utils/FastString.hs20
1 files changed, 13 insertions, 7 deletions
diff --git a/compiler/utils/FastString.hs b/compiler/utils/FastString.hs
index d96bf33fac..58284de19e 100644
--- a/compiler/utils/FastString.hs
+++ b/compiler/utils/FastString.hs
@@ -519,16 +519,22 @@ cmpStringPrefix ptr1 ptr2 len =
do r <- memcmp ptr1 ptr2 len
return (r == 0)
-
hashStr :: Ptr Word8 -> Int -> Int
-- use the Addr to produce a hash value between 0 & m (inclusive)
hashStr (Ptr a#) (I# len#) = loop 0# 0#
- where
- loop h n | isTrue# (n ==# len#) = I# h
- | otherwise = loop h2 (n +# 1#)
- where
- !c = ord# (indexCharOffAddr# a# n)
- !h2 = (h *# 16777619#) `xorI#` c
+ where
+ loop h n =
+ if isTrue# (n ==# len#) then
+ I# h
+ else
+ let
+ -- DO NOT move this let binding! indexCharOffAddr# reads from the
+ -- pointer so we need to evaluate this based on the length check
+ -- above. Not doing this right caused #17909.
+ !c = ord# (indexCharOffAddr# a# n)
+ !h2 = (h *# 16777619#) `xorI#` c
+ in
+ loop h2 (n +# 1#)
-- -----------------------------------------------------------------------------
-- Operations