aboutsummaryrefslogtreecommitdiffstats
path: root/src/xselect.c
diff options
context:
space:
mode:
authorJoakim Verona2011-08-27 19:45:48 +0200
committerJoakim Verona2011-08-27 19:45:48 +0200
commit9fb7b0cab34a48a4c7b66abb6b8edc4ee20467b4 (patch)
treee94476d49f15747fcb9409d773702e88201855a4 /src/xselect.c
parentc7489583c30031c0ecfae9d20b20c149ca1935e9 (diff)
parentb75258b32810f3690442bddef2e10eef126d2d25 (diff)
downloademacs-9fb7b0cab34a48a4c7b66abb6b8edc4ee20467b4.tar.gz
emacs-9fb7b0cab34a48a4c7b66abb6b8edc4ee20467b4.zip
upstream
Diffstat (limited to 'src/xselect.c')
-rw-r--r--src/xselect.c316
1 files changed, 185 insertions, 131 deletions
diff --git a/src/xselect.c b/src/xselect.c
index f63977a73de..77bda79007c 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,39 @@ 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/* Extreme 'short' and 'long' values suitable for libX11. */
115#define X_SHRT_MAX 0x7fff
116#define X_SHRT_MIN (-1 - X_SHRT_MAX)
117#define X_LONG_MAX 0x7fffffff
118#define X_LONG_MIN (-1 - X_LONG_MAX)
119
117/* If this is a smaller number than the max-request-size of the display, 120/* 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 121 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 122 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 123 emacs to use incremental selection transfers when the selection is
121 smaller than that, set this. I added this mostly for debugging the 124 smaller than that, set this. I added this mostly for debugging the
122 incremental transfer stuff, but it might improve server performance. */ 125 incremental transfer stuff, but it might improve server performance.
123#define MAX_SELECTION_QUANTUM 0xFFFFFF
124 126
125#define SELECTION_QUANTUM(dpy) ((XMaxRequestSize(dpy) << 2) - 100) 127 This value cannot exceed INT_MAX / max (X_LONG_SIZE, sizeof (long))
128 because it is multiplied by X_LONG_SIZE and by sizeof (long) in
129 subscript calculations. Similarly for PTRDIFF_MAX - 1 or SIZE_MAX
130 - 1 in place of INT_MAX. */
131#define MAX_SELECTION_QUANTUM \
132 ((int) min (0xFFFFFF, (min (INT_MAX, min (PTRDIFF_MAX, SIZE_MAX) - 1) \
133 / max (X_LONG_SIZE, sizeof (long)))))
134
135static int
136selection_quantum (Display *display)
137{
138 long mrs = XMaxRequestSize (display);
139 return (mrs < MAX_SELECTION_QUANTUM / X_LONG_SIZE + 25
140 ? (mrs - 25) * X_LONG_SIZE
141 : MAX_SELECTION_QUANTUM);
142}
126 143
127#define LOCAL_SELECTION(selection_symbol,dpyinfo) \ 144#define LOCAL_SELECTION(selection_symbol,dpyinfo) \
128 assq_no_quit (selection_symbol, dpyinfo->terminal->Vselection_alist) 145 assq_no_quit (selection_symbol, dpyinfo->terminal->Vselection_alist)
@@ -477,7 +494,7 @@ static struct x_display_info *selection_request_dpyinfo;
477struct selection_data 494struct selection_data
478{ 495{
479 unsigned char *data; 496 unsigned char *data;
480 unsigned int size; 497 ptrdiff_t size;
481 int format; 498 int format;
482 Atom type; 499 Atom type;
483 int nofree; 500 int nofree;
@@ -581,14 +598,11 @@ x_reply_selection_request (struct input_event *event, struct x_display_info *dpy
581 XSelectionEvent *reply = &(reply_base.xselection); 598 XSelectionEvent *reply = &(reply_base.xselection);
582 Display *display = SELECTION_EVENT_DISPLAY (event); 599 Display *display = SELECTION_EVENT_DISPLAY (event);
583 Window window = SELECTION_EVENT_REQUESTOR (event); 600 Window window = SELECTION_EVENT_REQUESTOR (event);
584 int bytes_remaining; 601 ptrdiff_t bytes_remaining;
585 int max_bytes = SELECTION_QUANTUM (display); 602 int max_bytes = selection_quantum (display);
586 int count = SPECPDL_INDEX (); 603 int count = SPECPDL_INDEX ();
587 struct selection_data *cs; 604 struct selection_data *cs;
588 605
589 if (max_bytes > MAX_SELECTION_QUANTUM)
590 max_bytes = MAX_SELECTION_QUANTUM;
591
592 reply->type = SelectionNotify; 606 reply->type = SelectionNotify;
593 reply->display = display; 607 reply->display = display;
594 reply->requestor = window; 608 reply->requestor = window;
@@ -616,11 +630,12 @@ x_reply_selection_request (struct input_event *event, struct x_display_info *dpy
616 if (cs->property == None) 630 if (cs->property == None)
617 continue; 631 continue;
618 632
619 bytes_remaining = cs->size * (cs->format / 8); 633 bytes_remaining = cs->size;
634 bytes_remaining *= cs->format >> 3;
620 if (bytes_remaining <= max_bytes) 635 if (bytes_remaining <= max_bytes)
621 { 636 {
622 /* Send all the data at once, with minimal handshaking. */ 637 /* Send all the data at once, with minimal handshaking. */
623 TRACE1 ("Sending all %d bytes", bytes_remaining); 638 TRACE1 ("Sending all %"pD"d bytes", bytes_remaining);
624 XChangeProperty (display, window, cs->property, 639 XChangeProperty (display, window, cs->property,
625 cs->type, cs->format, PropModeReplace, 640 cs->type, cs->format, PropModeReplace,
626 cs->data, cs->size); 641 cs->data, cs->size);
@@ -630,7 +645,7 @@ x_reply_selection_request (struct input_event *event, struct x_display_info *dpy
630 /* Send an INCR tag to initiate incremental transfer. */ 645 /* Send an INCR tag to initiate incremental transfer. */
631 long value[1]; 646 long value[1];
632 647
633 TRACE2 ("Start sending %d bytes incrementally (%s)", 648 TRACE2 ("Start sending %"pD"d bytes incrementally (%s)",
634 bytes_remaining, XGetAtomName (display, cs->property)); 649 bytes_remaining, XGetAtomName (display, cs->property));
635 cs->wait_object 650 cs->wait_object
636 = expect_property_change (display, window, cs->property, 651 = expect_property_change (display, window, cs->property,
@@ -638,7 +653,7 @@ x_reply_selection_request (struct input_event *event, struct x_display_info *dpy
638 653
639 /* XChangeProperty expects an array of long even if long is 654 /* XChangeProperty expects an array of long even if long is
640 more than 32 bits. */ 655 more than 32 bits. */
641 value[0] = bytes_remaining; 656 value[0] = min (bytes_remaining, X_LONG_MAX);
642 XChangeProperty (display, window, cs->property, 657 XChangeProperty (display, window, cs->property,
643 dpyinfo->Xatom_INCR, 32, PropModeReplace, 658 dpyinfo->Xatom_INCR, 32, PropModeReplace,
644 (unsigned char *) value, 1); 659 (unsigned char *) value, 1);
@@ -672,7 +687,8 @@ x_reply_selection_request (struct input_event *event, struct x_display_info *dpy
672 int had_errors = x_had_errors_p (display); 687 int had_errors = x_had_errors_p (display);
673 UNBLOCK_INPUT; 688 UNBLOCK_INPUT;
674 689
675 bytes_remaining = cs->size * format_bytes; 690 bytes_remaining = cs->size;
691 bytes_remaining *= format_bytes;
676 692
677 /* Wait for the requester to ack by deleting the property. 693 /* Wait for the requester to ack by deleting the property.
678 This can run Lisp code (process handlers) or signal. */ 694 This can run Lisp code (process handlers) or signal. */
@@ -810,7 +826,7 @@ x_handle_selection_request (struct input_event *event)
810 non-None property. */ 826 non-None property. */
811 Window requestor = SELECTION_EVENT_REQUESTOR (event); 827 Window requestor = SELECTION_EVENT_REQUESTOR (event);
812 Lisp_Object multprop; 828 Lisp_Object multprop;
813 int j, nselections; 829 ptrdiff_t j, nselections;
814 830
815 if (property == None) goto DONE; 831 if (property == None) goto DONE;
816 multprop 832 multprop
@@ -1269,19 +1285,28 @@ x_get_foreign_selection (Lisp_Object selection_symbol, Lisp_Object target_type,
1269 1285
1270static void 1286static void
1271x_get_window_property (Display *display, Window window, Atom property, 1287x_get_window_property (Display *display, Window window, Atom property,
1272 unsigned char **data_ret, int *bytes_ret, 1288 unsigned char **data_ret, ptrdiff_t *bytes_ret,
1273 Atom *actual_type_ret, int *actual_format_ret, 1289 Atom *actual_type_ret, int *actual_format_ret,
1274 unsigned long *actual_size_ret, int delete_p) 1290 unsigned long *actual_size_ret, int delete_p)
1275{ 1291{
1276 int total_size; 1292 ptrdiff_t total_size;
1277 unsigned long bytes_remaining; 1293 unsigned long bytes_remaining;
1278 int offset = 0; 1294 ptrdiff_t offset = 0;
1295 unsigned char *data = 0;
1279 unsigned char *tmp_data = 0; 1296 unsigned char *tmp_data = 0;
1280 int result; 1297 int result;
1281 int buffer_size = SELECTION_QUANTUM (display); 1298 int buffer_size = selection_quantum (display);
1299
1300 /* Wide enough to avoid overflow in expressions using it. */
1301 ptrdiff_t x_long_size = X_LONG_SIZE;
1282 1302
1283 if (buffer_size > MAX_SELECTION_QUANTUM) 1303 /* Maximum value for TOTAL_SIZE. It cannot exceed PTRDIFF_MAX - 1
1284 buffer_size = MAX_SELECTION_QUANTUM; 1304 and SIZE_MAX - 1, for an extra byte at the end. And it cannot
1305 exceed LONG_MAX * X_LONG_SIZE, for XGetWindowProperty. */
1306 ptrdiff_t total_size_max =
1307 ((min (PTRDIFF_MAX, SIZE_MAX) - 1) / x_long_size < LONG_MAX
1308 ? min (PTRDIFF_MAX, SIZE_MAX) - 1
1309 : LONG_MAX * x_long_size);
1285 1310
1286 BLOCK_INPUT; 1311 BLOCK_INPUT;
1287 1312
@@ -1292,49 +1317,44 @@ x_get_window_property (Display *display, Window window, Atom property,
1292 actual_size_ret, 1317 actual_size_ret,
1293 &bytes_remaining, &tmp_data); 1318 &bytes_remaining, &tmp_data);
1294 if (result != Success) 1319 if (result != Success)
1295 { 1320 goto done;
1296 UNBLOCK_INPUT;
1297 *data_ret = 0;
1298 *bytes_ret = 0;
1299 return;
1300 }
1301 1321
1302 /* This was allocated by Xlib, so use XFree. */ 1322 /* This was allocated by Xlib, so use XFree. */
1303 XFree ((char *) tmp_data); 1323 XFree ((char *) tmp_data);
1304 1324
1305 if (*actual_type_ret == None || *actual_format_ret == 0) 1325 if (*actual_type_ret == None || *actual_format_ret == 0)
1306 { 1326 goto done;
1307 UNBLOCK_INPUT;
1308 return;
1309 }
1310 1327
1311 total_size = bytes_remaining + 1; 1328 if (total_size_max < bytes_remaining)
1312 *data_ret = (unsigned char *) xmalloc (total_size); 1329 goto size_overflow;
1330 total_size = bytes_remaining;
1331 data = malloc (total_size + 1);
1332 if (! data)
1333 goto memory_exhausted;
1313 1334
1314 /* Now read, until we've gotten it all. */ 1335 /* Now read, until we've gotten it all. */
1315 while (bytes_remaining) 1336 while (bytes_remaining)
1316 { 1337 {
1317#ifdef TRACE_SELECTION 1338 ptrdiff_t bytes_gotten;
1318 unsigned long last = bytes_remaining; 1339 int bytes_per_item;
1319#endif
1320 result 1340 result
1321 = XGetWindowProperty (display, window, property, 1341 = XGetWindowProperty (display, window, property,
1322 (long)offset/4, (long)buffer_size/4, 1342 offset / X_LONG_SIZE,
1343 buffer_size / X_LONG_SIZE,
1323 False, 1344 False,
1324 AnyPropertyType, 1345 AnyPropertyType,
1325 actual_type_ret, actual_format_ret, 1346 actual_type_ret, actual_format_ret,
1326 actual_size_ret, &bytes_remaining, &tmp_data); 1347 actual_size_ret, &bytes_remaining, &tmp_data);
1327 1348
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 1349 /* 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 1350 some clod deleted the selection while we were in the midst of
1334 reading it. Deal with that, I guess.... */ 1351 reading it. Deal with that, I guess.... */
1335 if (result != Success) 1352 if (result != Success)
1336 break; 1353 break;
1337 1354
1355 bytes_per_item = *actual_format_ret >> 3;
1356 xassert (*actual_size_ret <= buffer_size / bytes_per_item);
1357
1338 /* The man page for XGetWindowProperty says: 1358 /* The man page for XGetWindowProperty says:
1339 "If the returned format is 32, the returned data is represented 1359 "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 1360 as a long array and should be cast to that type to obtain the
@@ -1348,32 +1368,61 @@ x_get_window_property (Display *display, Window window, Atom property,
1348 The bytes and offsets passed to XGetWindowProperty refers to the 1368 The bytes and offsets passed to XGetWindowProperty refers to the
1349 property and those are indeed in 32 bit quantities if format is 32. */ 1369 property and those are indeed in 32 bit quantities if format is 32. */
1350 1370
1371 bytes_gotten = *actual_size_ret;
1372 bytes_gotten *= bytes_per_item;
1373
1374 TRACE2 ("Read %"pD"d bytes from property %s",
1375 bytes_gotten, XGetAtomName (display, property));
1376
1377 if (total_size - offset < bytes_gotten)
1378 {
1379 unsigned char *data1;
1380 ptrdiff_t remaining_lim = total_size_max - offset - bytes_gotten;
1381 if (remaining_lim < 0 || remaining_lim < bytes_remaining)
1382 goto size_overflow;
1383 total_size = offset + bytes_gotten + bytes_remaining;
1384 data1 = realloc (data, total_size + 1);
1385 if (! data1)
1386 goto memory_exhausted;
1387 data = data1;
1388 }
1389
1351 if (32 < BITS_PER_LONG && *actual_format_ret == 32) 1390 if (32 < BITS_PER_LONG && *actual_format_ret == 32)
1352 { 1391 {
1353 unsigned long i; 1392 unsigned long i;
1354 int *idata = (int *) ((*data_ret) + offset); 1393 int *idata = (int *) (data + offset);
1355 long *ldata = (long *) tmp_data; 1394 long *ldata = (long *) tmp_data;
1356 1395
1357 for (i = 0; i < *actual_size_ret; ++i) 1396 for (i = 0; i < *actual_size_ret; ++i)
1358 { 1397 idata[i] = ldata[i];
1359 idata[i]= (int) ldata[i];
1360 offset += 4;
1361 }
1362 } 1398 }
1363 else 1399 else
1364 { 1400 memcpy (data + offset, tmp_data, bytes_gotten);
1365 *actual_size_ret *= *actual_format_ret / 8; 1401
1366 memcpy ((*data_ret) + offset, tmp_data, *actual_size_ret); 1402 offset += bytes_gotten;
1367 offset += *actual_size_ret;
1368 }
1369 1403
1370 /* This was allocated by Xlib, so use XFree. */ 1404 /* This was allocated by Xlib, so use XFree. */
1371 XFree ((char *) tmp_data); 1405 XFree ((char *) tmp_data);
1372 } 1406 }
1373 1407
1374 XFlush (display); 1408 XFlush (display);
1409 data[offset] = '\0';
1410
1411 done:
1375 UNBLOCK_INPUT; 1412 UNBLOCK_INPUT;
1413 *data_ret = data;
1376 *bytes_ret = offset; 1414 *bytes_ret = offset;
1415 return;
1416
1417 size_overflow:
1418 free (data);
1419 UNBLOCK_INPUT;
1420 memory_full (SIZE_MAX);
1421
1422 memory_exhausted:
1423 free (data);
1424 UNBLOCK_INPUT;
1425 memory_full (total_size + 1);
1377} 1426}
1378 1427
1379/* Use xfree, not XFree, to free the data obtained with this function. */ 1428/* Use xfree, not XFree, to free the data obtained with this function. */
@@ -1382,16 +1431,19 @@ static void
1382receive_incremental_selection (Display *display, Window window, Atom property, 1431receive_incremental_selection (Display *display, Window window, Atom property,
1383 Lisp_Object target_type, 1432 Lisp_Object target_type,
1384 unsigned int min_size_bytes, 1433 unsigned int min_size_bytes,
1385 unsigned char **data_ret, int *size_bytes_ret, 1434 unsigned char **data_ret,
1435 ptrdiff_t *size_bytes_ret,
1386 Atom *type_ret, int *format_ret, 1436 Atom *type_ret, int *format_ret,
1387 unsigned long *size_ret) 1437 unsigned long *size_ret)
1388{ 1438{
1389 int offset = 0; 1439 ptrdiff_t offset = 0;
1390 struct prop_location *wait_object; 1440 struct prop_location *wait_object;
1441 if (min (PTRDIFF_MAX, SIZE_MAX) < min_size_bytes)
1442 memory_full (SIZE_MAX);
1443 *data_ret = (unsigned char *) xmalloc (min_size_bytes);
1391 *size_bytes_ret = min_size_bytes; 1444 *size_bytes_ret = min_size_bytes;
1392 *data_ret = (unsigned char *) xmalloc (*size_bytes_ret);
1393 1445
1394 TRACE1 ("Read %d bytes incrementally", min_size_bytes); 1446 TRACE1 ("Read %u bytes incrementally", min_size_bytes);
1395 1447
1396 /* At this point, we have read an INCR property. 1448 /* At this point, we have read an INCR property.
1397 Delete the property to ack it. 1449 Delete the property to ack it.
@@ -1416,7 +1468,7 @@ receive_incremental_selection (Display *display, Window window, Atom property,
1416 while (1) 1468 while (1)
1417 { 1469 {
1418 unsigned char *tmp_data; 1470 unsigned char *tmp_data;
1419 int tmp_size_bytes; 1471 ptrdiff_t tmp_size_bytes;
1420 1472
1421 TRACE0 (" Wait for property change"); 1473 TRACE0 (" Wait for property change");
1422 wait_for_property_change (wait_object); 1474 wait_for_property_change (wait_object);
@@ -1429,7 +1481,7 @@ receive_incremental_selection (Display *display, Window window, Atom property,
1429 &tmp_data, &tmp_size_bytes, 1481 &tmp_data, &tmp_size_bytes,
1430 type_ret, format_ret, size_ret, 1); 1482 type_ret, format_ret, size_ret, 1);
1431 1483
1432 TRACE1 (" Read increment of %d bytes", tmp_size_bytes); 1484 TRACE1 (" Read increment of %"pD"d bytes", tmp_size_bytes);
1433 1485
1434 if (tmp_size_bytes == 0) /* we're done */ 1486 if (tmp_size_bytes == 0) /* we're done */
1435 { 1487 {
@@ -1452,11 +1504,10 @@ receive_incremental_selection (Display *display, Window window, Atom property,
1452 XFlush (display); 1504 XFlush (display);
1453 UNBLOCK_INPUT; 1505 UNBLOCK_INPUT;
1454 1506
1455 if (*size_bytes_ret < offset + tmp_size_bytes) 1507 if (*size_bytes_ret - offset < tmp_size_bytes)
1456 { 1508 *data_ret = xpalloc (*data_ret, size_bytes_ret,
1457 *size_bytes_ret = offset + tmp_size_bytes; 1509 tmp_size_bytes - (*size_bytes_ret - offset),
1458 *data_ret = (unsigned char *) xrealloc (*data_ret, *size_bytes_ret); 1510 -1, 1);
1459 }
1460 1511
1461 memcpy ((*data_ret) + offset, tmp_data, tmp_size_bytes); 1512 memcpy ((*data_ret) + offset, tmp_data, tmp_size_bytes);
1462 offset += tmp_size_bytes; 1513 offset += tmp_size_bytes;
@@ -1482,7 +1533,7 @@ x_get_window_property_as_lisp_data (Display *display, Window window,
1482 int actual_format; 1533 int actual_format;
1483 unsigned long actual_size; 1534 unsigned long actual_size;
1484 unsigned char *data = 0; 1535 unsigned char *data = 0;
1485 int bytes = 0; 1536 ptrdiff_t bytes = 0;
1486 Lisp_Object val; 1537 Lisp_Object val;
1487 struct x_display_info *dpyinfo = x_display_info_for_display (display); 1538 struct x_display_info *dpyinfo = x_display_info_for_display (display);
1488 1539
@@ -1574,7 +1625,7 @@ x_get_window_property_as_lisp_data (Display *display, Window window,
1574 1625
1575static Lisp_Object 1626static Lisp_Object
1576selection_data_to_lisp_data (Display *display, const unsigned char *data, 1627selection_data_to_lisp_data (Display *display, const unsigned char *data,
1577 int size, Atom type, int format) 1628 ptrdiff_t size, Atom type, int format)
1578{ 1629{
1579 struct x_display_info *dpyinfo = x_display_info_for_display (display); 1630 struct x_display_info *dpyinfo = x_display_info_for_display (display);
1580 1631
@@ -1607,7 +1658,7 @@ selection_data_to_lisp_data (Display *display, const unsigned char *data,
1607 /* Treat ATOM_PAIR type similar to list of atoms. */ 1658 /* Treat ATOM_PAIR type similar to list of atoms. */
1608 || type == dpyinfo->Xatom_ATOM_PAIR) 1659 || type == dpyinfo->Xatom_ATOM_PAIR)
1609 { 1660 {
1610 int i; 1661 ptrdiff_t i;
1611 /* On a 64 bit machine sizeof(Atom) == sizeof(long) == 8. 1662 /* On a 64 bit machine sizeof(Atom) == sizeof(long) == 8.
1612 But the callers of these function has made sure the data for 1663 But the callers of these function has made sure the data for
1613 format == 32 is an array of int. Thus, use int instead 1664 format == 32 is an array of int. Thus, use int instead
@@ -1634,28 +1685,29 @@ selection_data_to_lisp_data (Display *display, const unsigned char *data,
1634 else if (format == 32 && size == sizeof (int)) 1685 else if (format == 32 && size == sizeof (int))
1635 return INTEGER_TO_CONS (((unsigned int *) data) [0]); 1686 return INTEGER_TO_CONS (((unsigned int *) data) [0]);
1636 else if (format == 16 && size == sizeof (short)) 1687 else if (format == 16 && size == sizeof (short))
1637 return make_number ((int) (((unsigned short *) data) [0])); 1688 return make_number (((unsigned short *) data) [0]);
1638 1689
1639 /* Convert any other kind of data to a vector of numbers, represented 1690 /* 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.) 1691 as above (as an integer, or a cons of two 16 bit integers.)
1641 */ 1692 */
1642 else if (format == 16) 1693 else if (format == 16)
1643 { 1694 {
1644 int i; 1695 ptrdiff_t i;
1645 Lisp_Object v; 1696 Lisp_Object v;
1646 v = Fmake_vector (make_number (size / 2), make_number (0)); 1697 v = Fmake_vector (make_number (size / 2), make_number (0));
1647 for (i = 0; i < size / 2; i++) 1698 for (i = 0; i < size / 2; i++)
1648 { 1699 {
1649 int j = (int) ((unsigned short *) data) [i]; 1700 EMACS_INT j = ((unsigned short *) data) [i];
1650 Faset (v, make_number (i), make_number (j)); 1701 Faset (v, make_number (i), make_number (j));
1651 } 1702 }
1652 return v; 1703 return v;
1653 } 1704 }
1654 else 1705 else
1655 { 1706 {
1656 int i; 1707 ptrdiff_t i;
1657 Lisp_Object v = Fmake_vector (make_number (size / 4), make_number (0)); 1708 Lisp_Object v = Fmake_vector (make_number (size / X_LONG_SIZE),
1658 for (i = 0; i < size / 4; i++) 1709 make_number (0));
1710 for (i = 0; i < size / X_LONG_SIZE; i++)
1659 { 1711 {
1660 unsigned int j = ((unsigned int *) data) [i]; 1712 unsigned int j = ((unsigned int *) data) [i];
1661 Faset (v, make_number (i), INTEGER_TO_CONS (j)); 1713 Faset (v, make_number (i), INTEGER_TO_CONS (j));
@@ -1670,7 +1722,7 @@ selection_data_to_lisp_data (Display *display, const unsigned char *data,
1670static void 1722static void
1671lisp_data_to_selection_data (Display *display, Lisp_Object obj, 1723lisp_data_to_selection_data (Display *display, Lisp_Object obj,
1672 unsigned char **data_ret, Atom *type_ret, 1724 unsigned char **data_ret, Atom *type_ret,
1673 unsigned int *size_ret, 1725 ptrdiff_t *size_ret,
1674 int *format_ret, int *nofree_ret) 1726 int *format_ret, int *nofree_ret)
1675{ 1727{
1676 Lisp_Object type = Qnil; 1728 Lisp_Object type = Qnil;
@@ -1707,22 +1759,20 @@ lisp_data_to_selection_data (Display *display, Lisp_Object obj,
1707 } 1759 }
1708 else if (SYMBOLP (obj)) 1760 else if (SYMBOLP (obj))
1709 { 1761 {
1762 *data_ret = (unsigned char *) xmalloc (sizeof (Atom) + 1);
1710 *format_ret = 32; 1763 *format_ret = 32;
1711 *size_ret = 1; 1764 *size_ret = 1;
1712 *data_ret = (unsigned char *) xmalloc (sizeof (Atom) + 1);
1713 (*data_ret) [sizeof (Atom)] = 0; 1765 (*data_ret) [sizeof (Atom)] = 0;
1714 (*(Atom **) data_ret) [0] = symbol_to_x_atom (dpyinfo, obj); 1766 (*(Atom **) data_ret) [0] = symbol_to_x_atom (dpyinfo, obj);
1715 if (NILP (type)) type = QATOM; 1767 if (NILP (type)) type = QATOM;
1716 } 1768 }
1717 else if (INTEGERP (obj) 1769 else if (RANGED_INTEGERP (X_SHRT_MIN, obj, X_SHRT_MAX))
1718 && XINT (obj) < 0xFFFF
1719 && XINT (obj) > -0xFFFF)
1720 { 1770 {
1771 *data_ret = (unsigned char *) xmalloc (sizeof (short) + 1);
1721 *format_ret = 16; 1772 *format_ret = 16;
1722 *size_ret = 1; 1773 *size_ret = 1;
1723 *data_ret = (unsigned char *) xmalloc (sizeof (short) + 1);
1724 (*data_ret) [sizeof (short)] = 0; 1774 (*data_ret) [sizeof (short)] = 0;
1725 (*(short **) data_ret) [0] = (short) XINT (obj); 1775 (*(short **) data_ret) [0] = XINT (obj);
1726 if (NILP (type)) type = QINTEGER; 1776 if (NILP (type)) type = QINTEGER;
1727 } 1777 }
1728 else if (INTEGERP (obj) 1778 else if (INTEGERP (obj)
@@ -1731,11 +1781,11 @@ lisp_data_to_selection_data (Display *display, Lisp_Object obj,
1731 || (CONSP (XCDR (obj)) 1781 || (CONSP (XCDR (obj))
1732 && INTEGERP (XCAR (XCDR (obj))))))) 1782 && INTEGERP (XCAR (XCDR (obj)))))))
1733 { 1783 {
1784 *data_ret = (unsigned char *) xmalloc (sizeof (long) + 1);
1734 *format_ret = 32; 1785 *format_ret = 32;
1735 *size_ret = 1; 1786 *size_ret = 1;
1736 *data_ret = (unsigned char *) xmalloc (sizeof (long) + 1);
1737 (*data_ret) [sizeof (long)] = 0; 1787 (*data_ret) [sizeof (long)] = 0;
1738 (*(unsigned long **) data_ret) [0] = cons_to_unsigned (obj, ULONG_MAX); 1788 (*(long **) data_ret) [0] = cons_to_signed (obj, X_LONG_MIN, X_LONG_MAX);
1739 if (NILP (type)) type = QINTEGER; 1789 if (NILP (type)) type = QINTEGER;
1740 } 1790 }
1741 else if (VECTORP (obj)) 1791 else if (VECTORP (obj))
@@ -1744,50 +1794,55 @@ lisp_data_to_selection_data (Display *display, Lisp_Object obj,
1744 a set of 16 or 32 bit INTEGERs; 1794 a set of 16 or 32 bit INTEGERs;
1745 or a set of ATOM_PAIRs (represented as [[A1 A2] [A3 A4] ...] 1795 or a set of ATOM_PAIRs (represented as [[A1 A2] [A3 A4] ...]
1746 */ 1796 */
1747 int i; 1797 ptrdiff_t i;
1798 ptrdiff_t size = ASIZE (obj);
1748 1799
1749 if (SYMBOLP (XVECTOR (obj)->contents [0])) 1800 if (SYMBOLP (XVECTOR (obj)->contents [0]))
1750 /* This vector is an ATOM set */ 1801 /* This vector is an ATOM set */
1751 { 1802 {
1752 if (NILP (type)) type = QATOM; 1803 if (NILP (type)) type = QATOM;
1753 *size_ret = ASIZE (obj); 1804 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])) 1805 if (!SYMBOLP (XVECTOR (obj)->contents [i]))
1757 signal_error ("All elements of selection vector must have same type", obj); 1806 signal_error ("All elements of selection vector must have same type", obj);
1758 1807
1759 *data_ret = (unsigned char *) xmalloc ((*size_ret) * sizeof (Atom)); 1808 *data_ret = xnmalloc (size, sizeof (Atom));
1760 for (i = 0; i < *size_ret; i++) 1809 *format_ret = 32;
1810 *size_ret = size;
1811 for (i = 0; i < size; i++)
1761 (*(Atom **) data_ret) [i] 1812 (*(Atom **) data_ret) [i]
1762 = symbol_to_x_atom (dpyinfo, XVECTOR (obj)->contents [i]); 1813 = symbol_to_x_atom (dpyinfo, XVECTOR (obj)->contents [i]);
1763 } 1814 }
1764 else 1815 else
1765 /* This vector is an INTEGER set, or something like it */ 1816 /* This vector is an INTEGER set, or something like it */
1766 { 1817 {
1767 int data_size = 2; 1818 int format = 16;
1768 *size_ret = ASIZE (obj); 1819 int data_size = sizeof (short);
1769 if (NILP (type)) type = QINTEGER; 1820 if (NILP (type)) type = QINTEGER;
1770 *format_ret = 16; 1821 for (i = 0; i < size; i++)
1771 for (i = 0; i < *size_ret; i++) 1822 {
1772 if (CONSP (XVECTOR (obj)->contents [i])) 1823 intmax_t v = cons_to_signed (XVECTOR (obj)->contents[i],
1773 *format_ret = 32; 1824 X_LONG_MIN, X_LONG_MAX);
1774 else if (!INTEGERP (XVECTOR (obj)->contents [i])) 1825 if (X_SHRT_MIN <= v && v <= X_SHRT_MAX)
1775 signal_error (/* Qselection_error */ 1826 {
1776 "Elements of selection vector must be integers or conses of integers", 1827 /* Use sizeof (long) even if it is more than 32 bits.
1777 obj); 1828 See comment in x_get_window_property and
1778 1829 x_fill_property_data. */
1779 /* Use sizeof(long) even if it is more than 32 bits. See comment 1830 data_size = sizeof (long);
1780 in x_get_window_property and x_fill_property_data. */ 1831 format = 32;
1781 1832 }
1782 if (*format_ret == 32) data_size = sizeof(long); 1833 }
1783 *data_ret = (unsigned char *) xmalloc (*size_ret * data_size); 1834 *data_ret = xnmalloc (size, data_size);
1784 for (i = 0; i < *size_ret; i++) 1835 *format_ret = format;
1785 if (*format_ret == 32) 1836 *size_ret = size;
1786 (*((unsigned long **) data_ret)) [i] = 1837 for (i = 0; i < size; i++)
1787 cons_to_unsigned (XVECTOR (obj)->contents [i], ULONG_MAX); 1838 {
1788 else 1839 long v = cons_to_signed (XVECTOR (obj)->contents[i],
1789 (*((unsigned short **) data_ret)) [i] = 1840 X_LONG_MIN, X_LONG_MAX);
1790 cons_to_unsigned (XVECTOR (obj)->contents [i], USHRT_MAX); 1841 if (format == 32)
1842 (*((long **) data_ret)) [i] = v;
1843 else
1844 (*((short **) data_ret)) [i] = v;
1845 }
1791 } 1846 }
1792 } 1847 }
1793 else 1848 else
@@ -1817,8 +1872,8 @@ clean_local_selection_data (Lisp_Object obj)
1817 } 1872 }
1818 if (VECTORP (obj)) 1873 if (VECTORP (obj))
1819 { 1874 {
1820 int i; 1875 ptrdiff_t i;
1821 int size = ASIZE (obj); 1876 ptrdiff_t size = ASIZE (obj);
1822 Lisp_Object copy; 1877 Lisp_Object copy;
1823 if (size == 1) 1878 if (size == 1)
1824 return clean_local_selection_data (XVECTOR (obj)->contents [0]); 1879 return clean_local_selection_data (XVECTOR (obj)->contents [0]);
@@ -2213,6 +2268,8 @@ x_check_property_data (Lisp_Object data)
2213 else if (CONSP (o) && 2268 else if (CONSP (o) &&
2214 (! NUMBERP (XCAR (o)) || ! NUMBERP (XCDR (o)))) 2269 (! NUMBERP (XCAR (o)) || ! NUMBERP (XCDR (o))))
2215 return -1; 2270 return -1;
2271 if (size == INT_MAX)
2272 return -1;
2216 size++; 2273 size++;
2217 } 2274 }
2218 2275
@@ -2294,8 +2351,11 @@ Lisp_Object
2294x_property_data_to_lisp (struct frame *f, const unsigned char *data, 2351x_property_data_to_lisp (struct frame *f, const unsigned char *data,
2295 Atom type, int format, long unsigned int size) 2352 Atom type, int format, long unsigned int size)
2296{ 2353{
2354 ptrdiff_t format_bytes = format >> 3;
2355 if (PTRDIFF_MAX / format_bytes < size)
2356 memory_full (SIZE_MAX);
2297 return selection_data_to_lisp_data (FRAME_X_DISPLAY (f), 2357 return selection_data_to_lisp_data (FRAME_X_DISPLAY (f),
2298 data, size*format/8, type, format); 2358 data, size * format_bytes, type, format);
2299} 2359}
2300 2360
2301/* Get the mouse position in frame relative coordinates. */ 2361/* Get the mouse position in frame relative coordinates. */
@@ -2401,15 +2461,9 @@ FRAME is on. If FRAME is nil, the selected frame is used. */)
2401 return Qnil; 2461 return Qnil;
2402 2462
2403 if (dpyinfo->x_dnd_atoms_length == dpyinfo->x_dnd_atoms_size) 2463 if (dpyinfo->x_dnd_atoms_length == dpyinfo->x_dnd_atoms_size)
2404 { 2464 dpyinfo->x_dnd_atoms =
2405 if (min (PTRDIFF_MAX, SIZE_MAX) / sizeof *dpyinfo->x_dnd_atoms / 2 2465 xpalloc (dpyinfo->x_dnd_atoms, &dpyinfo->x_dnd_atoms_size,
2406 < dpyinfo->x_dnd_atoms_size) 2466 1, -1, sizeof *dpyinfo->x_dnd_atoms);
2407 memory_full (SIZE_MAX);
2408 dpyinfo->x_dnd_atoms_size *= 2;
2409 dpyinfo->x_dnd_atoms = xrealloc (dpyinfo->x_dnd_atoms,
2410 sizeof (*dpyinfo->x_dnd_atoms)
2411 * dpyinfo->x_dnd_atoms_size);
2412 }
2413 2467
2414 dpyinfo->x_dnd_atoms[dpyinfo->x_dnd_atoms_length++] = x_atom; 2468 dpyinfo->x_dnd_atoms[dpyinfo->x_dnd_atoms_length++] = x_atom;
2415 return Qnil; 2469 return Qnil;
@@ -2444,7 +2498,7 @@ x_handle_dnd_message (struct frame *f, XClientMessageEvent *event, struct x_disp
2444 if (32 < BITS_PER_LONG && event->format == 32) 2498 if (32 < BITS_PER_LONG && event->format == 32)
2445 { 2499 {
2446 for (i = 0; i < 5; ++i) /* There are only 5 longs in a ClientMessage. */ 2500 for (i = 0; i < 5; ++i) /* There are only 5 longs in a ClientMessage. */
2447 idata[i] = (int) event->data.l[i]; 2501 idata[i] = event->data.l[i];
2448 data = (unsigned char *) idata; 2502 data = (unsigned char *) idata;
2449 } 2503 }
2450 2504