ucode-mod-lua: various fixes
Properly handle accesses to properties of the userdatum itself in the lua_uv_index() __index metamethod and treat integer keys as array indexes in case of wrapped ucode array values. Also fix an incorrect refcount decrement in the function. Also fix uc_lua_vm_get() and uc_lua_lv_getraw() to gracefully handle accesses to not defined or non-table values and ensure that those functions properly reset the Lua stack after they complete. Signed-off-by: Jo-Philipp Wich <jo@mein.io>
This commit is contained in:
parent
36460dfd53
commit
629eb171b7
1 changed files with 31 additions and 11 deletions
|
@ -460,17 +460,20 @@ lua_uv_index(lua_State *L)
|
||||||
{
|
{
|
||||||
ucv_userdata_t *ud = luaL_checkudata(L, 1, "ucode.value");
|
ucv_userdata_t *ud = luaL_checkudata(L, 1, "ucode.value");
|
||||||
const char *key = luaL_checkstring(L, 2);
|
const char *key = luaL_checkstring(L, 2);
|
||||||
uc_value_t *proto, *rv;
|
long long idx;
|
||||||
bool found;
|
char *e;
|
||||||
|
|
||||||
proto = ucv_prototype_get(ud->uv);
|
if (ucv_type(ud->uv) == UC_ARRAY) {
|
||||||
rv = ucv_object_get(proto, key, &found);
|
idx = strtoll(key, &e, 10);
|
||||||
|
|
||||||
if (!found)
|
if (e != key && *e == 0 && idx >= 1 && idx <= (long long)ucv_array_length(ud->uv)) {
|
||||||
return 0;
|
ucv_to_lua(ud->vm, ucv_array_get(ud->uv, (size_t)(idx - 1)), L, NULL);
|
||||||
|
|
||||||
ucv_to_lua(ud->vm, rv, L, NULL);
|
return 1;
|
||||||
ucv_put(rv);
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ucv_to_lua(ud->vm, ucv_property_get(ud->uv, key), L, NULL);
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
@ -687,13 +690,22 @@ uc_lua_vm_get(uc_vm_t *vm, size_t nargs)
|
||||||
uc_value_t *key = uc_fn_arg(0);
|
uc_value_t *key = uc_fn_arg(0);
|
||||||
lua_resource_t *lv;
|
lua_resource_t *lv;
|
||||||
size_t i;
|
size_t i;
|
||||||
|
int top;
|
||||||
|
|
||||||
if (!L || !*L || ucv_type(key) != UC_STRING)
|
if (!L || !*L || ucv_type(key) != UC_STRING)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
|
top = lua_gettop(*L);
|
||||||
|
|
||||||
lua_getglobal(*L, ucv_string_get(key));
|
lua_getglobal(*L, ucv_string_get(key));
|
||||||
|
|
||||||
for (i = 1; i < nargs; i++) {
|
for (i = 1; i < nargs; i++) {
|
||||||
|
if (lua_type(*L, -1) != LUA_TTABLE) {
|
||||||
|
lua_settop(*L, top);
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
ucv_to_lua(vm, uc_fn_arg(i), *L, NULL);
|
ucv_to_lua(vm, uc_fn_arg(i), *L, NULL);
|
||||||
lua_gettable(*L, -2);
|
lua_gettable(*L, -2);
|
||||||
}
|
}
|
||||||
|
@ -702,8 +714,7 @@ uc_lua_vm_get(uc_vm_t *vm, size_t nargs)
|
||||||
lv->ref = luaL_ref(*L, LUA_REGISTRYINDEX);
|
lv->ref = luaL_ref(*L, LUA_REGISTRYINDEX);
|
||||||
lv->uvL = ucv_this_to_uvL(vm);
|
lv->uvL = ucv_this_to_uvL(vm);
|
||||||
|
|
||||||
if (nargs > 1)
|
lua_settop(*L, top);
|
||||||
lua_pop(*L, nargs - 1);
|
|
||||||
|
|
||||||
return uc_resource_new(lv_type, lv);
|
return uc_resource_new(lv_type, lv);
|
||||||
}
|
}
|
||||||
|
@ -788,15 +799,24 @@ uc_lua_lv_get_common(uc_vm_t *vm, size_t nargs, bool raw)
|
||||||
lua_State *L = uc_lua_lv_to_L(lv);
|
lua_State *L = uc_lua_lv_to_L(lv);
|
||||||
uc_value_t *key;
|
uc_value_t *key;
|
||||||
size_t i;
|
size_t i;
|
||||||
|
int top;
|
||||||
|
|
||||||
if (!L)
|
if (!L)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
|
top = lua_gettop(L);
|
||||||
|
|
||||||
lua_rawgeti(L, LUA_REGISTRYINDEX, (*lv)->ref);
|
lua_rawgeti(L, LUA_REGISTRYINDEX, (*lv)->ref);
|
||||||
|
|
||||||
for (i = 0; i < nargs; i++) {
|
for (i = 0; i < nargs; i++) {
|
||||||
key = uc_fn_arg(i);
|
key = uc_fn_arg(i);
|
||||||
|
|
||||||
|
if (lua_type(L, -1) != LUA_TTABLE) {
|
||||||
|
lua_settop(L, top);
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
if (raw) {
|
if (raw) {
|
||||||
if (ucv_type(key) == UC_INTEGER) {
|
if (ucv_type(key) == UC_INTEGER) {
|
||||||
lua_rawgeti(L, -1, (int)ucv_int64_get(key));
|
lua_rawgeti(L, -1, (int)ucv_int64_get(key));
|
||||||
|
@ -816,7 +836,7 @@ uc_lua_lv_get_common(uc_vm_t *vm, size_t nargs, bool raw)
|
||||||
ref->ref = luaL_ref(L, LUA_REGISTRYINDEX);
|
ref->ref = luaL_ref(L, LUA_REGISTRYINDEX);
|
||||||
ref->uvL = ucv_this_to_uvL(vm);
|
ref->uvL = ucv_this_to_uvL(vm);
|
||||||
|
|
||||||
lua_pop(L, nargs);
|
lua_settop(L, top);
|
||||||
|
|
||||||
return uc_resource_new(lv_type, ref);
|
return uc_resource_new(lv_type, ref);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue