From 611591d0fc7e62bb787ce5042ab626302e80dd96 Mon Sep 17 00:00:00 2001 From: Wim Taymans Date: Tue, 4 Jan 2022 12:35:09 +0100 Subject: [PATCH] json: add spa_json_parse_stringn() It also checks the destination size. --- pipewire-jack/src/match-rules.c | 3 ++- spa/include/spa/utils/json.h | 13 ++++++++++--- spa/plugins/bluez5/quirks.c | 3 ++- src/modules/module-filter-chain.c | 2 +- src/modules/module-protocol-pulse/quirks.c | 3 ++- src/pipewire/conf.c | 16 ++++++++-------- src/pipewire/properties.c | 2 +- src/tools/pw-cli.c | 2 +- test/test-spa-json.c | 6 +++--- 9 files changed, 30 insertions(+), 20 deletions(-) diff --git a/pipewire-jack/src/match-rules.c b/pipewire-jack/src/match-rules.c index 18324e764..77eb8e432 100644 --- a/pipewire-jack/src/match-rules.c +++ b/pipewire-jack/src/match-rules.c @@ -57,7 +57,8 @@ static bool find_match(struct spa_json *arr, const struct spa_dict *props) if (spa_json_is_null(value, len)) { success = str == NULL; } else { - spa_json_parse_string(value, SPA_MIN(len, 1023), val); + if (spa_json_parse_stringn(value, len, val, sizeof(val)) < 0) + continue; value = val; len = strlen(val); } diff --git a/spa/include/spa/utils/json.h b/spa/include/spa/utils/json.h index b00ec901e..b9b75fbb0 100644 --- a/spa/include/spa/utils/json.h +++ b/spa/include/spa/utils/json.h @@ -314,9 +314,11 @@ static inline bool spa_json_is_string(const char *val, int len) return len > 1 && *val == '"'; } -static inline int spa_json_parse_string(const char *val, int len, char *result) +static inline int spa_json_parse_stringn(const char *val, int len, char *result, int maxlen) { const char *p; + if (maxlen <= len) + return -1; if (!spa_json_is_string(val, len)) { if (result != val) strncpy(result, val, len); @@ -358,13 +360,18 @@ static inline int spa_json_parse_string(const char *val, int len, char *result) return 1; } +static inline int spa_json_parse_string(const char *val, int len, char *result) +{ + return spa_json_parse_stringn(val, len, result, len+1); +} + static inline int spa_json_get_string(struct spa_json *iter, char *res, int maxlen) { const char *value; int len; - if ((len = spa_json_next(iter, &value)) <= 0 || maxlen <= len) + if ((len = spa_json_next(iter, &value)) <= 0) return -1; - return spa_json_parse_string(value, len, res); + return spa_json_parse_stringn(value, len, res, maxlen); } static inline int spa_json_encode_string(char *str, int size, const char *val) diff --git a/spa/plugins/bluez5/quirks.c b/spa/plugins/bluez5/quirks.c index a53ebf692..217bb61f6 100644 --- a/spa/plugins/bluez5/quirks.c +++ b/spa/plugins/bluez5/quirks.c @@ -130,7 +130,8 @@ static int do_match(const char *rules, struct spa_dict *dict, uint32_t *no_featu if (spa_json_is_null(value, len)) { value = NULL; } else { - spa_json_parse_string(value, SPA_MIN(len, (int)sizeof(val)-1), val); + if (spa_json_parse_stringn(value, len, val, sizeof(val)) < 0) + continue; value = val; } diff --git a/src/modules/module-filter-chain.c b/src/modules/module-filter-chain.c index 7c4b52b50..2c6f56973 100644 --- a/src/modules/module-filter-chain.c +++ b/src/modules/module-filter-chain.c @@ -907,7 +907,7 @@ static int parse_config(struct node *node, struct spa_json *config) len = spa_json_container_len(config, val, len); if ((node->config = malloc(len+1)) != NULL) - spa_json_parse_string(val, len, node->config); + spa_json_parse_stringn(val, len, node->config, len+1); return 0; } diff --git a/src/modules/module-protocol-pulse/quirks.c b/src/modules/module-protocol-pulse/quirks.c index ecbf39637..8d218fa1d 100644 --- a/src/modules/module-protocol-pulse/quirks.c +++ b/src/modules/module-protocol-pulse/quirks.c @@ -94,7 +94,8 @@ static int match(const char *rules, struct spa_dict *dict, uint64_t *quirks) if (spa_json_is_null(value, len)) { value = NULL; } else { - spa_json_parse_string(value, SPA_MIN(len, (int)sizeof(val)-1), val); + if (spa_json_parse_stringn(value, len, val, sizeof(val)) < 0) + continue; value = val; } str = spa_dict_lookup(dict, key); diff --git a/src/pipewire/conf.c b/src/pipewire/conf.c index 1a19d4627..eee8c40c1 100644 --- a/src/pipewire/conf.c +++ b/src/pipewire/conf.c @@ -454,18 +454,18 @@ static int parse_modules(struct pw_context *context, char *str) if (spa_streq(key, "name")) { name = (char*)val; - spa_json_parse_string(val, len, name); + spa_json_parse_stringn(val, len, name, len+1); } else if (spa_streq(key, "args")) { if (spa_json_is_container(val, len)) len = spa_json_container_len(&it[2], val, len); args = (char*)val; - spa_json_parse_string(val, len, args); + spa_json_parse_stringn(val, len, args, len+1); } else if (spa_streq(key, "flags")) { if (spa_json_is_container(val, len)) len = spa_json_container_len(&it[2], val, len); flags = (char*)val; - spa_json_parse_string(val, len, flags); + spa_json_parse_stringn(val, len, flags, len+1); } } if (name != NULL) @@ -538,19 +538,19 @@ static int parse_objects(struct pw_context *context, char *str) if (spa_streq(key, "factory")) { factory = (char*)val; - spa_json_parse_string(val, len, factory); + spa_json_parse_stringn(val, len, factory, len+1); } else if (spa_streq(key, "args")) { if (spa_json_is_container(val, len)) len = spa_json_container_len(&it[2], val, len); args = (char*)val; - spa_json_parse_string(val, len, args); + spa_json_parse_stringn(val, len, args, len+1); } else if (spa_streq(key, "flags")) { if (spa_json_is_container(val, len)) len = spa_json_container_len(&it[2], val, len); flags = (char*)val; - spa_json_parse_string(val, len, flags); + spa_json_parse_stringn(val, len, flags, len+1); } } if (factory != NULL) @@ -625,10 +625,10 @@ static int parse_exec(struct pw_context *context, char *str) if (spa_streq(key, "path")) { path = (char*)val; - spa_json_parse_string(val, len, path); + spa_json_parse_stringn(val, len, path, len+1); } else if (spa_streq(key, "args")) { args = (char*)val; - spa_json_parse_string(val, len, args); + spa_json_parse_stringn(val, len, args, len+1); } } if (path != NULL) diff --git a/src/pipewire/properties.c b/src/pipewire/properties.c index cb1abf932..be52a7cc7 100644 --- a/src/pipewire/properties.c +++ b/src/pipewire/properties.c @@ -180,7 +180,7 @@ int pw_properties_update_string(struct pw_properties *props, const char *str, si len = spa_json_container_len(&it[1], value, len); if ((val = malloc(len+1)) != NULL) - spa_json_parse_string(value, len, val); + spa_json_parse_stringn(value, len, val, len+1); } count += pw_properties_set(&impl->this, key, val); free(val); diff --git a/src/tools/pw-cli.c b/src/tools/pw-cli.c index 4dcca9d91..a8f5d76d3 100644 --- a/src/tools/pw-cli.c +++ b/src/tools/pw-cli.c @@ -1632,7 +1632,7 @@ static int json_to_pod(struct spa_pod_builder *b, uint32_t id, } else { char *val = alloca(len+1); - spa_json_parse_string(value, len, val); + spa_json_parse_stringn(value, len, val, len+1); switch (info ? info->parent : SPA_TYPE_Struct) { case SPA_TYPE_Id: if ((ti = find_type_info(info->values, val)) != NULL) diff --git a/test/test-spa-json.c b/test/test-spa-json.c index 6b2dba56f..c4ae709ac 100644 --- a/test/test-spa-json.c +++ b/test/test-spa-json.c @@ -77,7 +77,7 @@ static void expect_string(struct spa_json *it, const char *str) pwtest_int_gt((len = spa_json_next(it, &value)), 0); check_type(TYPE_STRING, value, len); s = alloca(len+1); - spa_json_parse_string(value, len, s); + spa_json_parse_stringn(value, len, s, len+1); pwtest_str_eq(s, str); } static void expect_float(struct spa_json *it, float val) @@ -158,7 +158,7 @@ PWTEST(json_parse) PWTEST(json_encode) { - char dst[1024]; + char dst[128]; char dst4[4]; char dst6[6]; char result[1024]; @@ -172,7 +172,7 @@ PWTEST(json_encode) pwtest_str_eq(dst, "\"test\\\"\\n\\r \\t\\b\\f'\""); pwtest_int_eq(spa_json_encode_string(dst, sizeof(dst), "\x04\x05\x1f\x20\x01\x7f\x90"), 29); pwtest_str_eq(dst, "\"\\u0004\\u0005\\u001f \\u0001\x7f\x90\""); - pwtest_int_eq(spa_json_parse_string(dst, sizeof(dst), result), 1); + pwtest_int_eq(spa_json_parse_stringn(dst, sizeof(dst), result, sizeof(result)), 1); pwtest_str_eq(result, "\x04\x05\x1f\x20\x01\x7f\x90"); return PWTEST_PASS;