Patch 9.0.0045
Problem:    Reading past end of completion with a long line and 'infercase'
            set.
Solution:   Allocate the string if needed.
Files:      src/insexpand.c, src/testdir/test_ins_complete.vim


*** ../vim-9.0.0044/src/insexpand.c     2022-07-01 19:58:27.161837285 +0100
--- src/insexpand.c     2022-07-07 19:41:09.373495044 +0100
***************
*** 524,552 ****
  
  /*
   * Get the completed text by inferring the case of the originally typed text.
   */
      static char_u *
  ins_compl_infercase_gettext(
        char_u  *str,
!       int     actual_len,
!       int     actual_compl_length,
!       int     min_len)
  {
      int               *wca;                   // Wide character array.
      char_u    *p;
      int               i, c;
      int               has_lower = FALSE;
      int               was_letter = FALSE;
  
      IObuff[0] = NUL;
  
      // Allocate wide character array for the completion and fill it.
!     wca = ALLOC_MULT(int, actual_len);
      if (wca == NULL)
        return IObuff;
  
      p = str;
!     for (i = 0; i < actual_len; ++i)
        if (has_mbyte)
            wca[i] = mb_ptr2char_adv(&p);
        else
--- 524,555 ----
  
  /*
   * Get the completed text by inferring the case of the originally typed text.
+  * If the result is in allocated memory "tofree" is set to it.
   */
      static char_u *
  ins_compl_infercase_gettext(
        char_u  *str,
!       int     char_len,
!       int     compl_char_len,
!       int     min_len,
!       char_u  **tofree)
  {
      int               *wca;                   // Wide character array.
      char_u    *p;
      int               i, c;
      int               has_lower = FALSE;
      int               was_letter = FALSE;
+     garray_T  gap;
  
      IObuff[0] = NUL;
  
      // Allocate wide character array for the completion and fill it.
!     wca = ALLOC_MULT(int, char_len);
      if (wca == NULL)
        return IObuff;
  
      p = str;
!     for (i = 0; i < char_len; ++i)
        if (has_mbyte)
            wca[i] = mb_ptr2char_adv(&p);
        else
***************
*** 566,572 ****
            if (MB_ISUPPER(wca[i]))
            {
                // Rule 1 is satisfied.
!               for (i = actual_compl_length; i < actual_len; ++i)
                    wca[i] = MB_TOLOWER(wca[i]);
                break;
            }
--- 569,575 ----
            if (MB_ISUPPER(wca[i]))
            {
                // Rule 1 is satisfied.
!               for (i = compl_char_len; i < char_len; ++i)
                    wca[i] = MB_TOLOWER(wca[i]);
                break;
            }
***************
*** 587,593 ****
            if (was_letter && MB_ISUPPER(c) && MB_ISLOWER(wca[i]))
            {
                // Rule 2 is satisfied.
!               for (i = actual_compl_length; i < actual_len; ++i)
                    wca[i] = MB_TOUPPER(wca[i]);
                break;
            }
--- 590,596 ----
            if (was_letter && MB_ISUPPER(c) && MB_ISLOWER(wca[i]))
            {
                // Rule 2 is satisfied.
!               for (i = compl_char_len; i < char_len; ++i)
                    wca[i] = MB_TOUPPER(wca[i]);
                break;
            }
***************
*** 610,629 ****
      }
  
      // Generate encoding specific output from wide character array.
-     // Multi-byte characters can occupy up to five bytes more than
-     // ASCII characters, and we also need one byte for NUL, so stay
-     // six bytes away from the edge of IObuff.
      p = IObuff;
      i = 0;
!     while (i < actual_len && (p - IObuff + 6) < IOSIZE)
!       if (has_mbyte)
            p += (*mb_char2bytes)(wca[i++], p);
        else
            *(p++) = wca[i++];
!     *p = NUL;
! 
      vim_free(wca);
  
      return IObuff;
  }
  
--- 613,664 ----
      }
  
      // Generate encoding specific output from wide character array.
      p = IObuff;
      i = 0;
!     ga_init2(&gap, 1, 500);
!     while (i < char_len)
!     {
!       if (gap.ga_data != NULL)
!       {
!           if (ga_grow(&gap, 10) == FAIL)
!           {
!               ga_clear(&gap);
!               return (char_u *)"[failed]";
!           }
!           p = (char_u *)gap.ga_data + gap.ga_len;
!           if (has_mbyte)
!               gap.ga_len += (*mb_char2bytes)(wca[i++], p);
!           else
!           {
!               *p = wca[i++];
!               ++gap.ga_len;
!           }
!       }
!       else if ((p - IObuff) + 6 >= IOSIZE)
!       {
!           // Multi-byte characters can occupy up to five bytes more than
!           // ASCII characters, and we also need one byte for NUL, so when
!           // getting to six bytes from the edge of IObuff switch to using a
!           // growarray.  Add the character in the next round.
!           if (ga_grow(&gap, IOSIZE) == FAIL)
!               return (char_u *)"[failed]";
!           STRCPY(gap.ga_data, IObuff);
!           gap.ga_len = STRLEN(IObuff);
!       }
!       else if (has_mbyte)
            p += (*mb_char2bytes)(wca[i++], p);
        else
            *(p++) = wca[i++];
!     }
      vim_free(wca);
  
