lua/api: fix client update_permissions()

* the type checks were wrong, it was requiring the key to be string
  and the value integer
* add the ability to use "any" or "all" for a key, saving us the trouble
  of passing -1 from lua (int64) into a uint32 (ugh!)
* use a GArray instead of manual malloc/realloc
* allocate the array as late as possible, to minimize the risk of leaking
  its memory if we hit luaL_error()
This commit is contained in:
George Kiagiadakis
2021-02-18 16:41:42 +02:00
parent e6112d7579
commit d6ea7ffe76

View File

@@ -891,35 +891,25 @@ impl_node_new (lua_State *L)
static gboolean static gboolean
client_parse_permissions (const gchar * perms_str, guint32 *perms) client_parse_permissions (const gchar * perms_str, guint32 *perms)
{ {
guint32 res = 0; *perms = 0;
if (g_strcmp0 (perms_str, "all") == 0) { if (!perms_str)
res = PW_PERM_ALL; return FALSE;
} else { else if (g_strcmp0 (perms_str, "all") == 0)
*perms = PW_PERM_ALL;
else {
for (guint i = 0; i < strlen (perms_str); i++) { for (guint i = 0; i < strlen (perms_str); i++) {
switch (perms_str[i]) { switch (perms_str[i]) {
case 'r': case 'r': *perms |= PW_PERM_R; break;
res |= PW_PERM_R; case 'w': *perms |= PW_PERM_W; break;
break; case 'x': *perms |= PW_PERM_X; break;
case 'w': case 'm': *perms |= PW_PERM_M; break;
res |= PW_PERM_W; case '-': break;
break;
case 'x':
res |= PW_PERM_X;
break;
case 'm':
res |= PW_PERM_M;
case '-':
break;
default: default:
return FALSE; return FALSE;
} }
} }
} }
if (perms)
*perms = res;
return TRUE; return TRUE;
} }
@@ -927,35 +917,35 @@ static int
client_update_permissions (lua_State *L) client_update_permissions (lua_State *L)
{ {
WpClient *client = wplua_checkobject (L, 1, WP_TYPE_CLIENT); WpClient *client = wplua_checkobject (L, 1, WP_TYPE_CLIENT);
guint n_perm = 0; g_autoptr (GArray) arr = NULL;
guint size = 16;
g_autofree struct pw_permission *arr =
g_malloc0_n (size, sizeof (struct pw_permission));
luaL_checktype (L, 2, LUA_TTABLE); luaL_checktype (L, 2, LUA_TTABLE);
lua_pushnil(L); lua_pushnil(L);
while (lua_next (L, -2)) { while (lua_next (L, -2)) {
if (lua_type (L, -1) == LUA_TNUMBER && lua_type (L, -2) == LUA_TSTRING) { struct pw_permission perm = {0};
guint32 id = lua_tointeger (L, -2);
const gchar *perms_str = lua_tostring (L, -1); if (lua_type (L, -2) == LUA_TSTRING &&
guint32 perms = 0; (!g_ascii_strcasecmp (lua_tostring(L, -2), "any") ||
if (client_parse_permissions (perms_str, &perms)) { !g_ascii_strcasecmp (lua_tostring(L, -2), "all")))
if (size < n_perm) { perm.id = PW_ID_ANY;
size += 16; else if (lua_isinteger (L, -2))
arr = g_realloc (arr, size * sizeof (struct pw_permission)); perm.id = lua_tointeger (L, -2);
} else
arr[n_perm].id = id; luaL_error (L, "invalid key for permissions array");
arr[n_perm].permissions = perms;
n_perm++; if (!client_parse_permissions (lua_tostring (L, -1), &perm.permissions))
} else { luaL_error (L, "invalid permission string: '%s'", lua_tostring (L, -1));
wp_warning ("Ignored invalid permission '%s'", perms_str);
} if (!arr)
} arr = g_array_new (FALSE, FALSE, sizeof (struct pw_permission));
g_array_append_val (arr, perm);
lua_pop (L, 1); lua_pop (L, 1);
} }
wp_client_update_permissions_array (client, n_perm, arr); wp_client_update_permissions_array (client, arr->len,
(const struct pw_permission *) arr->data);
return 0; return 0;
} }