FastLED 3.10.9
Loading...
Searching...
No Matches
string_holder.cpp.hpp
Go to the documentation of this file.
1// IWYU pragma: begin_keep
2#include <stdlib.h>
3#include <string.h> // okay banned header (STL wrapper implementation requires standard header for strlen)
4
5// IWYU pragma: end_keep
7#include "fl/stl/cstring.h" // For memcpy
8#include "fl/stl/malloc.h" // For fl::malloc, fl::free, fl::realloc
9#include "fl/stl/noexcept.h"
10#ifdef FASTLED_TESTING
11#include "fl/stl/singleton.h"
12#endif
13
14namespace fl {
15
16#ifdef FASTLED_TESTING
17namespace {
18struct StringHolderGrowFailure {
19 bool fail = false;
20};
21}
22
23bool StringHolder::setGrowFailureForTesting(bool fail) FL_NO_EXCEPT {
25 const bool previous = state.fail;
26 state.fail = fail;
27 return previous;
28}
29#endif
30
31// StringHolder implementations
32//
33// OOM hardening (FastLED#3588): on classic ESP32 with WiFi + an HTTP
34// server active, free heap drops below 20 KB and fl::malloc genuinely
35// returns NULL. The previous "OOM is terminal" assumption turned that
36// into UB (writes through null; realloc leak plus null mData with a
37// stale nonzero capacity) and crashed unattended bench devices. On
38// failure a holder now degrades to a coherent empty state
39// (mData=null, mLength=0, mCapacity=0) and grow() keeps the old
40// buffer.
41
43 : mData((char*)fl::malloc(strlen(str) + 1))
44 , mLength(strlen(str))
45 , mCapacity(mLength + 1) {
46 if (mData == nullptr) {
47 mLength = 0;
48 mCapacity = 0;
49 return;
50 }
52 mData[mLength] = '\0';
53}
54
56 : mData((char*)fl::malloc(length + 1))
58 , mCapacity(length + 1) {
59 if (mData == nullptr) {
60 mLength = 0;
61 mCapacity = 0;
62 return;
63 }
64 mData[mLength] = '\0';
65}
66
68 : mData((char*)fl::malloc(length + 1))
70 , mCapacity(length + 1) {
71 if (mData == nullptr) {
72 mLength = 0;
73 mCapacity = 0;
74 return;
75 }
77 mData[mLength] = '\0';
78}
79
83
84void StringHolder::grow(size newLength) FL_NO_EXCEPT {
85 if (newLength + 1 <= mCapacity) {
86 // We have enough capacity for newLength + null terminator
87 mLength = newLength;
88 mData[mLength] = '\0';
89 return;
90 }
91
92 // Use fl::realloc for efficient growth without memory move.
93 // Keep the old buffer if the allocation fails — the string simply
94 // does not grow (callers observe the unchanged length).
95 char *grown = nullptr;
96#ifdef FASTLED_TESTING
98#endif
99 {
100 grown = (char*)fl::realloc(mData, newLength + 1);
101 }
102 if (grown == nullptr) {
103 return;
104 }
105 mData = grown;
106 mLength = newLength;
107 mCapacity = newLength + 1;
108 mData[mLength] = '\0'; // Ensure null-termination
109}
110
111} // namespace fl
TestState state
static T & instance() FL_NO_EXCEPT
Definition singleton.h:41
void grow(size newLength) FL_NO_EXCEPT
~StringHolder() FL_DTOR_NOEXCEPT
size length() const FL_NO_EXCEPT
StringHolder(const char *str) FL_NO_EXCEPT
void fail(const char *msg, const char *file, int line, bool isFatal) FL_NO_EXCEPT
Helper for FAIL macros.
u8 u8 fract8 blur_amount FL_NO_EXCEPT
Definition blur.h:186
FASTLED_FORCE_INLINE void free(void *ptr) FL_NO_EXCEPT
Definition malloc.h:23
FASTLED_FORCE_INLINE void * malloc(size_t size) FL_NO_EXCEPT
Definition malloc.h:21
FASTLED_FORCE_INLINE void * memcpy(void *dest, const void *src, size_t n) FL_NO_EXCEPT
Definition cstring.h:136
FASTLED_FORCE_INLINE void * realloc(void *ptr, size_t new_size) FL_NO_EXCEPT
Definition malloc.h:27
FASTLED_FORCE_INLINE size_t strlen(const char *s) FL_NO_EXCEPT
Definition cstring.h:56
Base definition for an LED controller.
#define FL_DTOR_NOEXCEPT