[vala/0.50] codegen: Don't leak memory of already assigned out-parameter on error
- From: Rico Tzschichholz <ricotz src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [vala/0.50] codegen: Don't leak memory of already assigned out-parameter on error
- Date: Sat, 2 Jan 2021 12:33:07 +0000 (UTC)
commit b293575308ff106407a7c0bd87acb4469badc028
Author: Rico Tzschichholz <ricotz ubuntu com>
Date: Thu Dec 31 09:55:16 2020 +0100
codegen: Don't leak memory of already assigned out-parameter on error
Fixes https://gitlab.gnome.org/GNOME/vala/issues/1123
codegen/valaccodebasemodule.vala | 11 ++++++
codegen/valagasyncmodule.vala | 4 +++
codegen/valagerrormodule.vala | 6 ++++
tests/Makefile.am | 2 ++
.../asynchronous/out-parameter-free-on-error.vala | 31 +++++++++++++++++
tests/methods/parameter-out-free-on-error.vala | 39 ++++++++++++++++++++++
6 files changed, 93 insertions(+)
---
diff --git a/codegen/valaccodebasemodule.vala b/codegen/valaccodebasemodule.vala
index 699ad7ae8..68c31946c 100644
--- a/codegen/valaccodebasemodule.vala
+++ b/codegen/valaccodebasemodule.vala
@@ -3966,6 +3966,17 @@ public abstract class Vala.CCodeBaseModule : CodeGenerator {
}
}
+ public void append_out_param_free (Method? m) {
+ if (m == null) {
+ return;
+ }
+ foreach (Parameter param in m.get_parameters ()) {
+ if (param.direction == ParameterDirection.OUT && param.variable_type.is_disposable
()) {
+ ccode.add_expression (destroy_parameter (param));
+ }
+ }
+ }
+
public bool variable_accessible_in_finally (LocalVariable local) {
if (current_try == null) {
return false;
diff --git a/codegen/valagasyncmodule.vala b/codegen/valagasyncmodule.vala
index f39f86c6e..c9946599f 100644
--- a/codegen/valagasyncmodule.vala
+++ b/codegen/valagasyncmodule.vala
@@ -743,8 +743,12 @@ public class Vala.GAsyncModule : GtkModule {
set_error.add_argument (error_expr);
ccode.add_expression (set_error);
+ // free local variables
append_local_free (current_symbol);
+ // free possibly already assigned out-parameter
+ append_out_param_free (current_method);
+
// We already returned the error above, we must not return anything else here.
var unref = new CCodeFunctionCall (new CCodeIdentifier ("g_object_unref"));
unref.add_argument (async_result_expr);
diff --git a/codegen/valagerrormodule.vala b/codegen/valagerrormodule.vala
index fedc424ae..d724c3c3a 100644
--- a/codegen/valagerrormodule.vala
+++ b/codegen/valagerrormodule.vala
@@ -104,6 +104,9 @@ public class Vala.GErrorModule : CCodeDelegateModule {
// free local variables
append_local_free (current_symbol);
+ // free possibly already assigned out-parameter
+ append_out_param_free (current_method);
+
if (current_method is CreationMethod && current_method.parent_symbol is Class) {
var cl = (Class) current_method.parent_symbol;
ccode.add_expression (destroy_value (new GLibValue (new ObjectType (cl), new
CCodeIdentifier ("self"), true)));
@@ -123,6 +126,9 @@ public class Vala.GErrorModule : CCodeDelegateModule {
append_local_free (current_symbol);
}
+ // free possibly already assigned out-parameter
+ append_out_param_free (current_method);
+
cfile.add_include ("glib.h");
var ccritical = new CCodeFunctionCall (new CCodeIdentifier ("g_critical"));
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 6abc62ddf..ba21f788a 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -161,6 +161,7 @@ TESTS = \
methods/extern.vala \
methods/iterator.vala \
methods/parameter-fixed-array-initializer.vala \
+ methods/parameter-out-free-on-error.vala \
methods/parameter-ref-array-resize.vala \
methods/parameter-ref-array-resize-captured.vala \
methods/parameter-ref-delegate.vala \
@@ -628,6 +629,7 @@ TESTS = \
asynchronous/constructor-argument-check.vala \
asynchronous/finish-name.vala \
asynchronous/generator.vala \
+ asynchronous/out-parameter-free-on-error.vala \
asynchronous/out-parameter-invalid.test \
asynchronous/params-array-invalid.test \
asynchronous/result-pos.vala \
diff --git a/tests/asynchronous/out-parameter-free-on-error.vala
b/tests/asynchronous/out-parameter-free-on-error.vala
new file mode 100644
index 000000000..a81d3df55
--- /dev/null
+++ b/tests/asynchronous/out-parameter-free-on-error.vala
@@ -0,0 +1,31 @@
+errordomain FooError {
+ FAIL
+}
+
+class Manam : Object {
+}
+
+async void foo_async (Manam i, out Manam o) throws FooError {
+ o = i;
+ throw new FooError.FAIL ("foo");
+}
+
+async void run () {
+ var manam = new Manam ();
+ assert (manam.ref_count == 1);
+ try {
+ Manam minim;
+ yield foo_async (manam, out minim);
+ } catch {
+ }
+ assert (manam.ref_count == 2);
+ loop.quit ();
+}
+
+MainLoop loop;
+
+void main () {
+ loop = new MainLoop ();
+ run.begin ();
+ loop.run ();
+}
diff --git a/tests/methods/parameter-out-free-on-error.vala b/tests/methods/parameter-out-free-on-error.vala
new file mode 100644
index 000000000..ee9716b87
--- /dev/null
+++ b/tests/methods/parameter-out-free-on-error.vala
@@ -0,0 +1,39 @@
+errordomain FooError {
+ FAIL
+}
+
+class Manam : Object {
+}
+
+void foo (Manam i, out Manam o) throws FooError {
+ o = i;
+ throw new FooError.FAIL ("foo");
+}
+
+void bar (Manam i, out unowned Manam o) throws FooError {
+ o = i;
+ throw new FooError.FAIL ("bar");
+}
+
+void main () {
+ {
+ var manam = new Manam ();
+ assert (manam.ref_count == 1);
+ try {
+ Manam minim;
+ foo (manam, out minim);
+ } catch (FooError e) {
+ }
+ assert (manam.ref_count == 1);
+ }
+ {
+ var manam = new Manam ();
+ assert (manam.ref_count == 1);
+ try {
+ unowned Manam minim;
+ bar (manam, out minim);
+ } catch (FooError e) {
+ }
+ assert (manam.ref_count == 1);
+ }
+}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]