Loading ...
Sorry, an error occurred while loading the content.

Patch 6.2.295

Expand Messages
  • Bram Moolenaar
    Patch 6.2.295 Problem: When in debug mode, receiving a message from a remote client causes a crash. Evaluating an expression causes Vim to wait for cont
    Message 1 of 1 , Feb 29, 2004
    • 0 Attachment
      Patch 6.2.295
      Problem: When in debug mode, receiving a message from a remote client
      causes a crash. Evaluating an expression causes Vim to wait for
      "cont" to be typed, without a prompt. (Hari Krishna Dara)
      Solution: Disable debugging when evaluating an expression for a client.
      (Michael Geddes) Don't try reading into the typehead buffer when
      it may have been filled in another way.
      Files: src/ex_getln.c, src/getchar.c, src/if_xcmdsrv.c, src/main.c,
      src/misc1.c, src/proto/getchar.pro, src/proto/main.pro,
      src/proto/os_unix.pro, src/proto/ui.pro, src/structs.h,
      src/os_unix.c, src/ui.c


      *** ../vim-6.2.294/src/ex_getln.c Tue Feb 24 15:23:58 2004
      --- src/ex_getln.c Sat Feb 28 16:33:29 2004
      ***************
      *** 1834,1840 ****
      p = (char_u *)line_ga.ga_data + line_ga.ga_len;

      /* Get one character (inchar gets a third of maxlen characters!) */
      ! len = inchar(p + off, 3, -1L);
      if (len < 0)
      continue; /* end of input script reached */
      /* for a special character, we need at least three characters */
      --- 1834,1840 ----
      p = (char_u *)line_ga.ga_data + line_ga.ga_len;

      /* Get one character (inchar gets a third of maxlen characters!) */
      ! len = inchar(p + off, 3, -1L, 0);
      if (len < 0)
      continue; /* end of input script reached */
      /* for a special character, we need at least three characters */
      *** ../vim-6.2.294/src/getchar.c Tue Feb 17 21:46:46 2004
      --- src/getchar.c Sun Feb 29 14:24:23 2004
      ***************
      *** 433,439 ****
      * of an escape sequence.
      * In an xterm we get one char at a time and we have to get them all.
      */
      ! while (inchar(typebuf.tb_buf, typebuf.tb_buflen - 1, 10L) != 0)
      ;
      typebuf.tb_off = MAXMAPLEN;
      typebuf.tb_len = 0;
      --- 433,440 ----
      * of an escape sequence.
      * In an xterm we get one char at a time and we have to get them all.
      */
      ! while (inchar(typebuf.tb_buf, typebuf.tb_buflen - 1, 10L,
      ! typebuf.tb_change_cnt) != 0)
      ;
      typebuf.tb_off = MAXMAPLEN;
      typebuf.tb_len = 0;
      ***************
      *** 860,866 ****

      /*
      * Initialize typebuf.tb_buf to point to typebuf_init.
      ! * Alloc() cannot be used here: In out-of-memory situations it would
      * be impossible to type anything.
      */
      static void
      --- 861,867 ----

      /*
      * Initialize typebuf.tb_buf to point to typebuf_init.
      ! * alloc() cannot be used here: In out-of-memory situations it would
      * be impossible to type anything.
      */
      static void
      ***************
      *** 873,878 ****
      --- 874,880 ----
      typebuf.tb_buflen = TYPELEN_INIT;
      typebuf.tb_len = 0;
      typebuf.tb_off = 0;
      + typebuf.tb_change_cnt = 1;
      }
      }

      ***************
      *** 910,915 ****
      --- 912,919 ----
      int nrm;

      init_typebuf();
      + if (++typebuf.tb_change_cnt == 0)
      + typebuf.tb_change_cnt = 1;

      addlen = (int)STRLEN(str);
      /*
      ***************
      *** 1013,1018 ****
      --- 1017,1041 ----
      }

      /*
      + * Return TRUE if the typeahead buffer was changed (while waiting for a
      + * character to arrive). Happens when a message was received from a client.
      + * But check in a more generic way to avoid trouble: When "typebuf.tb_buf"
      + * changed it was reallocated and the old pointer can no longer be used.
      + * Or "typebuf.tb_off" may have been changed and we would overwrite characters
      + * that was just added.
      + */
      + int
      + typebuf_changed(tb_change_cnt)
      + int tb_change_cnt; /* old value of typebuf.tb_change_cnt */
      + {
      + return (tb_change_cnt != 0 && (typebuf.tb_change_cnt != tb_change_cnt
      + #ifdef FEAT_CLIENTSERVER
      + || received_from_client
      + #endif
      + ));
      + }
      +
      + /*
      * Return TRUE if there are no characters in the typeahead buffer that have
      * not been typed (result from a mapping or come from ":normal").
      */
      ***************
      *** 1106,1111 ****
      --- 1129,1136 ----
      * typeahead buffer. */
      received_from_client = FALSE;
      #endif
      + if (++typebuf.tb_change_cnt == 0)
      + typebuf.tb_change_cnt = 1;
      }

      /*
      ***************
      *** 1185,1190 ****
      --- 1210,1217 ----
      typebuf.tb_maplen = 0;
      typebuf.tb_silent = 0;
      typebuf.tb_no_abbr_cnt = 0;
      + if (++typebuf.tb_change_cnt == 0)
      + typebuf.tb_change_cnt = 1;
      return OK;
      }

      ***************
      *** 1769,1777 ****
      if (got_int)
      {
      /* flush all input */
      ! c = inchar(typebuf.tb_buf, typebuf.tb_buflen - 1, 0L);
      /*
      ! * If inchar returns TRUE (script file was active) or we
      * are inside a mapping, get out of insert mode.
      * Otherwise we behave like having gotten a CTRL-C.
      * As a result typing CTRL-C in insert mode will
      --- 1796,1805 ----
      if (got_int)
      {
      /* flush all input */
      ! c = inchar(typebuf.tb_buf, typebuf.tb_buflen - 1, 0L,
      ! typebuf.tb_change_cnt);
      /*
      ! * If inchar() returns TRUE (script file was active) or we
      * are inside a mapping, get out of insert mode.
      * Otherwise we behave like having gotten a CTRL-C.
      * As a result typing CTRL-C in insert mode will
      ***************
      *** 2235,2242 ****
      && (State & INSERT)
      && (p_timeout || (keylen == KL_PART_KEY && p_ttimeout))
      && (c = inchar(typebuf.tb_buf + typebuf.tb_off
      ! + typebuf.tb_len, 3, 25L))
      ! == 0)
      {
      colnr_T col = 0, vcol;
      char_u *ptr;
      --- 2263,2270 ----
      && (State & INSERT)
      && (p_timeout || (keylen == KL_PART_KEY && p_ttimeout))
      && (c = inchar(typebuf.tb_buf + typebuf.tb_off
      ! + typebuf.tb_len, 3, 25L,
      ! typebuf.tb_change_cnt)) == 0)
      {
      colnr_T col = 0, vcol;
      char_u *ptr;
      ***************
      *** 2466,2472 ****
      ? -1L
      : ((keylen == KL_PART_KEY && p_ttm >= 0)
      ? p_ttm
      ! : p_tm)));

      #ifdef FEAT_CMDL_INFO
      if (i != 0)
      --- 2494,2500 ----
      ? -1L
      : ((keylen == KL_PART_KEY && p_ttm >= 0)
      ? p_ttm
      ! : p_tm)), typebuf.tb_change_cnt);

      #ifdef FEAT_CMDL_INFO
      if (i != 0)
      ***************
      *** 2549,2557 ****
      * 1. a scriptfile
      * 2. the keyboard
      *
      ! * As much characters as we can get (upto 'maxlen') are put in buf and
      * NUL terminated (buffer length must be 'maxlen' + 1).
      ! * Minimum for 'maxlen' is 3!!!!
      *
      * If we got an interrupt all input is read until none is available.
      *
      --- 2577,2590 ----
      * 1. a scriptfile
      * 2. the keyboard
      *
      ! * As much characters as we can get (upto 'maxlen') are put in "buf" and
      * NUL terminated (buffer length must be 'maxlen' + 1).
      ! * Minimum for "maxlen" is 3!!!!
      ! *
      ! * "tb_change_cnt" is the value of typebuf.tb_change_cnt if "buf" points into
      ! * it. When typebuf.tb_change_cnt changes (e.g., when a message is received
      ! * from a remote client) "buf" can no longer be used. "tb_change_cnt" is 0
      ! * otherwise.
      *
      * If we got an interrupt all input is read until none is available.
      *
      ***************
      *** 2562,2573 ****
      * Return the number of obtained characters.
      * Return -1 when end of input script reached.
      */
      -
      int
      ! inchar(buf, maxlen, wait_time)
      char_u *buf;
      int maxlen;
      long wait_time; /* milli seconds */
      {
      int len = 0; /* init for GCC */
      int retesc = FALSE; /* return ESC with gotint */
      --- 2595,2606 ----
      * Return the number of obtained characters.
      * Return -1 when end of input script reached.
      */
      int
      ! inchar(buf, maxlen, wait_time, tb_change_cnt)
      char_u *buf;
      int maxlen;
      long wait_time; /* milli seconds */
      + int tb_change_cnt;
      {
      int len = 0; /* init for GCC */
      int retesc = FALSE; /* return ESC with gotint */
      ***************
      *** 2648,2654 ****

      for (;;)
      {
      ! len = ui_inchar(dum, DUM_LEN, 0L);
      if (len == 0 || (len == 1 && dum[0] == 3))
      break;
      }
      --- 2681,2687 ----

      for (;;)
      {
      ! len = ui_inchar(dum, DUM_LEN, 0L, 0);
      if (len == 0 || (len == 1 && dum[0] == 3))
      break;
      }
      ***************
      *** 2665,2672 ****
      * Fill up to a third of the buffer, because each character may be
      * tripled below.
      */
      ! len = ui_inchar(buf, maxlen / 3, wait_time);
      }

      return fix_input_buffer(buf, len, script_char >= 0);
      }
      --- 2698,2708 ----
      * Fill up to a third of the buffer, because each character may be
      * tripled below.
      */
      ! len = ui_inchar(buf, maxlen / 3, wait_time, tb_change_cnt);
      }
      +
      + if (typebuf_changed(tb_change_cnt))
      + return 0;

      return fix_input_buffer(buf, len, script_char >= 0);
      }
      *** ../vim-6.2.294/src/if_xcmdsrv.c Thu Jul 24 21:52:31 2003
      --- src/if_xcmdsrv.c Fri Feb 27 17:33:19 2004
      ***************
      *** 388,396 ****
      {
      char_u *ret;

      ! ++emsg_skip;
      ! ret = eval_to_string(cmd, NULL);
      ! --emsg_skip;
      if (result != NULL)
      {
      if (ret == NULL)
      --- 388,394 ----
      {
      char_u *ret;

      ! ret = eval_client_expr_to_string(cmd);
      if (result != NULL)
      {
      if (ret == NULL)
      ***************
      *** 1238,1248 ****
      if (asKeys)
      server_to_input_buf(script);
      else
      ! {
      ! ++emsg_skip;
      ! res = eval_to_string(script, NULL);
      ! --emsg_skip;
      ! }
      }
      if (resWindow != None)
      {
      --- 1236,1242 ----
      if (asKeys)
      server_to_input_buf(script);
      else
      ! res = eval_client_expr_to_string(script);
      }
      if (resWindow != None)
      {
      *** ../vim-6.2.294/src/main.c Thu Feb 19 14:43:37 2004
      --- src/main.c Fri Feb 27 17:29:56 2004
      ***************
      *** 3094,3099 ****
      --- 3102,3134 ----
      /* Let input_available() know we inserted text in the typeahead buffer. */
      received_from_client = TRUE;
      }
      +
      + /*
      + * Evaluate an expression that the client sent to a string.
      + * Handles disabling error messages and disables debugging, otherwise Vim
      + * hangs, waiting for "cont" to be typed.
      + */
      + char_u *
      + eval_client_expr_to_string(expr)
      + char_u *expr;
      + {
      + char_u *res;
      + int save_dbl = debug_break_level;
      + int save_ro = redir_off;
      +
      + debug_break_level = -1;
      + redir_off = 0;
      + ++emsg_skip;
      +
      + res = eval_to_string(expr, NULL);
      +
      + debug_break_level = save_dbl;
      + redir_off = save_ro;
      + --emsg_skip;
      +
      + return res;
      + }
      +

      /*
      * Make our basic server name: use the specified "arg" if given, otherwise use
      *** ../vim-6.2.294/src/misc1.c Sun Feb 15 13:44:45 2004
      --- src/misc1.c Sat Feb 28 16:38:02 2004
      ***************
      *** 2771,2777 ****
      * insert a key code into (max 5 chars plus NUL). And
      * fix_input_buffer() can triple the number of bytes. */
      n = ui_inchar(buf + len, (CBUFLEN - 6 - len) / 3,
      ! len == 0 ? -1L : 100L);
      if (n > 0)
      {
      /* Replace zero and CSI by a special key code. */
      --- 2783,2789 ----
      * insert a key code into (max 5 chars plus NUL). And
      * fix_input_buffer() can triple the number of bytes. */
      n = ui_inchar(buf + len, (CBUFLEN - 6 - len) / 3,
      ! len == 0 ? -1L : 100L, 0);
      if (n > 0)
      {
      /* Replace zero and CSI by a special key code. */
      *** ../vim-6.2.294/src/proto/getchar.pro Sun Jun 1 12:26:10 2003
      --- src/proto/getchar.pro Sat Feb 28 16:40:34 2004
      ***************
      *** 21,26 ****
      --- 21,27 ----
      int start_redo_ins __ARGS((void));
      void stop_redo_ins __ARGS((void));
      int ins_typebuf __ARGS((char_u *str, int noremap, int offset, int nottyped, int silent));
      + int typebuf_changed __ARGS((int tb_change_cnt));
      int typebuf_typed __ARGS((void));
      int typebuf_maplen __ARGS((void));
      void del_typebuf __ARGS((int len, int offset));
      ***************
      *** 39,45 ****
      int vpeekc_any __ARGS((void));
      int char_avail __ARGS((void));
      void vungetc __ARGS((int c));
      ! int inchar __ARGS((char_u *buf, int maxlen, long wait_time));
      int fix_input_buffer __ARGS((char_u *buf, int len, int script));
      int input_available __ARGS((void));
      int do_map __ARGS((int maptype, char_u *arg, int mode, int abbrev));
      --- 40,46 ----
      int vpeekc_any __ARGS((void));
      int char_avail __ARGS((void));
      void vungetc __ARGS((int c));
      ! int inchar __ARGS((char_u *buf, int maxlen, long wait_time, int tb_change_cnt));
      int fix_input_buffer __ARGS((char_u *buf, int len, int script));
      int input_available __ARGS((void));
      int do_map __ARGS((int maptype, char_u *arg, int mode, int abbrev));
      *** ../vim-6.2.294/src/proto/main.pro Sun Jun 1 12:26:13 2003
      --- src/proto/main.pro Sat Feb 28 16:40:40 2004
      ***************
      *** 8,13 ****
      --- 8,14 ----
      void time_pop __ARGS((void *tp));
      void time_msg __ARGS((char *msg, void *tv_start));
      void server_to_input_buf __ARGS((char_u *str));
      + char_u *eval_client_expr_to_string __ARGS((char_u *expr));
      int toF_TyA __ARGS((int c));
      int fkmap __ARGS((int c));
      void conv_to_pvim __ARGS((void));
      *** ../vim-6.2.294/src/proto/os_unix.pro Sun Jun 1 12:26:18 2003
      --- src/proto/os_unix.pro Sat Feb 28 16:40:46 2004
      ***************
      *** 1,6 ****
      /* os_unix.c */
      void mch_write __ARGS((char_u *s, int len));
      ! int mch_inchar __ARGS((char_u *buf, int maxlen, long wtime));
      int mch_char_avail __ARGS((void));
      long_u mch_total_mem __ARGS((int special));
      void mch_delay __ARGS((long msec, int ignoreinput));
      --- 1,6 ----
      /* os_unix.c */
      void mch_write __ARGS((char_u *s, int len));
      ! int mch_inchar __ARGS((char_u *buf, int maxlen, long wtime, int tb_change_cnt));
      int mch_char_avail __ARGS((void));
      long_u mch_total_mem __ARGS((int special));
      void mch_delay __ARGS((long msec, int ignoreinput));
      *** ../vim-6.2.294/src/proto/ui.pro Sun Jun 1 12:26:21 2003
      --- src/proto/ui.pro Sat Feb 28 16:40:50 2004
      ***************
      *** 1,7 ****
      /* ui.c */
      void ui_write __ARGS((char_u *s, int len));
      void ui_inchar_undo __ARGS((char_u *s, int len));
      ! int ui_inchar __ARGS((char_u *buf, int maxlen, long wtime));
      int ui_char_avail __ARGS((void));
      void ui_delay __ARGS((long msec, int ignoreinput));
      void ui_suspend __ARGS((void));
      --- 1,7 ----
      /* ui.c */
      void ui_write __ARGS((char_u *s, int len));
      void ui_inchar_undo __ARGS((char_u *s, int len));
      ! int ui_inchar __ARGS((char_u *buf, int maxlen, long wtime, int tb_change_cnt));
      int ui_char_avail __ARGS((void));
      void ui_delay __ARGS((long msec, int ignoreinput));
      void ui_suspend __ARGS((void));
      *** ../vim-6.2.294/src/structs.h Thu Feb 5 12:09:25 2004
      --- src/structs.h Sun Feb 29 14:25:58 2004
      ***************
      *** 776,785 ****
      char_u *tb_noremap; /* mapping flags for characters in tb_buf[] */
      int tb_buflen; /* size of tb_buf[] */
      int tb_off; /* current position in tb_buf[] */
      ! int tb_len; /* number of valid chars in tb_buf[] */
      ! int tb_maplen; /* nr of mapped characters in tb_buf[] */
      ! int tb_silent; /* nr of silently mapped chars in tb_buf[] */
      ! int tb_no_abbr_cnt; /* nr of chars without abbrev. in tb_buf[] */
      } typebuf_T;

      /* Struct to hold the saved typeahead for save_typeahead(). */
      --- 779,789 ----
      char_u *tb_noremap; /* mapping flags for characters in tb_buf[] */
      int tb_buflen; /* size of tb_buf[] */
      int tb_off; /* current position in tb_buf[] */
      ! int tb_len; /* number of valid bytes in tb_buf[] */
      ! int tb_maplen; /* nr of mapped bytes in tb_buf[] */
      ! int tb_silent; /* nr of silently mapped bytes in tb_buf[] */
      ! int tb_no_abbr_cnt; /* nr of bytes without abbrev. in tb_buf[] */
      ! int tb_change_cnt; /* nr of time tb_buf was changed; never zero */
      } typebuf_T;

      /* Struct to hold the saved typeahead for save_typeahead(). */
      *** ../vim-6.2.294/src/os_unix.c Sun Feb 1 20:06:29 2004
      --- src/os_unix.c Sat Feb 28 16:38:11 2004
      ***************
      *** 309,318 ****
      * If wtime == -1 wait forever for characters.
      */
      int
      ! mch_inchar(buf, maxlen, wtime)
      char_u *buf;
      int maxlen;
      long wtime; /* don't use "time", MIPS cannot handle it */
      {
      int len;
      #ifdef FEAT_AUTOCMD
      --- 309,319 ----
      * If wtime == -1 wait forever for characters.
      */
      int
      ! mch_inchar(buf, maxlen, wtime, tb_change_cnt)
      char_u *buf;
      int maxlen;
      long wtime; /* don't use "time", MIPS cannot handle it */
      + int tb_change_cnt;
      {
      int len;
      #ifdef FEAT_AUTOCMD
      ***************
      *** 383,392 ****
      if (do_resize) /* interrupted by SIGWINCH signal */
      continue;

      ! #ifdef FEAT_CLIENTSERVER
      ! if (received_from_client)
      ! return 0; /* Input was put directly in typeahead buffer */
      ! #endif

      /*
      * For some terminals we only get one character at a time.
      --- 384,392 ----
      if (do_resize) /* interrupted by SIGWINCH signal */
      continue;

      ! /* If input was put directly in typeahead buffer bail out here. */
      ! if (typebuf_changed(tb_change_cnt))
      ! return 0;

      /*
      * For some terminals we only get one character at a time.
      ***************
      *** 3609,3615 ****
      len = 0;
      if (!(options & SHELL_EXPAND)
      && (ta_len > 0
      ! || (len = ui_inchar(ta_buf, BUFLEN, 10L)) > 0))
      {
      /*
      * For pipes:
      --- 3609,3616 ----
      len = 0;
      if (!(options & SHELL_EXPAND)
      && (ta_len > 0
      ! || (len = ui_inchar(ta_buf, BUFLEN, 10L,
      ! 0)) > 0))
      {
      /*
      * For pipes:
      *** ../vim-6.2.294/src/ui.c Sun Jan 18 20:58:01 2004
      --- src/ui.c Sat Feb 28 16:36:51 2004
      ***************
      *** 105,116 ****
      * If "wtime" == 0 do not wait for characters.
      * If "wtime" == -1 wait forever for characters.
      * If "wtime" > 0 wait "wtime" milliseconds for a character.
      */
      int
      ! ui_inchar(buf, maxlen, wtime)
      char_u *buf;
      int maxlen;
      long wtime; /* don't use "time", MIPS cannot handle it */
      {
      int retval = 0;

      --- 105,122 ----
      * If "wtime" == 0 do not wait for characters.
      * If "wtime" == -1 wait forever for characters.
      * If "wtime" > 0 wait "wtime" milliseconds for a character.
      + *
      + * "tb_change_cnt" is the value of typebuf.tb_change_cnt if "buf" points into
      + * it. When typebuf.tb_change_cnt changes (e.g., when a message is received
      + * from a remote client) "buf" can no longer be used. "tb_change_cnt" is NULL
      + * otherwise.
      */
      int
      ! ui_inchar(buf, maxlen, wtime, tb_change_cnt)
      char_u *buf;
      int maxlen;
      long wtime; /* don't use "time", MIPS cannot handle it */
      + int tb_change_cnt;
      {
      int retval = 0;

      ***************
      *** 143,150 ****
      static int count = 0;

      # ifndef NO_CONSOLE
      ! retval = mch_inchar(buf, maxlen, 10L);
      ! if (retval > 0)
      return retval;
      # endif
      if (wtime == -1 && ++count == 1000)
      --- 149,156 ----
      static int count = 0;

      # ifndef NO_CONSOLE
      ! retval = mch_inchar(buf, maxlen, 10L, tb_change_cnt);
      ! if (retval > 0 || typebuf_changed(tb_change_cnt))
      return retval;
      # endif
      if (wtime == -1 && ++count == 1000)
      ***************
      *** 162,168 ****
      #ifdef FEAT_GUI
      if (gui.in_use)
      {
      ! if (gui_wait_for_chars(wtime))
      retval = read_from_input_buf(buf, (long)maxlen);
      }
      #endif
      --- 168,174 ----
      #ifdef FEAT_GUI
      if (gui.in_use)
      {
      ! if (gui_wait_for_chars(wtime) && !typebuf_changed(tb_change_cnt))
      retval = read_from_input_buf(buf, (long)maxlen);
      }
      #endif
      ***************
      *** 170,176 ****
      # ifdef FEAT_GUI
      else
      # endif
      ! retval = mch_inchar(buf, maxlen, wtime);
      #endif

      ctrl_c_interrupts = TRUE;
      --- 176,182 ----
      # ifdef FEAT_GUI
      else
      # endif
      ! retval = mch_inchar(buf, maxlen, wtime, tb_change_cnt);
      #endif

      ctrl_c_interrupts = TRUE;
      *** ../vim-6.2.294/src/version.c Sat Feb 28 15:30:58 2004
      --- src/version.c Sun Feb 29 14:42:27 2004
      ***************
      *** 639,640 ****
      --- 639,642 ----
      { /* Add new patch number below this line */
      + /**/
      + 295,
      /**/

      --
      Not too long ago, a program was something you watched on TV...

      /// Bram Moolenaar -- Bram@... -- http://www.Moolenaar.net \\\
      /// Sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\
      \\\ Project leader for A-A-P -- http://www.A-A-P.org ///
      \\\ Buy at Amazon and help AIDS victims -- http://ICCF.nl/click1.html ///
    Your message has been successfully submitted and would be delivered to recipients shortly.