as-json icon indicating copy to clipboard operation
as-json copied to clipboard

partial initialisation of deserialised class object - RuntimeError: out of bounds memory access

Open spino17 opened this issue 8 months ago • 5 comments

I am trying out below code which has some imports which gets length prefixed strings from memory. These host native imports implementation is closed. Below is the code


import { JSON } from "json-as/assembly";

// Runtime imported functions
// @ts-ignore
@external("env", "get_state")
declare function getState(): i32

// @ts-ignore
@external("env", "get_args")
declare function getArgs(): i32

// @ts-ignore
@external("env", "debug_log")
declare function debugLog(buf: ArrayBuffer): i32

// @ts-ignore
@external("env", "set_state")
declare function setState(buf: ArrayBuffer): i32

type GetFn = () => i32;

function readStringFromMemory(fn: GetFn): string {
    let ptr = fn()
    let len: i32 = load<u32>(ptr)
    let buffer = new Uint8Array(len);

    for (let i = 0; i < len; ++i) {
        buffer[i] = load<u8>(ptr + 4 + i);
    }

    let s = String.UTF8.decode(buffer.buffer);
	return s
}

function getLengthPrefixedString(s: string): ArrayBuffer {
    let stringBuf = Uint8Array.wrap(String.UTF8.encode(s))
    let newLen = stringBuf.byteLength
    let buffer = new ArrayBuffer(4 + newLen);
    let dataView = new DataView(buffer);

    dataView.setUint32(0, newLen, true);

    for (let i = 0; i < newLen; ++i) {
        dataView.setInt8(4 + i, stringBuf[i])
    }

    return buffer
}

@json
class TokenMetaData {
  id: u64;
  name: string;
  uri: string;

  constructor(id: u64, name: string, uri: string) {
    this.id = id;
    this.name = name;
    this.uri = uri;
  }
}

@json
class NonFungibleToken {
  owner: string;
  counter: u64;
  tokens: Map<u64, TokenMetaData>;
  owners: Map<u64, string>;
  balances: Map<string, u64[]>;

  constructor() {
    this.owner = "";
    this.counter = 0;
    this.tokens = new Map();
    this.owners = new Map();
    this.balances = new Map();
  }

  mint(name: string, uri: string, toAddress: string): u64 {
    this.counter += 1;
    let id = this.counter;

    const tokenMetaData = new TokenMetaData(id, name, uri);

    // beyond this point program fails with `out of memory bound access` error!
    this.tokens.set(id, tokenMetaData);
    this.owners.set(id, toAddress);

    if (!this.balances.has(toAddress)) {
      this.balances.set(toAddress, []);
    }

    this.balances.get(toAddress).push(id);

    return id;
  }
}


// Argument classes
@json
class NonfungibletokenMintArgs {
    name!: string;
    uri!: string;
    toAddress!: string;
}


// WASM exported functions
export function init(): void {
	let serializedState = JSON.stringify<NonFungibleToken>(new NonFungibleToken());
	let buffer = getLengthPrefixedString(serializedState);
	setState(buffer);
}

export function mint(): void {
    let state_str = readStringFromMemory(getState);
    debugLog(getLengthPrefixedString("inside wasm module state: " + state_str)); // only for testing

    let args_str = readStringFromMemory(getArgs);
    debugLog(getLengthPrefixedString("inside wasm module args: " + args_str)); // only for testing


    let state = JSON.parse<NonFungibleToken>(state_str);
    let args = JSON.parse<NonfungibletokenMintArgs>(args_str);
    // let state = JSON.parse<NonFungibleToken>('{"owner":"","counter":0,"tokens":{},"owners":{},"balances":{}}');
    // let args = JSON.parse<NonfungibletokenMintArgs>('{"name":"yamini","toAddress":"awesome","uri":"bhavya"}');

    state.mint(args.name, args.uri, args.toAddress);

    let serializedState = JSON.stringify<NonFungibleToken>(state);
    let buffer = getLengthPrefixedString(serializedState);
	setState(buffer);
}

I am not understanding where the issue is, when I am using hardcoded strings (commented in above code), it is working fine, but when I am reading it from the memory and then parsing it, it is only able to initialise just the counter field rest the maps seem to be uninitialised. Is this issue related to json-as or assemblyscript garbage collection? I even tried compiler option --runtime stub but same error is occurring.

spino17 avatar Jul 02 '24 07:07 spino17