aboutsummaryrefslogtreecommitdiffstats
path: root/src/alloc.c
diff options
context:
space:
mode:
authorPaul Eggert2018-08-17 00:25:20 -0700
committerPaul Eggert2018-08-17 00:26:19 -0700
commit64eb9b71da7c3c34541929c1b0dfb7f0c11d3d88 (patch)
tree0b905edf417cb3e62706d84e5776a2a26065453f /src/alloc.c
parent3b9017b5ba6b7041fbf70691092533286cc9b98d (diff)
downloademacs-64eb9b71da7c3c34541929c1b0dfb7f0c11d3d88.tar.gz
emacs-64eb9b71da7c3c34541929c1b0dfb7f0c11d3d88.zip
Fix problems with logxor etc. and fixnums
These operations incorrectly treated negative fixnums as bignums greater than most-positive-fixnum. * src/alloc.c (mpz_set_intmax_slow): Avoid undefined behavior if signed unary negation overflows, while we’re in the neighborhood. (mpz_set_uintmax_slow): Remove. All uses removed. * src/data.c (arith_driver): Treat fixnums as signed, not unsigned, even for logical operations. * src/lisp.h (mpz_set_uintmax): Remove. All uses removed. * test/src/data-tests.el (data-tests-logand) (data-tests-logior, data-tests-logxor): New tests.
Diffstat (limited to 'src/alloc.c')
-rw-r--r--src/alloc.c23
1 files changed, 6 insertions, 17 deletions
diff --git a/src/alloc.c b/src/alloc.c
index 6a938211599..0cd3f0c0c3b 100644
--- a/src/alloc.c
+++ b/src/alloc.c
@@ -3793,28 +3793,17 @@ mpz_set_intmax_slow (mpz_t result, intmax_t v)
3793 /* If long is larger then a faster path is taken. */ 3793 /* If long is larger then a faster path is taken. */
3794 eassert (sizeof (intmax_t) > sizeof (long)); 3794 eassert (sizeof (intmax_t) > sizeof (long));
3795 3795
3796 bool negate = false; 3796 bool complement = v < 0;
3797 if (v < 0) 3797 if (complement)
3798 { 3798 v = -1 - v;
3799 v = -v;
3800 negate = true;
3801 }
3802 mpz_set_uintmax_slow (result, (uintmax_t) v);
3803 if (negate)
3804 mpz_neg (result, result);
3805}
3806
3807void
3808mpz_set_uintmax_slow (mpz_t result, uintmax_t v)
3809{
3810 /* If long is larger then a faster path is taken. */
3811 eassert (sizeof (uintmax_t) > sizeof (unsigned long));
3812 3799
3813 /* COUNT = 1 means just a single word of the given size. ORDER = -1 3800 /* COUNT = 1 means just a single word of the given size. ORDER = -1
3814 is arbitrary since there's only a single word. ENDIAN = 0 means 3801 is arbitrary since there's only a single word. ENDIAN = 0 means
3815 use the native endian-ness. NAILS = 0 means use the whole 3802 use the native endian-ness. NAILS = 0 means use the whole
3816 word. */ 3803 word. */
3817 mpz_import (result, 1, -1, sizeof (uintmax_t), 0, 0, &v); 3804 mpz_import (result, 1, -1, sizeof v, 0, 0, &v);
3805 if (complement)
3806 mpz_com (result, result);
3818} 3807}
3819 3808
3820 3809