Skip to content

Commit 6c82355

Browse files
committed
choose_formatter: q param fixes
1 parent 403c826 commit 6c82355

File tree

1 file changed

+36
-12
lines changed

1 file changed

+36
-12
lines changed

src/choose_formatter.cpp

+36-12
Original file line numberDiff line numberDiff line change
@@ -27,18 +27,45 @@
2727
#include <limits>
2828
#include <optional>
2929
#include <iostream>
30+
#include <ranges>
3031
#include <string>
3132
#include <vector>
3233
#include <algorithm>
3334
#include <charconv>
3435

3536
#include <fmt/core.h>
3637

38+
namespace {
39+
40+
bool parseQValue(std::string_view param, double &qValue) {
41+
#if !defined(__APPLE__)
42+
auto [ptr, ec] = std::from_chars(param.begin(), param.end(), qValue,
43+
std::chars_format::fixed);
44+
return (ec == std::errc() && ptr == param.end());
45+
#else
46+
std::string p(param);
47+
for (char ch : p) {
48+
if (!(std::isdigit(ch) || ch == '.')) {
49+
return false; // Invalid character found
50+
}
51+
}
52+
size_t pos;
53+
try {
54+
qValue = std::stod(p, &pos);
55+
return (pos == p.size()); // Check if the entire string was consumed
56+
} catch (const std::exception &) {
57+
return false; // Invalid value
58+
}
59+
#endif
60+
}
61+
62+
} // namespace
63+
3764
AcceptHeader::AcceptHeader(const std::string &header) {
3865

3966
acceptedTypes = parse(header);
4067

41-
std::sort(acceptedTypes.begin(), acceptedTypes.end(),
68+
std::ranges::sort(acceptedTypes,
4269
[](const AcceptElement &a, const AcceptElement &b) {
4370
return std::tie(a.q, a.type, a.subtype) >
4471
std::tie(b.q, b.type, b.subtype);
@@ -49,8 +76,7 @@ AcceptHeader::AcceptHeader(const std::string &header) {
4976
}
5077

5178
[[nodiscard]] bool AcceptHeader::is_acceptable(mime::type mt) const {
52-
return mapping.find(mt) != mapping.end() ||
53-
mapping.find(mime::type::any_type) != mapping.end();
79+
return mapping.contains(mt) || mapping.contains(mime::type::any_type);
5480
}
5581

5682
[[nodiscard]] mime::type AcceptHeader::most_acceptable_of(
@@ -135,17 +161,15 @@ std::vector<AcceptHeader::AcceptElement> AcceptHeader::parse(const std::string &
135161
}
136162

137163
if (param_parts[0] == "q") {
138-
auto [ptr, ec] = std::from_chars(param_parts[1].begin(),
139-
param_parts[1].end(),
140-
acceptElement.q,
141-
std::chars_format::fixed);
142-
if (ec != std::errc() ||
143-
ptr != param_parts[1].end() ||
144-
!std::isfinite(acceptElement.q) ||
145-
acceptElement.q < 0 ||
146-
acceptElement.q > 1) {
164+
if (!parseQValue(param_parts[1], acceptElement.q)) {
147165
throw http::bad_request("Invalid q parameter value in accept header");
148166
}
167+
168+
// Check if q is within the valid range [0, 1]
169+
if (!std::isfinite(acceptElement.q) || acceptElement.q < 0.0 || acceptElement.q > 1.0) {
170+
throw http::bad_request("Invalid q parameter value in accept header");
171+
}
172+
149173
} else {
150174
acceptElement.params[std::string{param_parts[0]}] = std::string{param_parts[1]};
151175
}

0 commit comments

Comments
 (0)