diff options
author | Monty <monty@mariadb.org> | 2021-03-28 18:50:40 +0300 |
---|---|---|
committer | Sergei Golubchik <serg@mariadb.org> | 2021-05-19 22:54:12 +0200 |
commit | e45b54b75db4060b550ff4a4820e783ff7b730c3 (patch) | |
tree | 9a8fdef04fcc9e0b38205332c92287d9ab95ae98 /sql/sql_string.h | |
parent | 85d6278fed9e2279117854d86219408f9787bd97 (diff) | |
download | mariadb-git-e45b54b75db4060b550ff4a4820e783ff7b730c3.tar.gz |
Removed Static_binary_string
This did not server any real purpose and also made it too difficult to add
asserts for string memory overrwrites.
Moved all functionallity from Static_binary_string to Binary_string.
Other things:
- Added asserts to q_xxx and qs_xxx functions to check for memory overruns
- Fixed wrong test in String_buffer::set_buffer_if_not_allocated().
The idea is to reuse allocated buffers (to avoid extra allocs), which
the code did not do.
Diffstat (limited to 'sql/sql_string.h')
-rw-r--r-- | sql/sql_string.h | 212 |
1 files changed, 103 insertions, 109 deletions
diff --git a/sql/sql_string.h b/sql/sql_string.h index 45bf7cf5f4d..76079f99f8d 100644 --- a/sql/sql_string.h +++ b/sql/sql_string.h @@ -39,6 +39,7 @@ extern PSI_memory_key key_memory_String_value; typedef struct st_io_cache IO_CACHE; typedef struct st_mem_root MEM_ROOT; +#define ASSERT_LENGTH(A) DBUG_ASSERT(str_length + (uint32) (A) <= Alloced_length) #include "pack.h" int sortcmp(const String *a,const String *b, CHARSET_INFO *cs); @@ -200,26 +201,75 @@ public: }; -/* - A storage for String. - Should be eventually derived from LEX_STRING. +/** + Storage for strings with both length and allocated length. + Automatically grows on demand. */ -class Static_binary_string : public Sql_alloc + +class Binary_string: public Sql_alloc { protected: char *Ptr; - uint32 str_length; + uint32 str_length, Alloced_length, extra_alloc; + bool alloced, thread_specific; + void init_private_data() + { + Ptr= 0; + Alloced_length= extra_alloc= str_length= 0; + alloced= thread_specific= false; + } + inline void free_buffer() + { + if (alloced) + { + alloced=0; + my_free(Ptr); + } + } public: - Static_binary_string() - :Ptr(NULL), - str_length(0) - { } - Static_binary_string(char *str, size_t length_arg) - :Ptr(str), - str_length((uint32) length_arg) + Binary_string() + { + init_private_data(); + } + explicit Binary_string(size_t length_arg) + { + init_private_data(); + (void) real_alloc(length_arg); + } + /* + NOTE: If one intend to use the c_ptr() method, the following two + contructors need the size of memory for STR to be at least LEN+1 (to make + room for zero termination). + */ + Binary_string(const char *str, size_t len) + { + Ptr= (char*) str; + str_length= (uint32) len; + Alloced_length= 0; /* Memory cannot be written to */ + extra_alloc= 0; + alloced= thread_specific= 0; + } + Binary_string(char *str, size_t len) { - DBUG_ASSERT(length_arg < UINT_MAX32); + Ptr= str; + str_length= Alloced_length= (uint32) len; + extra_alloc= 0; + alloced= thread_specific= 0; } + explicit Binary_string(const Binary_string &str) + { + Ptr= str.Ptr; + str_length= str.str_length; + Alloced_length= str.Alloced_length; + extra_alloc= 0; + alloced= thread_specific= 0; + } + + ~Binary_string() + { + free(); + } + inline uint32 length() const { return str_length;} inline char& operator [] (size_t i) const { return Ptr[i]; } inline void length(size_t len) { str_length=(uint32)len ; } @@ -236,24 +286,12 @@ public: return false; } - bool bin_eq(const Static_binary_string *other) const + bool bin_eq(const Binary_string *other) const { return length() == other->length() && !memcmp(ptr(), other->ptr(), length()); } - void set(char *str, size_t len) - { - Ptr= str; - str_length= (uint32) len; - } - - void swap(Static_binary_string &s) - { - swap_variables(char *, Ptr, s.Ptr); - swap_variables(uint32, str_length, s.str_length); - } - /* PMG 2004.11.12 This is a method that works the same as perl's "chop". It simply @@ -277,47 +315,57 @@ public: */ inline void chop() { - str_length--; - Ptr[str_length]= '\0'; - DBUG_ASSERT(strlen(Ptr) == str_length); + if (str_length) + { + str_length--; + Ptr[str_length]= '\0'; + DBUG_ASSERT(strlen(Ptr) == str_length); + } } // Returns offset to substring or -1 - int strstr(const Static_binary_string &search, uint32 offset=0); + int strstr(const Binary_string &search, uint32 offset=0); // Returns offset to substring or -1 - int strrstr(const Static_binary_string &search, uint32 offset=0); + int strrstr(const Binary_string &search, uint32 offset=0); /* - The following append operations do NOT check alloced memory + The following append operations do not extend the strings and in production + mode do NOT check that alloced memory! q_*** methods writes values of parameters itself qs_*** methods writes string representation of value */ void q_append(const char c) { + ASSERT_LENGTH(1); Ptr[str_length++] = c; } void q_append2b(const uint32 n) { + ASSERT_LENGTH(2); int2store(Ptr + str_length, n); str_length += 2; } void q_append(const uint32 n) { + ASSERT_LENGTH(4); int4store(Ptr + str_length, n); str_length += 4; } void q_append(double d) { + ASSERT_LENGTH(8); float8store(Ptr + str_length, d); str_length += 8; } void q_append(double *d) { + ASSERT_LENGTH(8); float8store(Ptr + str_length, *d); str_length += 8; } void q_append(const char *data, size_t data_len) { + ASSERT_LENGTH(data_len); if (data_len) memcpy(Ptr + str_length, data, data_len); DBUG_ASSERT(str_length <= UINT_MAX32 - data_len); @@ -331,8 +379,9 @@ public: q_append(ls->str, (uint32) ls->length); } - void write_at_position(int position, uint32 value) + void write_at_position(uint32 position, uint32 value) { + DBUG_ASSERT(str_length >= position + 4); int4store(Ptr + position,value); } @@ -349,8 +398,9 @@ public: void qs_append(const double *d); inline void qs_append(const char c) { - Ptr[str_length]= c; - str_length++; + ASSERT_LENGTH(1); + Ptr[str_length]= c; + str_length++; } void qs_append(int i); void qs_append(uint i) @@ -364,69 +414,10 @@ public: void qs_append(ulonglong i); void qs_append(longlong i, int radix) { + ASSERT_LENGTH(22); char *buff= Ptr + str_length; char *end= ll2str(i, buff, radix, 0); - str_length+= uint32(end-buff); - } -}; - - -class Binary_string: public Static_binary_string -{ -protected: - uint32 Alloced_length, extra_alloc; - bool alloced, thread_specific; - void init_private_data() - { - Alloced_length= extra_alloc= 0; - alloced= thread_specific= false; - } - inline void free_buffer() - { - if (alloced) - { - alloced=0; - my_free(Ptr); - } - } -public: - Binary_string() - { - init_private_data(); - } - explicit Binary_string(size_t length_arg) - { - init_private_data(); - (void) real_alloc(length_arg); - } - /* - NOTE: If one intend to use the c_ptr() method, the following two - contructors need the size of memory for STR to be at least LEN+1 (to make - room for zero termination). - */ - Binary_string(const char *str, size_t len) - :Static_binary_string((char *) str, len) - { - init_private_data(); - } - Binary_string(char *str, size_t len) - :Static_binary_string(str, len) - { - Alloced_length= (uint32) len; - extra_alloc= 0; - alloced= thread_specific= 0; - } - explicit Binary_string(const Binary_string &str) - :Static_binary_string(str) - { - Alloced_length= str.Alloced_length; - extra_alloc= 0; - alloced= thread_specific= 0; - } - - ~Binary_string() - { - free(); + str_length+= (uint32) (end-buff); } /* Mark variable thread specific it it's not allocated already */ @@ -449,7 +440,8 @@ public: /* Swap two string objects. Efficient way to exchange data without memcpy. */ void swap(Binary_string &s) { - Static_binary_string::swap(s); + swap_variables(char *, Ptr, s.Ptr); + swap_variables(uint32, str_length, s.str_length); swap_variables(uint32, Alloced_length, s.Alloced_length); swap_variables(bool, alloced, s.alloced); } @@ -461,29 +453,32 @@ public: null character. @note The new buffer will not be null terminated. */ - void set_alloced(char *str, size_t length_arg, size_t alloced_length_arg) + void set_alloced(char *str, size_t length, size_t alloced_length) { free_buffer(); - Static_binary_string::set(str, length_arg); - DBUG_ASSERT(alloced_length_arg < UINT_MAX32); - Alloced_length= (uint32) alloced_length_arg; + Ptr= str; + str_length= (uint32) length; + DBUG_ASSERT(alloced_length < UINT_MAX32); + Alloced_length= (uint32) alloced_length; } inline void set(char *str, size_t arg_length) { set_alloced(str, arg_length, arg_length); } - inline void set(const char *str, size_t arg_length) + inline void set(const char *str, size_t length) { free_buffer(); - Static_binary_string::set((char *) str, arg_length); + Ptr= (char*) str; + str_length= (uint32) length; Alloced_length= 0; } - void set(Binary_string &str, size_t offset, size_t arg_length) + void set(Binary_string &str, size_t offset, size_t length) { DBUG_ASSERT(&str != this); free_buffer(); - Static_binary_string::set((char*) str.ptr() + offset, arg_length); + Ptr= str.Ptr + offset; + str_length= (uint32) length; Alloced_length= 0; if (str.Alloced_length) Alloced_length= (uint32) (str.Alloced_length - offset); @@ -506,7 +501,6 @@ public: char *release() { char *old= Ptr; - Static_binary_string::set(NULL, 0); init_private_data(); return old; } @@ -525,8 +519,8 @@ public: Following should really set str_length= 0, but some code may depend on that the String length is same as buffer length. */ - Static_binary_string::set(str, arg_length); - Alloced_length= (uint32) arg_length; + Ptr= str; + str_length= Alloced_length= (uint32) arg_length; } /* One should set str_length before using it */ MEM_UNDEFINED(&str_length, sizeof(str_length)); @@ -746,7 +740,7 @@ public: If wrong parameter or not enough memory, do nothing */ bool replace(uint32 offset,uint32 arg_length, const char *to, uint32 length); - bool replace(uint32 offset,uint32 arg_length, const Static_binary_string &to) + bool replace(uint32 offset,uint32 arg_length, const Binary_string &to) { return replace(offset,arg_length,to.ptr(),to.length()); } |