summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorwm4 <wm4@nowhere>2020-03-18 20:51:38 +0100
committerwm4 <wm4@nowhere>2020-03-18 20:51:38 +0100
commit41e96d8b6bdef6afffe8fc89b2f09cae31e9a8da (patch)
tree87425cacd9e8f02241b69f493c8ba833c666ccd9
parenta550bf49275a4af232fbbd6a47ba2ce32a9ea98c (diff)
downloadmpv-41e96d8b6bdef6afffe8fc89b2f09cae31e9a8da.tar.bz2
mpv-41e96d8b6bdef6afffe8fc89b2f09cae31e9a8da.tar.xz
options: fix OPT_BYTE_SIZE upper limits
As an unfortunate disaster, min/max values use the type double, which causes tons of issues with int64_t types. Anyway, OPT_BYTE_SIZE is often used as maximum for size_t quantities, which can have a size different from (u)int64_t. OPT_BYTE_SIZE still uses in64_t, because in theory, you could use it for file sizes. (demux.c would for example be capable of caching more than 2GB on 32 bit platforms if a file cache is used. Though for some reason the accounting code still uses size_t, so that use case is broken. But still insist that it _could_ be used this way.) There were various inconsistent attempts to set m_option.max to a value such that the size_t/int64_t upper limit is not exceeded. Due to the double max field, this didn't really work correctly. Try to fix this with the M_MAX_MEM_BYTES constant. It's a good approximation, because on 32 bit it should allow 2GB (untested, also would probably exhaust address space in practice but whatever), and something "high enough" in 64 bit. For some reason, clang 11 still warns. But I think this might be a clang bug, or I'm crazy. The result is correct anyway.
-rw-r--r--demux/demux.c8
-rw-r--r--filters/f_decoder_wrapper.c6
-rw-r--r--options/m_option.h3
3 files changed, 8 insertions, 9 deletions
diff --git a/demux/demux.c b/demux/demux.c
index f5ced47887..478029b35a 100644
--- a/demux/demux.c
+++ b/demux/demux.c
@@ -106,8 +106,6 @@ struct demux_opts {
#define OPT_BASE_STRUCT struct demux_opts
-#define MAX_BYTES MPMIN(INT64_MAX, SIZE_MAX / 2)
-
static bool get_demux_sub_opts(int index, const struct m_sub_options **sub);
const struct m_sub_options demux_conf = {
@@ -116,12 +114,10 @@ const struct m_sub_options demux_conf = {
{"no", 0}, {"auto", -1}, {"yes", 1})},
{"cache-on-disk", OPT_FLAG(disk_cache)},
{"demuxer-readahead-secs", OPT_DOUBLE(min_secs), M_RANGE(0, DBL_MAX)},
- // (The MAX_BYTES sizes may not be accurate because the max field is
- // of double type.)
{"demuxer-max-bytes", OPT_BYTE_SIZE(max_bytes),
- M_RANGE(0, MAX_BYTES)},
+ M_RANGE(0, M_MAX_MEM_BYTES)},
{"demuxer-max-back-bytes", OPT_BYTE_SIZE(max_bytes_bw),
- M_RANGE(0, MAX_BYTES)},
+ M_RANGE(0, M_MAX_MEM_BYTES)},
{"demuxer-donate-buffer", OPT_FLAG(donate_fw)},
{"force-seekable", OPT_FLAG(force_seekable)},
{"cache-secs", OPT_DOUBLE(min_secs_cache), M_RANGE(0, DBL_MAX),
diff --git a/filters/f_decoder_wrapper.c b/filters/f_decoder_wrapper.c
index b49ec921c1..d96c780e9c 100644
--- a/filters/f_decoder_wrapper.c
+++ b/filters/f_decoder_wrapper.c
@@ -65,7 +65,7 @@ struct dec_queue_opts {
static const struct m_option dec_queue_opts_list[] = {
{"enable", OPT_FLAG(use_queue)},
{"max-secs", OPT_DOUBLE(max_duration), M_RANGE(0, DBL_MAX)},
- {"max-bytes", OPT_BYTE_SIZE(max_bytes), M_RANGE(0, (size_t)-1)},
+ {"max-bytes", OPT_BYTE_SIZE(max_bytes), M_RANGE(0, M_MAX_MEM_BYTES)},
{"max-samples", OPT_INT64(max_samples), M_RANGE(0, DBL_MAX)},
{0}
};
@@ -130,9 +130,9 @@ const struct m_sub_options dec_wrapper_conf = {
{"vd-queue", OPT_SUBSTRUCT(vdec_queue_opts, vdec_queue_conf)},
{"ad-queue", OPT_SUBSTRUCT(adec_queue_opts, adec_queue_conf)},
{"video-reversal-buffer", OPT_BYTE_SIZE(video_reverse_size),
- M_RANGE(0, (size_t)-1)},
+ M_RANGE(0, M_MAX_MEM_BYTES)},
{"audio-reversal-buffer", OPT_BYTE_SIZE(audio_reverse_size),
- M_RANGE(0, (size_t)-1)},
+ M_RANGE(0, M_MAX_MEM_BYTES)} ,
{0}
},
.size = sizeof(struct dec_wrapper_opts),
diff --git a/options/m_option.h b/options/m_option.h
index fc48b42bd2..84336ae3ce 100644
--- a/options/m_option.h
+++ b/options/m_option.h
@@ -627,6 +627,9 @@ extern const char m_option_path_separator;
#define OPT_BYTE_SIZE(field) \
OPT_TYPED_FIELD(m_option_type_byte_size, int64_t, field)
+// (Approximation of x<=SIZE_MAX/2 for m_option.max, which is double.)
+#define M_MAX_MEM_BYTES MPMIN((1ULL << 62), (size_t)-1 / 2)
+
#define OPT_GEOMETRY(field) \
OPT_TYPED_FIELD(m_option_type_geometry, struct m_geometry, field)