[standalone] Fix memory leak in the tag handler.

TEST=asan
Bug: https://github.com/dart-lang/sdk/issues/37030
Bug: https://github.com/dart-lang/sdk/issues/51210
Change-Id: Ia62a4d7d1805c6ac4a311ef9952fff248e7b4693
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/280284
Reviewed-by: Siva Annamalai <asiva@google.com>
Commit-Queue: Ryan Macnak <rmacnak@google.com>
This commit is contained in:
Ryan Macnak 2023-02-02 21:35:47 +00:00 committed by Commit Queue
parent 99a9f3d516
commit c81b00938d
5 changed files with 76 additions and 35 deletions

View file

@ -372,12 +372,19 @@ static void ReadFile(const char* filename, uint8_t** buffer, intptr_t* size) {
}
}
static void MallocFinalizer(void* isolate_callback_data, void* peer) {
free(peer);
}
static void MaybeLoadExtraInputs(const CommandLineOptions& inputs) {
for (intptr_t i = 1; i < inputs.count(); i++) {
uint8_t* buffer = NULL;
intptr_t size = 0;
ReadFile(inputs.GetArgument(i), &buffer, &size);
Dart_Handle result = Dart_LoadLibraryFromKernel(buffer, size);
Dart_Handle td = Dart_NewExternalTypedDataWithFinalizer(
Dart_TypedData_kUint8, buffer, size, buffer, size, MallocFinalizer);
CHECK_RESULT(td);
Dart_Handle result = Dart_LoadLibrary(td);
CHECK_RESULT(result);
}
}

View file

