diff options
Diffstat (limited to 'options/m_option.c')
-rw-r--r-- | options/m_option.c | 75 |
1 files changed, 57 insertions, 18 deletions
diff --git a/options/m_option.c b/options/m_option.c index 3d9ae26669..88ed04865c 100644 --- a/options/m_option.c +++ b/options/m_option.c @@ -28,7 +28,6 @@ #include <stdarg.h> #include <limits.h> #include <inttypes.h> -#include <unistd.h> #include <assert.h> #include <libavutil/common.h> @@ -2918,10 +2917,18 @@ static void obj_settings_list_del_at(m_obj_settings_t **p_obj_list, int idx) // Insert such that *p_obj_list[idx] is set to item. // If idx < 0, set idx = count + idx + 1 (i.e. -1 inserts it as last element). // Memory referenced by *item is not copied. -static void obj_settings_list_insert_at(m_obj_settings_t **p_obj_list, int idx, +static bool obj_settings_list_insert_at(struct mp_log *log, + m_obj_settings_t **p_obj_list, int idx, m_obj_settings_t *item) { int num = obj_settings_list_num_items(*p_obj_list); + // Limit list entries to 100. obj_settings_list is not designed to hold more + // items, and it quickly starts taking ages to add all items. + if (num > 100) { + mp_warn(log, "Object settings list capacity exceeded: " + "a maximum of 100 elements is allowed."); + return false; + } if (idx < 0) idx = num + idx + 1; assert(idx >= 0 && idx <= num); @@ -2931,6 +2938,7 @@ static void obj_settings_list_insert_at(m_obj_settings_t **p_obj_list, int idx, (num - idx) * sizeof(m_obj_settings_t)); (*p_obj_list)[idx] = *item; (*p_obj_list)[num + 1] = (m_obj_settings_t){0}; + return true; } static int obj_settings_list_find_by_label(m_obj_settings_t *obj_list, @@ -3267,7 +3275,10 @@ done: ; .enabled = enabled, .attribs = plist, }; - obj_settings_list_insert_at(_ret, -1, &item); + if (!obj_settings_list_insert_at(log, _ret, -1, &item)) { + obj_setting_free(&item); + return M_OPT_OUT_OF_RANGE; + } return 1; } @@ -3309,6 +3320,7 @@ static int parse_obj_settings_list(struct mp_log *log, const m_option_t *opt, bool *mark_del = NULL; int num_items = obj_settings_list_num_items(dst ? VAL(dst) : 0); const struct m_obj_list *ol = opt->priv; + int ret = 1; assert(opt->priv); @@ -3346,7 +3358,8 @@ static int parse_obj_settings_list(struct mp_log *log, const m_option_t *opt, opt->name, opt->name, opt->name, opt->name, opt->name, opt->name, opt->name, opt->name); - return M_OPT_EXIT; + ret = M_OPT_EXIT; + goto done; } if (!bstrcmp0(param, "help")) { @@ -3367,24 +3380,29 @@ static int parse_obj_settings_list(struct mp_log *log, const m_option_t *opt, mp_info(log, "Get help on individual entries via: --%s=entry=help\n", opt->name); } - return M_OPT_EXIT; + ret = M_OPT_EXIT; + goto done; } if (op == OP_CLR) { if (param.len) { mp_err(log, "Option %.*s: -clr does not take an argument.\n", BSTR_P(name)); - return M_OPT_INVALID; + ret = M_OPT_INVALID; + goto done; } if (dst) free_obj_settings_list(dst); - return 0; + ret = 0; + goto done; } else if (op == OP_REMOVE) { mark_del = talloc_zero_array(NULL, bool, num_items + 1); } - if (op != OP_NONE && param.len == 0) - return M_OPT_MISSING_PARAM; + if (op != OP_NONE && param.len == 0) { + ret = M_OPT_MISSING_PARAM; + goto done; + } while (param.len > 0) { int r = 0; @@ -3395,24 +3413,31 @@ static int parse_obj_settings_list(struct mp_log *log, const m_option_t *opt, } if (r < 0) { free_obj_settings_list(&res); - return r; + ret = r; + goto done; } if (param.len > 0) { const char sep[2] = {OPTION_LIST_SEPARATOR, 0}; if (!bstr_eatstart0(¶m, sep)) { free_obj_settings_list(&res); - return M_OPT_INVALID; + ret = M_OPT_INVALID; + goto done; } if (param.len == 0) { if (!ol->allow_trailer) { free_obj_settings_list(&res); - return M_OPT_INVALID; + ret = M_OPT_INVALID; + goto done; } if (dst) { m_obj_settings_t item = { .name = talloc_strdup(NULL, ""), }; - obj_settings_list_insert_at(&res, -1, &item); + if (!obj_settings_list_insert_at(log, &res, -1, &item)) { + obj_setting_free(&item); + ret = M_OPT_OUT_OF_RANGE; + goto done; + } } } } @@ -3423,7 +3448,8 @@ static int parse_obj_settings_list(struct mp_log *log, const m_option_t *opt, mp_err(log, "Option %.*s: -append takes only 1 item (no ',').\n", BSTR_P(name)); free_obj_settings_list(&res); - return M_OPT_INVALID; + ret = M_OPT_INVALID; + goto done; } mp_warn(log, "Passing more than 1 argument to %.*s is deprecated!\n", BSTR_P(name)); @@ -3436,7 +3462,11 @@ static int parse_obj_settings_list(struct mp_log *log, const m_option_t *opt, for (int n = 0; res && res[n].name; n++) { int label = obj_settings_list_find_by_label0(list, res[n].label); if (label < 0) { - obj_settings_list_insert_at(&list, prepend_counter, &res[n]); + if (!obj_settings_list_insert_at(log, &list, prepend_counter, &res[n])) { + obj_setting_free(&res[n]); + ret = M_OPT_OUT_OF_RANGE; + goto done; + } prepend_counter++; } else { // Prefer replacement semantics, instead of actually @@ -3450,7 +3480,11 @@ static int parse_obj_settings_list(struct mp_log *log, const m_option_t *opt, for (int n = 0; res && res[n].name; n++) { int label = obj_settings_list_find_by_label0(list, res[n].label); if (label < 0) { - obj_settings_list_insert_at(&list, -1, &res[n]); + if (!obj_settings_list_insert_at(log, &list, -1, &res[n])) { + obj_setting_free(&res[n]); + ret = M_OPT_OUT_OF_RANGE; + goto done; + } } else { // Prefer replacement semantics, instead of actually // appending. @@ -3475,7 +3509,11 @@ static int parse_obj_settings_list(struct mp_log *log, const m_option_t *opt, } else { int found = obj_settings_find_by_content(list, &res[n]); if (found < 0) { - obj_settings_list_insert_at(&list, -1, &res[n]); + if (!obj_settings_list_insert_at(log, &list, -1, &res[n])) { + obj_setting_free(&res[n]); + ret = M_OPT_OUT_OF_RANGE; + goto done; + } } else { obj_settings_list_del_at(&list, found); obj_setting_free(&res[n]); @@ -3502,8 +3540,9 @@ static int parse_obj_settings_list(struct mp_log *log, const m_option_t *opt, VAL(dst) = list; } +done: talloc_free(mark_del); - return 1; + return ret; } static void append_param(char **res, char *param) |