-
Notifications
You must be signed in to change notification settings - Fork 4.1k
Add redis allocation size limit #3035
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
Changes from 2 commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -20,6 +20,7 @@ | |
| #include "butil/logging.h" | ||
| #include "brpc/log.h" | ||
| #include "brpc/redis_command.h" | ||
| #include "gflags/gflags.h" | ||
|
|
||
| namespace { | ||
|
|
||
|
|
@@ -29,6 +30,8 @@ const size_t CTX_WIDTH = 5; | |
|
|
||
| namespace brpc { | ||
|
|
||
| DECLARE_int32(redis_max_allocation_size); | ||
|
|
||
| // Much faster than snprintf(..., "%lu", d); | ||
| inline size_t AppendDecimal(char* outbuf, unsigned long d) { | ||
| char buf[24]; // enough for decimal 64-bit integers | ||
|
|
@@ -403,6 +406,12 @@ ParseError RedisCommandParser::Consume(butil::IOBuf& buf, | |
| return PARSE_ERROR_ABSOLUTELY_WRONG; | ||
| } | ||
| if (!_parsing_array) { | ||
| if (value > (int64_t)(FLAGS_redis_max_allocation_size / sizeof(butil::StringPiece))) { | ||
| LOG(ERROR) << "command array size exceeds limit! max=" | ||
| << (FLAGS_redis_max_allocation_size / sizeof(butil::StringPiece)) | ||
| << ", actually=" << value; | ||
| return PARSE_ERROR_ABSOLUTELY_WRONG; | ||
| } | ||
| buf.pop_front(crlf_pos + 2/*CRLF*/); | ||
| _parsing_array = true; | ||
| _length = value; | ||
|
|
@@ -417,9 +426,9 @@ ParseError RedisCommandParser::Consume(butil::IOBuf& buf, | |
| LOG(ERROR) << "string in command is nil!"; | ||
| return PARSE_ERROR_ABSOLUTELY_WRONG; | ||
| } | ||
| if (len > (int64_t)std::numeric_limits<uint32_t>::max()) { | ||
| LOG(ERROR) << "string in command is too long! max length=2^32-1," | ||
| " actually=" << len; | ||
| if (len > FLAGS_redis_max_allocation_size) { | ||
| LOG(ERROR) << "command string exceeds max allocation size! max=" | ||
| << FLAGS_redis_max_allocation_size << ", actually=" << len; | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Format |
||
| return PARSE_ERROR_ABSOLUTELY_WRONG; | ||
| } | ||
| if (buf.size() < crlf_pos + 2 + (size_t)len + 2/*CRLF*/) { | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -20,9 +20,13 @@ | |
| #include "butil/logging.h" | ||
| #include "butil/string_printf.h" | ||
| #include "brpc/redis_reply.h" | ||
| #include "gflags/gflags.h" | ||
|
|
||
| namespace brpc { | ||
|
|
||
| DEFINE_int32(redis_max_allocation_size, 64 * 1024 * 1024, | ||
| "Maximum memory allocation size in bytes for a single redis request or reply (64MB by default)"); | ||
|
|
||
| //BAIDU_CASSERT(sizeof(RedisReply) == 24, size_match); | ||
| const int RedisReply::npos = -1; | ||
|
|
||
|
|
@@ -175,9 +179,9 @@ ParseError RedisReply::ConsumePartialIOBuf(butil::IOBuf& buf) { | |
| _data.integer = 0; | ||
| return PARSE_OK; | ||
| } | ||
| if (len > (int64_t)std::numeric_limits<uint32_t>::max()) { | ||
| LOG(ERROR) << "bulk string is too long! max length=2^32-1," | ||
| " actually=" << len; | ||
| if (len > FLAGS_redis_max_allocation_size) { | ||
| LOG(ERROR) << "bulk string exceeds max allocation size! max=" | ||
| << FLAGS_redis_max_allocation_size << ", actually=" << len; | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Format |
||
| return PARSE_ERROR_ABSOLUTELY_WRONG; | ||
| } | ||
| // We provide c_str(), thus even if bulk string is started with | ||
|
|
@@ -229,9 +233,10 @@ ParseError RedisReply::ConsumePartialIOBuf(butil::IOBuf& buf) { | |
| _data.array.replies = NULL; | ||
| return PARSE_OK; | ||
| } | ||
| if (count > (int64_t)std::numeric_limits<uint32_t>::max()) { | ||
| LOG(ERROR) << "Too many sub replies! max count=2^32-1," | ||
| " actually=" << count; | ||
| int64_t array_size = sizeof(RedisReply) * count; | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Use
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. array_size should better be modified with "const" |
||
| if (array_size > FLAGS_redis_max_allocation_size) { | ||
| LOG(ERROR) << "array allocation exceeds max allocation size! max=" | ||
| << FLAGS_redis_max_allocation_size << ", actually=" << array_size; | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Format |
||
| return PARSE_ERROR_ABSOLUTELY_WRONG; | ||
| } | ||
| // FIXME(gejun): Call allocate_aligned instead. | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Format.