Fix large string val allocation failure (#3724)

* Fix large string val allocation failure

Large bitmap will need use StringVal to allocate large memory, which is large than MAX_INT.
The overflow will cause serialization failure of bitmap.

Fixed #3600
This commit is contained in:
EmmyMiao87
2020-06-03 17:07:54 +08:00
committed by GitHub
parent 70aa9d6ca8
commit e16873a6c1
6 changed files with 17 additions and 15 deletions

View File

@ -273,7 +273,7 @@ public:
if (type.type == FunctionContext::TYPE_VARCHAR
|| type.type == FunctionContext::TYPE_CHAR) {
DCHECK(type.len >= 0);
val->len = std::min(val->len, type.len);
val->len = std::min(val->len, (int64_t)type.len);
}
}

View File

@ -488,7 +488,9 @@ StringVal BitmapFunctions::bitmap_from_string(FunctionContext* ctx, const String
}
std::vector<uint64_t> bits;
if (!SplitStringAndParse({(const char*)input.ptr, input.len}, ",", &safe_strtou64, &bits)) {
// The contructor of `stringpiece` only support int type.
if ((input.len > INT32_MAX)
|| !SplitStringAndParse({(const char*)input.ptr, (int)input.len}, ",", &safe_strtou64, &bits)) {
return StringVal::null();
}

View File

@ -51,7 +51,7 @@ public:
virtual ~FreePool() {}
// Allocates a buffer of size.
uint8_t* allocate(int size) {
uint8_t* allocate(int64_t size) {
// This is the typical malloc behavior. NULL is reserved for failures.
if (size == 0) {
return reinterpret_cast<uint8_t*>(0x1);
@ -98,7 +98,7 @@ public:
// Returns an allocation that is at least 'size'. If the current allocation
// backing 'ptr' is big enough, 'ptr' is returned. Otherwise a new one is
// made and the contents of ptr are copied into it.
uint8_t* reallocate(uint8_t* ptr, int size) {
uint8_t* reallocate(uint8_t* ptr, int64_t size) {
if (ptr == NULL || reinterpret_cast<int64_t>(ptr) == 0x1) {
return allocate(size);
}

View File

@ -122,7 +122,7 @@ void FunctionContextImpl::close() {
_closed = true;
}
uint8_t* FunctionContextImpl::allocate_local(int byte_size) {
uint8_t* FunctionContextImpl::allocate_local(int64_t byte_size) {
uint8_t* buffer = _pool->allocate(byte_size);
_local_allocations.push_back(buffer);
return buffer;
@ -365,12 +365,12 @@ bool FunctionContext::add_warning(const char* warning_msg) {
}
}
StringVal::StringVal(FunctionContext* context, int len) :
len(len),
StringVal::StringVal(FunctionContext* context, int64_t len) :
len(len),
ptr(context->impl()->allocate_local(len)) {
}
bool StringVal::resize(FunctionContext* ctx, int new_len) {
bool StringVal::resize(FunctionContext* ctx, int64_t new_len) {
if (new_len <= len) {
len = new_len;
return true;
@ -398,7 +398,7 @@ StringVal StringVal::copy_from(FunctionContext* ctx, const uint8_t* buf, size_t
return result;
}
StringVal StringVal::create_temp_string_val(FunctionContext* ctx, int len) {
StringVal StringVal::create_temp_string_val(FunctionContext* ctx, int64_t len) {
ctx->impl()->string_result().resize(len);
return StringVal((uint8_t*)ctx->impl()->string_result().c_str(), len);
}

View File

@ -600,7 +600,7 @@ struct DateTimeVal : public AnyVal {
struct StringVal : public AnyVal {
static const int MAX_LENGTH = (1 << 30);
int len;
int64_t len;
uint8_t* ptr;
// Construct a StringVal from ptr/len. Note: this does not make a copy of ptr
@ -609,7 +609,7 @@ struct StringVal : public AnyVal {
// Construct a StringVal from ptr/len. Note: this does not make a copy of ptr
// so the buffer must exist as long as this StringVal does.
StringVal(uint8_t* ptr, int len) : len(len), ptr(ptr) {}
StringVal(uint8_t* ptr, int64_t len) : len(len), ptr(ptr) {}
// Construct a StringVal from NULL-terminated c-string. Note: this does not make a
// copy of ptr so the underlying string must exist as long as this StringVal does.
@ -624,12 +624,12 @@ struct StringVal : public AnyVal {
// Creates a StringVal, allocating a new buffer with 'len'. This should
// be used to return StringVal objects in UDF/UDAs that need to allocate new
// string memory.
StringVal(FunctionContext* context, int len);
StringVal(FunctionContext* context, int64_t len);
// Creates a StringVal, which memory is avaliable when this funciont context is used next time
static StringVal create_temp_string_val(FunctionContext* ctx, int len);
static StringVal create_temp_string_val(FunctionContext* ctx, int64_t len);
bool resize(FunctionContext* context, int len);
bool resize(FunctionContext* context, int64_t len);
bool operator==(const StringVal& other) const {
if (is_null != other.is_null) {

View File

@ -108,7 +108,7 @@ public:
// This is used where the lifetime of the allocation is clear.
// For UDFs, the allocations can be freed at the row level.
// TODO: free them at the batch level and save some copies?
uint8_t* allocate_local(int byte_size);
uint8_t* allocate_local(int64_t byte_size);
// Frees all allocations returned by AllocateLocal().
void free_local_allocations();