diff --git a/SOURCES/0001-patch-8.2.4120-block-insert-goes-over-the-end-of-the.patch b/SOURCES/0001-patch-8.2.4120-block-insert-goes-over-the-end-of-the.patch
new file mode 100644
index 0000000..a248a8a
--- /dev/null
+++ b/SOURCES/0001-patch-8.2.4120-block-insert-goes-over-the-end-of-the.patch
@@ -0,0 +1,94 @@
+diff --git a/src/ops.c b/src/ops.c
+index d8e96ff..88992b6 100644
+--- a/src/ops.c
++++ b/src/ops.c
+@@ -534,22 +534,27 @@ block_insert(
+ 	    if (b_insert)
+ 	    {
+ 		off = (*mb_head_off)(oldp, oldp + offset + spaces);
++		spaces -= off;
++		count -= off;
+ 	    }
+ 	    else
+ 	    {
+-		off = (*mb_off_next)(oldp, oldp + offset);
+-		offset += off;
++		// spaces fill the gap, the character that's at the edge moves
++		// right
++		off = (*mb_head_off)(oldp, oldp + offset);
++		offset -= off;
+ 	    }
+-	    spaces -= off;
+-	    count -= off;
+ 	}
+ 
+-	newp = alloc(STRLEN(oldp) + s_len + count + 1);
++	// Make sure the allocated size matches what is actually copied below.
++	newp = alloc(STRLEN(oldp) + spaces + s_len
++		    + (spaces > 0 && !bdp->is_short ? ts_val - spaces : 0)
++								  + count + 1);
+ 	if (newp == NULL)
+ 	    continue;
+ 
+ 	// copy up to shifted part
+-	mch_memmove(newp, oldp, (size_t)(offset));
++	mch_memmove(newp, oldp, (size_t)offset);
+ 	oldp += offset;
+ 
+ 	// insert pre-padding
+@@ -560,14 +565,21 @@ block_insert(
+ 	mch_memmove(newp + startcol, s, (size_t)s_len);
+ 	offset += s_len;
+ 
+-	if (spaces && !bdp->is_short)
++	if (spaces > 0 && !bdp->is_short)
+ 	{
+-	    // insert post-padding
+-	    vim_memset(newp + offset + spaces, ' ', (size_t)(ts_val - spaces));
+-	    // We're splitting a TAB, don't copy it.
+-	    oldp++;
+-	    // We allowed for that TAB, remember this now
+-	    count++;
++	    if (*oldp == TAB)
++	    {
++		// insert post-padding
++		vim_memset(newp + offset + spaces, ' ',
++						    (size_t)(ts_val - spaces));
++		// we're splitting a TAB, don't copy it
++		oldp++;
++		// We allowed for that TAB, remember this now
++		count++;
++	    }
++	    else
++		// Not a TAB, no extra spaces
++		count = spaces;
+ 	}
+ 
+ 	if (spaces > 0)
+@@ -1574,7 +1586,7 @@ op_insert(oparg_T *oap, long count1)
+ 		oap->start_vcol = t;
+ 	    }
+ 	    else if (oap->op_type == OP_APPEND
+-		      && oap->end.col + oap->end.coladd
++		      && oap->start.col + oap->start.coladd
+ 			>= curbuf->b_op_start_orig.col
+ 					      + curbuf->b_op_start_orig.coladd)
+ 	    {
+diff --git a/src/testdir/test_visual.vim b/src/testdir/test_visual.vim
+index 7c5f973..dc8e376 100644
+--- a/src/testdir/test_visual.vim
++++ b/src/testdir/test_visual.vim
+@@ -967,4 +967,13 @@ func Test_visual_put_in_block()
+   bwipe!
+ endfunc
+ 
++func Test_visual_block_append_invalid_char()
++  " this was going over the end of the line
++  new
++  call setline(1, ['	   let xxx', 'xxxxxˆ', 'xxxxxxxxxxx'])
++  exe "normal 0\<C-V>jjA-\<Esc>"
++  call assert_equal(['	-   let xxx', 'xxxxx   -ˆ', 'xxxxxxxx-xxx'], getline(1, 3))
++  bwipe!
++endfunc
++
+ " vim: shiftwidth=2 sts=2 expandtab
diff --git a/SOURCES/0001-patch-8.2.4151-reading-beyond-the-end-of-a-line.patch b/SOURCES/0001-patch-8.2.4151-reading-beyond-the-end-of-a-line.patch
new file mode 100644
index 0000000..ad10a9a
--- /dev/null
+++ b/SOURCES/0001-patch-8.2.4151-reading-beyond-the-end-of-a-line.patch
@@ -0,0 +1,62 @@
+diff --git a/src/ops.c b/src/ops.c
+index 88992b6..80e0ea1 100644
+--- a/src/ops.c
++++ b/src/ops.c
+@@ -527,24 +527,8 @@ block_insert(
+ 	}
+ 
+ 	if (has_mbyte && spaces > 0)
+-	{
+-	    int off;
+-
+-	    // Avoid starting halfway a multi-byte character.
+-	    if (b_insert)
+-	    {
+-		off = (*mb_head_off)(oldp, oldp + offset + spaces);
+-		spaces -= off;
+-		count -= off;
+-	    }
+-	    else
+-	    {
+-		// spaces fill the gap, the character that's at the edge moves
+-		// right
+-		off = (*mb_head_off)(oldp, oldp + offset);
+-		offset -= off;
+-	    }
+-	}
++	    // avoid copying part of a multi-byte character
++	    offset -= (*mb_head_off)(oldp, oldp + offset);
+ 
+ 	// Make sure the allocated size matches what is actually copied below.
+ 	newp = alloc(STRLEN(oldp) + spaces + s_len
+diff --git a/src/testdir/test_utf8.vim b/src/testdir/test_utf8.vim
+index 5454e43..bedec20 100644
+--- a/src/testdir/test_utf8.vim
++++ b/src/testdir/test_utf8.vim
+@@ -7,7 +7,7 @@ func Test_visual_block_insert()
+   new
+   call setline(1, ["aaa", "あああ", "bbb"])
+   exe ":norm! gg0l\<C-V>jjIx\<Esc>"
+-  call assert_equal(['axaa', 'xあああ', 'bxbb'], getline(1, '$'))
++  call assert_equal(['axaa', ' xあああ', 'bxbb'], getline(1, '$'))
+   bwipeout!
+ endfunc
+ 
+diff --git a/src/testdir/test_visual.vim b/src/testdir/test_visual.vim
+index dc8e376..8de9e3d 100644
+--- a/src/testdir/test_visual.vim
++++ b/src/testdir/test_visual.vim
+@@ -976,4 +976,13 @@ func Test_visual_block_append_invalid_char()
+   bwipe!
+ endfunc
+ 
++func Test_visual_block_insert_round_off()
++  new
++  " The number of characters are tuned to fill a 4096 byte allocated block,
++  " so that valgrind reports going over the end.
++  call setline(1, ['xxxxx', repeat('0', 1350), "\t", repeat('x', 60)])
++  exe "normal gg0\<C-V>GI" .. repeat('0', 1320) .. "\<Esc>"
++  bwipe!
++endfunc
++
+ " vim: shiftwidth=2 sts=2 expandtab
diff --git a/SOURCES/0001-patch-8.2.4154-ml_get-error-when-exchanging-windows-.patch b/SOURCES/0001-patch-8.2.4154-ml_get-error-when-exchanging-windows-.patch
new file mode 100644
index 0000000..29e751a
--- /dev/null
+++ b/SOURCES/0001-patch-8.2.4154-ml_get-error-when-exchanging-windows-.patch
@@ -0,0 +1,43 @@
+diff -up vim82/src/testdir/test_visual.vim.cve0319 vim82/src/testdir/test_visual.vim
+--- vim82/src/testdir/test_visual.vim.cve0319	2022-02-08 13:24:54.170813231 +0100
++++ vim82/src/testdir/test_visual.vim	2022-02-08 13:26:21.313747976 +0100
+@@ -985,4 +985,15 @@ func Test_visual_block_insert_round_off(
+   bwipe!
+ endfunc
+ 
++" this was causing an ml_get error
++func Test_visual_exchange_windows()
++  enew!
++  new
++  call setline(1, ['foo', 'bar'])
++  exe "normal G\<C-V>gg\<C-W>\<C-X>OO\<Esc>"
++  bwipe!
++  bwipe!
++endfunc
++
++
+ " vim: shiftwidth=2 sts=2 expandtab
+diff -up vim82/src/window.c.cve0319 vim82/src/window.c
+--- vim82/src/window.c.cve0319	2022-02-08 13:24:54.137813879 +0100
++++ vim82/src/window.c	2022-02-08 13:24:54.171813211 +0100
+@@ -1697,6 +1697,11 @@ win_exchange(long Prenum)
+ 
+     (void)win_comp_pos();		// recompute window positions
+ 
++    if (wp->w_buffer != curbuf)
++	reset_VIsual_and_resel();
++    else if (VIsual_active)
++	wp->w_cursor = curwin->w_cursor;
++
+     win_enter(wp, TRUE);
+     redraw_all_later(NOT_VALID);
+ }
+@@ -5261,7 +5266,7 @@ frame_remove(frame_T *frp)
+ win_alloc_lines(win_T *wp)
+ {
+     wp->w_lines_valid = 0;
+-    wp->w_lines = ALLOC_CLEAR_MULT(wline_T, Rows );
++    wp->w_lines = ALLOC_CLEAR_MULT(wline_T, Rows);
+     if (wp->w_lines == NULL)
+ 	return FAIL;
+     return OK;
diff --git a/SOURCES/0001-patch-8.2.4214-illegal-memory-access-with-large-tabs.patch b/SOURCES/0001-patch-8.2.4214-illegal-memory-access-with-large-tabs.patch
new file mode 100644
index 0000000..33db8e5
--- /dev/null
+++ b/SOURCES/0001-patch-8.2.4214-illegal-memory-access-with-large-tabs.patch
@@ -0,0 +1,49 @@
+From 85b6747abc15a7a81086db31289cf1b8b17e6cb1 Mon Sep 17 00:00:00 2001
+From: Bram Moolenaar <Bram@vim.org>
+Date: Tue, 25 Jan 2022 11:55:02 +0000
+Subject: [PATCH] patch 8.2.4214: illegal memory access with large 'tabstop' in
+ Ex mode
+
+Problem:    Illegal memory access with large 'tabstop' in Ex mode.
+Solution:   Allocate enough memory.
+---
+ src/ex_getln.c               |  2 +-
+ src/testdir/test_ex_mode.vim | 10 ++++++++++
+ src/version.c                |  2 ++
+ 3 files changed, 13 insertions(+), 1 deletion(-)
+
+diff --git a/src/ex_getln.c b/src/ex_getln.c
+index 5dc43d845..097b97eeb 100644
+--- a/src/ex_getln.c
++++ b/src/ex_getln.c
+@@ -1513,7 +1513,7 @@ init_ccline(int firstc, int indent)
+     ccline.cmdindent = (firstc > 0 ? indent : 0);
+ 
+     // alloc initial ccline.cmdbuff
+-    alloc_cmdbuff(exmode_active ? 250 : indent + 1);
++    alloc_cmdbuff(indent + 50);
+     if (ccline.cmdbuff == NULL)
+ 	return FAIL;
+     ccline.cmdlen = ccline.cmdpos = 0;
+diff --git a/src/testdir/test_ex_mode.vim b/src/testdir/test_ex_mode.vim
+index 7031115fc..2642a16d2 100644
+--- a/src/testdir/test_ex_mode.vim
++++ b/src/testdir/test_ex_mode.vim
+@@ -241,4 +241,14 @@ func Test_ex_mode_count_overflow()
+   call delete('Xexmodescript')
+ endfunc
+ 
++func Test_ex_mode_large_indent()
++  new
++  set ts=500 ai
++  call setline(1, "\t")
++  exe "normal gQi\<CR>."
++  set ts=8 noai
++  bwipe!
++endfunc
++
++
+ " vim: shiftwidth=2 sts=2 expandtab
+-- 
+2.34.1
+
diff --git a/SOURCES/0001-patch-8.2.4215-illegal-memory-access-when-copying-li.patch b/SOURCES/0001-patch-8.2.4215-illegal-memory-access-when-copying-li.patch
new file mode 100644
index 0000000..27d8404
--- /dev/null
+++ b/SOURCES/0001-patch-8.2.4215-illegal-memory-access-when-copying-li.patch
@@ -0,0 +1,51 @@
+From dc5490e2cbc8c16022a23b449b48c1bd0083f366 Mon Sep 17 00:00:00 2001
+From: Bram Moolenaar <Bram@vim.org>
+Date: Tue, 25 Jan 2022 13:52:53 +0000
+Subject: [PATCH] patch 8.2.4215: illegal memory access when copying lines in
+ Visual mode
+
+Problem:    Illegal memory access when copying lines in Visual mode.
+Solution:   Adjust the Visual position after copying lines.
+---
+ src/ex_cmds.c               |  2 ++
+ src/testdir/test_visual.vim | 11 +++++++++++
+ src/version.c               |  2 ++
+ 3 files changed, 15 insertions(+)
+
+diff --git a/src/ex_cmds.c b/src/ex_cmds.c
+index 95209985e..f5d93e664 100644
+--- a/src/ex_cmds.c
++++ b/src/ex_cmds.c
+@@ -866,6 +866,8 @@ ex_copy(linenr_T line1, linenr_T line2, linenr_T n)
+     }
+ 
+     appended_lines_mark(n, count);
++    if (VIsual_active)
++	check_pos(curbuf, &VIsual);
+ 
+     msgmore((long)count);
+ }
+diff --git a/src/testdir/test_visual.vim b/src/testdir/test_visual.vim
+index 72f5388b9..9b322fd21 100644
+--- a/src/testdir/test_visual.vim
++++ b/src/testdir/test_visual.vim
+@@ -1328,5 +1328,16 @@ func Test_visual_exchange_windows()
+   bwipe!
+ endfunc
+ 
++" this was leaving the end of the Visual area beyond the end of a line
++func Test_visual_ex_copy_line()
++  new
++  call setline(1, ["aaa", "bbbbbbbbbxbb"])
++  /x
++  exe "normal ggvjfxO"
++  t0
++  normal gNU
++  bwipe!
++endfunc
++
+ 
+ " vim: shiftwidth=2 sts=2 expandtab
+-- 
+2.34.1
+
diff --git a/SOURCES/0001-patch-8.2.4217-illegal-memory-access-when-undo-makes.patch b/SOURCES/0001-patch-8.2.4217-illegal-memory-access-when-undo-makes.patch
new file mode 100644
index 0000000..adf946c
--- /dev/null
+++ b/SOURCES/0001-patch-8.2.4217-illegal-memory-access-when-undo-makes.patch
@@ -0,0 +1,55 @@
+From 8d02ce1ed75d008c34a5c9aaa51b67cbb9d33baa Mon Sep 17 00:00:00 2001
+From: Bram Moolenaar <Bram@vim.org>
+Date: Tue, 25 Jan 2022 18:24:00 +0000
+Subject: [PATCH] patch 8.2.4217: illegal memory access when undo makes Visual
+ area invalid
+
+Problem:    Illegal memory access when undo makes Visual area invalid.
+Solution:   Correct the Visual area after undo.
+---
+ src/testdir/test_visual.vim | 15 +++++++++++++++
+ src/undo.c                  |  2 ++
+ src/version.c               |  2 ++
+ 3 files changed, 19 insertions(+)
+
+diff --git a/src/testdir/test_visual.vim b/src/testdir/test_visual.vim
+index 9b322fd21..b2beda08d 100644
+--- a/src/testdir/test_visual.vim
++++ b/src/testdir/test_visual.vim
+@@ -1339,5 +1339,20 @@ func Test_visual_ex_copy_line()
+   bwipe!
+ endfunc
+ 
++" This was leaving the end of the Visual area beyond the end of a line.
++" Set 'undolevels' to start a new undo block.
++func Test_visual_undo_deletes_last_line()
++  new
++  call setline(1, ["aaa", "ccc", "dyd"])
++  set undolevels=100
++  exe "normal obbbbbbbbbxbb\<Esc>"
++  set undolevels=100
++  /y
++  exe "normal ggvjfxO"
++  undo
++  normal gNU
++  bwipe!
++endfunc
++
+ 
+ " vim: shiftwidth=2 sts=2 expandtab
+diff --git a/src/undo.c b/src/undo.c
+index 4d186d453..636144aef 100644
+--- a/src/undo.c
++++ b/src/undo.c
+@@ -3029,6 +3029,8 @@ u_undo_end(
+ 	}
+     }
+ #endif
++    if (VIsual_active)
++	check_pos(curbuf, &VIsual);
+ 
+     smsg_attr_keep(0, _("%ld %s; %s #%ld  %s"),
+ 	    u_oldcount < 0 ? -u_oldcount : u_oldcount,
+-- 
+2.34.1
+
diff --git a/SOURCES/0001-patch-8.2.4218-illegal-memory-access-with-bracketed-.patch b/SOURCES/0001-patch-8.2.4218-illegal-memory-access-with-bracketed-.patch
new file mode 100644
index 0000000..95afeff
--- /dev/null
+++ b/SOURCES/0001-patch-8.2.4218-illegal-memory-access-with-bracketed-.patch
@@ -0,0 +1,45 @@
+From 806d037671e133bd28a7864248763f643967973a Mon Sep 17 00:00:00 2001
+From: Bram Moolenaar <Bram@vim.org>
+Date: Tue, 25 Jan 2022 20:45:16 +0000
+Subject: [PATCH] patch 8.2.4218: illegal memory access with bracketed paste in
+ Ex mode
+
+Problem:    Illegal memory access with bracketed paste in Ex mode.
+Solution:   Reserve space for the trailing NUL.
+---
+ src/edit.c                 | 3 ++-
+ src/testdir/test_paste.vim | 3 +++
+ src/version.c              | 2 ++
+ 3 files changed, 7 insertions(+), 1 deletion(-)
+
+diff --git a/src/edit.c b/src/edit.c
+index ee3caf0da..2b5301100 100644
+--- a/src/edit.c
++++ b/src/edit.c
+@@ -4452,7 +4452,8 @@ bracketed_paste(paste_mode_T mode, int drop, garray_T *gap)
+ 		    break;
+ 
+ 		case PASTE_EX:
+-		    if (gap != NULL && ga_grow(gap, idx) == OK)
++		    // add one for the NUL that is going to be appended
++		    if (gap != NULL && ga_grow(gap, idx + 1) == OK)
+ 		    {
+ 			mch_memmove((char *)gap->ga_data + gap->ga_len,
+ 							     buf, (size_t)idx);
+diff --git a/src/testdir/test_paste.vim b/src/testdir/test_paste.vim
+index c94fe7c35..5b8d8a0e3 100644
+--- a/src/testdir/test_paste.vim
++++ b/src/testdir/test_paste.vim
+@@ -90,6 +90,9 @@ func Test_paste_ex_mode()
+   unlet! foo
+   call feedkeys("Qlet foo=\"\<Esc>[200~foo\<CR>bar\<Esc>[201~\"\<CR>vi\<CR>", 'xt')
+   call assert_equal("foo\rbar", foo)
++
++  " pasting more than 40 bytes
++  exe "norm Q\<PasteStart>0000000000000000000000000000000000000000000000000000000000000000000000\<C-C>"
+ endfunc
+ 
+ func Test_paste_onechar()
+-- 
+2.34.1
+
diff --git a/SOURCES/0001-patch-8.2.4245-retab-0-may-cause-illegal-memory-acce.patch b/SOURCES/0001-patch-8.2.4245-retab-0-may-cause-illegal-memory-acce.patch
new file mode 100644
index 0000000..be23fb3
--- /dev/null
+++ b/SOURCES/0001-patch-8.2.4245-retab-0-may-cause-illegal-memory-acce.patch
@@ -0,0 +1,95 @@
+diff -up vim82/src/indent.c.cve0417 vim82/src/indent.c
+--- vim82/src/indent.c.cve0417	2022-02-09 10:01:34.250009316 +0100
++++ vim82/src/indent.c	2022-02-09 10:02:54.802588536 +0100
+@@ -71,7 +71,7 @@ tabstop_set(char_u *var, int **array)
+ 	int n = atoi((char *)cp);
+ 
+ 	// Catch negative values, overflow and ridiculous big values.
+-	if (n < 0 || n > 9999)
++	if (n < 0 || n > TABSTOP_MAX)
+ 	{
+ 	    semsg(_(e_invarg2), cp);
+ 	    vim_free(*array);
+@@ -1595,7 +1595,7 @@ ex_retab(exarg_T *eap)
+ 	emsg(_(e_positive));
+ 	return;
+     }
+-    if (new_ts < 0 || new_ts > 9999)
++    if (new_ts < 0 || new_ts > TABSTOP_MAX)
+     {
+ 	semsg(_(e_invarg2), eap->arg);
+ 	return;
+diff -up vim82/src/option.c.cve0417 vim82/src/option.c
+--- vim82/src/option.c.cve0417	2022-02-09 10:01:34.196009598 +0100
++++ vim82/src/option.c	2022-02-09 10:28:10.398548161 +0100
+@@ -3640,6 +3640,11 @@ set_num_option(
+ 	errmsg = e_positive;
+ 	curbuf->b_p_ts = 8;
+     }
++    else if (curbuf->b_p_ts > TABSTOP_MAX)
++    {
++	errmsg = e_invarg;
++	curbuf->b_p_ts = 8;
++    }
+     if (p_tm < 0)
+     {
+ 	errmsg = e_positive;
+@@ -5830,7 +5835,7 @@ buf_copy_options(buf_T *buf, int flags)
+ 	    if (p_vsts && p_vsts != empty_option)
+ 		(void)tabstop_set(p_vsts, &buf->b_p_vsts_array);
+ 	    else
+-		buf->b_p_vsts_array = 0;
++		buf->b_p_vsts_array = NULL;
+ 	    buf->b_p_vsts_nopaste = p_vsts_nopaste
+ 				 ? vim_strsave(p_vsts_nopaste) : NULL;
+ #endif
+@@ -6649,9 +6654,7 @@ paste_option_changed(void)
+ 	    if (buf->b_p_vsts)
+ 		free_string_option(buf->b_p_vsts);
+ 	    buf->b_p_vsts = empty_option;
+-	    if (buf->b_p_vsts_array)
+-		vim_free(buf->b_p_vsts_array);
+-	    buf->b_p_vsts_array = 0;
++	    VIM_CLEAR(buf->b_p_vsts_array);
+ #endif
+ 	}
+ 
+@@ -6697,12 +6700,11 @@ paste_option_changed(void)
+ 		free_string_option(buf->b_p_vsts);
+ 	    buf->b_p_vsts = buf->b_p_vsts_nopaste
+ 			 ? vim_strsave(buf->b_p_vsts_nopaste) : empty_option;
+-	    if (buf->b_p_vsts_array)
+-		vim_free(buf->b_p_vsts_array);
++	    vim_free(buf->b_p_vsts_array);
+ 	    if (buf->b_p_vsts && buf->b_p_vsts != empty_option)
+ 		(void)tabstop_set(buf->b_p_vsts, &buf->b_p_vsts_array);
+ 	    else
+-		buf->b_p_vsts_array = 0;
++		buf->b_p_vsts_array = NULL;
+ #endif
+ 	}
+ 
+diff -up vim82/src/testdir/test_options.vim.cve0417 vim82/src/testdir/test_options.vim
+--- vim82/src/testdir/test_options.vim.cve0417	2021-03-22 10:02:42.000000000 +0100
++++ vim82/src/testdir/test_options.vim	2022-02-09 10:01:34.251009311 +0100
+@@ -362,6 +362,8 @@ func Test_set_errors()
+   call assert_fails('set shiftwidth=-1', 'E487:')
+   call assert_fails('set sidescroll=-1', 'E487:')
+   call assert_fails('set tabstop=-1', 'E487:')
++  call assert_fails('set tabstop=10000', 'E474:')
++  call assert_fails('set tabstop=5500000000', 'E474:')
+   call assert_fails('set textwidth=-1', 'E487:')
+   call assert_fails('set timeoutlen=-1', 'E487:')
+   call assert_fails('set updatecount=-1', 'E487:')
+diff -up vim82/src/vim.h.cve0417 vim82/src/vim.h
+--- vim82/src/vim.h.cve0417	2021-03-22 10:02:42.000000000 +0100
++++ vim82/src/vim.h	2022-02-09 10:01:34.252009306 +0100
+@@ -2032,6 +2032,8 @@ typedef int sock_T;
+ 
+ #define DICT_MAXNEST 100	// maximum nesting of lists and dicts
+ 
++#define TABSTOP_MAX 9999
++
+ #ifdef FEAT_CLIPBOARD
+ 
+ // VIM_ATOM_NAME is the older Vim-specific selection type for X11.  Still
diff --git a/SOURCES/0001-patch-8.2.4247-stack-corruption-when-looking-for-spe.patch b/SOURCES/0001-patch-8.2.4247-stack-corruption-when-looking-for-spe.patch
new file mode 100644
index 0000000..201e5e2
--- /dev/null
+++ b/SOURCES/0001-patch-8.2.4247-stack-corruption-when-looking-for-spe.patch
@@ -0,0 +1,75 @@
+diff --git a/src/spellsuggest.c b/src/spellsuggest.c
+index 3de9ff2..5462583 100644
+--- a/src/spellsuggest.c
++++ b/src/spellsuggest.c
+@@ -1200,7 +1200,7 @@ suggest_try_change(suginfo_T *su)
+ 
+ // Check the maximum score, if we go over it we won't try this change.
+ #define TRY_DEEPER(su, stack, depth, add) \
+-		(stack[depth].ts_score + (add) < su->su_maxscore)
++       (depth < MAXWLEN - 1 && stack[depth].ts_score + (add) < su->su_maxscore)
+ 
+ /*
+  * Try finding suggestions by adding/removing/swapping letters.
+@@ -1272,6 +1272,9 @@ suggest_trie_walk(
+     char_u	changename[MAXWLEN][80];
+ #endif
+     int		breakcheckcount = 1000;
++#ifdef FEAT_RELTIME
++    proftime_T	time_limit;
++#endif
+     int		compound_ok;
+ 
+     // Go through the whole case-fold tree, try changes at each node.
+@@ -1316,6 +1319,11 @@ suggest_trie_walk(
+ 	    sp->ts_state = STATE_START;
+ 	}
+     }
++#ifdef FEAT_RELTIME
++    // The loop may take an indefinite amount of time. Break out after five
++    // sectonds. TODO: add an option for the time limit.
++    profile_setlimit(5000, &time_limit);
++#endif
+ 
+     // Loop to find all suggestions.  At each round we either:
+     // - For the current state try one operation, advance "ts_curi",
+@@ -1350,7 +1358,8 @@ suggest_trie_walk(
+ 
+ 		// At end of a prefix or at start of prefixtree: check for
+ 		// following word.
+-		if (byts[arridx] == 0 || n == (int)STATE_NOPREFIX)
++		if (depth < MAXWLEN - 1
++			    && (byts[arridx] == 0 || n == (int)STATE_NOPREFIX))
+ 		{
+ 		    // Set su->su_badflags to the caps type at this position.
+ 		    // Use the caps type until here for the prefix itself.
+@@ -2644,6 +2653,10 @@ suggest_trie_walk(
+ 	    {
+ 		ui_breakcheck();
+ 		breakcheckcount = 1000;
++#ifdef FEAT_RELTIME
++		if (profile_passed_limit(&time_limit))
++		    got_int = TRUE;
++#endif
+ 	    }
+ 	}
+     }
+diff --git a/src/testdir/test_spell.vim b/src/testdir/test_spell.vim
+index a3a9621..35035a2 100644
+--- a/src/testdir/test_spell.vim
++++ b/src/testdir/test_spell.vim
+@@ -768,6 +768,14 @@ func Test_spell_long_word()
+   set nospell
+ endfunc
+ 
++func Test_spellsuggest_too_deep()
++  " This was incrementing "depth" over MAXWLEN.
++  new
++  norm s000G00�000000000000
++  sil norm ..vzG................vvzG0     v z=
++  bwipe!
++endfunc
++
+ func LoadAffAndDic(aff_contents, dic_contents)
+   set enc=latin1
+   set spellfile=
diff --git a/SOURCES/0001-patch-8.2.4253-using-freed-memory-when-substitute-wi.patch b/SOURCES/0001-patch-8.2.4253-using-freed-memory-when-substitute-wi.patch
new file mode 100644
index 0000000..bb58404
--- /dev/null
+++ b/SOURCES/0001-patch-8.2.4253-using-freed-memory-when-substitute-wi.patch
@@ -0,0 +1,69 @@
+diff -up vim82/src/ex_cmds.c.cve0413 vim82/src/ex_cmds.c
+--- vim82/src/ex_cmds.c.cve0413	2022-02-10 08:09:27.644493218 +0100
++++ vim82/src/ex_cmds.c	2022-02-10 08:09:27.653493168 +0100
+@@ -3627,6 +3627,7 @@ ex_substitute(exarg_T *eap)
+     int		save_do_all;		// remember user specified 'g' flag
+     int		save_do_ask;		// remember user specified 'c' flag
+     char_u	*pat = NULL, *sub = NULL;	// init for GCC
++    char_u	*sub_copy = NULL;
+     int		delimiter;
+     int		sublen;
+     int		got_quit = FALSE;
+@@ -3928,11 +3929,20 @@ ex_substitute(exarg_T *eap)
+     sub_firstline = NULL;
+ 
+     /*
+-     * ~ in the substitute pattern is replaced with the old pattern.
+-     * We do it here once to avoid it to be replaced over and over again.
+-     * But don't do it when it starts with "\=", then it's an expression.
++     * If the substitute pattern starts with "\=" then it's an expression.
++     * Make a copy, a recursive function may free it.
++     * Otherwise, '~' in the substitute pattern is replaced with the old
++     * pattern.  We do it here once to avoid it to be replaced over and over
++     * again.
+      */
+-    if (!(sub[0] == '\\' && sub[1] == '='))
++    if (sub[0] == '\\' && sub[1] == '=')
++    {
++	sub = vim_strsave(sub);
++	if (sub == NULL)
++	    return;
++	sub_copy = sub;
++    }
++    else
+ 	sub = regtilde(sub, magic_isset());
+ 
+     /*
+@@ -4737,6 +4747,7 @@ outofmem:
+ #endif
+ 
+     vim_regfree(regmatch.regprog);
++    vim_free(sub_copy);
+ 
+     // Restore the flag values, they can be used for ":&&".
+     subflags.do_all = save_do_all;
+diff -up vim82/src/testdir/test_substitute.vim.cve0413 vim82/src/testdir/test_substitute.vim
+--- vim82/src/testdir/test_substitute.vim.cve0413	2022-02-10 08:09:27.654493162 +0100
++++ vim82/src/testdir/test_substitute.vim	2022-02-10 08:10:14.392230843 +0100
+@@ -926,4 +926,21 @@ func Test_substitute_multiline_submatch(
+   close!
+ endfunc
+ 
++" This was using "old_sub" after it was freed.
++func Test_using_old_sub()
++  set compatible maxfuncdepth=10
++  new
++  call setline(1, 'some text.')
++  func Repl()
++    ~
++    s/
++  endfunc
++  silent!  s/\%')/\=Repl()
++
++  delfunc Repl
++  bwipe!
++  set nocompatible
++endfunc
++
++
+ " vim: shiftwidth=2 sts=2 expandtab
diff --git a/SOURCES/0001-patch-8.2.4281-using-freed-memory-with-lopen-and-bwi.patch b/SOURCES/0001-patch-8.2.4281-using-freed-memory-with-lopen-and-bwi.patch
new file mode 100644
index 0000000..78370cd
--- /dev/null
+++ b/SOURCES/0001-patch-8.2.4281-using-freed-memory-with-lopen-and-bwi.patch
@@ -0,0 +1,75 @@
+diff -up vim82/src/buffer.c.cve0443 vim82/src/buffer.c
+--- vim82/src/buffer.c.cve0443	2021-03-22 10:02:42.000000000 +0100
++++ vim82/src/buffer.c	2022-02-10 08:33:19.159488384 +0100
+@@ -1710,6 +1710,7 @@ set_curbuf(buf_T *buf, int action)
+ #endif
+     bufref_T	newbufref;
+     bufref_T	prevbufref;
++    int		valid;
+ 
+     setpcmark();
+     if ((cmdmod.cmod_flags & CMOD_KEEPALT) == 0)
+@@ -1763,13 +1764,19 @@ set_curbuf(buf_T *buf, int action)
+     // An autocommand may have deleted "buf", already entered it (e.g., when
+     // it did ":bunload") or aborted the script processing.
+     // If curwin->w_buffer is null, enter_buffer() will make it valid again
+-    if ((buf_valid(buf) && buf != curbuf
++    valid = buf_valid(buf);
++    if ((valid && buf != curbuf
+ #ifdef FEAT_EVAL
+ 		&& !aborting()
+ #endif
+ 	) || curwin->w_buffer == NULL)
+     {
+-	enter_buffer(buf);
++	// If the buffer is not valid but curwin->w_buffer is NULL we must
++	// enter some buffer.  Using the last one is hopefully OK.
++	if (!valid)
++	    enter_buffer(lastbuf);
++	else
++	    enter_buffer(buf);
+ #ifdef FEAT_SYN_HL
+ 	if (old_tw != curbuf->b_p_tw)
+ 	    check_colorcolumn(curwin);
+@@ -2286,8 +2293,7 @@ free_buf_options(
+     clear_string_option(&buf->b_p_vsts);
+     vim_free(buf->b_p_vsts_nopaste);
+     buf->b_p_vsts_nopaste = NULL;
+-    vim_free(buf->b_p_vsts_array);
+-    buf->b_p_vsts_array = NULL;
++    VIM_CLEAR(buf->b_p_vsts_array);
+     clear_string_option(&buf->b_p_vts);
+     VIM_CLEAR(buf->b_p_vts_array);
+ #endif
+diff -up vim82/src/testdir/test_quickfix.vim.cve0443 vim82/src/testdir/test_quickfix.vim
+--- vim82/src/testdir/test_quickfix.vim.cve0443	2021-03-22 10:02:42.000000000 +0100
++++ vim82/src/testdir/test_quickfix.vim	2022-02-10 08:34:10.288204457 +0100
+@@ -923,6 +923,7 @@ func Test_locationlist_curwin_was_closed
+   call assert_fails('lrewind', 'E924:')
+ 
+   augroup! testgroup
++  delfunc R
+ endfunc
+ 
+ func Test_locationlist_cross_tab_jump()
+@@ -5372,4 +5373,20 @@ func Test_vimgrep_noswapfile()
+   set swapfile
+ endfunc
+ 
++" Weird sequence of commands that caused entering a wiped-out buffer
++func Test_lopen_bwipe()
++  func R()
++    silent! tab lopen
++    e x
++    silent! lfile
++  endfunc
++
++  cal R()
++  cal R()
++  cal R()
++  bw!
++  delfunc R
++endfunc
++
++
+ " vim: shiftwidth=2 sts=2 expandtab
diff --git a/SOURCES/0001-patch-8.2.4359-crash-when-repeatedly-using-retab.patch b/SOURCES/0001-patch-8.2.4359-crash-when-repeatedly-using-retab.patch
new file mode 100644
index 0000000..276843a
--- /dev/null
+++ b/SOURCES/0001-patch-8.2.4359-crash-when-repeatedly-using-retab.patch
@@ -0,0 +1,61 @@
+diff --git a/src/errors.h b/src/errors.h
+index 3008020..3daf1a6 100644
+--- a/src/errors.h
++++ b/src/errors.h
+@@ -381,3 +381,5 @@ EXTERN char e_missing_end_block[]
+ 	INIT(= N_("E1171: Missing } after inline function"));
+ EXTERN char e_cannot_use_default_values_in_lambda[]
+ 	INIT(= N_("E1172: Cannot use default values in a lambda"));
++EXTERN char e_resulting_text_too_long[]
++	INIT(= N_("E1240: Resulting text too long"));
+diff --git a/src/indent.c b/src/indent.c
+index 4f909d0..77d8b0a 100644
+--- a/src/indent.c
++++ b/src/indent.c
+@@ -1696,6 +1696,11 @@ ex_retab(exarg_T *eap)
+ 	    if (ptr[col] == NUL)
+ 		break;
+ 	    vcol += chartabsize(ptr + col, (colnr_T)vcol);
++	    if (vcol >= MAXCOL)
++	    {
++		emsg(_(e_resulting_text_too_long));
++		break;
++	    }
+ 	    if (has_mbyte)
+ 		col += (*mb_ptr2len)(ptr + col);
+ 	    else
+diff --git a/src/testdir/test_retab.vim b/src/testdir/test_retab.vim
+index c7190aa..6133e8f 100644
+--- a/src/testdir/test_retab.vim
++++ b/src/testdir/test_retab.vim
+@@ -70,6 +70,8 @@ func Test_retab()
+   call assert_equal("    a       b        c    ",         Retab('!', 3))
+   call assert_equal("    a       b        c    ",         Retab('',  5))
+   call assert_equal("    a       b        c    ",         Retab('!', 5))
++
++  set tabstop& expandtab&
+ endfunc
+ 
+ func Test_retab_error()
+@@ -80,4 +82,21 @@ func Test_retab_error()
+   call assert_fails('ret 80000000000000000000', 'E475:')
+ endfunc
+ 
++func Test_retab_endless()
++  new
++  call setline(1, "\t0\t")
++  let caught = 'no'
++  try
++    while 1
++      set ts=4000
++      retab 4
++    endwhile
++  catch /E1240/
++    let caught = 'yes'
++  endtry
++  bwipe!
++  set tabstop&
++endfunc
++
++
+ " vim: shiftwidth=2 sts=2 expandtab
diff --git a/SPECS/vim.spec b/SPECS/vim.spec
index 234c6df..aa49305 100644
--- a/SPECS/vim.spec
+++ b/SPECS/vim.spec
@@ -27,7 +27,7 @@ Summary: The VIM editor
 URL:     http://www.vim.org/
 Name: vim
 Version: %{baseversion}.%{patchlevel}
-Release: 10%{?dist}
+Release: 13%{?dist}
 License: Vim and MIT
 Source0: ftp://ftp.vim.org/pub/vim/unix/vim-%{baseversion}-%{patchlevel}.tar.bz2
 Source1: virc
@@ -88,6 +88,30 @@ Patch3027: 0001-patch-8.2.3669-buffer-overflow-with-long-help-argume.patch
 Patch3028: 0001-patch-8.2.3950-going-beyond-the-end-of-the-line-with.patch
 # CVE-2021-4192 vim: vulnerable to Use After Free
 Patch3029: 0001-patch-8.2.3949-using-freed-memory-with-V.patch
+# CVE-2022-0261 vim: Heap-based Buffer Overflow in block_insert() in src/ops.c
+Patch3030: 0001-patch-8.2.4120-block-insert-goes-over-the-end-of-the.patch
+# CVE-2022-0318 vim: heap-based buffer overflow in utf_head_off() in mbyte.c
+Patch3031: 0001-patch-8.2.4151-reading-beyond-the-end-of-a-line.patch
+# CVE-2022-0359 vim: heap-based buffer overflow in init_ccline() in ex_getln.c
+Patch3032: 0001-patch-8.2.4214-illegal-memory-access-with-large-tabs.patch
+# CVE-2022-0319 vim: heap-based out-of-bounds read
+Patch3033: 0001-patch-8.2.4154-ml_get-error-when-exchanging-windows-.patch
+# CVE-2022-0361 vim: Heap-based Buffer Overflow in GitHub repository
+Patch3034: 0001-patch-8.2.4215-illegal-memory-access-when-copying-li.patch
+# CVE-2022-0368 vim: Out-of-bounds Read in vim
+Patch3035: 0001-patch-8.2.4217-illegal-memory-access-when-undo-makes.patch
+# CVE-2022-0417 vim: heap-based-buffer-overflow in ex_retab() of src/indent.c
+Patch3036: 0001-patch-8.2.4245-retab-0-may-cause-illegal-memory-acce.patch
+# CVE-2022-0408 vim: Stack-based Buffer Overflow in spellsuggest.c
+Patch3037: 0001-patch-8.2.4247-stack-corruption-when-looking-for-spe.patch
+# CVE-2022-0413 vim: use after free in src/ex_cmds.c
+Patch3038: 0001-patch-8.2.4253-using-freed-memory-when-substitute-wi.patch
+# CVE-2022-0443 vim: heap-use-after-free in enter_buffer() of src/buffer.c
+Patch3039: 0001-patch-8.2.4281-using-freed-memory-with-lopen-and-bwi.patch
+# CVE-2022-0392 vim: heap-based buffer overflow in getexmodeline() in ex_getln.c
+Patch3040: 0001-patch-8.2.4218-illegal-memory-access-with-bracketed-.patch
+# CVE-2022-0572 vim: heap overflow in ex_retab() may lead to crash
+Patch3041: 0001-patch-8.2.4359-crash-when-repeatedly-using-retab.patch
 
 # gcc is no longer in buildroot by default
 BuildRequires: gcc
@@ -304,6 +328,18 @@ perl -pi -e "s,bin/nawk,bin/awk,g" runtime/tools/mve.awk
 %patch3027 -p1 -b .cve4019
 %patch3028 -p1 -b .cve4193
 %patch3029 -p1 -b .cve4192
+%patch3030 -p1 -b .cve0261
+%patch3031 -p1 -b .cve0318
+%patch3032 -p1 -b .cve0359
+%patch3033 -p1 -b .cve0319
+%patch3034 -p1 -b .cve0361
+%patch3035 -p1 -b .cve0368
+%patch3036 -p1 -b .cve0417
+%patch3037 -p1 -b .cve0408
+%patch3038 -p1 -b .cve0413
+%patch3039 -p1 -b .cve0443
+%patch3040 -p1 -b .cve0392
+%patch3041 -p1 -b .cve0572
 
 %build
 cd src
@@ -861,6 +897,28 @@ touch %{buildroot}/%{_datadir}/%{name}/vimfiles/doc/tags
 %endif
 
 %changelog
+* Wed Feb 16 2022 Zdenek Dohnal <zdohnal@redhat.com> - 2:8.2.2637-13
+- CVE-2022-0572 vim: heap overflow in ex_retab() may lead to crash
+
+* Thu Feb 10 2022 Zdenek Dohnal <zdohnal@redhat.com> - 2:8.2.2637-12
+- CVE-2022-0413 vim: use after free in src/ex_cmds.c
+- CVE-2022-0443 vim: heap-use-after-free in enter_buffer() of src/buffer.c
+- CVE-2022-0392 vim: heap-based buffer overflow in getexmodeline() in ex_getln.c
+
+* Wed Feb 09 2022 Zdenek Dohnal <zdohnal@redhat.com> - 2:8.2.2637-12
+- CVE-2022-0368 vim: Out-of-bounds Read in vim
+- CVE-2022-0417 vim: heap-based-buffer-overflow in ex_retab() of src/indent.c
+- CVE-2022-0408 vim: Stack-based Buffer Overflow in spellsuggest.c
+
+* Tue Feb 08 2022 Zdenek Dohnal <zdohnal@redhat.com> - 2:8.2.2637-12
+- CVE-2022-0319 vim: heap-based out-of-bounds read
+- CVE-2022-0361 vim: Heap-based Buffer Overflow in GitHub repository
+
+* Thu Jan 27 2022 Zdenek Dohnal <zdohnal@redhat.com> - 2:8.2.2637-11
+- CVE-2022-0261 vim: Heap-based Buffer Overflow in block_insert() in src/ops.c
+- CVE-2022-0318 vim: heap-based buffer overflow in utf_head_off() in mbyte.c
+- CVE-2022-0359 vim: heap-based buffer overflow in init_ccline() in ex_getln.c
+
 * Thu Jan 13 2022 Zdenek Dohnal <zdohnal@redhat.com> - 2:8.2.2637-10
 - CVE-2021-4193 vim: vulnerable to Out-of-bounds Read
 - CVE-2021-4192 vim: vulnerable to Use After Free