mirror of
https://github.com/vim/vim.git
synced 2025-09-24 03:44:06 -04:00
patch 8.0.0737: crash when X11 selection is very big
Problem: Crash when X11 selection is very big. Solution: Use static items instead of allocating them. Add callbacks. (Ozaki Kiichi)
This commit is contained in:
@@ -111,14 +111,15 @@ endfunc
|
|||||||
" Wait for up to a second for "expr" to become true.
|
" Wait for up to a second for "expr" to become true.
|
||||||
" Return time slept in milliseconds. With the +reltime feature this can be
|
" Return time slept in milliseconds. With the +reltime feature this can be
|
||||||
" more than the actual waiting time. Without +reltime it can also be less.
|
" more than the actual waiting time. Without +reltime it can also be less.
|
||||||
func WaitFor(expr)
|
func WaitFor(expr, ...)
|
||||||
|
let timeout = get(a:000, 0, 1000)
|
||||||
" using reltime() is more accurate, but not always available
|
" using reltime() is more accurate, but not always available
|
||||||
if has('reltime')
|
if has('reltime')
|
||||||
let start = reltime()
|
let start = reltime()
|
||||||
else
|
else
|
||||||
let slept = 0
|
let slept = 0
|
||||||
endif
|
endif
|
||||||
for i in range(100)
|
for i in range(timeout / 10)
|
||||||
try
|
try
|
||||||
if eval(a:expr)
|
if eval(a:expr)
|
||||||
if has('reltime')
|
if has('reltime')
|
||||||
@@ -133,7 +134,7 @@ func WaitFor(expr)
|
|||||||
endif
|
endif
|
||||||
sleep 10m
|
sleep 10m
|
||||||
endfor
|
endfor
|
||||||
return 1000
|
return timeout
|
||||||
endfunc
|
endfunc
|
||||||
|
|
||||||
" Wait for up to a given milliseconds.
|
" Wait for up to a given milliseconds.
|
||||||
|
@@ -88,6 +88,18 @@ func Do_test_quotestar_for_x11()
|
|||||||
call WaitFor('@* == "yes"')
|
call WaitFor('@* == "yes"')
|
||||||
call assert_equal('yes', @*)
|
call assert_equal('yes', @*)
|
||||||
|
|
||||||
|
" Handle the large selection over 262040 byte.
|
||||||
|
let length = 262044
|
||||||
|
let sample = 'a' . repeat('b', length - 2) . 'c'
|
||||||
|
let @* = sample
|
||||||
|
call WaitFor('remote_expr("' . name . '", "len(@*) >= ' . length . '", "", 1)', 3000)
|
||||||
|
let res = remote_expr(name, "@*", "", 2)
|
||||||
|
call assert_equal(length, len(res))
|
||||||
|
" Check length to prevent a large amount of output at assertion failure.
|
||||||
|
if length == len(res)
|
||||||
|
call assert_equal(sample, res)
|
||||||
|
endif
|
||||||
|
|
||||||
if has('unix') && has('gui') && !has('gui_running')
|
if has('unix') && has('gui') && !has('gui_running')
|
||||||
let @* = ''
|
let @* = ''
|
||||||
|
|
||||||
|
61
src/ui.c
61
src/ui.c
@@ -2042,10 +2042,11 @@ x11_setup_atoms(Display *dpy)
|
|||||||
* X Selection stuff, for cutting and pasting text to other windows.
|
* X Selection stuff, for cutting and pasting text to other windows.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static Boolean clip_x11_convert_selection_cb(Widget, Atom *, Atom *, Atom *, XtPointer *, long_u *, int *);
|
static Boolean clip_x11_convert_selection_cb(Widget w, Atom *sel_atom, Atom *target, Atom *type, XtPointer *value, long_u *length, int *format);
|
||||||
static void clip_x11_lose_ownership_cb(Widget, Atom *);
|
static void clip_x11_lose_ownership_cb(Widget w, Atom *sel_atom);
|
||||||
|
static void clip_x11_notify_cb(Widget w, Atom *sel_atom, Atom *target);
|
||||||
static void clip_x11_timestamp_cb(Widget w, XtPointer n, XEvent *event, Boolean *cont);
|
static void clip_x11_timestamp_cb(Widget w, XtPointer n, XEvent *event, Boolean *cont);
|
||||||
static void clip_x11_request_selection_cb(Widget, XtPointer, Atom *, Atom *, XtPointer, long_u *, int *);
|
static void clip_x11_request_selection_cb(Widget w, XtPointer success, Atom *sel_atom, Atom *type, XtPointer value, long_u *length, int *format);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Property callback to get a timestamp for XtOwnSelection.
|
* Property callback to get a timestamp for XtOwnSelection.
|
||||||
@@ -2085,7 +2086,7 @@ clip_x11_timestamp_cb(
|
|||||||
/* Get the selection, using the event timestamp. */
|
/* Get the selection, using the event timestamp. */
|
||||||
if (XtOwnSelection(w, xproperty->atom, xproperty->time,
|
if (XtOwnSelection(w, xproperty->atom, xproperty->time,
|
||||||
clip_x11_convert_selection_cb, clip_x11_lose_ownership_cb,
|
clip_x11_convert_selection_cb, clip_x11_lose_ownership_cb,
|
||||||
NULL) == OK)
|
clip_x11_notify_cb) == OK)
|
||||||
{
|
{
|
||||||
/* Set the "owned" flag now, there may have been a call to
|
/* Set the "owned" flag now, there may have been a call to
|
||||||
* lose_ownership_cb in between. */
|
* lose_ownership_cb in between. */
|
||||||
@@ -2276,9 +2277,9 @@ clip_x11_request_selection(
|
|||||||
start_time = time(NULL);
|
start_time = time(NULL);
|
||||||
while (success == MAYBE)
|
while (success == MAYBE)
|
||||||
{
|
{
|
||||||
if (XCheckTypedEvent(dpy, SelectionNotify, &event)
|
if (XCheckTypedEvent(dpy, PropertyNotify, &event)
|
||||||
|| XCheckTypedEvent(dpy, SelectionRequest, &event)
|
|| XCheckTypedEvent(dpy, SelectionNotify, &event)
|
||||||
|| XCheckTypedEvent(dpy, PropertyNotify, &event))
|
|| XCheckTypedEvent(dpy, SelectionRequest, &event))
|
||||||
{
|
{
|
||||||
/* This is where clip_x11_request_selection_cb() should be
|
/* This is where clip_x11_request_selection_cb() should be
|
||||||
* called. It may actually happen a bit later, so we loop
|
* called. It may actually happen a bit later, so we loop
|
||||||
@@ -2331,8 +2332,9 @@ clip_x11_convert_selection_cb(
|
|||||||
long_u *length,
|
long_u *length,
|
||||||
int *format)
|
int *format)
|
||||||
{
|
{
|
||||||
|
static char_u *save_result = NULL;
|
||||||
|
static long_u save_length = 0;
|
||||||
char_u *string;
|
char_u *string;
|
||||||
char_u *result;
|
|
||||||
int motion_type;
|
int motion_type;
|
||||||
VimClipboard *cbd;
|
VimClipboard *cbd;
|
||||||
int i;
|
int i;
|
||||||
@@ -2348,10 +2350,8 @@ clip_x11_convert_selection_cb(
|
|||||||
/* requestor wants to know what target types we support */
|
/* requestor wants to know what target types we support */
|
||||||
if (*target == targets_atom)
|
if (*target == targets_atom)
|
||||||
{
|
{
|
||||||
Atom *array;
|
static Atom array[7];
|
||||||
|
|
||||||
if ((array = (Atom *)XtMalloc((unsigned)(sizeof(Atom) * 7))) == NULL)
|
|
||||||
return False;
|
|
||||||
*value = (XtPointer)array;
|
*value = (XtPointer)array;
|
||||||
i = 0;
|
i = 0;
|
||||||
array[i++] = targets_atom;
|
array[i++] = targets_atom;
|
||||||
@@ -2400,13 +2400,17 @@ clip_x11_convert_selection_cb(
|
|||||||
*length += STRLEN(p_enc) + 2;
|
*length += STRLEN(p_enc) + 2;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
*value = XtMalloc((Cardinal)*length);
|
if (save_length < *length || save_length / 2 >= *length)
|
||||||
result = (char_u *)*value;
|
*value = XtRealloc((char *)save_result, (Cardinal)*length + 1);
|
||||||
if (result == NULL)
|
else
|
||||||
|
*value = save_result;
|
||||||
|
if (*value == NULL)
|
||||||
{
|
{
|
||||||
vim_free(string);
|
vim_free(string);
|
||||||
return False;
|
return False;
|
||||||
}
|
}
|
||||||
|
save_result = (char_u *)*value;
|
||||||
|
save_length = *length;
|
||||||
|
|
||||||
if (*target == XA_STRING
|
if (*target == XA_STRING
|
||||||
#ifdef FEAT_MBYTE
|
#ifdef FEAT_MBYTE
|
||||||
@@ -2414,13 +2418,13 @@ clip_x11_convert_selection_cb(
|
|||||||
#endif
|
#endif
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
mch_memmove(result, string, (size_t)(*length));
|
mch_memmove(save_result, string, (size_t)(*length));
|
||||||
*type = *target;
|
*type = *target;
|
||||||
}
|
}
|
||||||
else if (*target == compound_text_atom || *target == text_atom)
|
else if (*target == compound_text_atom || *target == text_atom)
|
||||||
{
|
{
|
||||||
XTextProperty text_prop;
|
XTextProperty text_prop;
|
||||||
char *string_nt = (char *)alloc((unsigned)*length + 1);
|
char *string_nt = (char *)save_result;
|
||||||
int conv_result;
|
int conv_result;
|
||||||
|
|
||||||
/* create NUL terminated string which XmbTextListToTextProperty wants */
|
/* create NUL terminated string which XmbTextListToTextProperty wants */
|
||||||
@@ -2428,8 +2432,6 @@ clip_x11_convert_selection_cb(
|
|||||||
string_nt[*length] = NUL;
|
string_nt[*length] = NUL;
|
||||||
conv_result = XmbTextListToTextProperty(X_DISPLAY, (char **)&string_nt,
|
conv_result = XmbTextListToTextProperty(X_DISPLAY, (char **)&string_nt,
|
||||||
1, XCompoundTextStyle, &text_prop);
|
1, XCompoundTextStyle, &text_prop);
|
||||||
vim_free(string_nt);
|
|
||||||
XtFree(*value); /* replace with COMPOUND text */
|
|
||||||
if (conv_result != Success)
|
if (conv_result != Success)
|
||||||
{
|
{
|
||||||
vim_free(string);
|
vim_free(string);
|
||||||
@@ -2438,24 +2440,25 @@ clip_x11_convert_selection_cb(
|
|||||||
*value = (XtPointer)(text_prop.value); /* from plain text */
|
*value = (XtPointer)(text_prop.value); /* from plain text */
|
||||||
*length = text_prop.nitems;
|
*length = text_prop.nitems;
|
||||||
*type = compound_text_atom;
|
*type = compound_text_atom;
|
||||||
|
XtFree((char *)save_result);
|
||||||
|
save_result = (char_u *)*value;
|
||||||
|
save_length = *length;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef FEAT_MBYTE
|
#ifdef FEAT_MBYTE
|
||||||
else if (*target == vimenc_atom)
|
else if (*target == vimenc_atom)
|
||||||
{
|
{
|
||||||
int l = STRLEN(p_enc);
|
int l = STRLEN(p_enc);
|
||||||
|
|
||||||
result[0] = motion_type;
|
save_result[0] = motion_type;
|
||||||
STRCPY(result + 1, p_enc);
|
STRCPY(save_result + 1, p_enc);
|
||||||
mch_memmove(result + l + 2, string, (size_t)(*length - l - 2));
|
mch_memmove(save_result + l + 2, string, (size_t)(*length - l - 2));
|
||||||
*type = vimenc_atom;
|
*type = vimenc_atom;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
result[0] = motion_type;
|
save_result[0] = motion_type;
|
||||||
mch_memmove(result + 1, string, (size_t)(*length - 1));
|
mch_memmove(save_result + 1, string, (size_t)(*length - 1));
|
||||||
*type = vim_atom;
|
*type = vim_atom;
|
||||||
}
|
}
|
||||||
*format = 8; /* 8 bits per char */
|
*format = 8; /* 8 bits per char */
|
||||||
@@ -2479,6 +2482,12 @@ clip_x11_lose_selection(Widget myShell, VimClipboard *cbd)
|
|||||||
XtLastTimestampProcessed(XtDisplay(myShell)));
|
XtLastTimestampProcessed(XtDisplay(myShell)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
clip_x11_notify_cb(Widget w UNUSED, Atom *sel_atom UNUSED, Atom *target UNUSED)
|
||||||
|
{
|
||||||
|
/* To prevent automatically freeing the selection value. */
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
clip_x11_own_selection(Widget myShell, VimClipboard *cbd)
|
clip_x11_own_selection(Widget myShell, VimClipboard *cbd)
|
||||||
{
|
{
|
||||||
@@ -2492,7 +2501,7 @@ clip_x11_own_selection(Widget myShell, VimClipboard *cbd)
|
|||||||
if (XtOwnSelection(myShell, cbd->sel_atom,
|
if (XtOwnSelection(myShell, cbd->sel_atom,
|
||||||
XtLastTimestampProcessed(XtDisplay(myShell)),
|
XtLastTimestampProcessed(XtDisplay(myShell)),
|
||||||
clip_x11_convert_selection_cb, clip_x11_lose_ownership_cb,
|
clip_x11_convert_selection_cb, clip_x11_lose_ownership_cb,
|
||||||
NULL) == False)
|
clip_x11_notify_cb) == False)
|
||||||
return FAIL;
|
return FAIL;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@@ -769,6 +769,8 @@ static char *(features[]) =
|
|||||||
|
|
||||||
static int included_patches[] =
|
static int included_patches[] =
|
||||||
{ /* Add new patch number below this line */
|
{ /* Add new patch number below this line */
|
||||||
|
/**/
|
||||||
|
737,
|
||||||
/**/
|
/**/
|
||||||
736,
|
736,
|
||||||
/**/
|
/**/
|
||||||
|
Reference in New Issue
Block a user