• R/O
  • SSH

vim: Commit

Mirror of the Vim source from https://github.com/vim/vim


Commit MetaInfo

Révisionfba9e366ced4df6a798c5ad3abc9940b409a606b (tree)
l'heure2022-07-01 06:15:03
AuteurBram Moolenaar <Bram@vim....>
CommiterBram Moolenaar

Message de Log

patch 9.0.0013: reproducing memory access errors can be difficult

Commit: https://github.com/vim/vim/commit/fa4873ccfc10e0f278dc46f39d00136fab059b19
Author: Bram Moolenaar <Bram@vim.org>
Date: Thu Jun 30 22:13:59 2022 +0100

patch 9.0.0013: reproducing memory access errors can be difficult
Problem: Reproducing memory access errors can be difficult.
Solution: When testing, copy each line to allocated memory, so that valgrind
can detect accessing memory before and/or after it. Fix uncovered
problems.

Change Summary

Modification

diff -r a023e3008ae3 -r fba9e366ced4 runtime/doc/testing.txt
--- a/runtime/doc/testing.txt Thu Jun 30 17:30:06 2022 +0200
+++ b/runtime/doc/testing.txt Thu Jun 30 23:15:03 2022 +0200
@@ -268,6 +268,9 @@
268268 Current supported values for {name} are:
269269
270270 {name} effect when {val} is non-zero ~
271+ alloc_lines make a copy of every buffer line into allocated
272+ memory, so that memory access errors can be found
273+ by valgrind
271274 autoload `import autoload` will load the script right
272275 away, not postponed until an item is used
273276 char_avail disable the char_avail() function
@@ -287,7 +290,8 @@
287290 uptime overrules sysinfo.uptime
288291 vterm_title setting the window title by a job running in a
289292 terminal window
290- ALL clear all overrides ({val} is not used)
293+ ALL clear all overrides, except alloc_lines ({val} is
294+ not used)
291295
292296 "starting" is to be used when a test should behave like
293297 startup was done. Since the tests are run by sourcing a
diff -r a023e3008ae3 -r fba9e366ced4 src/change.c
--- a/src/change.c Thu Jun 30 17:30:06 2022 +0200
+++ b/src/change.c Thu Jun 30 23:15:03 2022 +0200
@@ -1535,13 +1535,17 @@
15351535 {
15361536 // End of C comment, indent should line up
15371537 // with the line containing the start of
1538- // the comment
1538+ // the comment.
15391539 curwin->w_cursor.col = (colnr_T)(p - ptr);
15401540 if ((pos = findmatch(NULL, NUL)) != NULL)
15411541 {
15421542 curwin->w_cursor.lnum = pos->lnum;
15431543 newindent = get_indent();
1544+ break;
15441545 }
1546+ // this may make "ptr" invalid, get it again
1547+ ptr = ml_get(curwin->w_cursor.lnum);
1548+ p = ptr + curwin->w_cursor.col;
15451549 }
15461550 }
15471551 }
diff -r a023e3008ae3 -r fba9e366ced4 src/cindent.c
--- a/src/cindent.c Thu Jun 30 17:30:06 2022 +0200
+++ b/src/cindent.c Thu Jun 30 23:15:03 2022 +0200
@@ -2794,8 +2794,6 @@
27942794 break;
27952795 }
27962796
2797- l = ml_get_curline();
2798-
27992797 // If we're in a comment or raw string now, skip to
28002798 // the start of it.
28012799 trypos = ind_find_start_CORS(NULL);
@@ -2806,6 +2804,8 @@
28062804 continue;
28072805 }
28082806
2807+ l = ml_get_curline();
2808+
28092809 // Skip preprocessor directives and blank lines.
28102810 if (cin_ispreproc_cont(&l, &curwin->w_cursor.lnum,
28112811 &amount))
@@ -2905,8 +2905,6 @@
29052905 < ourscope - FIND_NAMESPACE_LIM)
29062906 break;
29072907
2908- l = ml_get_curline();
2909-
29102908 // If we're in a comment or raw string now, skip
29112909 // to the start of it.
29122910 trypos = ind_find_start_CORS(NULL);
@@ -2917,6 +2915,8 @@
29172915 continue;
29182916 }
29192917
2918+ l = ml_get_curline();
2919+
29202920 // Skip preprocessor directives and blank lines.
29212921 if (cin_ispreproc_cont(&l, &curwin->w_cursor.lnum,
29222922 &amount))
@@ -3196,11 +3196,16 @@
31963196 && trypos->col < tryposBrace->col)))
31973197 trypos = NULL;
31983198
3199+ l = ml_get_curline();
3200+
31993201 // If we are looking for ',', we also look for matching
32003202 // braces.
3201- if (trypos == NULL && terminated == ','
3202- && find_last_paren(l, '{', '}'))
3203- trypos = find_start_brace();
3203+ if (trypos == NULL && terminated == ',')
3204+ {
3205+ if (find_last_paren(l, '{', '}'))
3206+ trypos = find_start_brace();
3207+ l = ml_get_curline();
3208+ }
32043209
32053210 if (trypos != NULL)
32063211 {
@@ -3233,6 +3238,7 @@
32333238 --curwin->w_cursor.lnum;
32343239 curwin->w_cursor.col = 0;
32353240 }
3241+ l = ml_get_curline();
32363242 }
32373243
32383244 // Get indent and pointer to text for current line,
diff -r a023e3008ae3 -r fba9e366ced4 src/edit.c
--- a/src/edit.c Thu Jun 30 17:30:06 2022 +0200
+++ b/src/edit.c Thu Jun 30 23:15:03 2022 +0200
@@ -5013,7 +5013,7 @@
50135013 mch_memmove(newp + col, ptr + i,
50145014 curbuf->b_ml.ml_line_len - col - i);
50155015
5016- if (curbuf->b_ml.ml_flags & ML_LINE_DIRTY)
5016+ if (curbuf->b_ml.ml_flags & (ML_LINE_DIRTY | ML_ALLOCATED))
50175017 vim_free(curbuf->b_ml.ml_line_ptr);
50185018 curbuf->b_ml.ml_line_ptr = newp;
50195019 curbuf->b_ml.ml_line_len -= i;
@@ -5232,10 +5232,10 @@
52325232 }
52335233
52345234 // try to advance to the cursor column
5235+ validate_virtcol();
52355236 temp = 0;
52365237 line = ptr = ml_get(lnum);
52375238 prev_ptr = ptr;
5238- validate_virtcol();
52395239 while ((colnr_T)temp < curwin->w_virtcol && *ptr != NUL)
52405240 {
52415241 prev_ptr = ptr;
diff -r a023e3008ae3 -r fba9e366ced4 src/globals.h
--- a/src/globals.h Thu Jun 30 17:30:06 2022 +0200
+++ b/src/globals.h Thu Jun 30 23:15:03 2022 +0200
@@ -1654,6 +1654,7 @@
16541654 EXTERN int disable_vterm_title_for_testing INIT(= FALSE);
16551655 EXTERN long override_sysinfo_uptime INIT(= -1);
16561656 EXTERN int override_autoload INIT(= FALSE);
1657+EXTERN int ml_get_alloc_lines INIT(= FALSE);
16571658
16581659 EXTERN int in_free_unref_items INIT(= FALSE);
16591660 #endif
diff -r a023e3008ae3 -r fba9e366ced4 src/memline.c
--- a/src/memline.c Thu Jun 30 17:30:06 2022 +0200
+++ b/src/memline.c Thu Jun 30 23:15:03 2022 +0200
@@ -858,7 +858,8 @@
858858 if (buf->b_ml.ml_mfp == NULL) // not open
859859 return;
860860 mf_close(buf->b_ml.ml_mfp, del_file); // close the .swp file
861- if (buf->b_ml.ml_line_lnum != 0 && (buf->b_ml.ml_flags & ML_LINE_DIRTY))
861+ if (buf->b_ml.ml_line_lnum != 0
862+ && (buf->b_ml.ml_flags & (ML_LINE_DIRTY | ML_ALLOCATED)))
862863 vim_free(buf->b_ml.ml_line_ptr);
863864 vim_free(buf->b_ml.ml_stack);
864865 #ifdef FEAT_BYTEOFF
@@ -2620,7 +2621,6 @@
26202621 --recursive;
26212622 }
26222623 ml_flush_line(buf);
2623- buf->b_ml.ml_flags &= ~ML_LINE_DIRTY;
26242624 errorret:
26252625 STRCPY(questions, "???");
26262626 buf->b_ml.ml_line_len = 4;
@@ -2686,17 +2686,44 @@
26862686 buf->b_ml.ml_line_ptr = (char_u *)dp + start;
26872687 buf->b_ml.ml_line_len = len;
26882688 buf->b_ml.ml_line_lnum = lnum;
2689- buf->b_ml.ml_flags &= ~ML_LINE_DIRTY;
2689+ buf->b_ml.ml_flags &= ~(ML_LINE_DIRTY | ML_ALLOCATED);
26902690 }
26912691 if (will_change)
2692+ {
26922693 buf->b_ml.ml_flags |= (ML_LOCKED_DIRTY | ML_LOCKED_POS);
2693-
2694+#ifdef FEAT_EVAL
2695+ if (ml_get_alloc_lines && (buf->b_ml.ml_flags & ML_ALLOCATED))
2696+ // can't make the change in the data block
2697+ buf->b_ml.ml_flags |= ML_LINE_DIRTY;
2698+#endif
2699+ }
2700+
2701+#ifdef FEAT_EVAL
2702+ if (ml_get_alloc_lines
2703+ && (buf->b_ml.ml_flags & (ML_LINE_DIRTY | ML_ALLOCATED)) == 0)
2704+ {
2705+ char_u *p = alloc(buf->b_ml.ml_line_len);
2706+
2707+ // make sure the text is in allocated memory
2708+ if (p != NULL)
2709+ {
2710+ memmove(p, buf->b_ml.ml_line_ptr, buf->b_ml.ml_line_len);
2711+ buf->b_ml.ml_line_ptr = p;
2712+ buf->b_ml.ml_flags |= ML_ALLOCATED;
2713+ if (will_change)
2714+ // can't make the change in the data block
2715+ buf->b_ml.ml_flags |= ML_LINE_DIRTY;
2716+ }
2717+ }
2718+#endif
26942719 return buf->b_ml.ml_line_ptr;
26952720 }
26962721
26972722 /*
26982723 * Check if a line that was just obtained by a call to ml_get
26992724 * is in allocated memory.
2725+ * This ignores ML_ALLOCATED to get the same behavior as without the test
2726+ * override.
27002727 */
27012728 int
27022729 ml_line_alloced(void)
@@ -3409,6 +3436,8 @@
34093436 * "len_arg" is the length of the text, excluding NUL.
34103437 * If "has_props" is TRUE then "line_arg" includes the text properties and
34113438 * "len_arg" includes the NUL of the text.
3439+ * When "copy" is TRUE copy the text into allocated memory, otherwise
3440+ * "line_arg" must be allocated and will be consumed here.
34123441 */
34133442 int
34143443 ml_replace_len(
@@ -3454,7 +3483,6 @@
34543483 {
34553484 // another line is buffered, flush it
34563485 ml_flush_line(curbuf);
3457- curbuf->b_ml.ml_flags &= ~ML_LINE_DIRTY;
34583486
34593487 #ifdef FEAT_PROP_POPUP
34603488 if (curbuf->b_has_textprop && !has_props)
@@ -3488,8 +3516,8 @@
34883516 }
34893517 #endif
34903518
3491- if (curbuf->b_ml.ml_flags & ML_LINE_DIRTY) // same line allocated
3492- vim_free(curbuf->b_ml.ml_line_ptr); // free it
3519+ if (curbuf->b_ml.ml_flags & (ML_LINE_DIRTY | ML_ALLOCATED))
3520+ vim_free(curbuf->b_ml.ml_line_ptr); // free allocated line
34933521
34943522 curbuf->b_ml.ml_line_ptr = line;
34953523 curbuf->b_ml.ml_line_len = len;
@@ -4064,7 +4092,10 @@
40644092
40654093 entered = FALSE;
40664094 }
4067-
4095+ else if (buf->b_ml.ml_flags & ML_ALLOCATED)
4096+ vim_free(buf->b_ml.ml_line_ptr);
4097+
4098+ buf->b_ml.ml_flags &= ~(ML_LINE_DIRTY | ML_ALLOCATED);
40684099 buf->b_ml.ml_line_lnum = 0;
40694100 }
40704101
diff -r a023e3008ae3 -r fba9e366ced4 src/netbeans.c
--- a/src/netbeans.c Thu Jun 30 17:30:06 2022 +0200
+++ b/src/netbeans.c Thu Jun 30 23:15:03 2022 +0200
@@ -2741,13 +2741,15 @@
27412741 if (nbbuf->insertDone)
27422742 nbbuf->modified = 1;
27432743
2744+ // send the "insert" EVT
2745+ newtxt = alloc(newlen + 1);
2746+ vim_strncpy(newtxt, txt, newlen);
2747+
2748+ // Note: this may make "txt" invalid
27442749 pos.lnum = linenr;
27452750 pos.col = col;
27462751 off = pos2off(bufp, &pos);
27472752
2748- // send the "insert" EVT
2749- newtxt = alloc(newlen + 1);
2750- vim_strncpy(newtxt, txt, newlen);
27512753 p = nb_quote(newtxt);
27522754 if (p != NULL)
27532755 {
diff -r a023e3008ae3 -r fba9e366ced4 src/normal.c
--- a/src/normal.c Thu Jun 30 17:30:06 2022 +0200
+++ b/src/normal.c Thu Jun 30 23:15:03 2022 +0200
@@ -5120,6 +5120,8 @@
51205120 count = (int)STRLEN(ptr) - pos.col;
51215121 netbeans_removed(curbuf, pos.lnum, pos.col,
51225122 (long)count);
5123+ // line may have been flushed, get it again
5124+ ptr = ml_get(pos.lnum);
51235125 netbeans_inserted(curbuf, pos.lnum, pos.col,
51245126 &ptr[pos.col], count);
51255127 }
diff -r a023e3008ae3 -r fba9e366ced4 src/ops.c
--- a/src/ops.c Thu Jun 30 17:30:06 2022 +0200
+++ b/src/ops.c Thu Jun 30 23:15:03 2022 +0200
@@ -1273,6 +1273,8 @@
12731273
12741274 netbeans_removed(curbuf, pos.lnum, bd.textcol,
12751275 (long)bd.textlen);
1276+ // get the line again, it may have been flushed
1277+ ptr = ml_get_buf(curbuf, pos.lnum, FALSE);
12761278 netbeans_inserted(curbuf, pos.lnum, bd.textcol,
12771279 &ptr[bd.textcol], bd.textlen);
12781280 }
@@ -1322,6 +1324,8 @@
13221324 ptr = ml_get_buf(curbuf, pos.lnum, FALSE);
13231325 count = (int)STRLEN(ptr) - pos.col;
13241326 netbeans_removed(curbuf, pos.lnum, pos.col, (long)count);
1327+ // get the line again, it may have been flushed
1328+ ptr = ml_get_buf(curbuf, pos.lnum, FALSE);
13251329 netbeans_inserted(curbuf, pos.lnum, pos.col,
13261330 &ptr[pos.col], count);
13271331 pos.col = 0;
@@ -1330,6 +1334,8 @@
13301334 ptr = ml_get_buf(curbuf, pos.lnum, FALSE);
13311335 count = oap->end.col - pos.col + 1;
13321336 netbeans_removed(curbuf, pos.lnum, pos.col, (long)count);
1337+ // get the line again, it may have been flushed
1338+ ptr = ml_get_buf(curbuf, pos.lnum, FALSE);
13331339 netbeans_inserted(curbuf, pos.lnum, pos.col,
13341340 &ptr[pos.col], count);
13351341 }
diff -r a023e3008ae3 -r fba9e366ced4 src/structs.h
--- a/src/structs.h Thu Jun 30 17:30:06 2022 +0200
+++ b/src/structs.h Thu Jun 30 23:15:03 2022 +0200
@@ -756,10 +756,11 @@
756756 int ml_stack_top; // current top of ml_stack
757757 int ml_stack_size; // total number of entries in ml_stack
758758
759-#define ML_EMPTY 1 // empty buffer
760-#define ML_LINE_DIRTY 2 // cached line was changed and allocated
761-#define ML_LOCKED_DIRTY 4 // ml_locked was changed
762-#define ML_LOCKED_POS 8 // ml_locked needs positive block number
759+#define ML_EMPTY 0x01 // empty buffer
760+#define ML_LINE_DIRTY 0x02 // cached line was changed and allocated
761+#define ML_LOCKED_DIRTY 0x04 // ml_locked was changed
762+#define ML_LOCKED_POS 0x08 // ml_locked needs positive block number
763+#define ML_ALLOCATED 0x10 // ml_line_ptr is an allocated copy
763764 int ml_flags;
764765
765766 colnr_T ml_line_len; // length of the cached line, including NUL
diff -r a023e3008ae3 -r fba9e366ced4 src/testdir/runtest.vim
--- a/src/testdir/runtest.vim Thu Jun 30 17:30:06 2022 +0200
+++ b/src/testdir/runtest.vim Thu Jun 30 23:15:03 2022 +0200
@@ -154,6 +154,10 @@
154154 " Prepare for calling test_garbagecollect_now().
155155 let v:testing = 1
156156
157+" By default, copy each buffer line into allocated memory, so that valgrind can
158+" detect accessing memory before and after it.
159+call test_override('alloc_lines', 1)
160+
157161 " Support function: get the alloc ID by name.
158162 function GetAllocId(name)
159163 exe 'split ' . s:srcdir . '/alloc.h'
@@ -182,7 +186,7 @@
182186 " mode message.
183187 set noshowmode
184188
185- " Clear any overrides.
189+ " Clear any overrides, except "alloc_lines".
186190 call test_override('ALL', 0)
187191
188192 " Some tests wipe out buffers. To be consistent, always wipe out all
diff -r a023e3008ae3 -r fba9e366ced4 src/testdir/test_breakindent.vim
--- a/src/testdir/test_breakindent.vim Thu Jun 30 17:30:06 2022 +0200
+++ b/src/testdir/test_breakindent.vim Thu Jun 30 23:15:03 2022 +0200
@@ -10,7 +10,9 @@
1010 source view_util.vim
1111 source screendump.vim
1212
13-let s:input ="\tabcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOP"
13+func SetUp()
14+ let s:input ="\tabcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOP"
15+endfunc
1416
1517 func s:screen_lines(lnum, width) abort
1618 return ScreenLines([a:lnum, a:lnum + 2], a:width)
@@ -714,6 +716,9 @@
714716 endfunc
715717
716718 func Test_breakindent20_list()
719+ " FIXME - this should not matter
720+ call test_override('alloc_lines', 0)
721+
717722 call s:test_windows('setl breakindent breakindentopt= linebreak')
718723 " default:
719724 call setline(1, [' 1. Congress shall make no law',
@@ -830,6 +835,9 @@
830835 let lines = s:screen_lines2(1, 6, 20)
831836 call s:compare_lines(expect, lines)
832837 call s:close_windows('set breakindent& briopt& linebreak& list& listchars& showbreak&')
838+
839+ " FIXME - this should not matter
840+ call test_override('alloc_lines', 1)
833841 endfunc
834842
835843 " The following used to crash Vim. This is fixed by 8.2.3391.
@@ -873,15 +881,20 @@
873881 endfunc
874882
875883 func Test_no_spurious_match()
884+ " FIXME - fails under valgrind - this should not matter - timing issue?
885+ call test_override('alloc_lines', 0)
886+
876887 let s:input = printf('- y %s y %s', repeat('x', 50), repeat('x', 50))
877888 call s:test_windows('setl breakindent breakindentopt=list:-1 formatlistpat=^- hls')
878889 let @/ = '\%>3v[y]'
879890 redraw!
880891 call searchcount().total->assert_equal(1)
892+
881893 " cleanup
882894 set hls&vim
883- let s:input = "\tabcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOP"
884895 bwipeout!
896+ " FIXME - this should not matter
897+ call test_override('alloc_lines', 1)
885898 endfunc
886899
887900 func Test_no_extra_indent()
@@ -945,8 +958,6 @@
945958 endfunc
946959
947960 func Test_breakindent_column()
948- " restore original
949- let s:input ="\tabcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOP"
950961 call s:test_windows('setl breakindent breakindentopt=column:10')
951962 redraw!
952963 " 1) default: does not indent, too wide :(
diff -r a023e3008ae3 -r fba9e366ced4 src/testdir/test_edit.vim
--- a/src/testdir/test_edit.vim Thu Jun 30 17:30:06 2022 +0200
+++ b/src/testdir/test_edit.vim Thu Jun 30 23:15:03 2022 +0200
@@ -1860,6 +1860,9 @@
18601860 call writefile(lines, 'Xtest_edit_insertmode_ex_edit')
18611861
18621862 let buf = RunVimInTerminal('-S Xtest_edit_insertmode_ex_edit', #{rows: 6})
1863+ " Somehow this can be very slow with valgrind. A separate TermWait() works
1864+ " better than a longer time with WaitForAssert() (why?)
1865+ call TermWait(buf, 1000)
18631866 call WaitForAssert({-> assert_match('^-- INSERT --\s*$', term_getline(buf, 6))})
18641867 call term_sendkeys(buf, "\<C-B>\<C-L>")
18651868 call WaitForAssert({-> assert_notmatch('^-- INSERT --\s*$', term_getline(buf, 6))})
diff -r a023e3008ae3 -r fba9e366ced4 src/textprop.c
--- a/src/textprop.c Thu Jun 30 17:30:06 2022 +0200
+++ b/src/textprop.c Thu Jun 30 23:15:03 2022 +0200
@@ -287,7 +287,7 @@
287287 props + i * sizeof(textprop_T),
288288 sizeof(textprop_T) * (proplen - i));
289289
290- if (buf->b_ml.ml_flags & ML_LINE_DIRTY)
290+ if (buf->b_ml.ml_flags & (ML_LINE_DIRTY | ML_ALLOCATED))
291291 vim_free(buf->b_ml.ml_line_ptr);
292292 buf->b_ml.ml_line_ptr = newtext;
293293 buf->b_ml.ml_line_len += sizeof(textprop_T);
@@ -564,7 +564,7 @@
564564 mch_memmove(newtext, text, textlen);
565565 if (len > 0)
566566 mch_memmove(newtext + textlen, props, len);
567- if (curbuf->b_ml.ml_flags & ML_LINE_DIRTY)
567+ if (curbuf->b_ml.ml_flags & (ML_LINE_DIRTY | ML_ALLOCATED))
568568 vim_free(curbuf->b_ml.ml_line_ptr);
569569 curbuf->b_ml.ml_line_ptr = newtext;
570570 curbuf->b_ml.ml_line_len = textlen + len;
@@ -698,6 +698,8 @@
698698 // need to allocate the line now
699699 if (newtext == NULL)
700700 return;
701+ if (buf->b_ml.ml_flags & ML_ALLOCATED)
702+ vim_free(buf->b_ml.ml_line_ptr);
701703 buf->b_ml.ml_line_ptr = newtext;
702704 buf->b_ml.ml_flags |= ML_LINE_DIRTY;
703705 }
@@ -1273,6 +1275,8 @@
12731275 return;
12741276 mch_memmove(newptr, buf->b_ml.ml_line_ptr,
12751277 buf->b_ml.ml_line_len);
1278+ if (buf->b_ml.ml_flags & ML_ALLOCATED)
1279+ vim_free(buf->b_ml.ml_line_ptr);
12761280 buf->b_ml.ml_line_ptr = newptr;
12771281 buf->b_ml.ml_flags |= ML_LINE_DIRTY;
12781282
@@ -1766,8 +1770,13 @@
17661770 colnr_T newlen = (int)textlen + wi * (colnr_T)sizeof(textprop_T);
17671771
17681772 if ((curbuf->b_ml.ml_flags & ML_LINE_DIRTY) == 0)
1769- curbuf->b_ml.ml_line_ptr =
1770- vim_memsave(curbuf->b_ml.ml_line_ptr, newlen);
1773+ {
1774+ char_u *p = vim_memsave(curbuf->b_ml.ml_line_ptr, newlen);
1775+
1776+ if (curbuf->b_ml.ml_flags & ML_ALLOCATED)
1777+ vim_free(curbuf->b_ml.ml_line_ptr);
1778+ curbuf->b_ml.ml_line_ptr = p;
1779+ }
17711780 curbuf->b_ml.ml_flags |= ML_LINE_DIRTY;
17721781 curbuf->b_ml.ml_line_len = newlen;
17731782 }
diff -r a023e3008ae3 -r fba9e366ced4 src/version.c
--- a/src/version.c Thu Jun 30 17:30:06 2022 +0200
+++ b/src/version.c Thu Jun 30 23:15:03 2022 +0200
@@ -736,6 +736,8 @@
736736 static int included_patches[] =
737737 { /* Add new patch number below this line */
738738 /**/
739+ 13,
740+/**/
739741 12,
740742 /**/
741743 11,
Afficher sur ancien navigateur de dépôt.