Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Replace std::stol with ParseInt #897

Merged
merged 13 commits into from
Sep 25, 2022
168 changes: 86 additions & 82 deletions src/redis_cmd.cc
Original file line number Diff line number Diff line change
Expand Up @@ -488,16 +488,12 @@ class CommandSet : public Commander {
if (ttl_ <= 0) return Status(Status::RedisParseErr, errInvalidExpireTime);
} else if (opt == "px" && !ttl_ && !last_arg) {
int64_t ttl_ms = 0;
try {
std::string s = args_[++i];
std::string::size_type sz;
ttl_ms = std::stol(s, &sz);
if (sz != s.size()) {
return Status(Status::RedisParseErr, errValueNotInterger);
}
} catch (std::exception &e) {
std::string s = args_[++i];
auto parseResult = ParseInt<int64_t>(s, /* base= */ 10);
PragmaTwice marked this conversation as resolved.
Show resolved Hide resolved
if (!parseResult.IsOK()) {
tanruixiang marked this conversation as resolved.
Show resolved Hide resolved
return Status(Status::RedisParseErr, errValueNotInterger);
}
ttl_ms = parseResult.GetValue();
if (ttl_ms <= 0) return Status(Status::RedisParseErr, errInvalidExpireTime);
if (ttl_ms > 0 && ttl_ms < 1000) {
ttl_ = 1; // round up the pttl to second
Expand Down Expand Up @@ -564,17 +560,17 @@ class CommandSetEX : public Commander {
class CommandPSetEX : public Commander {
public:
Status Parse(const std::vector<std::string> &args) override {
try {
auto ttl_ms = std::stol(args[2]);
if (ttl_ms <= 0) return Status(Status::RedisParseErr, errInvalidExpireTime);
if (ttl_ms > 0 && ttl_ms < 1000) {
ttl_ = 1;
} else {
ttl_ = ttl_ms / 1000;
}
} catch (std::exception &e) {
auto parseResult = ParseInt<int64_t>(args[2], /* base= */ 10);
tanruixiang marked this conversation as resolved.
Show resolved Hide resolved
if (!parseResult.IsOK()) {
return Status(Status::RedisParseErr, errValueNotInterger);
}
auto ttl_ms = parseResult.GetValue();
if (ttl_ms <= 0) return Status(Status::RedisParseErr, errInvalidExpireTime);
if (ttl_ms > 0 && ttl_ms < 1000) {
ttl_ = 1;
} else {
ttl_ = ttl_ms / 1000;
}
return Commander::Parse(args);
}

Expand Down Expand Up @@ -677,11 +673,11 @@ class CommandDecr : public Commander {
class CommandIncrBy : public Commander {
public:
Status Parse(const std::vector<std::string> &args) override {
try {
increment_ = std::stoll(args[2]);
} catch (std::exception &e) {
auto parseResult = ParseInt<int64_t>(args[2], /* base= */ 10);
if (!parseResult.IsOK()) {
return Status(Status::RedisParseErr, errValueNotInterger);
}
increment_ = parseResult.GetValue();
return Commander::Parse(args);
}

Expand Down Expand Up @@ -725,11 +721,11 @@ class CommandIncrByFloat : public Commander {
class CommandDecrBy : public Commander {
public:
Status Parse(const std::vector<std::string> &args) override {
try {
increment_ = std::stoll(args[2]);
} catch (std::exception &e) {
auto parseResult = ParseInt<int64_t>(args[2], /* base= */ 10);
if (!parseResult.IsOK()) {
return Status(Status::RedisParseErr, errValueNotInterger);
}
increment_ = parseResult.GetValue();
return Commander::Parse(args);
}

Expand Down Expand Up @@ -820,12 +816,11 @@ class CommandDel : public Commander {
};

Status getBitOffsetFromArgument(std::string arg, uint32_t *offset) {
int64_t offset_arg = 0;
try {
offset_arg = std::stoll(arg);
} catch (std::exception &e) {
auto parseResult = ParseInt<int64_t>(arg, /* base= */ 10);
if (!parseResult.IsOK()) {
return Status(Status::RedisParseErr, errValueNotInterger);
}
int64_t offset_arg = offset_arg = parseResult.GetValue();
tanruixiang marked this conversation as resolved.
Show resolved Hide resolved
if (offset_arg < 0 || offset_arg > UINT_MAX) {
return Status(Status::RedisParseErr, "bit offset is out of range");
}
Expand Down Expand Up @@ -889,12 +884,16 @@ class CommandBitCount : public Commander {
return Status(Status::RedisParseErr, errInvalidSyntax);
}
if (args.size() == 4) {
try {
start_ = std::stol(args[2]);
stop_ = std::stol(args[3]);
} catch (std::exception &e) {
auto parseArgs2Result = ParseInt<int64_t>(args[2], /* base= */ 10);
tanruixiang marked this conversation as resolved.
Show resolved Hide resolved
if (!parseArgs2Result.IsOK()){
return Status(Status::RedisParseErr, errValueNotInterger);
}
start_ = parseArgs2Result.GetValue();
auto parseArgs3Result = ParseInt<int64_t>(args[3], /* base= */ 10);
if (!parseArgs3Result.IsOK()){
return Status(Status::RedisParseErr, errValueNotInterger);
}
stop_ = parseArgs3Result.GetValue();
}
return Commander::Parse(args);
}
Expand All @@ -915,14 +914,20 @@ class CommandBitCount : public Commander {
class CommandBitPos: public Commander {
public:
Status Parse(const std::vector<std::string> &args) override {
try {
if (args.size() >= 4) start_ = std::stol(args[3]);
if (args.size() >= 5) {
stop_given_ = true;
stop_ = std::stol(args[4]);
if (args.size() >= 4){
auto parseArgs3Result = ParseInt<int64_t>(args[3], /* base= */ 10);
if (!parseArgs3Result.IsOK()){
return Status(Status::RedisParseErr, errValueNotInterger);
}
} catch (std::exception &e) {
return Status(Status::RedisParseErr, errValueNotInterger);
start_ = parseArgs3Result.GetValue();
}
if (args.size() >= 5) {
auto parseArgs4Result = ParseInt<int64_t>(args[4], /* base= */ 10);
if (!parseArgs4Result.IsOK()){
return Status(Status::RedisParseErr, errValueNotInterger);
}
stop_given_ = true;
stop_ = parseArgs4Result.GetValue();
}
if (args[2] == "0") {
bit_ = false;
Expand Down Expand Up @@ -1104,20 +1109,20 @@ class CommandPExpire : public Commander {
Status Parse(const std::vector<std::string> &args) override {
int64_t now;
rocksdb::Env::Default()->GetCurrentTime(&now);
try {
auto ttl_ms = std::stol(args[2]);
if (ttl_ms > 0 && ttl_ms < 1000) {
seconds_ = 1;
} else {
seconds_ = ttl_ms / 1000;
if (seconds_ >= INT32_MAX - now) {
return Status(Status::RedisParseErr, "the expire time was overflow");
}
}
seconds_ += now;
} catch (std::exception &e) {
auto parseResult = ParseInt<int64_t>(args[2], /* base= */ 10);
tanruixiang marked this conversation as resolved.
Show resolved Hide resolved
if (!parseResult.IsOK()) {
return Status(Status::RedisParseErr, errValueNotInterger);
}
auto ttl_ms = parseResult.GetValue();
if (ttl_ms > 0 && ttl_ms < 1000) {
seconds_ = 1;
} else {
seconds_ = ttl_ms / 1000;
if (seconds_ >= INT32_MAX - now) {
return Status(Status::RedisParseErr, "the expire time was overflow");
}
}
seconds_ += now;
return Commander::Parse(args);
}

Expand Down Expand Up @@ -1167,14 +1172,14 @@ class CommandExpireAt : public Commander {
class CommandPExpireAt : public Commander {
public:
Status Parse(const std::vector<std::string> &args) override {
try {
timestamp_ = static_cast<int>(std::stol(args[2])/1000);
if (timestamp_ >= INT32_MAX) {
return Status(Status::RedisParseErr, "the expire time was overflow");
}
} catch (std::exception &e) {
auto parseResult = ParseInt<int64_t>(args[2], /* base= */ 10);
if (!parseResult.IsOK()) {
return Status(Status::RedisParseErr, errValueNotInterger);
}
if (parseResult.GetValue()/1000 >= INT32_MAX) {
return Status(Status::RedisParseErr, "the expire time was overflow");
}
timestamp_ = static_cast<int>(parseResult.GetValue()/1000);
return Commander::Parse(args);
}
Status Execute(Server *svr, Connection *conn, std::string *output) override {
Expand Down Expand Up @@ -1301,11 +1306,11 @@ class CommandHLen : public Commander {
class CommandHIncrBy : public Commander {
public:
Status Parse(const std::vector<std::string> &args) override {
try {
increment_ = std::stoll(args[3]);
} catch (std::exception &e) {
auto parseResult = ParseInt<int64_t>(args[3], /* base= */ 10);
if (!parseResult.IsOK()) {
return Status(Status::RedisParseErr, errValueNotInterger);
}
increment_ = parseResult.GetValue();
return Commander::Parse(args);
}
Status Execute(Server *svr, Connection *conn, std::string *output) override {
Expand Down Expand Up @@ -1517,16 +1522,16 @@ class CommandPop : public Commander {
if (args.size() == 2) {
return Status::OK();
}
try {
int32_t v = std::stol(args[2]);
if (v < 0) {
return Status(Status::RedisParseErr, errValueMustBePositive);
}
count_ = v;
with_count_ = true;
} catch (const std::exception& ) {
auto parseResult = ParseInt<int64_t>(args[2], /* base= */ 10);
if (!parseResult.IsOK()) {
return Status(Status::RedisParseErr, errValueNotInterger);
}
int32_t v = parseResult.GetValue();
if (v < 0) {
return Status(Status::RedisParseErr, errValueMustBePositive);
}
count_ = v;
with_count_ = true;
return Status::OK();
}

Expand Down Expand Up @@ -3962,11 +3967,11 @@ class CommandClient : public Commander {
if (!strcasecmp(args[i].c_str(), "addr") && moreargs) {
addr_ = args[i+1];
} else if (!strcasecmp(args[i].c_str(), "id") && moreargs) {
try {
id_ = std::stoll(args[i+1]);
} catch (std::exception &e) {
auto parseResult = ParseInt<int64_t>(args[i+1], /* base= */ 10);
if (!parseResult.IsOK()) {
return Status(Status::RedisParseErr, errValueNotInterger);
}
id_ = parseResult.GetValue();
} else if (!strcasecmp(args[i].c_str(), "skipme") && moreargs) {
if (!strcasecmp(args[i+1].c_str(), "yes")) {
skipme_ = true;
Expand Down Expand Up @@ -5363,13 +5368,12 @@ class CommandXRead : public Commander {
if (i+1 >= args.size()) {
return Status(Status::RedisParseErr, errInvalidSyntax);
}

try {
with_count_ = true;
count_ = static_cast<uint64_t>(std::stoll(args[i+1]));
} catch (const std::exception &) {
with_count_ = true;
auto parseResult = ParseInt<int64_t>(args[i+1], /* base= */ 10);
if (!parseResult.IsOK()) {
return Status(Status::RedisParseErr, errValueNotInterger);
}
count_ = static_cast<uint64_t>(parseResult.GetValue());
tanruixiang marked this conversation as resolved.
Show resolved Hide resolved
i += 2;
continue;
}
Expand All @@ -5380,15 +5384,15 @@ class CommandXRead : public Commander {
}

block_ = true;
try {
auto v = std::stoll(args[i+1]);
if (v < 0) {
return Status(Status::RedisParseErr, errTimeoutIsNegative);
}
block_timeout_ = v;
} catch (const std::exception &) {
auto parseResult = ParseInt<int64_t>(args[i+1], /* base= */ 10);
if (!parseResult.IsOK()) {
return Status(Status::RedisParseErr, errValueNotInterger);
}
auto v = parseResult.GetValue();
if (v < 0) {
return Status(Status::RedisParseErr, errTimeoutIsNegative);
}
block_timeout_ = v;
i += 2;
continue;
}
Expand Down
13 changes: 5 additions & 8 deletions src/redis_hash.cc
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
#include <iostream>
#include <rocksdb/status.h>
#include "db_util.h"
#include "parse_util.h"

namespace Redis {
rocksdb::Status Hash::GetMetadata(const Slice &ns_key, HashMetadata *metadata) {
Expand Down Expand Up @@ -73,18 +74,14 @@ rocksdb::Status Hash::IncrBy(const Slice &user_key, const Slice &field, int64_t
InternalKey(ns_key, field, metadata.version, storage_->IsSlotIdEncoded()).Encode(&sub_key);
if (s.ok()) {
std::string value_bytes;
std::size_t idx = 0;
s = db_->Get(rocksdb::ReadOptions(), sub_key, &value_bytes);
if (!s.ok() && !s.IsNotFound()) return s;
if (s.ok()) {
try {
old_value = std::stoll(value_bytes, &idx);
} catch (std::exception &e) {
return rocksdb::Status::InvalidArgument(e.what());
}
if (isspace(value_bytes[0]) || idx != value_bytes.size()) {
return rocksdb::Status::InvalidArgument("value is not an integer");
auto parseResult = ParseInt<int64_t>(value_bytes, /* base= */ 10);
if (!parseResult.IsOK()) {
return rocksdb::Status::InvalidArgument(parseResult.Msg());
}
old_value = parseResult.GetValue();
exists = true;
}
}
Expand Down
7 changes: 4 additions & 3 deletions src/redis_request.cc
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
#include "server.h"
#include "redis_slot.h"
#include "event_util.h"
#include "parse_util.h"

namespace Redis {
const size_t PROTO_INLINE_MAX_SIZE = 16 * 1024L;
Expand Down Expand Up @@ -66,11 +67,11 @@ Status Request::Tokenize(evbuffer *input) {
pipeline_size++;
svr_->stats_.IncrInbondBytes(line.length);
if (line[0] == '*') {
try {
multi_bulk_len_ = std::stoll(std::string(line.get() + 1, line.length - 1));
} catch (std::exception &e) {
auto parseResult = ParseInt<int64_t>(std::string(line.get() + 1, line.length - 1), /* base= */ 10);
if (!parseResult.IsOK()) {
return Status(Status::NotOK, "Protocol error: invalid multibulk length");
}
multi_bulk_len_ = parseResult.GetValue();
if (isOnlyLF || multi_bulk_len_ > (int64_t)PROTO_MULTI_MAX_SIZE) {
return Status(Status::NotOK, "Protocol error: invalid multibulk length");
}
Expand Down
13 changes: 5 additions & 8 deletions src/redis_string.cc
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
#include <string>
#include <limits>
#include <cmath>
#include "parse_util.h"

namespace Redis {

Expand Down Expand Up @@ -274,16 +275,12 @@ rocksdb::Status String::IncrBy(const std::string &user_key, int64_t increment, i

value = raw_value.substr(STRING_HDR_SIZE, raw_value.size()-STRING_HDR_SIZE);
int64_t n = 0;
std::size_t idx = 0;
if (!value.empty()) {
try {
n = std::stoll(value, &idx);
} catch(std::exception &e) {
return rocksdb::Status::InvalidArgument("value is not an integer or out of range");
}
if (isspace(value[0]) || idx != value.size()) {
return rocksdb::Status::InvalidArgument("value is not an integer");
auto parseResult = ParseInt<int64_t>(value, /* base= */ 10);
if (!parseResult.IsOK()) {
return rocksdb::Status::InvalidArgument(parseResult.Msg());
}
n = parseResult.GetValue();
}
if ((increment < 0 && n <= 0 && increment < (LLONG_MIN-n))
|| (increment > 0 && n >= 0 && increment > (LLONG_MAX-n))) {
Expand Down
Loading