Valgrind memory checker reports the following error when
running "make test" in test91:
==17704== Invalid read of size 1
==17704== at 0x4511AA: find_var_in_ht (eval.c:20062)
==17704== by 0x444D61: f_gettabvar (eval.c:11782)
==17704== by 0x43FD17: call_func (eval.c:8531)
==17704== by 0x43F7E9: get_func_tv (eval.c:8344)
==17704== by 0x43B213: eval7 (eval.c:5164)
==17704== by 0x43AA8D: eval6 (eval.c:4816)
==17704== by 0x43A652: eval5 (eval.c:4632)
==17704== by 0x439BE3: eval4 (eval.c:4325)
==17704== by 0x439A3F: eval3 (eval.c:4237)
==17704== by 0x4398BE: eval2 (eval.c:4166)
==17704== by 0x4396FD: eval1 (eval.c:4091)
==17704== by 0x43F74E: get_func_tv (eval.c:8329)
==17704== by 0x43B213: eval7 (eval.c:5164)
==17704== by 0x43AA8D: eval6 (eval.c:4816)
==17704== by 0x43A652: eval5 (eval.c:4632)
==17704== by 0x439BE3: eval4 (eval.c:4325)
==17704== by 0x439A3F: eval3 (eval.c:4237)
==17704== by 0x4398BE: eval2 (eval.c:4166)
==17704== by 0x4396FD: eval1 (eval.c:4091)
==17704== by 0x43965C: eval0 (eval.c:4048)
==17704== by 0x434858: eval_to_string (eval.c:1361)
==17704== by 0x501F52: get_expr_line (ops.c:818)
==17704== by 0x502F52: get_spec_reg (ops.c:1504)
==17704== by 0x506CEB: do_put (ops.c:3362)
==17704== by 0x479AD3: ex_put (ex_docmd.c:8570)
==17704== by 0x46FE4C: do_one_cmd (ex_docmd.c:2684)
==17704== by 0x46D4A8: do_cmdline (ex_docmd.c:1122)
==17704== by 0x4F9B6A: nv_colon (normal.c:5453)
==17704== by 0x4F2740: normal_cmd (normal.c:1199)
==17704== by 0x5D088A: main_loop (main.c:1322)
==17704== by 0x5D01E7: main (main.c:1013)
==17704== Address 0xca9d97e is 2 bytes before a block of size 1 alloc'd
==17704== at 0x4C2C78F: malloc (vg_replace_malloc.c:270)
==17704== by 0x4DFE4C: lalloc (misc2.c:929)
==17704== by 0x4DFD5A: alloc (misc2.c:828)
==17704== by 0x43C3AE: get_lit_string_tv (eval.c:5783)
==17704== by 0x43AFBE: eval7 (eval.c:5083)
==17704== by 0x43AA8D: eval6 (eval.c:4816)
==17704== by 0x43A652: eval5 (eval.c:4632)
==17704== by 0x439BE3: eval4 (eval.c:4325)
==17704== by 0x439A3F: eval3 (eval.c:4237)
==17704== by 0x4398BE: eval2 (eval.c:4166)
==17704== by 0x4396FD: eval1 (eval.c:4091)
==17704== by 0x43F74E: get_func_tv (eval.c:8329)
==17704== by 0x43B213: eval7 (eval.c:5164)
==17704== by 0x43AA8D: eval6 (eval.c:4816)
==17704== by 0x43A652: eval5 (eval.c:4632)
==17704== by 0x439BE3: eval4 (eval.c:4325)
==17704== by 0x439A3F: eval3 (eval.c:4237)
==17704== by 0x4398BE: eval2 (eval.c:4166)
==17704== by 0x4396FD: eval1 (eval.c:4091)
==17704== by 0x43F74E: get_func_tv (eval.c:8329)
==17704== by 0x43B213: eval7 (eval.c:5164)
==17704== by 0x43AA8D: eval6 (eval.c:4816)
==17704== by 0x43A652: eval5 (eval.c:4632)
==17704== by 0x439BE3: eval4 (eval.c:4325)
==17704== by 0x439A3F: eval3 (eval.c:4237)
==17704== by 0x4398BE: eval2 (eval.c:4166)
==17704== by 0x4396FD: eval1 (eval.c:4091)
==17704== by 0x43965C: eval0 (eval.c:4048)
==17704== by 0x434858: eval_to_string (eval.c:1361)
==17704== by 0x501F52: get_expr_line (ops.c:818)
==17704== by 0x502F52: get_spec_reg (ops.c:1504)
==17704== by 0x506CEB: do_put (ops.c:3362)
==17704== by 0x479AD3: ex_put (ex_docmd.c:8570)
==17704== by 0x46FE4C: do_one_cmd (ex_docmd.c:2684)
==17704== by 0x46D4A8: do_cmdline (ex_docmd.c:1122)
==17704== by 0x4F9B6A: nv_colon (normal.c:5453)
==17704== by 0x4F2740: normal_cmd (normal.c:1199)
==17704== by 0x5D088A: main_loop (main.c:1322)
==17704== by 0x5D01E7: main (main.c:1013)
Code in eval.c around line 20062 looks like this:
20051 static dictitem_T *
20052 find_var_in_ht(ht, varname, writing)
20053 hashtab_T *ht;
20054 char_u *varname;
20055 int writing;
20056 {
20057 hashitem_T *hi;
20058
20059 if (*varname == NUL)
20060 {
20061 /* Must be something like "s:", otherwise "ht" would be NULL. */
!!20062 switch (varname[-2])
20063 {
20064 case 's': return &SCRIPT_SV(current_SID)->sv_var;
20065 case 'g': return &globvars_var;
20066 case 'v': return &vimvars_var;
20067 case 'b': return &curbuf->b_bufvar;
20068 case 'w': return &curwin->w_winvar;
It looks quite dangerous to take varname[-2] assuming that
there is valid memory before varname. The comment at above
line 20061 says that it should be valid, but it's proven
wrong with Valgrind: Valgrind indicates that varname was
allocated in get_lit_string_tv (eval.c:5783):
5780 /*
5781 * Copy the string into allocated memory, handling '' to ' reduction.
5782 */
!!5783 str = alloc((unsigned)((p - *arg) - reduce));
test91 is fairly recent as it was added in this checkin:
$ hg -v log -r4157:cb185366f5c8
changeset: 4157:cb185366f5c8
tag: v7-3-831
user: Bram Moolenaar <bram@vim.org>
date: Wed Feb 20 21:12:10 2013 +0100
files: runtime/doc/eval.txt src/eval.c src/testdir/Make_amiga.mak
src/testdir/Make_dos.mak src/testdir/Make_ming.mak src/testdir/Make_os2.mak
src/testdir/Make_vms.mms src/testdir/Makefile src/testdir/test91.in
src/testdir/test91.ok src/version.c
description:
updated for version 7.3.831
Problem: Clumsy to handle the situation that a variable does not exist.
Solution: Add default value to getbufvar() et al. (Shougo Matsushita,
Hirohito Higashi)
What steps will reproduce the problem?
1. Uncomment VALGRIND = ... in src/testdir/Makefile
2. cd src/testdir
3. make test91.out
4. observe valgrind errors in valgrind.test91
What is the expected output? What do you see instead?
Valgrind should obviously not complain with "Invalid read" errors.
What version of the product are you using? On what operating system?
Vim-7.3.888, huge, on Linux x86_64.
Original issue reported on code.google.com by dominiqu...@gmail.com on 12 Apr 2013 at 10:50
Original issue reported on code.google.com by
dominiqu...@gmail.com
on 12 Apr 2013 at 10:50