Skip to content

FunC codegen error for obvious cases of zero division in statements #716

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
anton-trunov opened this issue Aug 19, 2024 · 4 comments · May be fixed by #1596
Open

FunC codegen error for obvious cases of zero division in statements #716

anton-trunov opened this issue Aug 19, 2024 · 4 comments · May be fixed by #1596
Assignees
Labels
kind: bug Something isn't working or isn't right misc: func Any issues related to FunC scope: partial-eval The constant and partial evaluation optimization mechanisms (src/optimizer/constEval.ts)
Milestone

Comments

@anton-trunov
Copy link
Member

contract Test {

    a: Int = 0;

    init() {
        self.a / self.a;
        // self. a / 0 would fail too
    }

    get fun foo(): Int {
        let x = 42 - 42;
        return 42 / x;   // this also fails
    }
}

Results in the following error message from FunC:

Func compilation error: cannot generate code for function `$Test$_contract_init`:
/dist/tact_Test.code.fc:15:14: error: division by zero
($self'a / $self'a)

As far as I understand this happens during code generation when going from FunC to Fift-asm.

To resolve this, we need to track variables whose values can be determined at compile-time.

@anton-trunov anton-trunov added kind: bug Something isn't working or isn't right scope: const-eval labels Aug 19, 2024
@jeshecdom
Copy link
Contributor

Mmmm... the main problem I see here is that const-eval (or the interpreter) is only called to simplify expressions. For example, inside function foo, it is called to simplify the argument of the return. const-eval will not execute function foo because there is no expression calling function foo. As such, it will treat variable x in the return statement as uninterpreted.

To solve this issue, we would need some form of code analysis outside of const-eval. Another possibility would be to attempt calling functions that do not have parameters, just to check if its execution generates an error.
Probably, we will need an analysis/optimization pass after the typecheck pass, because currently, optimization and interpretation is only carried out on pieces of the code (in expressions, to be exact).

@anton-trunov
Copy link
Member Author

To solve this issue, we would need some form of code analysis outside of const-eval.

To solve this issue you need to partially evaluate contracts (I almost always mean partial evaluation or constant evaluation by "const-eval", sorry if that's confusing)

@anton-trunov anton-trunov added the misc: func Any issues related to FunC label Aug 31, 2024
@anton-trunov anton-trunov added this to the v1.5.0 milestone Sep 5, 2024
@anton-trunov anton-trunov modified the milestones: v1.5.0, v1.6.0 Sep 15, 2024
@verytactical verytactical added scope: partial-eval The constant and partial evaluation optimization mechanisms (src/optimizer/constEval.ts) and removed scope: const-eval labels Jan 20, 2025
@jeshecdom jeshecdom linked a pull request Jan 27, 2025 that will close this issue
5 tasks
@anton-trunov anton-trunov modified the milestones: v1.6.0, v1.7.0 Feb 18, 2025
@Gusarich Gusarich marked this as a duplicate of #2454 Mar 24, 2025
@Gusarich
Copy link
Member

this fails too (explicit / 0 without "hiding" it):

contract EdgeCases {
    fun testShortCircuit(x: Int): Bool {
        return x != 0 || (x / 0 == 1);
    }

    receive () {
        self.testShortCircuit(1);
    }
}

LLM Fuzzing discovery (see #2490)

@jeshecdom
Copy link
Contributor

this fails too (explicit / 0 without "hiding" it):

contract EdgeCases {
fun testShortCircuit(x: Int): Bool {
return x != 0 || (x / 0 == 1);
}

receive () {
    self.testShortCircuit(1);
}

}

LLM Fuzzing discovery (see #2490)

In this one, FunC reports an error, but the program would not produce a division by zero at runtime, because testShortCircuit is called with parameter 1. However, if the parameter is 0, it would produce the division by zero at runtime.

Hence, I think that analyzing testShortCircuit in isolation should not issue an error, because it cannot determine that there is a division by zero with certainty, because the value of x is not known, and as such, one possible execution of || is safe, but the other one is not.

It will depend of what we want for the analyzer. Either: to report an error if there is a potential division by zero (as FunC does in this case), or to report an error only if there is a certain division by zero.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
kind: bug Something isn't working or isn't right misc: func Any issues related to FunC scope: partial-eval The constant and partial evaluation optimization mechanisms (src/optimizer/constEval.ts)
Projects
None yet
4 participants