Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion redis/src/storages/redis/parse_reply.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -263,7 +263,7 @@ std::string Parse(ReplyData&& reply_data, const std::string& request_description
double Parse(ReplyData&& reply_data, const std::string& request_description, To<double>) {
reply_data.ExpectString(request_description);
try {
return std::stod(reply_data.GetString());
return utils::FromString<double>(reply_data.GetString());
} catch (const std::exception& ex) {
throw ParseReplyException(
"Can't parse value from reply to '" + request_description + "' request (" + reply_data.ToDebugString() +
Expand Down
43 changes: 43 additions & 0 deletions redis/src/storages/redis/parse_reply_test.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
#include <userver/storages/redis/parse_reply.hpp>

#include <cmath>

#include <gtest/gtest.h>

#include <userver/storages/redis/exception.hpp>
#include <userver/storages/redis/reply.hpp>

USERVER_NAMESPACE_BEGIN

namespace {

double ParseDouble(std::string value) {
return storages::redis::Parse(
storages::redis::ReplyData{std::move(value)}, "test_request", storages::redis::To<double>{}
);
}

} // namespace

TEST(ParseReply, DoubleValid) {
EXPECT_DOUBLE_EQ(ParseDouble("3.14"), 3.14);
EXPECT_DOUBLE_EQ(ParseDouble("-2.5"), -2.5);
EXPECT_DOUBLE_EQ(ParseDouble("1e3"), 1000.0);
}

TEST(ParseReply, DoubleInfinity) {
// ZSCORE and friends report infinite scores as "inf"/"-inf".
EXPECT_TRUE(std::isinf(ParseDouble("inf")));
EXPECT_TRUE(std::isinf(ParseDouble("-inf")));
}

TEST(ParseReply, DoubleTrailingJunk) {
// A compromised, misbehaving, or MITM'd server can return a bulk string with
// a valid numeric prefix followed by junk. std::stod silently accepted the
// prefix and dropped the rest; the strict parser rejects the whole reply.
EXPECT_THROW(ParseDouble("3.14garbage"), storages::redis::ParseReplyException);
EXPECT_THROW(ParseDouble("nonsense"), storages::redis::ParseReplyException);
EXPECT_THROW(ParseDouble(""), storages::redis::ParseReplyException);
}

USERVER_NAMESPACE_END
Loading