aboutsummaryrefslogtreecommitdiffstats
path: root/src/data.c
diff options
context:
space:
mode:
authorPaul Eggert2011-06-03 12:02:25 -0700
committerPaul Eggert2011-06-03 12:02:25 -0700
commit201f31ae3de0b747b47863b93d6f6a747c36c960 (patch)
tree800c2c66fc648660cb957df676ea59cc911ae0fa /src/data.c
parentbe14b9ab109c8deb5745dc47cbc471e97be06486 (diff)
downloademacs-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.c100
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. */
2330uintmax_t
2331cons_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
2331Lisp_Object 2364 if (! (valid && val <= max))
2332long_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
2343unsigned long 2369/* Convert the cons-of-integers, integer, or float value C to a signed
2344cons_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. */
2372intmax_t
2373cons_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
2356DEFUN ("number-to-string", Fnumber_to_string, Snumber_to_string, 1, 1, 0, 2412DEFUN ("number-to-string", Fnumber_to_string, Snumber_to_string, 1, 1, 0,