vlang / v

Simple, fast, safe, compiled language for developing maintainable software. Compiles itself in <1s with zero library dependencies. Supports automatic C => V translation. https://vlang.io
MIT License
35.79k stars 2.16k forks source link

Unsafe math operations #4261

Open angusluckmann opened 4 years ago

angusluckmann commented 4 years ago

V version: 0.1.24 OS: Android 9, Termux (could have probably been any other)

What did you do?

fn add(num1 int, num2 int) int {
    return (num1 + num2)
}

fn sub(num1 int, num2 int) int {
    return (num1 - num2)
}

fn mul(num1 int, num2 int) int {
    return (num1 * num2)
}

fn div(num1 int, num2 int) int {
    return (num1 / num2)
}

fn main() {
    // Define necessary constants
    max_possible_int32 := int(2147483647)
    min_possible_int32 := int(-2147483648)

    // Check direct addition
    println("========== DIRECT ADDITION TEST ==========")
    mut res := int(max_possible_int32 + max_possible_int32)
    println(res)
    println("")

    // Check direct substraction
    println("========== DIRECT SUBSTRACTION TEST ==========")
    res = int(min_possible_int32 - max_possible_int32)
    println(res)
    println("")

    //Check direct multiplication
    println("========== DIRECT MULTIPLICATION TEST ==========")
    res = int(max_possible_int32 * max_possible_int32)
    println(res)
    println("")

    // Check indirect addition
    println("========== INDIRECT ADDITION TEST ==========")
    mut tmp := add(max_possible_int32, max_possible_int32)
    println(tmp)
    println("")

    // Check indirect substraction
    println("========== INDIRECT SUBSTRACTION TEST ==========")
    tmp = sub(min_possible_int32, max_possible_int32)
    println(tmp)
    println("")

    // Check indirect multiplication
    println("========== INDIRECT MULTIPLICATION TEST ==========")
    tmp = mul(max_possible_int32, max_possible_int32)
    println(tmp)
    println("")

    // Check direct division
    println("========== DIRECT DIVISION TEST ==========")
    mydiv := int(1/0)
    println(mydiv)
    println("")

    // Check indirect division
    println("========== INDIRECT DIVISION TEST ==========")
    mydiv := div(1,0)
    println(mydiv)
    println("")
}

What did you expect to see? 4 compiler errors/warnings and 4 runtime errors

What did you see instead? 1 compiler error (direct division test) and the program spitting out 7 wrong values to the screen. (and a bunch of compiler warnings saying that "casting int to int is not needed")

angusluckmann commented 4 years ago

Sorry if I created the issue the wrong way. I'm new to Github Issues :)

danieldaeschle commented 4 years ago

try it with the new compiler v0.1.26 please!

angusluckmann commented 4 years ago

