diff --git a/src/gvar.cpp b/src/gvar.cpp index 4b580061..95b64440 100644 --- a/src/gvar.cpp +++ b/src/gvar.cpp @@ -165,16 +165,8 @@ void GuestVariant::set(Sandbox &emu, const Variant &value) { case Variant::OBJECT: { // Objects are represented as uintptr_t godot::Object *obj = value.operator godot::Object *(); - // XXX: Information leak, we are exposing the object address to the guest - // TODO: Use a hash table to map object addresses to guest object IDs - godot::Node *node = godot::Object::cast_to(obj); - if (!node) { - ERR_PRINT("SetVariant(): Object is not a Node (unsupported!)"); - this->v.i = 0; - break; - } - emu.add_scoped_object(node); - this->v.i = (uintptr_t)node; + emu.add_scoped_object(obj); + this->v.i = (uintptr_t)obj; break; } case Variant::NODE_PATH: { // Node paths are represented as strings diff --git a/src/syscalls.cpp b/src/syscalls.cpp index 6d215ed5..8408561f 100644 --- a/src/syscalls.cpp +++ b/src/syscalls.cpp @@ -34,26 +34,44 @@ APICALL(api_vcall) { auto &emu = riscv::emu(machine); - std::array vargs; - std::array argptrs; - if (args_size > vargs.size()) { + if (args_size > 8) { emu.print("Too many arguments."); return; } const GuestVariant *args = emu.machine().memory.memarray(args_ptr, args_size); - for (size_t i = 0; i < args_size; i++) { - vargs[i] = args[i].toVariant(emu); - argptrs[i] = &vargs[i]; - } - GDExtensionCallError error; - auto *vcall = vp->toVariantPtr(emu); - Variant ret; - vcall->callp("call", argptrs.data(), args_size, ret, error); - vret->set(emu, ret); + if (vp->type == Variant::CALLABLE) { + std::array vargs; + std::array argptrs; + for (size_t i = 0; i < args_size; i++) { + vargs[i] = args[i].toVariant(emu); + argptrs[i] = &vargs[i]; + } + + auto *vcall = vp->toVariantPtr(emu); + Variant ret; + vcall->callp(String::utf8(method.data(), method.size()), argptrs.data(), args_size, ret, error); + vret->set(emu, ret); + } else if (vp->type == Variant::OBJECT) { + auto *obj = reinterpret_cast(uintptr_t(vp->v.i)); + if (!emu.is_scoped_object(obj)) { + ERR_PRINT("Object is not scoped"); + throw std::runtime_error("Object is not scoped"); + } + + Array vargs; + vargs.resize(args_size); + for (unsigned i = 0; i < args_size; i++) { + vargs[i] = args[i].toVariant(emu); + } + Variant ret = obj->callv(String::utf8(method.data(), method.size()), vargs); + vret->set(emu, ret); + } else { + ERR_PRINT("Invalid Variant type for Object::call"); + } } APICALL(api_veval) {