diff options
| author | Paul Eggert | 2019-08-15 02:18:06 -0700 |
|---|---|---|
| committer | Paul Eggert | 2019-08-15 02:18:44 -0700 |
| commit | 3548fd8a53869ce6b42c47f690660cb8eddb8aab (patch) | |
| tree | 4da084bfab97e61c649abb3332254d0ea898188f /src/lisp.h | |
| parent | 6cbf73b5f9f51b5e25b855bf9f521c1ef070dd4a (diff) | |
| download | emacs-3548fd8a53869ce6b42c47f690660cb8eddb8aab.tar.gz emacs-3548fd8a53869ce6b42c47f690660cb8eddb8aab.zip | |
Debug out-of-range make_fixnum args
With --enable-checking, make_fixnum (N) now checks that N is
in fixnum range. Suggested by Pip Cet in:
https://lists.gnu.org/r/emacs-devel/2019-07/msg00548.html
A new function make_ufixnum (N) is for the rare cases where N
is intended to be unsigned and is in the range 0..INTMASK.
* configure.ac (AC_C_TYPEOF): Add.
(HAVE_STATEMENT_EXPRESSIONS): Resurrect this macro.
* src/fns.c (Frandom, hashfn_eq, hashfn_equal, hashfn_user_defined):
* src/profiler.c (hashfn_profiler):
Use make_ufixnum rather than make_fixum, since the argument is
an unsigned integer in the range 0..INTMASK rather than a signed
integer in the range MOST_NEGATIVE_FIXNUM..MOST_POSITIVE_FIXNUM.
Typically this is for hashes.
* src/lisp.h (lisp_h_make_fixnum_wrap) [USE_LSB_TAG]:
Rename from lisp_h_make_fixnum.
(lisp_h_make_fixnum): Redefine in terms of lisp_h_make_fixnum_wrap.
Check for fixnum overflow on compilers like GCC that
have statement expressions and typeof.
(FIXNUM_OVERFLOW_P): Move up.
(make_fixnum): Check for fixnum overflow.
(make_ufixnum): New function, which checks that the arg
fits into 0..INTMASK range.
Diffstat (limited to 'src/lisp.h')
| -rw-r--r-- | src/lisp.h | 47 |
1 files changed, 40 insertions, 7 deletions
diff --git a/src/lisp.h b/src/lisp.h index 0370c52fad6..1c98925fa8d 100644 --- a/src/lisp.h +++ b/src/lisp.h | |||
| @@ -397,8 +397,16 @@ typedef EMACS_INT Lisp_Word; | |||
| 397 | (eassert (CONSP (a)), XUNTAG (a, Lisp_Cons, struct Lisp_Cons)) | 397 | (eassert (CONSP (a)), XUNTAG (a, Lisp_Cons, struct Lisp_Cons)) |
| 398 | #define lisp_h_XHASH(a) XUFIXNUM_RAW (a) | 398 | #define lisp_h_XHASH(a) XUFIXNUM_RAW (a) |
| 399 | #if USE_LSB_TAG | 399 | #if USE_LSB_TAG |
| 400 | # define lisp_h_make_fixnum(n) \ | 400 | # define lisp_h_make_fixnum_wrap(n) \ |
| 401 | XIL ((EMACS_INT) (((EMACS_UINT) (n) << INTTYPEBITS) + Lisp_Int0)) | 401 | XIL ((EMACS_INT) (((EMACS_UINT) (n) << INTTYPEBITS) + Lisp_Int0)) |
| 402 | # if defined HAVE_STATEMENT_EXPRESSIONS && defined HAVE_TYPEOF | ||
| 403 | # define lisp_h_make_fixnum(n) \ | ||
| 404 | ({ typeof (n) lisp_h_make_fixnum_n = n; \ | ||
| 405 | eassert (!FIXNUM_OVERFLOW_P (lisp_h_make_fixnum_n)); \ | ||
| 406 | lisp_h_make_fixnum_wrap (lisp_h_make_fixnum_n); }) | ||
| 407 | # else | ||
| 408 | # define lisp_h_make_fixnum(n) lisp_h_make_fixnum_wrap (n) | ||
| 409 | # endif | ||
| 402 | # define lisp_h_XFIXNUM_RAW(a) (XLI (a) >> INTTYPEBITS) | 410 | # define lisp_h_XFIXNUM_RAW(a) (XLI (a) >> INTTYPEBITS) |
| 403 | # define lisp_h_XTYPE(a) ((enum Lisp_Type) (XLI (a) & ~VALMASK)) | 411 | # define lisp_h_XTYPE(a) ((enum Lisp_Type) (XLI (a) & ~VALMASK)) |
| 404 | #endif | 412 | #endif |
| @@ -1125,12 +1133,18 @@ enum More_Lisp_Bits | |||
| 1125 | #define MOST_POSITIVE_FIXNUM (EMACS_INT_MAX >> INTTYPEBITS) | 1133 | #define MOST_POSITIVE_FIXNUM (EMACS_INT_MAX >> INTTYPEBITS) |
| 1126 | #define MOST_NEGATIVE_FIXNUM (-1 - MOST_POSITIVE_FIXNUM) | 1134 | #define MOST_NEGATIVE_FIXNUM (-1 - MOST_POSITIVE_FIXNUM) |
| 1127 | 1135 | ||
| 1136 | /* True if the possibly-unsigned integer I doesn't fit in a fixnum. */ | ||
| 1137 | |||
| 1138 | #define FIXNUM_OVERFLOW_P(i) \ | ||
| 1139 | (! ((0 <= (i) || MOST_NEGATIVE_FIXNUM <= (i)) && (i) <= MOST_POSITIVE_FIXNUM)) | ||
| 1140 | |||
| 1128 | #if USE_LSB_TAG | 1141 | #if USE_LSB_TAG |
| 1129 | 1142 | ||
| 1130 | INLINE Lisp_Object | 1143 | INLINE Lisp_Object |
| 1131 | (make_fixnum) (EMACS_INT n) | 1144 | (make_fixnum) (EMACS_INT n) |
| 1132 | { | 1145 | { |
| 1133 | return lisp_h_make_fixnum (n); | 1146 | eassert (!FIXNUM_OVERFLOW_P (n)); |
| 1147 | return lisp_h_make_fixnum_wrap (n); | ||
| 1134 | } | 1148 | } |
| 1135 | 1149 | ||
| 1136 | INLINE EMACS_INT | 1150 | INLINE EMACS_INT |
| @@ -1139,6 +1153,13 @@ INLINE EMACS_INT | |||
| 1139 | return lisp_h_XFIXNUM_RAW (a); | 1153 | return lisp_h_XFIXNUM_RAW (a); |
| 1140 | } | 1154 | } |
| 1141 | 1155 | ||
| 1156 | INLINE Lisp_Object | ||
| 1157 | make_ufixnum (EMACS_INT n) | ||
| 1158 | { | ||
| 1159 | eassert (0 <= n && n <= INTMASK); | ||
| 1160 | return lisp_h_make_fixnum_wrap (n); | ||
| 1161 | } | ||
| 1162 | |||
| 1142 | #else /* ! USE_LSB_TAG */ | 1163 | #else /* ! USE_LSB_TAG */ |
| 1143 | 1164 | ||
| 1144 | /* Although compiled only if ! USE_LSB_TAG, the following functions | 1165 | /* Although compiled only if ! USE_LSB_TAG, the following functions |
| @@ -1149,6 +1170,7 @@ INLINE EMACS_INT | |||
| 1149 | INLINE Lisp_Object | 1170 | INLINE Lisp_Object |
| 1150 | make_fixnum (EMACS_INT n) | 1171 | make_fixnum (EMACS_INT n) |
| 1151 | { | 1172 | { |
| 1173 | eassert (! FIXNUM_OVERFLOW_P (n)); | ||
| 1152 | EMACS_INT int0 = Lisp_Int0; | 1174 | EMACS_INT int0 = Lisp_Int0; |
| 1153 | if (USE_LSB_TAG) | 1175 | if (USE_LSB_TAG) |
| 1154 | { | 1176 | { |
| @@ -1179,6 +1201,22 @@ XFIXNUM_RAW (Lisp_Object a) | |||
| 1179 | return i >> INTTYPEBITS; | 1201 | return i >> INTTYPEBITS; |
| 1180 | } | 1202 | } |
| 1181 | 1203 | ||
| 1204 | INLINE Lisp_Object | ||
| 1205 | make_ufixnum (EMACS_INT n) | ||
| 1206 | { | ||
| 1207 | eassert (0 <= n && n <= INTMASK); | ||
| 1208 | EMACS_INT int0 = Lisp_Int0; | ||
| 1209 | if (USE_LSB_TAG) | ||
| 1210 | { | ||
| 1211 | EMACS_UINT u = n; | ||
| 1212 | n = u << INTTYPEBITS; | ||
| 1213 | n += int0; | ||
| 1214 | } | ||
| 1215 | else | ||
| 1216 | n += int0 << VALBITS; | ||
| 1217 | return XIL (n); | ||
| 1218 | } | ||
| 1219 | |||
| 1182 | #endif /* ! USE_LSB_TAG */ | 1220 | #endif /* ! USE_LSB_TAG */ |
| 1183 | 1221 | ||
| 1184 | INLINE bool | 1222 | INLINE bool |
| @@ -1232,11 +1270,6 @@ INLINE bool | |||
| 1232 | return lisp_h_EQ (x, y); | 1270 | return lisp_h_EQ (x, y); |
| 1233 | } | 1271 | } |
| 1234 | 1272 | ||
| 1235 | /* True if the possibly-unsigned integer I doesn't fit in a fixnum. */ | ||
| 1236 | |||
| 1237 | #define FIXNUM_OVERFLOW_P(i) \ | ||
| 1238 | (! ((0 <= (i) || MOST_NEGATIVE_FIXNUM <= (i)) && (i) <= MOST_POSITIVE_FIXNUM)) | ||
| 1239 | |||
| 1240 | INLINE intmax_t | 1273 | INLINE intmax_t |
| 1241 | clip_to_bounds (intmax_t lower, intmax_t num, intmax_t upper) | 1274 | clip_to_bounds (intmax_t lower, intmax_t num, intmax_t upper) |
| 1242 | { | 1275 | { |