V version: 0.1.26 4e01bf4.78440be Discoveries: Now I get a weird C error on the division function (even if I don't call it). And all the tests (even the direct division test) seem to run through.

More info:

I did a build through ...

git clone https://github.com/vlang/v
cd v
make

In that state I got the C error and an error on the direct division test.

Then I ran ... v up And after the update, the C error was still there, but the direct division test passed with a weird number (-973237312)

The version number mentioned above is the one after the v up command.

angusluckmann commented 4 years ago

I obviously added the v command to path with ... export PATH=$PWD:$PATH ... and checked the version correctness with ... v --version

danieldaeschle commented 4 years ago

thank you. the new error should be reproduceable.

can you paste the new error which you get?

angusluckmann commented 4 years ago

Just for the record, I'm gonna repeat some of the information to some them up. V version: V 0.1.26 4e01bf4.78440be Source Code:

fn add(num1 int, num2 int) int {
    return (num1 + num2)
}

fn sub(num1 int, num2 int) int {
    return (num1 - num2)
}

fn mul(num1 int, num2 int) int {
    return (num1 * num2)
}

fn div(num1 int, num2 int) int {
    return (num1 / num2)
}

fn main() {
    // Define necessary constants
    max_possible_int32 := int(2147483647)
    min_possible_int32 := int(-2147483648)

    // Check direct addition
    println("========== DITECT ADDITION TEST ==========")
    mut res := int(max_possible_int32 + max_possible_int32)
    println(res)
    println("")

    // Check direct substraction
    println("========== DIRECT SUBSTRACTION TEST ==========")
    res = int(min_possible_int32 - max_possible_int32)
    println(res)
    println("")

    //Check direct multiplication
    println("========== DIRECT MULTIPLICATION TEST ==========")
    res = int(max_possible_int32 * max_possible_int32)
    println(res)
    println("")

    // Check indirect addition
    println("========== INDIRECT ADDITION TEST ==========")
    mut tmp := add(max_possible_int32, max_possible_int32)
    println(tmp)
    println("")

    // Check indirect substraction
    println("========== INDIRECT SUBSTRACTION TEST ==========")
    tmp = sub(min_possible_int32, max_possible_int32)
    println(tmp)
    println("")

    // Check indirect multiplication
    println("========== INDIRECT MULTIPLICATION TEST ==========")
    tmp = mul(max_possible_int32, max_possible_int32)
    println(tmp)
    println("")

    // Check direct division
    println("========== DIRECT DIVISION TEST ==========")
    mydiv := int(1/0)
    println(mydiv)
    println("")

    // Check indirect division
    println("========== INDIRECT DIVISION TEST ==========")
    mydiv = div(1,0)
    println(mydiv)
    println("")
}

Compiler output:

==================
                          ^
/data/data/com.termux/files/home/vtest2/tmp.c:4519:5: error: conflicting types for 'div'
int div(int num1, int num2) {
    ^
/data/data/com.termux/files/usr/include/stdlib.h:183:7: note: previous declaration is here
div_t div(int __numerator, int __denominator) __attribute_const__;
      ^                                         /data/data/com.termux/files/home/vtest2/tmp.c:4556:8: error: assigning to 'int' from incompatible type 'div_t'                                          mydiv = div(1, 0);
              ^ ~~~~~~~~~
/data/data/com.termux/files/home/vtest2/tmp.c:4552:23: warning: division by zero is undefined [-Wdivision-by-zero]
        int mydiv = ((int)(1 / 0));
...
==================
(Use `v -cg` to print the entire error message)

builder error: C error.

Please make sure that:
- You have all V dependencies installed.
- You did not declare a C function that was not included. (Try commenting your code that involves C interop)
- You are running the latest version of V. (Try running `v up` and rerunning your command)

If you're confident that all of the above is true, please try running V with the `-cg` option which enables more debugging capabilities.
angusluckmann commented 4 years ago

Second experiment

V version: V 0.1.26 4e01bf4.78440be Source Code:

fn add(num1 int, num2 int) int {
    return (num1 + num2)
}

fn sub(num1 int, num2 int) int {
    return (num1 - num2)
}

fn mul(num1 int, num2 int) int {
    return (num1 * num2)
}

fn div(num1 int, num2 int) int {
    return (num1 / num2)
}

fn main() {
    // Define necessary constants
    max_possible_int32 := int(2147483647)
    min_possible_int32 := int(-2147483648)

    // Check direct addition
    println("========== DITECT ADDITION TEST ==========")
    mut res := int(max_possible_int32 + max_possible_int32)
    println(res)
    println("")

    // Check direct substraction
    println("========== DIRECT SUBSTRACTION TEST ==========")
    res = int(min_possible_int32 - max_possible_int32)
    println(res)
    println("")

    //Check direct multiplication
    println("========== DIRECT MULTIPLICATION TEST ==========")
    res = int(max_possible_int32 * max_possible_int32)
    println(res)
    println("")

    // Check indirect addition
    println("========== INDIRECT ADDITION TEST ==========")
    mut tmp := add(max_possible_int32, max_possible_int32)
    println(tmp)
    println("")

    // Check indirect substraction
    println("========== INDIRECT SUBSTRACTION TEST ==========")
    tmp = sub(min_possible_int32, max_possible_int32)
    println(tmp)
    println("")

    // Check indirect multiplication
    println("========== INDIRECT MULTIPLICATION TEST ==========")
    tmp = mul(max_possible_int32, max_possible_int32)
    println(tmp)
    println("")

    // Check direct division
    println("========== DIRECT DIVISION TEST ==========")
    mydiv := int(1/0)
    println(mydiv)
    println("")

    // Check indirect division
    // println("========== INDIRECT DIVISION TEST ==========")
    // mydiv = div(1,0)
    // println(mydiv)
    // println("")
}

Compiler output (probably the same as last one):

==================                                                        ^
/data/data/com.termux/files/home/vtest2/tmp02.c:4519:5: error: conflicting types for 'div'
int div(int num1, int num2) {
    ^
/data/data/com.termux/files/usr/include/stdlib.h:183:7: note: previous declaration is here
div_t div(int __numerator, int __denominator) __attribute_const__;
      ^                                         /data/data/com.termux/files/home/vtest2/tmp02.c:4552:23: warning: division by zero is undefined [-Wdivision-by-zero]                                    int mydiv = ((int)(1 / 0));
                             ^ ~
/data/data/com.termux/files/home/vtest2/tmp02.c:6440:407: warning: integer literal is too large to be represented in a signed integer type, interpreting as unsigned [-Wimplicitly-unsigned-literal]
((u64)(1)), ((u64)(10)), ((u64)(100)), ((u64)(1000)), ((u64)(10000)), ((u64)(100000)), ((u64)(1000000)), ((u64)(10000000)), ((u64)(100000000)), ((u64)(1000000000)), ((u64)(10000000000)), ((u64)(100000000000)), ((u64)(1000000000000)), ((u64)(10000000000000)), ((u64)(100000000000000)), ((u64)(1000000000000000)), ((u64)(10000000000000000)), ((u64)(100000000000000000)), ((u64)(1000000000000000000)), ((u64)(10000000000000000000)),
...
==================
(Use `v -cg` to print the entire error message)

builder error: C error.

Please make sure that:
- You have all V dependencies installed.
- You did not declare a C function that was not included. (Try commenting your code that involves C interop)
- You are running the latest version of V. (Try running `v up` and rerunning your command)

If you're confident that all of the above is true, please try running V with the `-cg` option which enables more debugging capabilities.
angusluckmann commented 4 years ago

Third experiment

V version: V 0.1.26 4e01bf4.78440be Source Code:

fn add(num1 int, num2 int) int {
    return (num1 + num2)
}

fn sub(num1 int, num2 int) int {
    return (num1 - num2)
}

fn mul(num1 int, num2 int) int {
    return (num1 * num2)
}

/*
fn div(num1 int, num2 int) int {
    return (num1 / num2)
}
*/

fn main() {
    // Define necessary constants
    max_possible_int32 := int(2147483647)
    min_possible_int32 := int(-2147483648)

    // Check direct addition
    println("========== DITECT ADDITION TEST ==========")
    mut res := int(max_possible_int32 + max_possible_int32)
    println(res)
    println("")

    // Check direct substraction
    println("========== DIRECT SUBSTRACTION TEST ==========")
    res = int(min_possible_int32 - max_possible_int32)
    println(res)
    println("")

    //Check direct multiplication
    println("========== DIRECT MULTIPLICATION TEST ==========")
    res = int(max_possible_int32 * max_possible_int32)
    println(res)
    println("")

    // Check indirect addition
    println("========== INDIRECT ADDITION TEST ==========")
    mut tmp := add(max_possible_int32, max_possible_int32)
    println(tmp)
    println("")

    // Check indirect substraction
    println("========== INDIRECT SUBSTRACTION TEST ==========")
    tmp = sub(min_possible_int32, max_possible_int32)
    println(tmp)
    println("")

    // Check indirect multiplication
    println("========== INDIRECT MULTIPLICATION TEST ==========")
    tmp = mul(max_possible_int32, max_possible_int32)
    println(tmp)
    println("")

    // Check direct division
    println("========== DIRECT DIVISION TEST ==========")
    mydiv := int(1/0)
    println(mydiv)
    println("")

    // Check indirect division
    // println("========== INDIRECT DIVISION TEST ==========")
    // mydiv = div(1,0)
    // println(mydiv)
    // println("")
}

Compiler output: none (just successfully compiling) Program output:

========== DITECT ADDITION TEST ==========
-2

========== DIRECT SUBSTRACTION TEST ==========
1

========== DIRECT MULTIPLICATION TEST ==========
1

========== INDIRECT ADDITION TEST ==========
-2

========== INDIRECT SUBSTRACTION TEST ==========
1                                               
========== INDIRECT MULTIPLICATION TEST ==========
1

========== DIRECT DIVISION TEST ==========
-65227424
angusluckmann commented 4 years ago

That should be it.

Ivo-Balbaert commented 4 years ago

The Direct Division Test now (v 0.1.27) gives a V error as it should: mydiv := int(1/0) // error: division by zero. Is this issue now solved?