diff options
| author | Po Lu | 2022-08-30 19:27:39 +0800 |
|---|---|---|
| committer | Po Lu | 2022-08-30 19:28:03 +0800 |
| commit | 0bf5463f8147ea9143d286d5a9df7c8421a1ac4b (patch) | |
| tree | d7d01c0aee60bcf6963d25f48ee5fe3e013d2d91 /src | |
| parent | db6e574567350f8cf2eec698ea82e62dcd9d27a6 (diff) | |
| download | emacs-0bf5463f8147ea9143d286d5a9df7c8421a1ac4b.tar.gz emacs-0bf5463f8147ea9143d286d5a9df7c8421a1ac4b.zip | |
Fix junk data being returned with incremental selection transfers
* src/xselect.c (receive_incremental_selection): New arg
REAL_BYTES_RET. Set it to the actual size instead of using the
size of the array after it was grown by xpalloc.
(x_get_window_property_as_lisp_data): Adjust call to
receive_incremental_selection.
Diffstat (limited to 'src')
| -rw-r--r-- | src/xselect.c | 34 |
1 files changed, 29 insertions, 5 deletions
diff --git a/src/xselect.c b/src/xselect.c index bab0400540e..74d762f3055 100644 --- a/src/xselect.c +++ b/src/xselect.c | |||
| @@ -1567,7 +1567,8 @@ receive_incremental_selection (struct x_display_info *dpyinfo, | |||
| 1567 | unsigned char **data_ret, | 1567 | unsigned char **data_ret, |
| 1568 | ptrdiff_t *size_bytes_ret, | 1568 | ptrdiff_t *size_bytes_ret, |
| 1569 | Atom *type_ret, int *format_ret, | 1569 | Atom *type_ret, int *format_ret, |
| 1570 | unsigned long *size_ret) | 1570 | unsigned long *size_ret, |
| 1571 | ptrdiff_t *real_bytes_ret) | ||
| 1571 | { | 1572 | { |
| 1572 | ptrdiff_t offset = 0; | 1573 | ptrdiff_t offset = 0; |
| 1573 | struct prop_location *wait_object; | 1574 | struct prop_location *wait_object; |
| @@ -1622,7 +1623,8 @@ receive_incremental_selection (struct x_display_info *dpyinfo, | |||
| 1622 | 1623 | ||
| 1623 | if (tmp_size_bytes == 0) /* we're done */ | 1624 | if (tmp_size_bytes == 0) /* we're done */ |
| 1624 | { | 1625 | { |
| 1625 | TRACE0 ("Done reading incrementally"); | 1626 | TRACE1 ("Done reading incrementally; total bytes: %"pD"d", |
| 1627 | *size_bytes_ret); | ||
| 1626 | 1628 | ||
| 1627 | if (! waiting_for_other_props_on_window (display, window)) | 1629 | if (! waiting_for_other_props_on_window (display, window)) |
| 1628 | XSelectInput (display, window, STANDARD_EVENT_SET); | 1630 | XSelectInput (display, window, STANDARD_EVENT_SET); |
| @@ -1652,6 +1654,19 @@ receive_incremental_selection (struct x_display_info *dpyinfo, | |||
| 1652 | memcpy ((*data_ret) + offset, tmp_data, tmp_size_bytes); | 1654 | memcpy ((*data_ret) + offset, tmp_data, tmp_size_bytes); |
| 1653 | offset += tmp_size_bytes; | 1655 | offset += tmp_size_bytes; |
| 1654 | 1656 | ||
| 1657 | /* *size_bytes_ret is not really the size of the data inside the | ||
| 1658 | buffer; it is the size of the buffer allocated by xpalloc. | ||
| 1659 | |||
| 1660 | This matters when the cardinal specified in the INCR property | ||
| 1661 | (a _lower bound_ on the size of the selection data) is | ||
| 1662 | smaller than the actual selection contents, which can happen | ||
| 1663 | when programs are streaming selection data from a file | ||
| 1664 | descriptor. In that case, we used to return junk if xpalloc | ||
| 1665 | decided to grow the buffer by more than the provided | ||
| 1666 | increment; to avoid that, store the actual size of the | ||
| 1667 | selection data in *real_bytes_ret. */ | ||
| 1668 | *real_bytes_ret += tmp_size_bytes; | ||
| 1669 | |||
| 1655 | /* Use xfree, not XFree, because x_get_window_property | 1670 | /* Use xfree, not XFree, because x_get_window_property |
| 1656 | calls xmalloc itself. */ | 1671 | calls xmalloc itself. */ |
| 1657 | xfree (tmp_data); | 1672 | xfree (tmp_data); |
| @@ -1674,10 +1689,14 @@ x_get_window_property_as_lisp_data (struct x_display_info *dpyinfo, | |||
| 1674 | int actual_format; | 1689 | int actual_format; |
| 1675 | unsigned long actual_size; | 1690 | unsigned long actual_size; |
| 1676 | unsigned char *data = 0; | 1691 | unsigned char *data = 0; |
| 1677 | ptrdiff_t bytes = 0; | 1692 | ptrdiff_t bytes = 0, array_bytes; |
| 1678 | Lisp_Object val; | 1693 | Lisp_Object val; |
| 1679 | Display *display = dpyinfo->display; | 1694 | Display *display = dpyinfo->display; |
| 1680 | 1695 | ||
| 1696 | /* array_bytes is only used as an argument to xpalloc. The actual | ||
| 1697 | size of the data inside the buffer is inside bytes. */ | ||
| 1698 | array_bytes = 0; | ||
| 1699 | |||
| 1681 | TRACE0 ("Reading selection data"); | 1700 | TRACE0 ("Reading selection data"); |
| 1682 | 1701 | ||
| 1683 | x_get_window_property (display, window, property, &data, &bytes, | 1702 | x_get_window_property (display, window, property, &data, &bytes, |
| @@ -1718,10 +1737,15 @@ x_get_window_property_as_lisp_data (struct x_display_info *dpyinfo, | |||
| 1718 | calls xmalloc itself. */ | 1737 | calls xmalloc itself. */ |
| 1719 | xfree (data); | 1738 | xfree (data); |
| 1720 | unblock_input (); | 1739 | unblock_input (); |
| 1740 | |||
| 1741 | /* Clear bytes again. Previously, receive_incremental_selection | ||
| 1742 | would set this to min_size_bytes, but that is now done to | ||
| 1743 | array_bytes instead. */ | ||
| 1744 | bytes = 0; | ||
| 1721 | receive_incremental_selection (dpyinfo, window, property, target_type, | 1745 | receive_incremental_selection (dpyinfo, window, property, target_type, |
| 1722 | min_size_bytes, &data, &bytes, | 1746 | min_size_bytes, &data, &array_bytes, |
| 1723 | &actual_type, &actual_format, | 1747 | &actual_type, &actual_format, |
| 1724 | &actual_size); | 1748 | &actual_size, &bytes); |
| 1725 | } | 1749 | } |
| 1726 | 1750 | ||
| 1727 | if (!for_multiple) | 1751 | if (!for_multiple) |