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

Reply via email to