To: vim-dev@vim.org Subject: Patch 6.1.145 Fcc: outbox From: Bram Moolenaar Mime-Version: 1.0 Content-Type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: 8bit ------------ Patch 6.1.145 Problem: GTK: Drag&drop with more than 3 files may cause a crash. (Mickael Marchand) Solution: Rewrite the code that parses the received list of files to be more robust. Files: src/charset.c, src/gui_gtk_x11.c *** ../vim61.144/src/charset.c Sat Aug 3 14:05:15 2002 --- src/charset.c Tue Jul 30 19:28:32 2002 *************** *** 1558,1564 **** return c - '0'; } ! #if defined(FEAT_TERMRESPONSE) || defined(PROTO) /* * Convert two hex characters to a byte. * Return -1 if one of the characters is not hex. --- 1558,1565 ---- return c - '0'; } ! #if defined(FEAT_TERMRESPONSE) \ ! || (defined(FEAT_GUI_GTK) && defined(FEAT_WINDOWS)) || defined(PROTO) /* * Convert two hex characters to a byte. * Return -1 if one of the characters is not hex. *** ../vim61.144/src/gui_gtk_x11.c Sat May 4 22:23:07 2002 --- src/gui_gtk_x11.c Thu Jul 18 21:20:54 2002 *************** *** 1400,1408 **** int redo_dirs = FALSE; int i; int n; ! char *start; ! char *stop; ! char *copy; int nfiles; int url = FALSE; GdkModifierType current_modifiers; --- 1400,1408 ---- int redo_dirs = FALSE; int i; int n; ! char_u *start; ! char_u *copy; ! char_u *names = data->data; int nfiles; int url = FALSE; GdkModifierType current_modifiers; *************** *** 1415,1495 **** /* guard against trash */ if (data->length <= 0 || data->format != 8 ! || ((char *)data->data)[data->length] != '\0') { gtk_drag_finish(context, FALSE, FALSE, time); return; } ! /* Count how many items there may be and normalize delimiters. */ ! n = 1; ! copy = strdup((char *)data->data); for (i = 0; i < data->length; ++i) { ! if (copy[i] == '\n') ! ++n; ! else if (copy[i] == '\r') { ! copy[i] = '\n'; ! ++n; } } ! fnames = (char_u **)alloc((n + 1) * sizeof(char_u *)); start = copy; ! stop = copy; ! nfiles = 0; ! for (i = 0; i < n; ++i) { ! stop = strchr(start, '\n'); ! if (stop != NULL) ! *stop = '\0'; ! ! if (strlen(start) == 0) ! continue; ! ! if (strncmp(start, "http://", 7) == 0 ! || strncmp(start, "ftp://", 6) == 0) ! { ! url = TRUE; ! } ! else if (strncmp(start, "file:", 5) != 0) ! { ! int j; ! ! free(copy); ! for (j = 0; j < nfiles; ++j) ! free(fnames[j]); ! gtk_drag_finish(context, FALSE, FALSE, time); ! ! return; ! } ! ! if (strncmp(start, "file://localhost", 16) == 0) ! { ! fnames[nfiles] = (char_u *)strdup(start + 16); ! ++nfiles; ! } else { ! if (url == FALSE) { start += 5; while (start[0] == '/' && start[1] == '/') ++start; } - fnames[nfiles] = (char_u *)strdup(start); - ++nfiles; } ! start = stop + 2; } - free(copy); /* accept */ gtk_drag_finish(context, TRUE, FALSE, time); ! /* Real files (i.e. not http and not ftp) */ if (url == FALSE) { if (nfiles == 1) --- 1415,1485 ---- /* guard against trash */ if (data->length <= 0 || data->format != 8 ! || names[data->length] != '\0') { gtk_drag_finish(context, FALSE, FALSE, time); return; } ! /* Count how many items there may be and separate them with a NUL. ! * Apparently the items are separated with \r\n. This is not documented, ! * thus be careful not to go past the end. Also allow separation with NUL ! * characters. */ ! nfiles = 0; ! copy = alloc((unsigned)(data->length + 1)); ! start = copy; for (i = 0; i < data->length; ++i) { ! if (names[i] == NUL || names[i] == '\n' || names[i] == '\r') ! { ! if (start > copy && start[-1] != NUL) ! { ! ++nfiles; ! *start++ = NUL; ! } ! } ! else if (names[i] == '%' && i + 2 < data->length ! && hexhex2nr(names + i + 1) > 0) { ! *start++ = hexhex2nr(names + i + 1); ! i += 2; } + else + *start++ = names[i]; + } + if (start > copy && start[-1] != NUL) + { + *start = NUL; /* last item didn't have \r or \n */ + ++nfiles; } ! fnames = (char_u **)alloc((unsigned)(nfiles * sizeof(char_u *))); + url = FALSE; /* Set when a non-file URL was found. */ start = copy; ! for (n = 0; n < nfiles; ++n) { ! if (STRNCMP(start, "file://localhost", 16) == 0) ! start += 16; else { ! if (STRNCMP(start, "file:", 5) != 0) ! url = TRUE; ! else { start += 5; while (start[0] == '/' && start[1] == '/') ++start; } } ! fnames[n] = vim_strsave(start); ! start += STRLEN(start) + 1; } /* accept */ gtk_drag_finish(context, TRUE, FALSE, time); ! /* Special handling when all items are real files. */ if (url == FALSE) { if (nfiles == 1) *************** *** 1499,1505 **** /* Handle dropping a directory on Vim. */ if (mch_chdir((char *)fnames[0]) == 0) { ! free(fnames[0]); fnames[0] = NULL; redo_dirs = TRUE; } --- 1489,1495 ---- /* Handle dropping a directory on Vim. */ if (mch_chdir((char *)fnames[0]) == 0) { ! vim_free(fnames[0]); fnames[0] = NULL; redo_dirs = TRUE; } *************** *** 1543,1548 **** --- 1533,1539 ---- } } } + vim_free(copy); /* Handle the drop, :edit or :split to get to the file */ handle_drop(nfiles, fnames, current_modifiers & GDK_CONTROL_MASK); *************** *** 1552,1560 **** /* Update the screen display */ update_screen(NOT_VALID); ! #ifdef FEAT_MENU gui_update_menus(0); ! #endif setcursor(); out_flush(); gui_update_cursor(FALSE, FALSE); --- 1543,1551 ---- /* Update the screen display */ update_screen(NOT_VALID); ! # ifdef FEAT_MENU gui_update_menus(0); ! # endif setcursor(); out_flush(); gui_update_cursor(FALSE, FALSE); *** ../vim61.144/src/version.c Sat Aug 3 14:05:15 2002 --- src/version.c Sat Aug 3 14:09:44 2002 *************** *** 608,609 **** --- 608,611 ---- { /* Add new patch number below this line */ + /**/ + 145, /**/ -- From "know your smileys": :'-D Laughing so much that they're crying /// Bram Moolenaar -- Bram@moolenaar.net -- http://www.moolenaar.net \\\ /// Creator of Vim -- http://vim.sf.net -- ftp://ftp.vim.org/pub/vim \\\ \\\ Project leader for A-A-P -- http://www.a-a-p.org /// \\\ Lord Of The Rings helps Uganda - http://iccf-holland.org/lotr.html ///