Skip to content

Commit 71cac73

Browse files
Fix NativeStringContext: fixed 8MB pool, malloc fallback, and proper free (#1264)
* Initial plan * Add NativeStringContext::free and fix pool allocation in NativeString Agent-Logs-Url: https://github.com/uNetworking/uWebSockets.js/sessions/32b57b77-b272-4971-920c-090468456f40 Co-authored-by: uNetworkingAB <110806833+uNetworkingAB@users.noreply.github.com> --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: uNetworkingAB <110806833+uNetworkingAB@users.noreply.github.com>
1 parent 41fb93a commit 71cac73

1 file changed

Lines changed: 23 additions & 2 deletions

File tree

src/Utilities.h

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
#include <openssl/x509.h>
2323
#include <v8.h>
2424
#include <vector>
25+
#include <cstdlib>
2526
using namespace v8;
2627

2728
/* Unfortunately we _have_ to depend on Node.js crap */
@@ -125,20 +126,29 @@ class NativeStringContext {
125126
public:
126127
char *alloc(size_t size) {
127128
if (pool_offset + size > pool.size()) {
128-
pool.resize(pool_offset + size);
129+
return (char *) malloc(size);
129130
}
130131
char *ptr = pool.data() + pool_offset;
131132
pool_offset += size;
132133
return ptr;
133134
}
135+
136+
void free(char *ptr) {
137+
if (ptr >= pool.data() && ptr < pool.data() + pool.size()) {
138+
return;
139+
}
140+
::free(ptr);
141+
}
134142
};
135143

136144
class NativeString {
137145
char *data;
138146
size_t length;
139147
bool invalid = false;
148+
bool allocated = false;
149+
NativeStringContext *ctx = nullptr;
140150
public:
141-
NativeString(NativeStringContext &ctx, Isolate *isolate, const Local<Value> &value) {
151+
NativeString(NativeStringContext &ctx, Isolate *isolate, const Local<Value> &value) : ctx(&ctx) {
142152
if (value->IsUndefined()) {
143153
data = nullptr;
144154
length = 0;
@@ -154,11 +164,13 @@ class NativeString {
154164
// utf16: copy and convert to utf8
155165
length = string->Utf8LengthV2(isolate);
156166
data = ctx.alloc(length);
167+
allocated = true;
157168
string->WriteUtf8V2(isolate, data, length);
158169
}
159170
#else // Fallback Node.js < 24
160171
length = string->Utf8Length(isolate);
161172
data = ctx.alloc(length);
173+
allocated = true;
162174
string->WriteUtf8(isolate, data, length, nullptr, String::WriteOptions::NO_NULL_TERMINATION);
163175
#endif
164176
} else if (value->IsArrayBufferView()) { /* DataView or TypedArray */
@@ -181,6 +193,15 @@ class NativeString {
181193
}
182194
}
183195

196+
~NativeString() noexcept {
197+
if (allocated) {
198+
ctx->free(data);
199+
}
200+
}
201+
202+
NativeString(const NativeString &) = delete;
203+
NativeString &operator=(const NativeString &) = delete;
204+
184205
bool isInvalid(const FunctionCallbackInfo<Value> &args) {
185206
if (invalid) {
186207
args.GetReturnValue().Set(args.GetIsolate()->ThrowException(v8::Exception::Error(String::NewFromUtf8(args.GetIsolate(), "Text and data can only be passed by String, ArrayBuffer, SharedArrayBuffer or ArrayBufferView.", NewStringType::kNormal).ToLocalChecked())));

0 commit comments

Comments
 (0)