+     if (gap.ga_data != NULL)
+     {
+       *tofree = gap.ga_data;
+       return gap.ga_data;
+     }
+ 
+     *p = NUL;
      return IObuff;
  }
  
***************
*** 644,653 ****
  {
      char_u    *str = str_arg;
      char_u    *p;
!     int               actual_len;             // Take multi-byte characters
!     int               actual_compl_length;    // into account.
      int               min_len;
      int               flags = 0;
  
      if (p_ic && curbuf->b_p_inf && len > 0)
      {
--- 679,690 ----
  {
      char_u    *str = str_arg;
      char_u    *p;
!     int               char_len;               // count multi-byte characters
!     int               compl_char_len;
      int               min_len;
      int               flags = 0;
+     int               res;
+     char_u    *tofree = NULL;
  
      if (p_ic && curbuf->b_p_inf && len > 0)
      {
***************
*** 657,700 ****
        if (has_mbyte)
        {
            p = str;
!           actual_len = 0;
            while (*p != NUL)
            {
                MB_PTR_ADV(p);
!               ++actual_len;
            }
        }
        else
!           actual_len = len;
  
        // Find actual length of original text.
        if (has_mbyte)
        {
            p = compl_orig_text;
!           actual_compl_length = 0;
            while (*p != NUL)
            {
                MB_PTR_ADV(p);
!               ++actual_compl_length;
            }
        }
        else
!           actual_compl_length = compl_length;
  
!       // "actual_len" may be smaller than "actual_compl_length" when using
        // thesaurus, only use the minimum when comparing.
!       min_len = actual_len < actual_compl_length
!                                          ? actual_len : actual_compl_length;
  
!       str = ins_compl_infercase_gettext(str, actual_len, actual_compl_length,
!                                                               min_len);
      }
      if (cont_s_ipos)
        flags |= CP_CONT_S_IPOS;
      if (icase)
        flags |= CP_ICASE;
  
!     return ins_compl_add(str, len, fname, NULL, NULL, dir, flags, FALSE);
  }
  
  /*
--- 694,738 ----
        if (has_mbyte)
        {
            p = str;
!           char_len = 0;
            while (*p != NUL)
            {
                MB_PTR_ADV(p);
!               ++char_len;
            }
        }
        else
!           char_len = len;
  
        // Find actual length of original text.
        if (has_mbyte)
        {
            p = compl_orig_text;
!           compl_char_len = 0;
            while (*p != NUL)
            {
                MB_PTR_ADV(p);
!               ++compl_char_len;
            }
        }
        else
!           compl_char_len = compl_length;
  
!       // "char_len" may be smaller than "compl_char_len" when using
        // thesaurus, only use the minimum when comparing.
!       min_len = char_len < compl_char_len ? char_len : compl_char_len;
  
!       str = ins_compl_infercase_gettext(str, char_len,
!                                         compl_char_len, min_len, &tofree);
      }
      if (cont_s_ipos)
        flags |= CP_CONT_S_IPOS;
      if (icase)
        flags |= CP_ICASE;
  
!     res = ins_compl_add(str, len, fname, NULL, NULL, dir, flags, FALSE);
!     vim_free(tofree);
!     return res;
  }
  
  /*
*** ../vim-9.0.0044/src/testdir/test_ins_complete.vim   2022-07-02 
16:29:15.031193541 +0100
--- src/testdir/test_ins_complete.vim   2022-07-07 19:36:05.384951624 +0100
***************
*** 2097,2100 ****
--- 2097,2116 ----
    bwipe!
  endfunc
  
+ func Test_infercase_very_long_line()
+   " this was truncating the line when inferring case
+   new
+   let longLine = "blah "->repeat(300)
+   let verylongLine = "blah "->repeat(400)
+   call setline(1, verylongLine)
+   call setline(2, longLine)
+   set ic infercase
+   exe "normal 2Go\<C-X>\<C-L>\<Esc>"
+   call assert_equal(longLine, getline(3))
+ 
+   bwipe!
+   set noic noinfercase
+ endfunc
+ 
+ 
  " vim: shiftwidth=2 sts=2 expandtab
*** ../vim-9.0.0044/src/version.c       2022-07-06 13:31:25.299369947 +0100
--- src/version.c       2022-07-07 19:41:39.669563285 +0100
***************
*** 737,738 ****
--- 737,740 ----
  {   /* Add new patch number below this line */
+ /**/
+     45,
  /**/

-- 
hundred-and-one symptoms of being an internet addict:
77. The phone company asks you to test drive their new PBX system

 /// Bram Moolenaar -- [email protected] -- http://www.Moolenaar.net   \\\
///                                                                      \\\
\\\        sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ ///
 \\\            help me help AIDS victims -- http://ICCF-Holland.org    ///

-- 
-- 
You received this message from the "vim_dev" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php

--- 
You received this message because you are subscribed to the Google Groups 
"vim_dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/vim_dev/20220707184300.EC3071C08DA%40moolenaar.net.

Raspunde prin e-mail lui