Skip to content
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

Cannot pass nested arrays/slices to foreign functions #4052

Open
ggiraldez opened this issue Jan 16, 2024 · 0 comments
Open

Cannot pass nested arrays/slices to foreign functions #4052

ggiraldez opened this issue Jan 16, 2024 · 0 comments
Labels
bug Something isn't working

Comments

@ggiraldez
Copy link
Contributor

Aim

For the debugger implementation in #3015 we are tracking variable values by instrumenting the code injecting foreign calls to a debugging oracle. To do that we need to be able to pass arrays nested inside other arrays. But because of how arrays are represented internally in the Brillig VM and how they are marshaled to foreign calls, this cannot be done. At best, the data received in the oracle function is incorrect, and at worst there is a panic at runtime.

Expected Behavior

We should be able to pass arbitrary data to oracle functions.

Bug

The bug happens because of the memory model used by the Brillig VM. Arrays are stored as a struct in memory with a pointer to the contents and a reference count. Slices (stored as heap vectors) are similar, but the struct includes the size in elements of the contents. Whenever an array or slice is an element of another array or slice, the value stored is a pointer to the array/slice itself.

But the code to read an array to construct a foreign call parameter has no knowledge of how to interpret the values stored in the array contents. This results in the VM gathering only the pointers to the inner arrays/slices instead of the contents of them. The foreign call code OTOH, expects the arrays to be flattened.

To Reproduce

This program will panic at runtime when executing with nargo execute

use dep::std;

fn main() {
    let x = [333, 444, 555];
    let y = [666, 777, 888];
    let a = [x, y];
    std::println(a);
}

with the following error:

The application panicked (crashed).
Message:  called `Option::unwrap()` on a `None` value
Location: compiler/noirc_printable_type/src/lib.rs:307

This is a bug. We may have already fixed this in newer versions of Nargo so try searching for similar issues at https://github.com/noir-lang/noir/issues/.
If there isn't an open issue for this bug, consider opening one at https://github.com/noir-lang/noir/issues/new?labels=bug&template=bug_report.yml

This variation will not crash but print incorrect data:

use dep::std;

fn main() {
    let a = [[123]];
    std::println(a);
}

The value printed will correspond to the location in memory where the inner array is stored, instead of the value 123. This doesn't crash because the foreign call parameter contains the expected number of values, a single element.

Installation Method

Binary

Nargo Version

nargo version = 0.22.0 noirc version = 0.22.0+420a5c74a14dcfeede04337a42282093a7b5e63e (git version hash: 420a5c7, is dirty: false)

Additional Context

No response

Would you like to submit a PR for this Issue?

Yes

Support Needs

No response

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
Status: 📋 Backlog
1 participant