Skip to content

Commit 19b6157

Browse files
committed
Merge branch 'fix/pls-input-limit' of github.com:acts-1631/MPD into v0.24.x
2 parents 4c8af76 + daf13d3 commit 19b6157

5 files changed

Lines changed: 86 additions & 2 deletions

File tree

NEWS

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ ver 0.24.15 (not yet released)
22
* protocol
33
- fix crash on "sticker delete"
44
* playlist
5-
- asx, rss, xspf: limit to 16 MB
5+
- asx, pls, rss, xspf: limit to 16 MB
66
- cue: fix problem playing CUE tracks in music directory root
77

88
ver 0.24.14 (2026/08/13)

src/input/LimitedInputStream.cxx

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
// SPDX-License-Identifier: GPL-2.0-or-later
2+
// Copyright The Music Player Daemon Project
3+
4+
#include "LimitedInputStream.hxx"
5+
6+
#include <cassert>
7+
#include <stdexcept>
8+
9+
LimitedInputStream::LimitedInputStream(InputStreamPtr _input,
10+
const offset_type max_size)
11+
:ProxyInputStream(std::move(_input)), remaining(max_size)
12+
{
13+
ProxyInputStream::Update();
14+
Check();
15+
}
16+
17+
void
18+
LimitedInputStream::CheckSize()
19+
{
20+
if (size_checked || !IsReady())
21+
return;
22+
23+
if (input->KnownSize() && input->GetRest() > remaining)
24+
throw std::runtime_error("Input stream is too large");
25+
26+
size_checked = true;
27+
}
28+
29+
void
30+
LimitedInputStream::Check()
31+
{
32+
ProxyInputStream::Check();
33+
CheckSize();
34+
}
35+
36+
std::size_t
37+
LimitedInputStream::Read(std::unique_lock<Mutex> &lock,
38+
std::span<std::byte> dest)
39+
{
40+
assert(!dest.empty());
41+
42+
if (remaining < dest.size())
43+
dest = dest.first(static_cast<std::size_t>(remaining) + 1);
44+
45+
const std::size_t nbytes = input->Read(lock, dest);
46+
if (nbytes > remaining)
47+
throw std::runtime_error("Input stream is too large");
48+
49+
remaining -= nbytes;
50+
CopyAttributes();
51+
return nbytes;
52+
}

src/input/LimitedInputStream.hxx

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
// SPDX-License-Identifier: GPL-2.0-or-later
2+
// Copyright The Music Player Daemon Project
3+
4+
#pragma once
5+
6+
#include "ProxyInputStream.hxx"
7+
8+
/**
9+
* An #InputStream proxy which limits the amount of data that may be
10+
* read from the underlying stream.
11+
*/
12+
class LimitedInputStream final : public ProxyInputStream {
13+
offset_type remaining;
14+
bool size_checked = false;
15+
16+
void CheckSize();
17+
18+
public:
19+
LimitedInputStream(InputStreamPtr _input, offset_type max_size);
20+
21+
/* virtual methods from class InputStream */
22+
void Check() override;
23+
std::size_t Read(std::unique_lock<Mutex> &lock,
24+
std::span<std::byte> dest) override;
25+
};

src/input/meson.build

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ input_basic = static_library(
2323
'input_basic',
2424
'AsyncInputStream.cxx',
2525
'LastInputStream.cxx',
26+
'LimitedInputStream.cxx',
2627
'MemoryInputStream.cxx',
2728
'ProxyInputStream.cxx',
2829
'RewindInputStream.cxx',

src/playlist/plugins/PlsPlaylistPlugin.cxx

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
#include "PlsPlaylistPlugin.hxx"
55
#include "../PlaylistPlugin.hxx"
66
#include "../MemorySongEnumerator.hxx"
7+
#include "input/LimitedInputStream.hxx"
78
#include "input/TextInputStream.hxx"
89
#include "input/InputStream.hxx"
910
#include "song/DetachedSong.hxx"
@@ -19,6 +20,9 @@
1920

2021
using std::string_view_literals::operator""sv;
2122

23+
/* PLS playlists are materialized before any songs are returned. */
24+
static constexpr offset_type PLS_PLAYLIST_MAX_SIZE = 16 * 1024 * 1024;
25+
2226
static bool
2327
FindPlaylistSection(TextInputStream &is)
2428
{
@@ -133,7 +137,9 @@ ParsePls(TextInputStream &is, std::forward_list<DetachedSong> &songs)
133137
static bool
134138
ParsePls(InputStreamPtr &&is, std::forward_list<DetachedSong> &songs)
135139
{
136-
TextInputStream tis(std::move(is));
140+
InputStreamPtr limited = std::make_unique<LimitedInputStream>
141+
(std::move(is), PLS_PLAYLIST_MAX_SIZE);
142+
TextInputStream tis(std::move(limited));
137143
if (!ParsePls(tis, songs)) {
138144
is = tis.StealInputStream();
139145
return false;

0 commit comments

Comments
 (0)