From b3b542af518742e0ac065f58ac52365af22e079b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kacper=20Michaj=C5=82ow?= Date: Mon, 17 Jun 2024 19:56:52 +0200 Subject: [PATCH] m_options: limit list entries to 100 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. 100 is more than enough. Fixes 30s timeout on OSS-Fuzz and generally fixes possible DoS on mpv. --- DOCS/man/mpv.rst | 2 ++ options/m_option.c | 40 ++++++++++++++++++++++++++++++++++------ 2 files changed, 36 insertions(+), 6 deletions(-) diff --git a/DOCS/man/mpv.rst b/DOCS/man/mpv.rst index 3b29124ea7..9f8207865b 100644 --- a/DOCS/man/mpv.rst +++ b/DOCS/man/mpv.rst @@ -671,6 +671,8 @@ Options of this type can be changed at runtime using the ``change-list`` command, which takes the suffix (without the ``-``) as separate operation parameter. +An object settings list can hold up to 100 elements. + CONFIGURATION FILES =================== diff --git a/options/m_option.c b/options/m_option.c index 5a988ae69b..88ed04865c 100644 --- a/options/m_option.c +++ b/options/m_option.c @@ -2917,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); @@ -2930,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, @@ -3266,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; } @@ -3421,7 +3433,11 @@ static int parse_obj_settings_list(struct mp_log *log, const m_option_t *opt, 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; + } } } } @@ -3446,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 @@ -3460,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. @@ -3485,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]);