V: Shadowing variable dangerous bug

Created on 14 Dec 2019  路  3Comments  路  Source: vlang/v

V version:
V 0.1.23 cddfbf7

OS:
Ubuntu 18.04.3
gcc (Ubuntu 7.4.0-1ubuntu1~18.04.1) 7.4.0

What did you do?

fn main () {
    mut i := 0
    i++
    println(i)

    a:=[f32(5.0), 6.0, 7.0, 8.0 ]

    for i in a{
        i++  //  this must lead to a compiler error!! it doesn't
        println(i)
    }
    println(i)
}

What did you expect to see?

1
5.000000 
6.000000
7.000000
8.000000
1

What did you see instead?

1
-771174608
-836962736
-836962736
-836962736
1

Analysis of the bug
There is a problem decoupling at the same scope level a mut variable and a loop iter variable with the same name.
The problem is present when a internal val in a for loop has the same name of a mut variable in the same scope.
This bug allow to modify the val variable and can cause unpredictable results on memory.

Possible fix
in the file vlib\compiler\fn.v the function register_var need to check if in the same scope there is yet a variable with the same name and emit an error.
two way are possible:

1) the simple way
Avoid at the same level two variables with the same name even for the loops:

fn (p mut Parser) register_var(v Var) {
    mut new_var := {v | idx: p.var_idx, scope_level: p.cur_fn.scope_level}
    if v.line_nr == 0 {
        new_var.token_idx = p.cur_tok_index()
        new_var.line_nr = p.cur_tok().line_nr
    }

    //
    //====================================================
    //
    for x in p.local_vars {
        //println("var pres: $x.name")
        if x.name == v.name {
            line_num := p.cur_tok().line_nr
            println("file: $p.scanner.file_path line: $line_num")
            println("variable [$v.name] already declared in the same scope!! Change variable name!!")
        }
    }
    //
    //====================================================
    //

    // Expand the array
    if p.var_idx >= p.local_vars.len {
        p.local_vars << new_var
    }
    else {
        p.local_vars[p.var_idx] = new_var
    }
    p.var_idx++
}

compiling the previous test program with this modification in v compiler the result is:

file: /home/user/temp/v/vlib/builtin/string.v line: 377
variable [j] already declared in the same scope!! Change variable name!!
file: /home/user/temp/v/vlib/builtin/string.v line: 551
variable [i] already declared in the same scope!! Change variable name!!
file: /home/user/temp/v/vlib/builtin/string.v line: 721
variable [err] already declared in the same scope!! Change variable name!!
file: /home/user/temp/v/vlib/builtin/string.v line: 721
variable [errcode] already declared in the same scope!! Change variable name!!
file: /home/user/temp/v/vlib/builtin/string.v line: 934
variable [i] already declared in the same scope!! Change variable name!!
file: /home/user/temp/v/vlib/builtin/string.v line: 936
variable [char_len] already declared in the same scope!! Change variable name!!
warning: a.v:7:13: casting `f32` to `f32` is not needed
file: a.v line: 8
variable [i] already declared in the same scope!! Change variable name!!
warning: a.v:9:12: `i` declared and not used

2) the hard way
Modify the compiler to manage the scope level in the variables names.
At the present time no idea how to do this.

Bug

Most helpful comment

Good find, thanks.

Shadowing is not allowed in V, but for loop variables were not handled.

All 3 comments

Good find, thanks.

Shadowing is not allowed in V, but for loop variables were not handled.

Have any idea how to solve this issue?
Can I help?

Fixed:

redefinition of `i`
Was this page helpful?
0 / 5 - 0 ratings

Related issues

markgraydev picture markgraydev  路  3Comments

taojy123 picture taojy123  路  3Comments

vtereshkov picture vtereshkov  路  3Comments

ArcDrake picture ArcDrake  路  3Comments

arg2das picture arg2das  路  3Comments