aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorPaul Eggert2011-07-28 22:08:30 -0700
committerPaul Eggert2011-07-28 22:08:30 -0700
commit864d7ce76d118b7bc157176a03a0a8a1b02fd989 (patch)
tree0b7a4cb6cb22ace9f19c313b3b966b3d56878791 /src
parenta3d9c2a4ce11ea001c9ac97c8a6fb9a4f9a1d1ac (diff)
downloademacs-864d7ce76d118b7bc157176a03a0a8a1b02fd989.tar.gz
emacs-864d7ce76d118b7bc157176a03a0a8a1b02fd989.zip
* xselect.c: Integer and memory overflow issues.
(X_LONG_SIZE, X_USHRT_MAX, X_ULONG_MAX): New macros. Use them to make the following changes clearer. (MAX_SELECTION_QUANTUM): Make the other bounds on this value clearer. This change doesn't affect the value now, but it may help remind future maintainers not to raise the value too much later. (SELECTION_QUANTUM): Remove, replacing with ... (selection_quantum): ... new function, which avoids overflow. All uses changed. (struct selection_data.size): Now ptrdiff_t, not int, to avoid assumption that selection length fits in 'int'. (x_reply_selection_request, x_handle_selection_request) (x_get_window_property, receive_incremental_selection) (x_get_window_property_as_lisp_data, selection_data_to_lisp_data) (lisp_data_to_selection_data, clean_local_selection_data): Use ptrdiff_t, not int, to record length of selection. (x_reply_selection_request, x_get_window_property) (receive_incremental_selection, x_property_data_to_lisp): Redo calculations to avoid overflow. (x_reply_selection_request): When sending hint, ceiling it at X_ULONG_MAX rather than relying on wraparound overflow to send something. (x_get_window_property, receive_incremental_selection) (lisp_data_to_selection_data, x_property_data_to_lisp): Check for size-calculation overflow. (x_get_window_property, receive_incremental_selection) (lisp_data_to_selection_data, Fx_register_dnd_atom): Don't store size until memory allocation succeeds. (x_get_window_property): Plug memory leak on memory exhaustion. Don't double-block input; malloc is safe here. Don't assume 2**34 - 4 fits in unsigned long. Add an xassert to check XGetWindowProperty overflow. Be more careful about overflow calculations, and distinguish size from memory overflow better. (receive_incremental_selection): When tracing, don't assume unsigned int is less than INT_MAX. (x_selection_data_to_lisp_data): Remove unnecessary (and in theory harmful) conversions of unsigned short to int. (lisp_data_to_selection_data): Don't assume that integers in the range -65535 through -1 fit in an X unsigned short. Don't assume that ULONG_MAX == X_ULONG_MAX. Don't store into result parameters unless successful. Rely on cons_to_unsigned to report problems with elements; the old code wasn't right anyway. (x_check_property_data): Check for int overflow; we cannot use a wider type due to X limits. (x_handle_dnd_message): Use unsigned int, to avoid int overflow.
Diffstat (limited to 'src')
-rw-r--r--src/ChangeLog46
-rw-r--r--src/xselect.c307
2 files changed, 232 insertions, 121 deletions
diff --git a/src/ChangeLog b/src/ChangeLog
index 09ee5a8e4dc..f8e5ca78b33 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,5 +1,51 @@
12011-07-29 Paul Eggert <eggert@cs.ucla.edu> 12011-07-29 Paul Eggert <eggert@cs.ucla.edu>
2 2
3 * xselect.c: Integer and memory overflow issues.
4 (X_LONG_SIZE, X_USHRT_MAX, X_ULONG_MAX): New macros.
5 Use them to make the following changes clearer.
6 (MAX_SELECTION_QUANTUM): Make the other bounds on this value clearer.
7 This change doesn't affect the value now, but it may help remind
8 future maintainers not to raise the value too much later.
9 (SELECTION_QUANTUM): Remove, replacing with ...
10 (selection_quantum): ... new function, which avoids overflow.
11 All uses changed.
12 (struct selection_data.size): Now ptrdiff_t, not int, to avoid
13 assumption that selection length fits in 'int'.
14 (x_reply_selection_request, x_handle_selection_request)
15 (x_get_window_property, receive_incremental_selection)
16 (x_get_window_property_as_lisp_data, selection_data_to_lisp_data)
17 (lisp_data_to_selection_data, clean_local_selection_data):
18 Use ptrdiff_t, not int, to record length of selection.
19 (x_reply_selection_request, x_get_window_property)
20 (receive_incremental_selection, x_property_data_to_lisp):
21 Redo calculations to avoid overflow.
22 (x_reply_selection_request): When sending hint, ceiling it at
23 X_ULONG_MAX rather than relying on wraparound overflow to send
24 something.
25 (x_get_window_property, receive_incremental_selection)
26 (lisp_data_to_selection_data, x_property_data_to_lisp):
27 Check for size-calculation overflow.
28 (x_get_window_property, receive_incremental_selection)
29 (lisp_data_to_selection_data, Fx_register_dnd_atom):
30 Don't store size until memory allocation succeeds.
31 (x_get_window_property): Plug memory leak on memory exhaustion.
32 Don't double-block input; malloc is safe here. Don't assume 2**34
33 - 4 fits in unsigned long. Add an xassert to check
34 XGetWindowProperty overflow. Be more careful about overflow
35 calculations, and distinguish size from memory overflow better.
36 (receive_incremental_selection): When tracing, don't assume
37 unsigned int is less than INT_MAX.
38 (x_selection_data_to_lisp_data): Remove unnecessary (and in theory
39 harmful) conversions of unsigned short to int.
40 (lisp_data_to_selection_data): Don't assume that integers
41 in the range -65535 through -1 fit in an X unsigned short.
42 Don't assume that ULONG_MAX == X_ULONG_MAX. Don't store into
43 result parameters unless successful. Rely on cons_to_unsigned
44 to report problems with elements; the old code wasn't right anyway.
45 (x_check_property_data): Check for int overflow; we cannot use
46 a wider type due to X limits.
47 (x_handle_dnd_message): Use unsigned int, to avoid int overflow.
48
3 * xrdb.c: Integer and memory overflow issues. 49 * xrdb.c: Integer and memory overflow issues.
4 (magic_file_p): Plug memory leak on size overflow. 50 (magic_file_p): Plug memory leak on size overflow.
5 (get_environ_db): Don't assume path length fits in int, 51 (get_environ_db): Don't assume path length fits in int,
diff --git a/src/xselect.c b/src/xselect.c
index f63977a73de..d8b7b077a8c 100644
--- a/src/xselect.c
+++ b/src/xselect.c
@@ -66,22 +66,15 @@ static Lisp_Object wait_for_property_change_unwind (Lisp_Object);
66static void wait_for_property_change (struct prop_location *); 66static void wait_for_property_change (struct prop_location *);
67static Lisp_Object x_get_foreign_selection (Lisp_Object, Lisp_Object, 67static Lisp_Object x_get_foreign_selection (Lisp_Object, Lisp_Object,
68 Lisp_Object, Lisp_Object); 68 Lisp_Object, Lisp_Object);
69static void x_get_window_property (Display *, Window, Atom,
70 unsigned char **, int *,
71 Atom *, int *, unsigned long *, int);
72static void receive_incremental_selection (Display *, Window, Atom,
73 Lisp_Object, unsigned,
74 unsigned char **, int *,
75 Atom *, int *, unsigned long *);
76static Lisp_Object x_get_window_property_as_lisp_data (Display *, 69static Lisp_Object x_get_window_property_as_lisp_data (Display *,
77 Window, Atom, 70 Window, Atom,
78 Lisp_Object, Atom); 71 Lisp_Object, Atom);
79static Lisp_Object selection_data_to_lisp_data (Display *, 72static Lisp_Object selection_data_to_lisp_data (Display *,
80 const unsigned char *, 73 const unsigned char *,
81 int, Atom, int); 74 ptrdiff_t, Atom, int);
82static void lisp_data_to_selection_data (Display *, Lisp_Object, 75static void lisp_data_to_selection_data (Display *, Lisp_Object,
83 unsigned char **, Atom *, 76 unsigned char **, Atom *,
84 unsigned *, int *, int *); 77 ptrdiff_t *, int *, int *);
85static Lisp_Object clean_local_selection_data (Lisp_Object); 78static Lisp_Object clean_local_selection_data (Lisp_Object);
86 79
87/* Printing traces to stderr. */ 80/* Printing traces to stderr. */
@@ -114,15 +107,37 @@ static Lisp_Object Qcompound_text_with_extensions;
114static Lisp_Object Qforeign_selection; 107static Lisp_Object Qforeign_selection;
115static Lisp_Object Qx_lost_selection_functions, Qx_sent_selection_functions; 108static Lisp_Object Qx_lost_selection_functions, Qx_sent_selection_functions;
116 109
110/* Bytes needed to represent 'long' data. This is as per libX11; it
111 is not necessarily sizeof (long). */
112#define X_LONG_SIZE 4
113
114/* Maximum unsigned 'short' and 'long' values suitable for libX11. */
115#define X_USHRT_MAX 0xffff
116#define X_ULONG_MAX 0xffffffff
117
117/* If this is a smaller number than the max-request-size of the display, 118/* If this is a smaller number than the max-request-size of the display,
118 emacs will use INCR selection transfer when the selection is larger 119 emacs will use INCR selection transfer when the selection is larger
119 than this. The max-request-size is usually around 64k, so if you want 120 than this. The max-request-size is usually around 64k, so if you want
120 emacs to use incremental selection transfers when the selection is 121 emacs to use incremental selection transfers when the selection is
121 smaller than that, set this. I added this mostly for debugging the 122 smaller than that, set this. I added this mostly for debugging the
122 incremental transfer stuff, but it might improve server performance. */ 123 incremental transfer stuff, but it might improve server performance.
123#define MAX_SELECTION_QUANTUM 0xFFFFFF 124
125 This value cannot exceed INT_MAX / max (X_LONG_SIZE, sizeof (long))
126 because it is multiplied by X_LONG_SIZE and by sizeof (long) in
127 subscript calculations. Similarly for PTRDIFF_MAX - 1 or SIZE_MAX
128 - 1 in place of INT_MAX. */
129#define MAX_SELECTION_QUANTUM \
130 ((int) min (0xFFFFFF, (min (INT_MAX, min (PTRDIFF_MAX, SIZE_MAX) - 1) \
131 / max (X_LONG_SIZE, sizeof (long)))))
124 132
125#define SELECTION_QUANTUM(dpy) ((XMaxRequestSize(dpy) << 2) - 100) 133static int
134selection_quantum (Display *display)
135{
136 long mrs = XMaxRequestSize (display);
137 return (mrs < MAX_SELECTION_QUANTUM / X_LONG_SIZE + 25
138 ? (mrs - 25) * X_LONG_SIZE
139 : MAX_SELECTION_QUANTUM);
140}
126 141
127#define LOCAL_SELECTION(selection_symbol,dpyinfo) \ 142#define LOCAL_SELECTION(selection_symbol,dpyinfo) \
128 assq_no_quit (selection_symbol, dpyinfo->terminal->Vselection_alist) 143 assq_no_quit (selection_symbol, dpyinfo->terminal->Vselection_alist)
@@ -477,7 +492,7 @@ static struct x_display_info *selection_request_dpyinfo;
477struct selection_data 492struct selection_data
478{ 493{
479 unsigned char *data; 494 unsigned char *data;
480 unsigned int size; 495 ptrdiff_t size;
481 int format; 496 int format;
482 Atom type; 497 Atom type;
483 int nofree; 498 int nofree;
@@ -581,14 +596,11 @@ x_reply_selection_request (struct input_event *event, struct x_display_info *dpy
581 XSelectionEvent *reply = &(reply_base.xselection); 596 XSelectionEvent *reply = &(reply_base.xselection);
582 Display *display = SELECTION_EVENT_DISPLAY (event); 597 Display *display = SELECTION_EVENT_DISPLAY (event);
583 Window window = SELECTION_EVENT_REQUESTOR (event); 598 Window window = SELECTION_EVENT_REQUESTOR (event);
584 int bytes_remaining; 599 ptrdiff_t bytes_remaining;
585 int max_bytes = SELECTION_QUANTUM (display); 600 int max_bytes = selection_quantum (display);
586 int count = SPECPDL_INDEX (); 601 int count = SPECPDL_INDEX ();
587 struct selection_data *cs; 602 struct selection_data *cs;
588 603
589 if (max_bytes > MAX_SELECTION_QUANTUM)
590 max_bytes = MAX_SELECTION_QUANTUM;
591
592 reply->type = SelectionNotify; 604 reply->type = SelectionNotify;
593 reply->display = display; 605 reply->display = display;
594 reply->requestor = window; 606 reply->requestor = window;
@@ -616,11 +628,12 @@ x_reply_selection_request (struct input_event *event, struct x_display_info *dpy
616 if (cs->property == None) 628 if (cs->property == None)
617 continue; 629 continue;
618 630
619 bytes_remaining = cs->size * (cs->format / 8); 631 bytes_remaining = cs->size;
632 bytes_remaining *= cs->format >> 3;
620 if (bytes_remaining <= max_bytes) 633 if (bytes_remaining <= max_bytes)
621 { 634 {
622 /* Send all the data at once, with minimal handshaking. */ 635 /* Send all the data at once, with minimal handshaking. */
623 TRACE1 ("Sending all %d bytes", bytes_remaining); 636 TRACE1 ("Sending all %"pD"d bytes", bytes_remaining);
624 XChangeProperty (display, window, cs->property, 637 XChangeProperty (display, window, cs->property,
625 cs->type, cs->format, PropModeReplace, 638 cs->type, cs->format, PropModeReplace,
626 cs->data, cs->size); 639 cs->data, cs->size);
@@ -628,9 +641,9 @@ x_reply_selection_request (struct input_event *event, struct x_display_info *dpy
628 else 641 else
629 { 642 {
630 /* Send an INCR tag to initiate incremental transfer. */ 643 /* Send an INCR tag to initiate incremental transfer. */
631 long value[1]; 644 unsigned long value[1];
632 645
633 TRACE2 ("Start sending %d bytes incrementally (%s)", 646 TRACE2 ("Start sending %"pD"d bytes incrementally (%s)",
634 bytes_remaining, XGetAtomName (display, cs->property)); 647 bytes_remaining, XGetAtomName (display, cs->property));
635 cs->wait_object 648 cs->wait_object
636 = expect_property_change (display, window, cs->property, 649 = expect_property_change (display, window, cs->property,
@@ -638,7 +651,7 @@ x_reply_selection_request (struct input_event *event, struct x_display_info *dpy
638 651
639 /* XChangeProperty expects an array of long even if long is 652 /* XChangeProperty expects an array of long even if long is
640 more than 32 bits. */ 653 more than 32 bits. */
641 value[0] = bytes_remaining; 654 value[0] = min (bytes_remaining, X_ULONG_MAX);
642 XChangeProperty (display, window, cs->property, 655 XChangeProperty (display, window, cs->property,
643 dpyinfo->Xatom_INCR, 32, PropModeReplace, 656 dpyinfo->Xatom_INCR, 32, PropModeReplace,
644 (unsigned char *) value, 1); 657 (unsigned char *) value, 1);
@@ -672,7 +685,8 @@ x_reply_selection_request (struct input_event *event, struct x_display_info *dpy
672 int had_errors = x_had_errors_p (display); 685 int had_errors = x_had_errors_p (display);
673 UNBLOCK_INPUT; 686 UNBLOCK_INPUT;
674 687
675 bytes_remaining = cs->size * format_bytes; 688 bytes_remaining = cs->size;
689 bytes_remaining *= format_bytes;
676 690
677 /* Wait for the requester to ack by deleting the property. 691 /* Wait for the requester to ack by deleting the property.
678 This can run Lisp code (process handlers) or signal. */ 692 This can run Lisp code (process handlers) or signal. */
@@ -810,7 +824,7 @@ x_handle_selection_request (struct input_event *event)
810 non-None property. */ 824 non-None property. */
811 Window requestor = SELECTION_EVENT_REQUESTOR (event); 825 Window requestor = SELECTION_EVENT_REQUESTOR (event);
812 Lisp_Object multprop; 826 Lisp_Object multprop;
813 int j, nselections; 827 ptrdiff_t j, nselections;
814 828
815 if (property == None) goto DONE; 829 if (property == None) goto DONE;
816 multprop 830 multprop
@@ -1269,19 +1283,28 @@ x_get_foreign_selection (Lisp_Object selection_symbol, Lisp_Object target_type,
1269 1283
1270static void 1284static void
1271x_get_window_property (Display *display, Window window, Atom property, 1285x_get_window_property (Display *display, Window window, Atom property,
1272 unsigned char **data_ret, int *bytes_ret, 1286 unsigned char **data_ret, ptrdiff_t *bytes_ret,
1273 Atom *actual_type_ret, int *actual_format_ret, 1287 Atom *actual_type_ret, int *actual_format_ret,
1274 unsigned long *actual_size_ret, int delete_p) 1288 unsigned long *actual_size_ret, int delete_p)
1275{ 1289{
1276 int total_size; 1290 ptrdiff_t total_size;
1277 unsigned long bytes_remaining; 1291 unsigned long bytes_remaining;
1278 int offset = 0; 1292 ptrdiff_t offset = 0;
1293 unsigned char *data = 0;
1279 unsigned char *tmp_data = 0; 1294 unsigned char *tmp_data = 0;
1280 int result; 1295 int result;
1281 int buffer_size = SELECTION_QUANTUM (display); 1296 int buffer_size = selection_quantum (display);
1297
1298 /* Wide enough to avoid overflow in expressions using it. */
1299 ptrdiff_t x_long_size = X_LONG_SIZE;
1282 1300
1283 if (buffer_size > MAX_SELECTION_QUANTUM) 1301 /* Maximum value for TOTAL_SIZE. It cannot exceed PTRDIFF_MAX - 1
1284 buffer_size = MAX_SELECTION_QUANTUM; 1302 and SIZE_MAX - 1, for an extra byte at the end. And it cannot
1303 exceed LONG_MAX * X_LONG_SIZE, for XGetWindowProperty. */
1304 ptrdiff_t total_size_max =
1305 ((min (PTRDIFF_MAX, SIZE_MAX) - 1) / x_long_size < LONG_MAX
1306 ? min (PTRDIFF_MAX, SIZE_MAX) - 1
1307 : LONG_MAX * x_long_size);
1285 1308
1286 BLOCK_INPUT; 1309 BLOCK_INPUT;
1287 1310
@@ -1292,49 +1315,44 @@ x_get_window_property (Display *display, Window window, Atom property,
1292 actual_size_ret, 1315 actual_size_ret,
1293 &bytes_remaining, &tmp_data); 1316 &bytes_remaining, &tmp_data);
1294 if (result != Success) 1317 if (result != Success)
1295 { 1318 goto done;
1296 UNBLOCK_INPUT;
1297 *data_ret = 0;
1298 *bytes_ret = 0;
1299 return;
1300 }
1301 1319
1302 /* This was allocated by Xlib, so use XFree. */ 1320 /* This was allocated by Xlib, so use XFree. */
1303 XFree ((char *) tmp_data); 1321 XFree ((char *) tmp_data);
1304 1322
1305 if (*actual_type_ret == None || *actual_format_ret == 0) 1323 if (*actual_type_ret == None || *actual_format_ret == 0)
1306 { 1324 goto done;
1307 UNBLOCK_INPUT;
1308 return;
1309 }
1310 1325
1311 total_size = bytes_remaining + 1; 1326 if (total_size_max < bytes_remaining)
1312 *data_ret = (unsigned char *) xmalloc (total_size); 1327 goto size_overflow;
1328 total_size = bytes_remaining;
1329 data = malloc (total_size + 1);
1330 if (! data)
1331 goto memory_exhausted;
1313 1332
1314 /* Now read, until we've gotten it all. */ 1333 /* Now read, until we've gotten it all. */
1315 while (bytes_remaining) 1334 while (bytes_remaining)
1316 { 1335 {
1317#ifdef TRACE_SELECTION 1336 ptrdiff_t bytes_gotten;
1318 unsigned long last = bytes_remaining; 1337 int bytes_per_item;
1319#endif
1320 result 1338 result
1321 = XGetWindowProperty (display, window, property, 1339 = XGetWindowProperty (display, window, property,
1322 (long)offset/4, (long)buffer_size/4, 1340 offset / X_LONG_SIZE,
1341 buffer_size / X_LONG_SIZE,
1323 False, 1342 False,
1324 AnyPropertyType, 1343 AnyPropertyType,
1325 actual_type_ret, actual_format_ret, 1344 actual_type_ret, actual_format_ret,
1326 actual_size_ret, &bytes_remaining, &tmp_data); 1345 actual_size_ret, &bytes_remaining, &tmp_data);
1327 1346
1328 TRACE2 ("Read %lu bytes from property %s",
1329 last - bytes_remaining,
1330 XGetAtomName (display, property));
1331
1332 /* If this doesn't return Success at this point, it means that 1347 /* If this doesn't return Success at this point, it means that
1333 some clod deleted the selection while we were in the midst of 1348 some clod deleted the selection while we were in the midst of
1334 reading it. Deal with that, I guess.... */ 1349 reading it. Deal with that, I guess.... */
1335 if (result != Success) 1350 if (result != Success)
1336 break; 1351 break;
1337 1352
1353 bytes_per_item = *actual_format_ret >> 3;
1354 xassert (*actual_size_ret <= buffer_size / bytes_per_item);
1355
1338 /* The man page for XGetWindowProperty says: 1356 /* The man page for XGetWindowProperty says:
1339 "If the returned format is 32, the returned data is represented 1357 "If the returned format is 32, the returned data is represented
1340 as a long array and should be cast to that type to obtain the 1358 as a long array and should be cast to that type to obtain the
@@ -1348,32 +1366,61 @@ x_get_window_property (Display *display, Window window, Atom property,
1348 The bytes and offsets passed to XGetWindowProperty refers to the 1366 The bytes and offsets passed to XGetWindowProperty refers to the
1349 property and those are indeed in 32 bit quantities if format is 32. */ 1367 property and those are indeed in 32 bit quantities if format is 32. */
1350 1368
1369 bytes_gotten = *actual_size_ret;
1370 bytes_gotten *= bytes_per_item;
1371
1372 TRACE2 ("Read %"pD"d bytes from property %s",
1373 bytes_gotten, XGetAtomName (display, property));
1374
1375 if (total_size - offset < bytes_gotten)
1376 {
1377 unsigned char *data1;
1378 ptrdiff_t remaining_lim = total_size_max - offset - bytes_gotten;
1379 if (remaining_lim < 0 || remaining_lim < bytes_remaining)
1380 goto size_overflow;
1381 total_size = offset + bytes_gotten + bytes_remaining;
1382 data1 = realloc (data, total_size + 1);
1383 if (! data1)
1384 goto memory_exhausted;
1385 data = data1;
1386 }
1387
1351 if (32 < BITS_PER_LONG && *actual_format_ret == 32) 1388 if (32 < BITS_PER_LONG && *actual_format_ret == 32)
1352 { 1389 {
1353 unsigned long i; 1390 unsigned long i;
1354 int *idata = (int *) ((*data_ret) + offset); 1391 int *idata = (int *) (data + offset);
1355 long *ldata = (long *) tmp_data; 1392 long *ldata = (long *) tmp_data;
1356 1393
1357 for (i = 0; i < *actual_size_ret; ++i) 1394 for (i = 0; i < *actual_size_ret; ++i)
1358 { 1395 idata[i] = ldata[i];
1359 idata[i]= (int) ldata[i];
1360 offset += 4;
1361 }
1362 } 1396 }
1363 else 1397 else
1364 { 1398 memcpy (data + offset, tmp_data, bytes_gotten);
1365 *actual_size_ret *= *actual_format_ret / 8; 1399
1366 memcpy ((*data_ret) + offset, tmp_data, *actual_size_ret); 1400 offset += bytes_gotten;
1367 offset += *actual_size_ret;
1368 }
1369 1401
1370 /* This was allocated by Xlib, so use XFree. */ 1402 /* This was allocated by Xlib, so use XFree. */
1371 XFree ((char *) tmp_data); 1403 XFree ((char *) tmp_data);
1372 } 1404 }
1373 1405
1374 XFlush (display); 1406 XFlush (display);
1407 data[offset] = '\0';
1408
1409 done:
1375 UNBLOCK_INPUT; 1410 UNBLOCK_INPUT;
1411 *data_ret = data;
1376 *bytes_ret = offset; 1412 *bytes_ret = offset;
1413 return;
1414
1415 size_overflow:
1416 free (data);
1417 UNBLOCK_INPUT;
1418 memory_full (SIZE_MAX);
1419
1420 memory_exhausted:
1421 free (data);
1422 UNBLOCK_INPUT;
1423 memory_full (total_size + 1);
1377} 1424}
1378 1425
1379/* Use xfree, not XFree, to free the data obtained with this function. */ 1426/* Use xfree, not XFree, to free the data obtained with this function. */
@@ -1382,16 +1429,19 @@ static void
1382receive_incremental_selection (Display *display, Window window, Atom property, 1429receive_incremental_selection (Display *display, Window window, Atom property,
1383 Lisp_Object target_type, 1430 Lisp_Object target_type,
1384 unsigned int min_size_bytes, 1431 unsigned int min_size_bytes,
1385 unsigned char **data_ret, int *size_bytes_ret, 1432 unsigned char **data_ret,
1433 ptrdiff_t *size_bytes_ret,
1386 Atom *type_ret, int *format_ret, 1434 Atom *type_ret, int *format_ret,
1387 unsigned long *size_ret) 1435 unsigned long *size_ret)
1388{ 1436{
1389 int offset = 0; 1437 ptrdiff_t offset = 0;
1390 struct prop_location *wait_object; 1438 struct prop_location *wait_object;
1439 if (min (PTRDIFF_MAX, SIZE_MAX) < min_size_bytes)
1440 memory_full (SIZE_MAX);
1441 *data_ret = (unsigned char *) xmalloc (min_size_bytes);
1391 *size_bytes_ret = min_size_bytes; 1442 *size_bytes_ret = min_size_bytes;
1392 *data_ret = (unsigned char *) xmalloc (*size_bytes_ret);
1393 1443
1394 TRACE1 ("Read %d bytes incrementally", min_size_bytes); 1444 TRACE1 ("Read %u bytes incrementally", min_size_bytes);
1395 1445
1396 /* At this point, we have read an INCR property. 1446 /* At this point, we have read an INCR property.
1397 Delete the property to ack it. 1447 Delete the property to ack it.
@@ -1416,7 +1466,7 @@ receive_incremental_selection (Display *display, Window window, Atom property,
1416 while (1) 1466 while (1)
1417 { 1467 {
1418 unsigned char *tmp_data; 1468 unsigned char *tmp_data;
1419 int tmp_size_bytes; 1469 ptrdiff_t tmp_size_bytes;
1420 1470
1421 TRACE0 (" Wait for property change"); 1471 TRACE0 (" Wait for property change");
1422 wait_for_property_change (wait_object); 1472 wait_for_property_change (wait_object);
@@ -1429,7 +1479,7 @@ receive_incremental_selection (Display *display, Window window, Atom property,
1429 &tmp_data, &tmp_size_bytes, 1479 &tmp_data, &tmp_size_bytes,
1430 type_ret, format_ret, size_ret, 1); 1480 type_ret, format_ret, size_ret, 1);
1431 1481
1432 TRACE1 (" Read increment of %d bytes", tmp_size_bytes); 1482 TRACE1 (" Read increment of %"pD"d bytes", tmp_size_bytes);
1433 1483
1434 if (tmp_size_bytes == 0) /* we're done */ 1484 if (tmp_size_bytes == 0) /* we're done */
1435 { 1485 {
@@ -1452,10 +1502,17 @@ receive_incremental_selection (Display *display, Window window, Atom property,
1452 XFlush (display); 1502 XFlush (display);
1453 UNBLOCK_INPUT; 1503 UNBLOCK_INPUT;
1454 1504
1455 if (*size_bytes_ret < offset + tmp_size_bytes) 1505 if (*size_bytes_ret - offset < tmp_size_bytes)
1456 { 1506 {
1457 *size_bytes_ret = offset + tmp_size_bytes; 1507 ptrdiff_t size;
1458 *data_ret = (unsigned char *) xrealloc (*data_ret, *size_bytes_ret); 1508 if (min (PTRDIFF_MAX, SIZE_MAX) - offset < tmp_size_bytes)
1509 {
1510 xfree (tmp_data);
1511 memory_full (SIZE_MAX);
1512 }
1513 size = offset + tmp_size_bytes;
1514 *data_ret = (unsigned char *) xrealloc (*data_ret, size);
1515 *size_bytes_ret = size;
1459 } 1516 }
1460 1517
1461 memcpy ((*data_ret) + offset, tmp_data, tmp_size_bytes); 1518 memcpy ((*data_ret) + offset, tmp_data, tmp_size_bytes);
@@ -1482,7 +1539,7 @@ x_get_window_property_as_lisp_data (Display *display, Window window,
1482 int actual_format; 1539 int actual_format;
1483 unsigned long actual_size; 1540 unsigned long actual_size;
1484 unsigned char *data = 0; 1541 unsigned char *data = 0;
1485 int bytes = 0; 1542 ptrdiff_t bytes = 0;
1486 Lisp_Object val; 1543 Lisp_Object val;
1487 struct x_display_info *dpyinfo = x_display_info_for_display (display); 1544 struct x_display_info *dpyinfo = x_display_info_for_display (display);
1488 1545
@@ -1574,7 +1631,7 @@ x_get_window_property_as_lisp_data (Display *display, Window window,
1574 1631
1575static Lisp_Object 1632static Lisp_Object
1576selection_data_to_lisp_data (Display *display, const unsigned char *data, 1633selection_data_to_lisp_data (Display *display, const unsigned char *data,
1577 int size, Atom type, int format) 1634 ptrdiff_t size, Atom type, int format)
1578{ 1635{
1579 struct x_display_info *dpyinfo = x_display_info_for_display (display); 1636 struct x_display_info *dpyinfo = x_display_info_for_display (display);
1580 1637
@@ -1607,7 +1664,7 @@ selection_data_to_lisp_data (Display *display, const unsigned char *data,
1607 /* Treat ATOM_PAIR type similar to list of atoms. */ 1664 /* Treat ATOM_PAIR type similar to list of atoms. */
1608 || type == dpyinfo->Xatom_ATOM_PAIR) 1665 || type == dpyinfo->Xatom_ATOM_PAIR)
1609 { 1666 {
1610 int i; 1667 ptrdiff_t i;
1611 /* On a 64 bit machine sizeof(Atom) == sizeof(long) == 8. 1668 /* On a 64 bit machine sizeof(Atom) == sizeof(long) == 8.
1612 But the callers of these function has made sure the data for 1669 But the callers of these function has made sure the data for
1613 format == 32 is an array of int. Thus, use int instead 1670 format == 32 is an array of int. Thus, use int instead
@@ -1634,28 +1691,29 @@ selection_data_to_lisp_data (Display *display, const unsigned char *data,
1634 else if (format == 32 && size == sizeof (int)) 1691 else if (format == 32 && size == sizeof (int))
1635 return INTEGER_TO_CONS (((unsigned int *) data) [0]); 1692 return INTEGER_TO_CONS (((unsigned int *) data) [0]);
1636 else if (format == 16 && size == sizeof (short)) 1693 else if (format == 16 && size == sizeof (short))
1637 return make_number ((int) (((unsigned short *) data) [0])); 1694 return make_number (((unsigned short *) data) [0]);
1638 1695
1639 /* Convert any other kind of data to a vector of numbers, represented 1696 /* Convert any other kind of data to a vector of numbers, represented
1640 as above (as an integer, or a cons of two 16 bit integers.) 1697 as above (as an integer, or a cons of two 16 bit integers.)
1641 */ 1698 */
1642 else if (format == 16) 1699 else if (format == 16)
1643 { 1700 {
1644 int i; 1701 ptrdiff_t i;
1645 Lisp_Object v; 1702 Lisp_Object v;
1646 v = Fmake_vector (make_number (size / 2), make_number (0)); 1703 v = Fmake_vector (make_number (size / 2), make_number (0));
1647 for (i = 0; i < size / 2; i++) 1704 for (i = 0; i < size / 2; i++)
1648 { 1705 {
1649 int j = (int) ((unsigned short *) data) [i]; 1706 EMACS_INT j = ((unsigned short *) data) [i];
1650 Faset (v, make_number (i), make_number (j)); 1707 Faset (v, make_number (i), make_number (j));
1651 } 1708 }
1652 return v; 1709 return v;
1653 } 1710 }
1654 else 1711 else
1655 { 1712 {
1656 int i; 1713 ptrdiff_t i;
1657 Lisp_Object v = Fmake_vector (make_number (size / 4), make_number (0)); 1714 Lisp_Object v = Fmake_vector (make_number (size / X_LONG_SIZE),
1658 for (i = 0; i < size / 4; i++) 1715 make_number (0));
1716 for (i = 0; i < size / X_LONG_SIZE; i++)
1659 { 1717 {
1660 unsigned int j = ((unsigned int *) data) [i]; 1718 unsigned int j = ((unsigned int *) data) [i];
1661 Faset (v, make_number (i), INTEGER_TO_CONS (j)); 1719 Faset (v, make_number (i), INTEGER_TO_CONS (j));
@@ -1670,7 +1728,7 @@ selection_data_to_lisp_data (Display *display, const unsigned char *data,
1670static void 1728static void
1671lisp_data_to_selection_data (Display *display, Lisp_Object obj, 1729lisp_data_to_selection_data (Display *display, Lisp_Object obj,
1672 unsigned char **data_ret, Atom *type_ret, 1730 unsigned char **data_ret, Atom *type_ret,
1673 unsigned int *size_ret, 1731 ptrdiff_t *size_ret,
1674 int *format_ret, int *nofree_ret) 1732 int *format_ret, int *nofree_ret)
1675{ 1733{
1676 Lisp_Object type = Qnil; 1734 Lisp_Object type = Qnil;
@@ -1707,22 +1765,20 @@ lisp_data_to_selection_data (Display *display, Lisp_Object obj,
1707 } 1765 }
1708 else if (SYMBOLP (obj)) 1766 else if (SYMBOLP (obj))
1709 { 1767 {
1768 *data_ret = (unsigned char *) xmalloc (sizeof (Atom) + 1);
1710 *format_ret = 32; 1769 *format_ret = 32;
1711 *size_ret = 1; 1770 *size_ret = 1;
1712 *data_ret = (unsigned char *) xmalloc (sizeof (Atom) + 1);
1713 (*data_ret) [sizeof (Atom)] = 0; 1771 (*data_ret) [sizeof (Atom)] = 0;
1714 (*(Atom **) data_ret) [0] = symbol_to_x_atom (dpyinfo, obj); 1772 (*(Atom **) data_ret) [0] = symbol_to_x_atom (dpyinfo, obj);
1715 if (NILP (type)) type = QATOM; 1773 if (NILP (type)) type = QATOM;
1716 } 1774 }
1717 else if (INTEGERP (obj) 1775 else if (RANGED_INTEGERP (0, obj, X_USHRT_MAX))
1718 && XINT (obj) < 0xFFFF
1719 && XINT (obj) > -0xFFFF)
1720 { 1776 {
1777 *data_ret = (unsigned char *) xmalloc (sizeof (short) + 1);
1721 *format_ret = 16; 1778 *format_ret = 16;
1722 *size_ret = 1; 1779 *size_ret = 1;
1723 *data_ret = (unsigned char *) xmalloc (sizeof (short) + 1);
1724 (*data_ret) [sizeof (short)] = 0; 1780 (*data_ret) [sizeof (short)] = 0;
1725 (*(short **) data_ret) [0] = (short) XINT (obj); 1781 (*(unsigned short **) data_ret) [0] = XINT (obj);
1726 if (NILP (type)) type = QINTEGER; 1782 if (NILP (type)) type = QINTEGER;
1727 } 1783 }
1728 else if (INTEGERP (obj) 1784 else if (INTEGERP (obj)
@@ -1731,11 +1787,11 @@ lisp_data_to_selection_data (Display *display, Lisp_Object obj,
1731 || (CONSP (XCDR (obj)) 1787 || (CONSP (XCDR (obj))
1732 && INTEGERP (XCAR (XCDR (obj))))))) 1788 && INTEGERP (XCAR (XCDR (obj)))))))
1733 { 1789 {
1790 *data_ret = (unsigned char *) xmalloc (sizeof (long) + 1);
1734 *format_ret = 32; 1791 *format_ret = 32;
1735 *size_ret = 1; 1792 *size_ret = 1;
1736 *data_ret = (unsigned char *) xmalloc (sizeof (long) + 1);
1737 (*data_ret) [sizeof (long)] = 0; 1793 (*data_ret) [sizeof (long)] = 0;
1738 (*(unsigned long **) data_ret) [0] = cons_to_unsigned (obj, ULONG_MAX); 1794 (*(unsigned long **) data_ret) [0] = cons_to_unsigned (obj, X_ULONG_MAX);
1739 if (NILP (type)) type = QINTEGER; 1795 if (NILP (type)) type = QINTEGER;
1740 } 1796 }
1741 else if (VECTORP (obj)) 1797 else if (VECTORP (obj))
@@ -1744,50 +1800,54 @@ lisp_data_to_selection_data (Display *display, Lisp_Object obj,
1744 a set of 16 or 32 bit INTEGERs; 1800 a set of 16 or 32 bit INTEGERs;
1745 or a set of ATOM_PAIRs (represented as [[A1 A2] [A3 A4] ...] 1801 or a set of ATOM_PAIRs (represented as [[A1 A2] [A3 A4] ...]
1746 */ 1802 */
1747 int i; 1803 ptrdiff_t i;
1804 ptrdiff_t size = ASIZE (obj);
1748 1805
1749 if (SYMBOLP (XVECTOR (obj)->contents [0])) 1806 if (SYMBOLP (XVECTOR (obj)->contents [0]))
1750 /* This vector is an ATOM set */ 1807 /* This vector is an ATOM set */
1751 { 1808 {
1809 if (min (PTRDIFF_MAX, SIZE_MAX) / sizeof (Atom) < size)
1810 memory_full (SIZE_MAX);
1752 if (NILP (type)) type = QATOM; 1811 if (NILP (type)) type = QATOM;
1753 *size_ret = ASIZE (obj); 1812 for (i = 0; i < size; i++)
1754 *format_ret = 32;
1755 for (i = 0; i < *size_ret; i++)
1756 if (!SYMBOLP (XVECTOR (obj)->contents [i])) 1813 if (!SYMBOLP (XVECTOR (obj)->contents [i]))
1757 signal_error ("All elements of selection vector must have same type", obj); 1814 signal_error ("All elements of selection vector must have same type", obj);
1758 1815
1759 *data_ret = (unsigned char *) xmalloc ((*size_ret) * sizeof (Atom)); 1816 *data_ret = (unsigned char *) xmalloc (size * sizeof (Atom));
1760 for (i = 0; i < *size_ret; i++) 1817 *format_ret = 32;
1818 *size_ret = size;
1819 for (i = 0; i < size; i++)
1761 (*(Atom **) data_ret) [i] 1820 (*(Atom **) data_ret) [i]
1762 = symbol_to_x_atom (dpyinfo, XVECTOR (obj)->contents [i]); 1821 = symbol_to_x_atom (dpyinfo, XVECTOR (obj)->contents [i]);
1763 } 1822 }
1764 else 1823 else
1765 /* This vector is an INTEGER set, or something like it */ 1824 /* This vector is an INTEGER set, or something like it */
1766 { 1825 {
1826 int format = 16;
1767 int data_size = 2; 1827 int data_size = 2;
1768 *size_ret = ASIZE (obj);
1769 if (NILP (type)) type = QINTEGER; 1828 if (NILP (type)) type = QINTEGER;
1770 *format_ret = 16; 1829 for (i = 0; i < size; i++)
1771 for (i = 0; i < *size_ret; i++) 1830 if (X_USHRT_MAX
1772 if (CONSP (XVECTOR (obj)->contents [i])) 1831 < cons_to_unsigned (XVECTOR (obj)->contents[i], X_ULONG_MAX))
1773 *format_ret = 32; 1832 {
1774 else if (!INTEGERP (XVECTOR (obj)->contents [i])) 1833 /* Use sizeof (long) even if it is more than 32 bits.
1775 signal_error (/* Qselection_error */ 1834 See comment in x_get_window_property and
1776 "Elements of selection vector must be integers or conses of integers", 1835 x_fill_property_data. */
1777 obj); 1836 data_size = sizeof (long);
1778 1837 format = 32;
1779 /* Use sizeof(long) even if it is more than 32 bits. See comment 1838 }
1780 in x_get_window_property and x_fill_property_data. */ 1839 if (min (PTRDIFF_MAX, SIZE_MAX) / data_size < size)
1781 1840 memory_full (SIZE_MAX);
1782 if (*format_ret == 32) data_size = sizeof(long); 1841 *data_ret = (unsigned char *) xmalloc (size * data_size);
1783 *data_ret = (unsigned char *) xmalloc (*size_ret * data_size); 1842 *format_ret = format;
1784 for (i = 0; i < *size_ret; i++) 1843 *size_ret = size;
1785 if (*format_ret == 32) 1844 for (i = 0; i < size; i++)
1845 if (format == 32)
1786 (*((unsigned long **) data_ret)) [i] = 1846 (*((unsigned long **) data_ret)) [i] =
1787 cons_to_unsigned (XVECTOR (obj)->contents [i], ULONG_MAX); 1847 cons_to_unsigned (XVECTOR (obj)->contents[i], X_ULONG_MAX);
1788 else 1848 else
1789 (*((unsigned short **) data_ret)) [i] = 1849 (*((unsigned short **) data_ret)) [i] =
1790 cons_to_unsigned (XVECTOR (obj)->contents [i], USHRT_MAX); 1850 cons_to_unsigned (XVECTOR (obj)->contents[i], X_USHRT_MAX);
1791 } 1851 }
1792 } 1852 }
1793 else 1853 else
@@ -1817,8 +1877,8 @@ clean_local_selection_data (Lisp_Object obj)
1817 } 1877 }
1818 if (VECTORP (obj)) 1878 if (VECTORP (obj))
1819 { 1879 {
1820 int i; 1880 ptrdiff_t i;
1821 int size = ASIZE (obj); 1881 ptrdiff_t size = ASIZE (obj);
1822 Lisp_Object copy; 1882 Lisp_Object copy;
1823 if (size == 1) 1883 if (size == 1)
1824 return clean_local_selection_data (XVECTOR (obj)->contents [0]); 1884 return clean_local_selection_data (XVECTOR (obj)->contents [0]);
@@ -2213,6 +2273,8 @@ x_check_property_data (Lisp_Object data)
2213 else if (CONSP (o) && 2273 else if (CONSP (o) &&
2214 (! NUMBERP (XCAR (o)) || ! NUMBERP (XCDR (o)))) 2274 (! NUMBERP (XCAR (o)) || ! NUMBERP (XCDR (o))))
2215 return -1; 2275 return -1;
2276 if (size == INT_MAX)
2277 return -1;
2216 size++; 2278 size++;
2217 } 2279 }
2218 2280
@@ -2294,8 +2356,11 @@ Lisp_Object
2294x_property_data_to_lisp (struct frame *f, const unsigned char *data, 2356x_property_data_to_lisp (struct frame *f, const unsigned char *data,
2295 Atom type, int format, long unsigned int size) 2357 Atom type, int format, long unsigned int size)
2296{ 2358{
2359 ptrdiff_t format_bytes = format >> 3;
2360 if (PTRDIFF_MAX / format_bytes < size)
2361 memory_full (SIZE_MAX);
2297 return selection_data_to_lisp_data (FRAME_X_DISPLAY (f), 2362 return selection_data_to_lisp_data (FRAME_X_DISPLAY (f),
2298 data, size*format/8, type, format); 2363 data, size * format_bytes, type, format);
2299} 2364}
2300 2365
2301/* Get the mouse position in frame relative coordinates. */ 2366/* Get the mouse position in frame relative coordinates. */
@@ -2405,10 +2470,10 @@ FRAME is on. If FRAME is nil, the selected frame is used. */)
2405 if (min (PTRDIFF_MAX, SIZE_MAX) / sizeof *dpyinfo->x_dnd_atoms / 2 2470 if (min (PTRDIFF_MAX, SIZE_MAX) / sizeof *dpyinfo->x_dnd_atoms / 2
2406 < dpyinfo->x_dnd_atoms_size) 2471 < dpyinfo->x_dnd_atoms_size)
2407 memory_full (SIZE_MAX); 2472 memory_full (SIZE_MAX);
2408 dpyinfo->x_dnd_atoms_size *= 2;
2409 dpyinfo->x_dnd_atoms = xrealloc (dpyinfo->x_dnd_atoms, 2473 dpyinfo->x_dnd_atoms = xrealloc (dpyinfo->x_dnd_atoms,
2410 sizeof (*dpyinfo->x_dnd_atoms) 2474 (2 * sizeof *dpyinfo->x_dnd_atoms
2411 * dpyinfo->x_dnd_atoms_size); 2475 * dpyinfo->x_dnd_atoms_size));
2476 dpyinfo->x_dnd_atoms_size *= 2;
2412 } 2477 }
2413 2478
2414 dpyinfo->x_dnd_atoms[dpyinfo->x_dnd_atoms_length++] = x_atom; 2479 dpyinfo->x_dnd_atoms[dpyinfo->x_dnd_atoms_length++] = x_atom;
@@ -2426,7 +2491,7 @@ x_handle_dnd_message (struct frame *f, XClientMessageEvent *event, struct x_disp
2426 unsigned long size = 160/event->format; 2491 unsigned long size = 160/event->format;
2427 int x, y; 2492 int x, y;
2428 unsigned char *data = (unsigned char *) event->data.b; 2493 unsigned char *data = (unsigned char *) event->data.b;
2429 int idata[5]; 2494 unsigned int idata[5];
2430 ptrdiff_t i; 2495 ptrdiff_t i;
2431 2496
2432 for (i = 0; i < dpyinfo->x_dnd_atoms_length; ++i) 2497 for (i = 0; i < dpyinfo->x_dnd_atoms_length; ++i)
@@ -2444,7 +2509,7 @@ x_handle_dnd_message (struct frame *f, XClientMessageEvent *event, struct x_disp
2444 if (32 < BITS_PER_LONG && event->format == 32) 2509 if (32 < BITS_PER_LONG && event->format == 32)
2445 { 2510 {
2446 for (i = 0; i < 5; ++i) /* There are only 5 longs in a ClientMessage. */ 2511 for (i = 0; i < 5; ++i) /* There are only 5 longs in a ClientMessage. */
2447 idata[i] = (int) event->data.l[i]; 2512 idata[i] = event->data.l[i];
2448 data = (unsigned char *) idata; 2513 data = (unsigned char *) idata;
2449 } 2514 }
2450 2515