From: Rico Tzschichholz Date: Fri, 1 Jan 2021 10:10:41 +0000 (+0100) Subject: codegen: Don't leak memory on internal value comparison of property setter X-Git-Tag: 0.40.25~7 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=6f896c36f56eb8f14f9cb7276526439bdfd71a95;p=thirdparty%2Fvala.git codegen: Don't leak memory on internal value comparison of property setter --- diff --git a/codegen/valaccodebasemodule.vala b/codegen/valaccodebasemodule.vala index 93236afe1..5974c577a 100644 --- a/codegen/valaccodebasemodule.vala +++ b/codegen/valaccodebasemodule.vala @@ -1879,13 +1879,17 @@ public abstract class Vala.CCodeBaseModule : CodeGenerator { get_call.add_argument (new CCodeIdentifier (is_virtual ? "base" : "self")); if (property_type is ArrayType) { + ccode.add_declaration (get_ccode_name (property_type), new CCodeVariableDeclarator ("old_value")); ccode.add_declaration ("int", new CCodeVariableDeclarator ("old_value_length")); get_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("old_value_length"))); - ccode.open_if (new CCodeBinaryExpression (CCodeBinaryOperator.INEQUALITY, get_call, new CCodeIdentifier ("value"))); + ccode.add_assignment (new CCodeIdentifier ("old_value"), get_call); + ccode.open_if (new CCodeBinaryExpression (CCodeBinaryOperator.INEQUALITY, new CCodeIdentifier ("old_value"), new CCodeIdentifier ("value"))); } else if (property_type.compatible (string_type)) { + ccode.add_declaration (get_ccode_name (property_type), new CCodeVariableDeclarator ("old_value")); + ccode.add_assignment (new CCodeIdentifier ("old_value"), get_call); var ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_strcmp0")); ccall.add_argument (new CCodeIdentifier ("value")); - ccall.add_argument (get_call); + ccall.add_argument (new CCodeIdentifier ("old_value")); ccode.open_if (new CCodeBinaryExpression (CCodeBinaryOperator.INEQUALITY, ccall, new CCodeConstant ("0"))); } else if (property_type is StructValueType) { ccode.add_declaration (get_ccode_name (property_type), new CCodeVariableDeclarator ("old_value")); @@ -1901,12 +1905,22 @@ public abstract class Vala.CCodeBaseModule : CodeGenerator { ccall.add_argument (get_expr); ccode.open_if (new CCodeBinaryExpression (CCodeBinaryOperator.INEQUALITY, ccall, new CCodeConstant ("TRUE"))); } else { - ccode.open_if (new CCodeBinaryExpression (CCodeBinaryOperator.INEQUALITY, get_call, new CCodeIdentifier ("value"))); + ccode.add_declaration (get_ccode_name (property_type), new CCodeVariableDeclarator ("old_value")); + ccode.add_assignment (new CCodeIdentifier ("old_value"), get_call); + ccode.open_if (new CCodeBinaryExpression (CCodeBinaryOperator.INEQUALITY, new CCodeIdentifier ("old_value"), new CCodeIdentifier ("value"))); } acc.body.emit (this); ccode.add_expression (notify_call); ccode.close (); + + if (prop.get_accessor.value_type.is_disposable ()) { + var old_value = new GLibValue (prop.get_accessor.value_type, new CCodeIdentifier ("old_value"), true); + if (property_type is ArrayType && get_ccode_array_length (prop)) { + old_value.append_array_length_cvalue (new CCodeIdentifier ("old_value_length")); + } + ccode.add_expression (destroy_value (old_value)); + } } else { acc.body.emit (this); ccode.add_expression (notify_call); diff --git a/tests/Makefile.am b/tests/Makefile.am index 5c84e74d4..d6b1bfea5 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -374,6 +374,7 @@ TESTS = \ objects/property-array-length.vala \ objects/property-base-access.vala \ objects/property-enum.vala \ + objects/property-notify-owned-getter.vala \ objects/property-ownership.vala \ objects/property-read-only-auto.vala \ objects/property-read-only-write.test \ diff --git a/tests/objects/property-notify-owned-getter.vala b/tests/objects/property-notify-owned-getter.vala new file mode 100644 index 000000000..7633abaa1 --- /dev/null +++ b/tests/objects/property-notify-owned-getter.vala @@ -0,0 +1,54 @@ +class Bar : Object { +} + +struct Manam { + public string s; +} + +class Foo : Object { + public Bar o { owned get; set; } + + public Manam st { owned get; set; } + + public Manam? stn { owned get; set; } + + public string s { owned get; set; } + + public string[] strv { owned get; set; } + + construct { + o = bar; + st = { "foo" }; + stn = { "bar" }; + s = "foo"; + strv = { "foo", "bar" }; + } +} + +Bar bar; + +void main () { + bar = new Bar (); + assert (bar.ref_count == 1); + + var foo = new Foo (); + assert (bar.ref_count == 2); + foo.o = bar; + assert (bar.ref_count == 2); + + assert (foo.st.s == "foo"); + foo.st = { "manam" }; + assert (foo.st.s == "manam"); + + assert (foo.stn.s == "bar"); + foo.stn = { "minim" }; + assert (foo.stn.s == "minim"); + + assert (foo.s == "foo"); + foo.s = "manam"; + assert (foo.s == "manam"); + + assert (foo.strv[1] == "bar"); + foo.strv = { "manam", "minim" }; + assert (foo.strv[1] == "minim"); +}