From: Jeremy Philippe Date: Wed, 8 Jan 2020 12:20:31 +0000 (+0100) Subject: vala: Non-nullable value-type in coalesce expression needs to be copied X-Git-Tag: 0.47.3~17 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=6cfa112524d13f878d02149475079e34cd366116;p=thirdparty%2Fvala.git vala: Non-nullable value-type in coalesce expression needs to be copied The code generated by the coalesce expression could lead to stale pointers to the stack if the right-side expression is an immediate value (such as an integer literal or a struct). Fixes https://gitlab.gnome.org/GNOME/vala/issues/893 --- diff --git a/tests/Makefile.am b/tests/Makefile.am index 2c66135bf..314b01439 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -166,6 +166,7 @@ TESTS = \ control-flow/break.vala \ control-flow/break-invalid.test \ control-flow/coalesce-reference-transfer.vala \ + control-flow/coalesce-right-value.vala \ control-flow/continue-invalid.test \ control-flow/double-catch.test \ control-flow/expressions-conditional.vala \ diff --git a/tests/control-flow/coalesce-right-value.vala b/tests/control-flow/coalesce-right-value.vala new file mode 100644 index 000000000..ca64126d7 --- /dev/null +++ b/tests/control-flow/coalesce-right-value.vala @@ -0,0 +1,17 @@ +struct Foo { + public int i; +} + +void main () { + { + int? null_int = null; + int i = null_int ?? 42; + assert (i == 42); + } + { + Foo? null_foo = null; + Foo right_foo = { 42 }; + Foo foo = null_foo ?? right_foo; + assert (foo.i == 42); + } +} diff --git a/vala/valabinaryexpression.vala b/vala/valabinaryexpression.vala index fe559e1d5..927ca5413 100644 --- a/vala/valabinaryexpression.vala +++ b/vala/valabinaryexpression.vala @@ -234,6 +234,12 @@ public class Vala.BinaryExpression : Expression { local_type = right.value_type.copy (); } + if (local_type != null && right.value_type is ValueType && !right.value_type.nullable) { + // immediate values in the right expression must always be boxed, + // otherwise the local variable may receive a stale pointer to the stack + local_type.value_owned = true; + } + var local = new LocalVariable (local_type, get_temp_name (), left, source_reference); var decl = new DeclarationStatement (local, source_reference);