[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>
diff --git a/runtime/bin/gen_snapshot.cc b/runtime/bin/gen_snapshot.cc
index 6a24139..ada246f6 100644
--- a/runtime/bin/gen_snapshot.cc
+++ b/runtime/bin/gen_snapshot.cc
@@ -372,12 +372,19 @@
}
}
+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);
}
}
diff --git a/runtime/bin/loader.cc b/runtime/bin/loader.cc
index 709fc54..4043580 100644
--- a/runtime/bin/loader.cc
+++ b/runtime/bin/loader.cc
@@ -52,6 +52,16 @@
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 @@
&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 @@
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);
diff --git a/runtime/include/dart_api.h b/runtime/include/dart_api.h
index 4f4baea..aac0427 100644
--- a/runtime/include/dart_api.h
+++ b/runtime/include/dart_api.h
@@ -3646,6 +3646,8 @@
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.
diff --git a/runtime/vm/dart_api_impl.cc b/runtime/vm/dart_api_impl.cc
index 5a5a47b..3a83464 100644
--- a/runtime/vm/dart_api_impl.cc
+++ b/runtime/vm/dart_api_impl.cc
@@ -5841,24 +5841,8 @@
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 @@
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)
}
diff --git a/runtime/vm/unit_test.cc b/runtime/vm/unit_test.cc
index 82323cd..57286f7 100644
--- a/runtime/vm/unit_test.cc
+++ b/runtime/vm/unit_test.cc
@@ -433,6 +433,10 @@
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 @@
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 @@
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));