Hi! While looking into the strange behavior found in #793 I found out the following disturbing fact (ONLY on amd64):
#;1> (random most-positive-fixnum) -2147483648 #;2> (random most-positive-fixnum) -2147483648 #;3> (random most-positive-fixnum) -2147483648 #;4> (random most-positive-fixnum) -2147483648 ..etc.. Turns out that this is caused by an erroneous cast to (int) of the result value of the division in C_random_fixnum. Since hash tables use this for a value, I suppose people on 64 bit platforms who are running the latest master with the hash table randomization fix (or any other use of random for security reasons with large fixnums) are still vulnerable until they also apply the attached patch. I also saw that C_num_to_int contains a similar cast, but I wasn't able to trigger an error. For example, a program with a trivial foreign-lambda using size_t (which uses num_to_int) seems to receive the full 64-bit value. I'm unsure if this is coincidence or actual correct behaviour we can rely on. I didn't dare to change it because I feared I might be breaking other things (a C function accepting "int" *should* get its arguments truncated to int, and the FFI also uses C_num_to_int for those types) Possibly we need to distinguish between C_num_to_int and C_num_to_size_t or C_num_to_word? Cheers, Peter -- http://sjamaan.ath.cx -- "The process of preparing programs for a digital computer is especially attractive, not only because it can be economically and scientifically rewarding, but also because it can be an aesthetic experience much like composing poetry or music." -- Donald Knuth
>From 2edf7a9f6cf23c96af056029026410c2ec189ebc Mon Sep 17 00:00:00 2001 From: Peter Bex <peter....@xs4all.nl> Date: Wed, 29 Feb 2012 20:50:52 +0100 Subject: [PATCH] Fix cast in C_random_fixnum so it doesn't cause overflow and truncation on amd64 for large arguments like most-positive-fixnum (as used in hash-tables) --- chicken.h | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/chicken.h b/chicken.h index b304d22..ffac46c 100644 --- a/chicken.h +++ b/chicken.h @@ -1128,7 +1128,7 @@ extern double trunc(double); C_unfix(end1) - C_unfix(start1) ), C_SCHEME_UNDEFINED) #define C_words(n) C_fix(C_bytestowords(C_unfix(n))) #define C_bytes(n) C_fix(C_wordstobytes(C_unfix(n))) -#define C_random_fixnum(n) C_fix((int)(((double)rand())/(RAND_MAX + 1.0) * C_unfix(n))) +#define C_random_fixnum(n) C_fix((C_word)(((double)rand())/(RAND_MAX + 1.0) * C_unfix(n))) #define C_randomize(n) (srand(C_unfix(n)), C_SCHEME_UNDEFINED) #define C_block_size(x) C_fix(C_header_size(x)) #define C_pointer_address(x) ((C_byte *)C_block_item((x), 0)) -- 1.7.9.1
_______________________________________________ Chicken-hackers mailing list Chicken-hackers@nongnu.org https://lists.nongnu.org/mailman/listinfo/chicken-hackers