spa-acp-tool: parse properties with spa_json

Fixes crash in parsing properties due to access after end of string.
This commit is contained in:
Pauli Virtanen 2024-12-07 14:23:04 +02:00
parent 51e7ed3421
commit 7d7019d939

View file

@ -10,8 +10,11 @@
#include <time.h> #include <time.h>
#include <stdbool.h> #include <stdbool.h>
#include <getopt.h> #include <getopt.h>
#include <alloca.h>
#include <spa/debug/context.h>
#include <spa/utils/string.h> #include <spa/utils/string.h>
#include <spa/utils/json.h>
#include <acp/acp.h> #include <acp/acp.h>
@ -587,40 +590,34 @@ static int do_probe(struct data *data)
uint32_t n_items = 0; uint32_t n_items = 0;
struct acp_dict_item items[64]; struct acp_dict_item items[64];
struct acp_dict props; struct acp_dict props;
struct spa_json it;
acp_set_log_func(log_func, data); acp_set_log_func(log_func, data);
acp_set_log_level(data->verbose); acp_set_log_level(data->verbose);
items[n_items++] = ACP_DICT_ITEM_INIT("use-ucm", "true"); items[n_items++] = ACP_DICT_ITEM_INIT("use-ucm", "true");
items[n_items++] = ACP_DICT_ITEM_INIT("verbose", data->verbose ? "true" : "false"); items[n_items++] = ACP_DICT_ITEM_INIT("verbose", data->verbose ? "true" : "false");
if (data->properties != NULL) {
char *p = data->properties, *e, f;
while (*p) { if (spa_json_begin_object_relax(&it, data->properties, strlen(data->properties)) > 0) {
const char *k, *v; char key[1024];
const char *value;
if ((e = strchr(p, '=')) == NULL) int len;
break; struct spa_error_location loc;
*e = '\0'; while ((len = spa_json_object_next(&it, key, sizeof(key), &value)) > 0) {
k = p; char *k = alloca(strlen(key) + 1);
p = e+1; char *v = alloca(len + 1);
memcpy(k, key, strlen(key) + 1);
if (*p == '\"') { spa_json_parse_stringn(value, len, v, len + 1);
p++;
f = '\"';
} else {
f = ' ';
}
if ((e = strchr(p, f)) == NULL &&
(e = strchr(p, '\0')) == NULL)
break;
*e = '\0';
v = p;
p = e+1;
items[n_items++] = ACP_DICT_ITEM_INIT(k, v); items[n_items++] = ACP_DICT_ITEM_INIT(k, v);
if (n_items == 64) if (n_items >= SPA_N_ELEMENTS(items))
break; break;
} }
if (spa_json_get_error(&it, data->properties, &loc)) {
struct spa_debug_context *c = NULL;
spa_debugc(c, "invalid --properties: %s", loc.reason);
spa_debugc_error_location(c, &loc);
return -EINVAL;
}
} }
props = ACP_DICT_INIT(items, n_items); props = ACP_DICT_INIT(items, n_items);
@ -714,7 +711,7 @@ int main(int argc, char *argv[])
{ {
int c, res; int c, res;
int longopt_index = 0, ret; int longopt_index = 0, ret;
struct data data = { 0, }; struct data data = { .properties = strdup("") };
data.verbose = 1; data.verbose = 1;
@ -735,6 +732,7 @@ int main(int argc, char *argv[])
data.card_index = ret; data.card_index = ret;
break; break;
case 'p': case 'p':
free(data.properties);
data.properties = strdup(optarg); data.properties = strdup(optarg);
break; break;
default: default: