summaryrefslogtreecommitdiffstats
path: root/options/m_option.c
diff options
context:
space:
mode:
Diffstat (limited to 'options/m_option.c')
-rw-r--r--options/m_option.c75
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(&param, 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)