diff options
| author | Paul Eggert | 2011-06-03 12:02:25 -0700 |
|---|---|---|
| committer | Paul Eggert | 2011-06-03 12:02:25 -0700 |
| commit | 201f31ae3de0b747b47863b93d6f6a747c36c960 (patch) | |
| tree | 800c2c66fc648660cb957df676ea59cc911ae0fa /src/data.c | |
| parent | be14b9ab109c8deb5745dc47cbc471e97be06486 (diff) | |
| download | emacs-201f31ae3de0b747b47863b93d6f6a747c36c960.tar.gz emacs-201f31ae3de0b747b47863b93d6f6a747c36c960.zip | |
Check for overflow when converting integer to cons and back.
* charset.c (Fdefine_charset_internal, Fdecode_char):
Use cons_to_unsigned to catch overflow.
(Fencode_char): Use INTEGER_TO_CONS.
* composite.h (LGLYPH_CODE): Use cons_to_unsigned.
(LGLYPH_SET_CODE): Use INTEGER_TO_CONS.
* data.c (long_to_cons, cons_to_long): Remove.
(cons_to_unsigned, cons_to_signed): New functions.
These signal an error for invalid or out-of-range values.
* dired.c (Ffile_attributes): Use INTEGER_TO_CONS.
* fileio.c (Fset_visited_file_modtime): Use CONS_TO_INTEGER.
* font.c (Ffont_variation_glyphs):
* fontset.c (Finternal_char_font): Use INTEGER_TO_CONS.
* lisp.h (INTEGER_TO_CONS, CONS_TO_INTEGER): New macros.
(cons_to_signed, cons_to_unsigned): New decls.
(long_to_cons, cons_to_long): Remove decls.
* undo.c (record_first_change): Use INTEGER_TO_CONS.
(Fprimitive_undo): Use CONS_TO_INTEGER.
* xfns.c (Fx_window_property): Likewise.
* xselect.c (x_own_selection, selection_data_to_lisp_data):
Use INTEGER_TO_CONS.
(x_handle_selection_request, x_handle_selection_clear)
(x_get_foreign_selection, Fx_disown_selection_internal)
(Fx_get_atom_name, x_send_client_event): Use CONS_TO_INTEGER.
(lisp_data_to_selection_data): Use cons_to_unsigned.
(x_fill_property_data): Use cons_to_signed. Report values out of range.
Diffstat (limited to 'src/data.c')
| -rw-r--r-- | src/data.c | 100 |
1 files changed, 78 insertions, 22 deletions
diff --git a/src/data.c b/src/data.c index 522f0156ebd..408234f25cb 100644 --- a/src/data.c +++ b/src/data.c | |||
| @@ -2324,33 +2324,89 @@ DEFUN ("zerop", Fzerop, Szerop, 1, 1, 0, | |||
| 2324 | return Qnil; | 2324 | return Qnil; |
| 2325 | } | 2325 | } |
| 2326 | 2326 | ||
| 2327 | /* Convert between long values and pairs of Lisp integers. | 2327 | /* Convert the cons-of-integers, integer, or float value C to an |
| 2328 | Note that long_to_cons returns a single Lisp integer | 2328 | unsigned value with maximum value MAX. Signal an error if C does not |
| 2329 | when the value fits in one. */ | 2329 | have a valid format or is out of range. */ |
| 2330 | uintmax_t | ||
| 2331 | cons_to_unsigned (Lisp_Object c, uintmax_t max) | ||
| 2332 | { | ||
| 2333 | int valid = 0; | ||
| 2334 | uintmax_t val IF_LINT (= 0); | ||
| 2335 | if (INTEGERP (c)) | ||
| 2336 | { | ||
| 2337 | valid = 0 <= XINT (c); | ||
| 2338 | val = XINT (c); | ||
| 2339 | } | ||
| 2340 | else if (FLOATP (c)) | ||
| 2341 | { | ||
| 2342 | double d = XFLOAT_DATA (c); | ||
| 2343 | if (0 <= d | ||
| 2344 | && d < (max == UINTMAX_MAX ? (double) UINTMAX_MAX + 1 : max + 1)) | ||
| 2345 | { | ||
| 2346 | val = d; | ||
| 2347 | valid = 1; | ||
| 2348 | } | ||
| 2349 | } | ||
| 2350 | else if (CONSP (c)) | ||
| 2351 | { | ||
| 2352 | Lisp_Object top = XCAR (c); | ||
| 2353 | Lisp_Object bot = XCDR (c); | ||
| 2354 | if (CONSP (bot)) | ||
| 2355 | bot = XCAR (bot); | ||
| 2356 | if (NATNUMP (top) && XFASTINT (top) <= UINTMAX_MAX >> 16 && NATNUMP (bot)) | ||
| 2357 | { | ||
| 2358 | uintmax_t utop = XFASTINT (top); | ||
| 2359 | val = (utop << 16) | XFASTINT (bot); | ||
| 2360 | valid = 1; | ||
| 2361 | } | ||
| 2362 | } | ||
| 2330 | 2363 | ||
| 2331 | Lisp_Object | 2364 | if (! (valid && val <= max)) |
| 2332 | long_to_cons (long unsigned int i) | 2365 | error ("Not an in-range integer, float, or cons of integers"); |
| 2333 | { | 2366 | return val; |
| 2334 | unsigned long top = i >> 16; | ||
| 2335 | unsigned int bot = i & 0xFFFF; | ||
| 2336 | if (top == 0) | ||
| 2337 | return make_number (bot); | ||
| 2338 | if (top == (unsigned long)-1 >> 16) | ||
| 2339 | return Fcons (make_number (-1), make_number (bot)); | ||
| 2340 | return Fcons (make_number (top), make_number (bot)); | ||
| 2341 | } | 2367 | } |
| 2342 | 2368 | ||
| 2343 | unsigned long | 2369 | /* Convert the cons-of-integers, integer, or float value C to a signed |
| 2344 | cons_to_long (Lisp_Object c) | 2370 | value with extrema MIN and MAX. Signal an error if C does not have |
| 2371 | a valid format or is out of range. */ | ||
| 2372 | intmax_t | ||
| 2373 | cons_to_signed (Lisp_Object c, intmax_t min, intmax_t max) | ||
| 2345 | { | 2374 | { |
| 2346 | Lisp_Object top, bot; | 2375 | int valid = 0; |
| 2376 | intmax_t val IF_LINT (= 0); | ||
| 2347 | if (INTEGERP (c)) | 2377 | if (INTEGERP (c)) |
| 2348 | return XINT (c); | 2378 | { |
| 2349 | top = XCAR (c); | 2379 | val = XINT (c); |
| 2350 | bot = XCDR (c); | 2380 | valid = 1; |
| 2351 | if (CONSP (bot)) | 2381 | } |
| 2352 | bot = XCAR (bot); | 2382 | else if (FLOATP (c)) |
| 2353 | return ((XINT (top) << 16) | XINT (bot)); | 2383 | { |
| 2384 | double d = XFLOAT_DATA (c); | ||
| 2385 | if (min <= d | ||
| 2386 | && d < (max == INTMAX_MAX ? (double) INTMAX_MAX + 1 : max + 1)) | ||
| 2387 | { | ||
| 2388 | val = d; | ||
| 2389 | valid = 1; | ||
| 2390 | } | ||
| 2391 | } | ||
| 2392 | else if (CONSP (c)) | ||
| 2393 | { | ||
| 2394 | Lisp_Object top = XCAR (c); | ||
| 2395 | Lisp_Object bot = XCDR (c); | ||
| 2396 | if (CONSP (bot)) | ||
| 2397 | bot = XCAR (bot); | ||
| 2398 | if (INTEGERP (top) && INTMAX_MIN >> 16 <= XINT (top) | ||
| 2399 | && XINT (top) <= INTMAX_MAX >> 16 && INTEGERP (bot)) | ||
| 2400 | { | ||
| 2401 | intmax_t itop = XINT (top); | ||
| 2402 | val = (itop << 16) | XINT (bot); | ||
| 2403 | valid = 1; | ||
| 2404 | } | ||
| 2405 | } | ||
| 2406 | |||
| 2407 | if (! (valid && min <= val && val <= max)) | ||
| 2408 | error ("Not an in-range integer, float, or cons of integers"); | ||
| 2409 | return val; | ||
| 2354 | } | 2410 | } |
| 2355 | 2411 | ||
| 2356 | DEFUN ("number-to-string", Fnumber_to_string, Snumber_to_string, 1, 1, 0, | 2412 | DEFUN ("number-to-string", Fnumber_to_string, Snumber_to_string, 1, 1, 0, |