diff options
author | Bram Moolenaar <Bram@vim.org> | 2017-07-19 19:55:58 +0200 |
---|---|---|
committer | Bram Moolenaar <Bram@vim.org> | 2017-07-19 19:55:58 +0200 |
commit | cdb7e1b7f9e18a7b165ff09103a9994f84966123 (patch) | |
tree | 7c4cda3abde0d0b1b3d821c7fb825c99512c0dc7 /src/ui.c | |
parent | 04f62f881c5743d2fdaf7324f6a715381f0d5fcf (diff) | |
download | vim-git-cdb7e1b7f9e18a7b165ff09103a9994f84966123.tar.gz |
patch 8.0.0737: crash when X11 selection is very bigv8.0.0737
Problem: Crash when X11 selection is very big.
Solution: Use static items instead of allocating them. Add callbacks.
(Ozaki Kiichi)
Diffstat (limited to 'src/ui.c')
-rw-r--r-- | src/ui.c | 69 |
1 files changed, 39 insertions, 30 deletions
@@ -2042,10 +2042,11 @@ x11_setup_atoms(Display *dpy) * 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 void clip_x11_lose_ownership_cb(Widget, Atom *); +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 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_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. @@ -2085,7 +2086,7 @@ clip_x11_timestamp_cb( /* Get the selection, using the event timestamp. */ if (XtOwnSelection(w, xproperty->atom, xproperty->time, 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 * lose_ownership_cb in between. */ @@ -2276,9 +2277,9 @@ clip_x11_request_selection( start_time = time(NULL); while (success == MAYBE) { - if (XCheckTypedEvent(dpy, SelectionNotify, &event) - || XCheckTypedEvent(dpy, SelectionRequest, &event) - || XCheckTypedEvent(dpy, PropertyNotify, &event)) + if (XCheckTypedEvent(dpy, PropertyNotify, &event) + || XCheckTypedEvent(dpy, SelectionNotify, &event) + || XCheckTypedEvent(dpy, SelectionRequest, &event)) { /* This is where clip_x11_request_selection_cb() should be * called. It may actually happen a bit later, so we loop @@ -2331,11 +2332,12 @@ clip_x11_convert_selection_cb( long_u *length, int *format) { - char_u *string; - char_u *result; - int motion_type; - VimClipboard *cbd; - int i; + static char_u *save_result = NULL; + static long_u save_length = 0; + char_u *string; + int motion_type; + VimClipboard *cbd; + int i; if (*sel_atom == clip_plus.sel_atom) cbd = &clip_plus; @@ -2348,10 +2350,8 @@ clip_x11_convert_selection_cb( /* requestor wants to know what target types we support */ if (*target == targets_atom) { - Atom *array; + static Atom array[7]; - if ((array = (Atom *)XtMalloc((unsigned)(sizeof(Atom) * 7))) == NULL) - return False; *value = (XtPointer)array; i = 0; array[i++] = targets_atom; @@ -2400,13 +2400,17 @@ clip_x11_convert_selection_cb( *length += STRLEN(p_enc) + 2; #endif - *value = XtMalloc((Cardinal)*length); - result = (char_u *)*value; - if (result == NULL) + if (save_length < *length || save_length / 2 >= *length) + *value = XtRealloc((char *)save_result, (Cardinal)*length + 1); + else + *value = save_result; + if (*value == NULL) { vim_free(string); return False; } + save_result = (char_u *)*value; + save_length = *length; if (*target == XA_STRING #ifdef FEAT_MBYTE @@ -2414,13 +2418,13 @@ clip_x11_convert_selection_cb( #endif ) { - mch_memmove(result, string, (size_t)(*length)); + mch_memmove(save_result, string, (size_t)(*length)); *type = *target; } else if (*target == compound_text_atom || *target == text_atom) { XTextProperty text_prop; - char *string_nt = (char *)alloc((unsigned)*length + 1); + char *string_nt = (char *)save_result; int conv_result; /* create NUL terminated string which XmbTextListToTextProperty wants */ @@ -2428,8 +2432,6 @@ clip_x11_convert_selection_cb( string_nt[*length] = NUL; conv_result = XmbTextListToTextProperty(X_DISPLAY, (char **)&string_nt, 1, XCompoundTextStyle, &text_prop); - vim_free(string_nt); - XtFree(*value); /* replace with COMPOUND text */ if (conv_result != Success) { vim_free(string); @@ -2438,24 +2440,25 @@ clip_x11_convert_selection_cb( *value = (XtPointer)(text_prop.value); /* from plain text */ *length = text_prop.nitems; *type = compound_text_atom; + XtFree((char *)save_result); + save_result = (char_u *)*value; + save_length = *length; } - #ifdef FEAT_MBYTE else if (*target == vimenc_atom) { int l = STRLEN(p_enc); - result[0] = motion_type; - STRCPY(result + 1, p_enc); - mch_memmove(result + l + 2, string, (size_t)(*length - l - 2)); + save_result[0] = motion_type; + STRCPY(save_result + 1, p_enc); + mch_memmove(save_result + l + 2, string, (size_t)(*length - l - 2)); *type = vimenc_atom; } #endif - else { - result[0] = motion_type; - mch_memmove(result + 1, string, (size_t)(*length - 1)); + save_result[0] = motion_type; + mch_memmove(save_result + 1, string, (size_t)(*length - 1)); *type = vim_atom; } *format = 8; /* 8 bits per char */ @@ -2479,6 +2482,12 @@ clip_x11_lose_selection(Widget myShell, VimClipboard *cbd) 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 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, XtLastTimestampProcessed(XtDisplay(myShell)), clip_x11_convert_selection_cb, clip_x11_lose_ownership_cb, - NULL) == False) + clip_x11_notify_cb) == False) return FAIL; } else |