]> git.ipfire.org Git - thirdparty/vala.git/commitdiff
vala: Non-nullable value-type in coalesce expression needs to be copied 6cfa112524d13f878d02149475079e34cd366116
authorJeremy Philippe <jeremy.philippe@gmail.com>
Wed, 8 Jan 2020 12:20:31 +0000 (13:20 +0100)
committerRico Tzschichholz <ricotz@ubuntu.com>
Wed, 8 Jan 2020 14:01:21 +0000 (15:01 +0100)
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

tests/Makefile.am
tests/control-flow/coalesce-right-value.vala [new file with mode: 0644]
vala/valabinaryexpression.vala

index 2c66135bf9d3818cebfe229b9435a43db93e6c8d..314b01439abc67d5aa91746bad9338e2eb3247c6 100644 (file)
@@ -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 (file)
index 0000000..ca64126
--- /dev/null
@@ -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);
+       }
+}
index fe559e1d56a6396a05fac92f27c2741af0a6db0b..927ca541383735299601e1a658bd625041aaf0dd 100644 (file)
@@ -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);