From 06b0f25f2a6fc961f3db39c7378c36a7768269a1 Mon Sep 17 00:00:00 2001 From: Doyle Thai Date: Sun, 28 Jan 2018 12:43:53 +1100 Subject: [PATCH] Fix realloc bug destroying memory in stack --- dqn.h | 121 +++++++++++++++++++++++++++++++++++----------------------- 1 file changed, 73 insertions(+), 48 deletions(-) diff --git a/dqn.h b/dqn.h index 33ec427..bda6bbd 100644 --- a/dqn.h +++ b/dqn.h @@ -478,13 +478,14 @@ public: // API // ============================================================================================= // return: These functions return false if allocation failed. String is preserved. - bool Expand (const i32 newMax); - bool Sprintf(char const *const fmt, ...); - bool Append (DqnString const string); - bool Append (char const *const cstr, i32 bytesToCopy = -1); + bool Expand (i32 newMax); + bool Sprintf (char const *const fmt, ...); + bool VSprintf(char const *const fmt, va_list argList); + bool Append (DqnString const string); + bool Append (char const *const cstr, i32 bytesToCopy = -1); - void Clear (); - void Free (); + void Clear (); + void Free (); // return: -1 if invalid, or if bufSize is 0 the required buffer length in wchar_t characters i32 ToWChar(wchar_t *const buf, i32 const bufSize); @@ -493,6 +494,12 @@ public: wchar_t *ToWChar(DqnMemAPI *const api = &DQN_DEFAULT_HEAP_ALLOCATOR); }; +class DqnSmartString : public DqnString +{ +public: + ~DqnSmartString() { this->Free(); } +}; + DQN_FILE_SCOPE DqnString DqnString_(DqnMemAPI *const api = &DQN_DEFAULT_HEAP_ALLOCATOR); DQN_FILE_SCOPE DqnString DqnString_(DqnMemStack *const stack); @@ -526,8 +533,9 @@ public: bool InitSize (isize size_, DqnMemStack *const stack); void Free (); - bool Resize (isize newMax); + bool Resize (isize newMax); // If (newMax < count), it will destroy the left over elements. bool Grow (isize multiplier = 2); + T *Make (); // Get a ptr to the next free element in the array, increment count. T *Push (T const *item, isize num); T *Push (T const item); T *Insert (T const item, isize index); @@ -681,6 +689,24 @@ bool DqnArray::Grow(isize multiplier) return result; } +template +T *DqnArray::Make() +{ + bool accessible = true; + if (!this->data || this->count >= this->max) + { + accessible = this->Grow(); + } + + if (accessible) + { + T *result = this->data[this->count++]; + return result; + } + + return nullptr; +} + template T *DqnArray::Push(T const *item, isize num) { @@ -2815,26 +2841,23 @@ DQN_FILE_SCOPE void DqnLog(char *file, char const *const functionName, i32 const char userMsg[2048]; userMsg[0] = '\0'; - if (msg) + va_list argList; + va_start(argList, msg); { - va_list argList; - va_start(argList, msg); + u32 numCopied = Dqn_vsprintf(userMsg, msg, argList); + if (numCopied > DQN_ARRAY_COUNT(userMsg)) { - u32 numCopied = Dqn_vsprintf(userMsg, msg, argList); - if (numCopied > DQN_ARRAY_COUNT(userMsg)) - { - (*((int *)0)) = 0; - } + (*((int *)0)) = 0; } - va_end(argList); } + va_end(argList); - char const *const formatStr = "DqnLog:%s:%s,%d: %s\n"; - fprintf(stderr, formatStr, file, functionName, lineNum, userMsg); + char const *const formatStr = "DqnLog:%s:%s,%d: %s\n"; + fprintf(stderr, formatStr, file, functionName, lineNum, userMsg); - #if defined(DQN_WIN32_PLATFORM) - DqnWin32_OutputDebugString(formatStr, file, functionName, lineNum, userMsg); - #endif + #if defined(DQN_WIN32_PLATFORM) + DqnWin32_OutputDebugString(formatStr, file, functionName, lineNum, userMsg); + #endif } DQN_FILE_SCOPE void DqnLog(char *file, char const *const functionName, i32 const lineNum, @@ -2853,19 +2876,16 @@ DQN_FILE_SCOPE void DqnLog(char *file, char const *const functionName, i32 const char userMsg[2048]; userMsg[0] = '\0'; - if (msg) + va_list argList; + va_start(argList, msg); { - va_list argList; - va_start(argList, msg); + u32 numCopied = Dqn_vsprintf(userMsg, msg, argList); + if (numCopied > DQN_ARRAY_COUNT(userMsg)) { - u32 numCopied = Dqn_vsprintf(userMsg, msg, argList); - if (numCopied > DQN_ARRAY_COUNT(userMsg)) - { - (*((int *)0)) = 0; - } + (*((int *)0)) = 0; } - va_end(argList); } + va_end(argList); char const *const formatStr = "DqnLog:%s:%s,%d(%s): %s\n"; fprintf(stderr, formatStr, file, functionName, lineNum, expr, userMsg); @@ -3084,7 +3104,7 @@ FILE_SCOPE u8 *DqnMemAPIInternal_StackAllocatorCallback(DqnMemAPI *api, DqnMemAP u8 *checkPtr = currUsagePtr - DQN_ALIGN_POW_N(request->oldSize, stack->byteAlign); // Last allocation, can safely allocate the remainder space. - if (checkPtr == (u8 *)request->oldMemPtr || request->oldMemPtr == block->memory) + if (checkPtr == (u8 *)request->oldMemPtr) { size_t remainingBytesToAlloc = request->newRequestSize - request->oldSize; DQN_ASSERT(remainingBytesToAlloc > 0); @@ -5612,7 +5632,7 @@ bool DqnString::InitLiteralNoAlloc(char *const cstr, i32 cstrLen) return true; } -bool DqnString::Expand(const i32 newMax) +bool DqnString::Expand(i32 newMax) { if (newMax < this->max) { @@ -5696,6 +5716,16 @@ DQN_FILE_SCOPE bool DqnStringInternal_Append(DqnString *const str, char const *c } bool DqnString::Sprintf(char const *fmt, ...) +{ + va_list argList; + va_start(argList, fmt); + bool result = this->VSprintf(fmt, argList); + va_end(argList); + + return result; +} + +bool DqnString::VSprintf(char const *fmt, va_list argList) { LOCAL_PERSIST char tmp[STB_SPRINTF_MIN]; @@ -5705,26 +5735,21 @@ bool DqnString::Sprintf(char const *fmt, ...) return buf; }; - va_list argList; - va_start(argList, fmt); + i32 const reqLen = Dqn_vsprintfcb(PrintCallback, nullptr, tmp, fmt, argList); + auto const remainingSpace = this->max - this->len; + if (reqLen > remainingSpace) { - i32 const reqLen = Dqn_vsprintfcb(PrintCallback, nullptr, tmp, fmt, argList); - auto const remainingSpace = this->max - this->len; - if (reqLen > remainingSpace) + i32 const newMax = this->max + reqLen; + if (!this->Expand(newMax)) { - i32 const newMax = this->max + reqLen; - if (!this->Expand(newMax)) - { - return false; - } + return false; } - - char *bufStart = this->str + this->len; - i32 numCopied = Dqn_vsprintf(bufStart, fmt, argList); - this->len += numCopied; - DQN_ASSERT(this->len <= this->max); } - va_end(argList); + + char *bufStart = this->str + this->len; + i32 numCopied = Dqn_vsprintf(bufStart, fmt, argList); + this->len += numCopied; + DQN_ASSERT(this->len <= this->max); return true; }