From b89dfba0893181f66b535eace19b4ac027aa44de Mon Sep 17 00:00:00 2001 From: emeric Date: Wed, 8 Nov 2023 22:47:41 +0100 Subject: [PATCH] Subsonic API: limit size parameter to 500 for various methods --- src/libs/subsonic/impl/SubsonicResponse.hpp | 12 ++++++++++++ .../subsonic/impl/entrypoints/AlbumSongLists.cpp | 12 ++++++++---- src/libs/subsonic/impl/entrypoints/Searching.cpp | 13 ++++++++++--- 3 files changed, 30 insertions(+), 7 deletions(-) diff --git a/src/libs/subsonic/impl/SubsonicResponse.hpp b/src/libs/subsonic/impl/SubsonicResponse.hpp index 4414d4d1..cf661a51 100644 --- a/src/libs/subsonic/impl/SubsonicResponse.hpp +++ b/src/libs/subsonic/impl/SubsonicResponse.hpp @@ -185,6 +185,18 @@ namespace API::Subsonic const std::string _parameterName; }; + class ParameterValueTooHighGenericError : public GenericError + { + public: + ParameterValueTooHighGenericError(std::string_view parameterName, std::size_t max) : _parameterName{ parameterName }, _max{ max } {} + + private: + std::string getMessage() const override { return "Parameter '" + _parameterName + "': bad value"; } + + const std::string _parameterName; + std::size_t _max; + }; + class Response { public: diff --git a/src/libs/subsonic/impl/entrypoints/AlbumSongLists.cpp b/src/libs/subsonic/impl/entrypoints/AlbumSongLists.cpp index 721577d0..5dc3b2b4 100644 --- a/src/libs/subsonic/impl/entrypoints/AlbumSongLists.cpp +++ b/src/libs/subsonic/impl/entrypoints/AlbumSongLists.cpp @@ -47,6 +47,8 @@ namespace API::Subsonic // Optional params const std::size_t size{ getParameterAs(context.parameters, "size").value_or(10) }; const std::size_t offset{ getParameterAs(context.parameters, "offset").value_or(0) }; + if (size > 500) + throw ParameterValueTooHighGenericError{ "size", 500 }; const Range range{ offset, size }; @@ -196,7 +198,8 @@ namespace API::Subsonic { // Optional params std::size_t size{ getParameterAs(context.parameters, "size").value_or(50) }; - size = std::min(size, std::size_t{ 500 }); + if (size > 500) + throw ParameterValueTooHighGenericError{"size", 500}; auto transaction{ context.dbSession.createSharedTransaction() }; @@ -221,8 +224,9 @@ namespace API::Subsonic std::string genre{ getMandatoryParameterAs(context.parameters, "genre") }; // Optional params - std::size_t size{ getParameterAs(context.parameters, "count").value_or(10) }; - size = std::min(size, std::size_t{ 500 }); + std::size_t count{ getParameterAs(context.parameters, "count").value_or(10) }; + if (count > 500) + throw ParameterValueTooHighGenericError{"count", 500}; std::size_t offset{ getParameterAs(context.parameters, "offset").value_or(0) }; @@ -245,7 +249,7 @@ namespace API::Subsonic Track::FindParameters params; params.setClusters({ cluster->getId() }); - params.setRange({ offset, size }); + params.setRange({ offset, count }); const auto tracks{ Track::find(context.dbSession, params) }; for (const Track::pointer& track : tracks.results) diff --git a/src/libs/subsonic/impl/entrypoints/Searching.cpp b/src/libs/subsonic/impl/entrypoints/Searching.cpp index a3ed2968..79dccac7 100644 --- a/src/libs/subsonic/impl/entrypoints/Searching.cpp +++ b/src/libs/subsonic/impl/entrypoints/Searching.cpp @@ -57,15 +57,22 @@ namespace API::Subsonic std::size_t songCount{ getParameterAs(context.parameters, "songCount").value_or(20) }; std::size_t songOffset{ getParameterAs(context.parameters, "songOffset").value_or(0) }; + if (artistCount > 500) + throw ParameterValueTooHighGenericError{ "artistCount", 500 }; + else if (albumCount > 500) + throw ParameterValueTooHighGenericError{ "albumCount", 500 }; + else if (songCount > 500) + throw ParameterValueTooHighGenericError{ "songCount", 500 }; + + Response response{ Response::createOkResponse(context.serverProtocolVersion) }; + Response::Node& searchResult2Node{ response.createNode(id3 ? "searchResult3" : "searchResult2") }; + auto transaction{ context.dbSession.createSharedTransaction() }; User::pointer user{ User::find(context.dbSession, context.userId) }; if (!user) throw UserNotAuthorizedError{}; - Response response{ Response::createOkResponse(context.serverProtocolVersion) }; - Response::Node& searchResult2Node{ response.createNode(id3 ? "searchResult3" : "searchResult2") }; - if (artistCount > 0) { Artist::FindParameters params;