@ -52,6 +52,16 @@ Dart_Handle Loader::Init(const char* packages_file,
static void MallocFinalizer(void* isolate_callback_data, void* peer) {
free(peer);
}
static Dart_Handle WrapMallocedKernelBuffer(uint8_t* kernel_buffer,
intptr_t kernel_buffer_size) {
Dart_Handle result = Dart_NewExternalTypedDataWithFinalizer(
Dart_TypedData_kUint8, kernel_buffer, kernel_buffer_size, kernel_buffer,
kernel_buffer_size, MallocFinalizer);
if (Dart_IsError(result)) {
free(kernel_buffer);
}
return result;
}
#endif
Dart_Handle Loader::LibraryTagHandler(Dart_LibraryTag tag,
@ -87,11 +97,7 @@ Dart_Handle Loader::LibraryTagHandler(Dart_LibraryTag tag,
&kernel_buffer_size)) {
return DartUtils::NewError("'%s' is not a kernel file", url_string);
}
result = Dart_NewExternalTypedData(Dart_TypedData_kUint8, kernel_buffer,
kernel_buffer_size);
Dart_NewFinalizableHandle(result, kernel_buffer, kernel_buffer_size,
MallocFinalizer);
return result;
return WrapMallocedKernelBuffer(kernel_buffer, kernel_buffer_size);
}
if (dfe.CanUseDartFrontend() && dfe.UseDartFrontend() &&
(tag == Dart_kImportTag)) {
@ -103,7 +109,8 @@ Dart_Handle Loader::LibraryTagHandler(Dart_LibraryTag tag,
dfe.CompileAndReadScript(url_string, &kernel_buffer, &kernel_buffer_size,
&error, &exit_code, NULL, false);
if (exit_code == 0) {
return Dart_LoadLibraryFromKernel(kernel_buffer, kernel_buffer_size);
return Dart_LoadLibrary(
WrapMallocedKernelBuffer(kernel_buffer, kernel_buffer_size));
} else if (exit_code == kCompilationErrorExitCode) {
Dart_Handle result = Dart_NewCompilationError(error);
free(error);

View file

@ -3646,6 +3646,8 @@ DART_EXPORT Dart_Handle Dart_LibraryHandleError(Dart_Handle library,
DART_EXPORT DART_WARN_UNUSED_RESULT Dart_Handle
Dart_LoadLibraryFromKernel(const uint8_t* kernel_buffer,
intptr_t kernel_buffer_size);
DART_EXPORT DART_WARN_UNUSED_RESULT Dart_Handle
Dart_LoadLibrary(Dart_Handle kernel_buffer);
/**
* Indicates that all outstanding load requests have been satisfied.

View file

@ -5841,24 +5841,8 @@ DART_EXPORT Dart_Handle Dart_LibraryHandleError(Dart_Handle library_in,
return error_in;
}
DART_EXPORT Dart_Handle Dart_LoadLibraryFromKernel(const uint8_t* buffer,
intptr_t buffer_size) {
#if defined(DART_PRECOMPILED_RUNTIME)
return Api::NewError("%s: Cannot compile on an AOT runtime.", CURRENT_FUNC);
#else
DARTSCOPE(Thread::Current());
API_TIMELINE_DURATION(T);
StackZone zone(T);
CHECK_CALLBACK_STATE(T);
// NOTE: We do not attach a finalizer for this object, because the embedder
// will/should free it once the isolate group has shutdown.
// See also http://dartbug.com/37030.
const auto& td = ExternalTypedData::Handle(ExternalTypedData::New(
kExternalTypedDataUint8ArrayCid, const_cast<uint8_t*>(buffer),
buffer_size, Heap::kOld));
#if !defined(DART_PRECOMPILED_RUNTIME)
static Dart_Handle LoadLibrary(Thread* T, const ExternalTypedData& td) {
const char* error = nullptr;
std::unique_ptr<kernel::Program> program =
kernel::Program::ReadFromTypedData(td, &error);
@ -5873,6 +5857,40 @@ DART_EXPORT Dart_Handle Dart_LoadLibraryFromKernel(const uint8_t* buffer,
source->add_loaded_blob(Z, td);
return Api::NewHandle(T, result.ptr());
}
#endif // !defined(DART_PRECOMPILED_RUNTIME)
DART_EXPORT Dart_Handle Dart_LoadLibraryFromKernel(const uint8_t* buffer,
intptr_t buffer_size) {
#if defined(DART_PRECOMPILED_RUNTIME)
return Api::NewError("%s: Cannot compile on an AOT runtime.", CURRENT_FUNC);
#else
DARTSCOPE(Thread::Current());
API_TIMELINE_DURATION(T);
StackZone zone(T);
CHECK_CALLBACK_STATE(T);
// NOTE: We do not attach a finalizer for this object, because the embedder
// will/should free it once the isolate group has shutdown.
const auto& td = ExternalTypedData::Handle(ExternalTypedData::New(
kExternalTypedDataUint8ArrayCid, const_cast<uint8_t*>(buffer),
buffer_size, Heap::kOld));
return LoadLibrary(T, td);
#endif // defined(DART_PRECOMPILED_RUNTIME)
}
DART_EXPORT Dart_Handle Dart_LoadLibrary(Dart_Handle kernel_buffer) {
#if defined(DART_PRECOMPILED_RUNTIME)
return Api::NewError("%s: Cannot compile on an AOT runtime.", CURRENT_FUNC);
#else
DARTSCOPE(Thread::Current());
const ExternalTypedData& td =
Api::UnwrapExternalTypedDataHandle(Z, kernel_buffer);
if (td.IsNull()) {
RETURN_TYPE_ERROR(Z, kernel_buffer, ExternalTypedData);
}
return LoadLibrary(T, td);
#endif // defined(DART_PRECOMPILED_RUNTIME)
}

View file

@ -433,6 +433,10 @@ Dart_Handle TestCase::LoadTestScript(const char* script,
return result;
}
static void MallocFinalizer(void* isolate_callback_data, void* peer) {
free(peer);
}
Dart_Handle TestCase::LoadTestLibrary(const char* lib_uri,
const char* script,
Dart_NativeEntryResolver resolver) {
@ -448,12 +452,14 @@ Dart_Handle TestCase::LoadTestLibrary(const char* lib_uri,
if ((kernel_buffer == NULL) && (error != NULL)) {
return Dart_NewApiError(error);
}
Dart_Handle lib =
Dart_LoadLibraryFromKernel(kernel_buffer, kernel_buffer_size);
EXPECT_VALID(lib);
// Ensure kernel buffer isn't leaked after test is run.
AddToKernelBuffers(kernel_buffer);
Dart_Handle td = Dart_NewExternalTypedDataWithFinalizer(
Dart_TypedData_kUint8, const_cast<uint8_t*>(kernel_buffer),
kernel_buffer_size, const_cast<uint8_t*>(kernel_buffer),
kernel_buffer_size, MallocFinalizer);
EXPECT_VALID(td);
Dart_Handle lib = Dart_LoadLibrary(td);
EXPECT_VALID(lib);
// TODO(32618): Kernel doesn't correctly represent the root library.
lib = Dart_LookupLibrary(Dart_NewStringFromCString(sourcefiles[0].uri));
@ -488,13 +494,14 @@ Dart_Handle TestCase::LoadTestScriptWithDFE(int sourcefiles_count,
return Dart_NewApiError(error);
}
Dart_Handle lib =
Dart_LoadLibraryFromKernel(kernel_buffer, kernel_buffer_size);
Dart_Handle td = Dart_NewExternalTypedDataWithFinalizer(
Dart_TypedData_kUint8, const_cast<uint8_t*>(kernel_buffer),
kernel_buffer_size, const_cast<uint8_t*>(kernel_buffer),
kernel_buffer_size, MallocFinalizer);
EXPECT_VALID(td);
Dart_Handle lib = Dart_LoadLibrary(td);
EXPECT_VALID(lib);
// Ensure kernel buffer isn't leaked after test is run.
AddToKernelBuffers(kernel_buffer);
// BOGUS: Kernel doesn't correctly represent the root library.
lib = Dart_LookupLibrary(Dart_NewStringFromCString(
entry_script_uri != NULL ? entry_script_uri : sourcefiles[0].uri));