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:
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -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();
|
||||
}
|
||||
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
@ -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) {
|
||||
|
||||
@ -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();
|
||||
|
||||
Reference in New Issue
Block a user