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
177 changes: 87 additions & 90 deletions src/redis_cmd.cc
Original file line number Diff line number Diff line change
Expand Up @@ -490,16 +490,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 parse_result = ParseInt<int64_t>(s, 10);
if (!parse_result) {
return Status(Status::RedisParseErr, errValueNotInterger);
}
ttl_ms = *parse_result;
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 @@ -566,17 +562,16 @@ 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 ttl_ms = ParseInt<int64_t>(args[2], 10);
if (!ttl_ms) {
return Status(Status::RedisParseErr, errValueNotInterger);
}
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 @@ -679,11 +674,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 parse_result = ParseInt<int64_t>(args[2], 10);
if (!parse_result) {
return Status(Status::RedisParseErr, errValueNotInterger);
}
increment_ = *parse_result;
return Commander::Parse(args);
}

Expand Down Expand Up @@ -727,11 +722,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 parse_result = ParseInt<int64_t>(args[2], 10);
if (!parse_result) {
return Status(Status::RedisParseErr, errValueNotInterger);
}
increment_ = *parse_result;
return Commander::Parse(args);
}

Expand Down Expand Up @@ -822,16 +817,12 @@ 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) {
return Status(Status::RedisParseErr, errValueNotInterger);
}
if (offset_arg < 0 || offset_arg > UINT_MAX) {
return Status(Status::RedisParseErr, "bit offset is out of range");
auto parse_result = ParseInt<uint32_t>(arg, 10);
if (!parse_result) {
return parse_result.ToStatus();
}
*offset = static_cast<uint32_t>(offset_arg);

*offset = *parse_result;
return Status::OK();
}

Expand Down Expand Up @@ -891,12 +882,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 parse_start = ParseInt<int64_t>(args[2], 10);
if (!parse_start) {
return Status(Status::RedisParseErr, errValueNotInterger);
}
start_ = *parse_start;
auto parse_stop = ParseInt<int64_t>(args[3], 10);
if (!parse_stop) {
return Status(Status::RedisParseErr, errValueNotInterger);
}
stop_ = *parse_stop;
}
return Commander::Parse(args);
}
Expand All @@ -917,14 +912,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 parse_start = ParseInt<int64_t>(args[3], 10);
if (!parse_start) {
return Status(Status::RedisParseErr, errValueNotInterger);
}
} catch (std::exception &e) {
return Status(Status::RedisParseErr, errValueNotInterger);
start_ = *parse_start;
}
if (args.size() >= 5) {
auto parse_stop = ParseInt<int64_t>(args[4], 10);
if (!parse_stop) {
return Status(Status::RedisParseErr, errValueNotInterger);
}
stop_given_ = true;
stop_ = *parse_stop;
}
if (args[2] == "0") {
bit_ = false;
Expand Down Expand Up @@ -1106,20 +1107,19 @@ 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 ttl_ms = ParseInt<int64_t>(args[2], 10);
if (!ttl_ms) {
return Status(Status::RedisParseErr, errValueNotInterger);
}
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 @@ -1169,14 +1169,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 parse_result = ParseInt<int64_t>(args[2], 10);
if (!parse_result) {
return Status(Status::RedisParseErr, errValueNotInterger);
}
if (*parse_result/1000 >= INT32_MAX) {
return Status(Status::RedisParseErr, "the expire time was overflow");
}
timestamp_ = static_cast<int>(*parse_result/1000);
return Commander::Parse(args);
}
Status Execute(Server *svr, Connection *conn, std::string *output) override {
Expand Down Expand Up @@ -1303,11 +1303,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 parse_result = ParseInt<int64_t>(args[3], 10);
if (!parse_result) {
return Status(Status::RedisParseErr, errValueNotInterger);
}
increment_ = *parse_result;
return Commander::Parse(args);
}
Status Execute(Server *svr, Connection *conn, std::string *output) override {
Expand Down Expand Up @@ -1557,16 +1557,15 @@ 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 v = ParseInt<int32_t>(args[2], 10);
if (!v) {
return Status(Status::RedisParseErr, errValueNotInterger);
}
if (*v < 0) {
return Status(Status::RedisParseErr, errValueMustBePositive);
}
count_ = *v;
with_count_ = true;
return Status::OK();
}

Expand Down Expand Up @@ -4005,11 +4004,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 parse_result = ParseInt<uint64_t>(args[i+1], 10);
if (!parse_result) {
return Status(Status::RedisParseErr, errValueNotInterger);
}
id_ = *parse_result;
} else if (!strcasecmp(args[i].c_str(), "skipme") && moreargs) {
if (!strcasecmp(args[i+1].c_str(), "yes")) {
skipme_ = true;
Expand Down Expand Up @@ -4201,12 +4200,12 @@ class CommandHello final : public Commander {
size_t next_arg = 1;
if (args_.size() >= 2) {
int64_t protocol;
auto parseResult = ParseInt<int64_t>(args_[next_arg], /* base= */ 10);
auto parse_result = ParseInt<int64_t>(args_[next_arg], 10);
++next_arg;
if (!parseResult.IsOK()) {
if (!parse_result) {
return Status(Status::NotOK, "Protocol version is not an integer or out of range");
}
protocol = parseResult.GetValue();
protocol = *parse_result;

// In redis, it will check protocol < 2 or protocol > 3,
// kvrocks only supports REPL2 by now, but for supporting some
Expand Down Expand Up @@ -5428,13 +5427,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 parse_result = ParseInt<uint64_t>(args[i+1], 10);
if (!parse_result) {
return Status(Status::RedisParseErr, errValueNotInterger);
}
count_ = *parse_result;
i += 2;
continue;
}
Expand All @@ -5445,15 +5443,14 @@ 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 parse_result = ParseInt<int64_t>(args[i+1], 10);
if (!parse_result) {
return Status(Status::RedisParseErr, errValueNotInterger);
}
if (*parse_result < 0) {
return Status(Status::RedisParseErr, errTimeoutIsNegative);
}
block_timeout_ = *parse_result;
i += 2;
continue;
}
Expand Down
13 changes: 7 additions & 6 deletions src/redis_hash.cc
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,15 @@
*/

#include "redis_hash.h"
#include <cctype>
#include <utility>
#include <algorithm>
#include <limits>
#include <cmath>
#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 @@ -74,18 +76,17 @@ 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());
auto parse_result = ParseInt<int64_t>(value_bytes, 10);
if (!parse_result) {
return rocksdb::Status::InvalidArgument(parse_result.Msg());
}
if (isspace(value_bytes[0]) || idx != value_bytes.size()) {
if (isspace(value_bytes[0])) {
return rocksdb::Status::InvalidArgument("value is not an integer");
}
old_value = *parse_result;
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 parse_result = ParseInt<int64_t>(std::string(line.get() + 1, line.length - 1), 10);
if (!parse_result) {
return Status(Status::NotOK, "Protocol error: invalid multibulk length");
}
multi_bulk_len_ = *parse_result;
if (isOnlyLF || multi_bulk_len_ > (int64_t)PROTO_MULTI_MAX_SIZE) {
return Status(Status::NotOK, "Protocol error: invalid multibulk length");
}
Expand Down
Loading