]> git.ipfire.org Git - thirdparty/vala.git/commitdiff
codegen: Improve array-dup-wrapper for empty arrays 48679761c7298f14bdab9c6ea3bd4c48db192cf5
authorRico Tzschichholz <ricotz@ubuntu.com>
Sun, 24 May 2020 17:25:41 +0000 (19:25 +0200)
committerRico Tzschichholz <ricotz@ubuntu.com>
Wed, 27 May 2020 07:35:40 +0000 (09:35 +0200)
Guard against negative lengths and consistently return NULL if allocated
size would be 0.

See https://gitlab.gnome.org/GNOME/vala/issues/999

codegen/valaccodearraymodule.vala
tests/Makefile.am
tests/arrays/empty-length-0.vala [new file with mode: 0644]

index 5fa9ea23df4451ff67712e3b78127212e5f9cfe1..0192f2cc93b81935f394d119a2a71e99a0b91499 100644 (file)
@@ -541,9 +541,13 @@ public class Vala.CCodeArrayModule : CCodeMethodCallModule {
                        }
 
                        CCodeExpression length_expr = new CCodeIdentifier ("length");
+                       CCodeBinaryOperator length_check_op;
                        // add extra item to have array NULL-terminated for all reference types
                        if (array_type.element_type.type_symbol != null && array_type.element_type.type_symbol.is_reference_type ()) {
                                length_expr = new CCodeBinaryExpression (CCodeBinaryOperator.PLUS, length_expr, new CCodeConstant ("1"));
+                               length_check_op = CCodeBinaryOperator.GREATER_THAN_OR_EQUAL;
+                       } else {
+                               length_check_op = CCodeBinaryOperator.GREATER_THAN;
                        }
                        gnew.add_argument (length_expr);
 
@@ -553,6 +557,10 @@ public class Vala.CCodeArrayModule : CCodeMethodCallModule {
                                gnew.add_argument (csizeof);
                        }
 
+                       // only attempt to dup if length >=/> 0, this deals with negative lengths and returns NULL
+                       var length_check = new CCodeBinaryExpression (length_check_op, new CCodeIdentifier ("length"), new CCodeConstant ("0"));
+                       ccode.open_if (length_check);
+
                        ccode.add_declaration (get_ccode_name (array_type), cvardecl);
                        ccode.add_assignment (new CCodeIdentifier ("result"), gnew);
 
@@ -566,7 +574,14 @@ public class Vala.CCodeArrayModule : CCodeMethodCallModule {
                        ccode.close ();
 
                        ccode.add_return (new CCodeIdentifier ("result"));
+
+                       ccode.close ();
+                       ccode.add_return (new CCodeIdentifier ("NULL"));
                } else {
+                       // only dup if length > 0, this deals with negative lengths and returns NULL
+                       var length_check = new CCodeBinaryExpression (CCodeBinaryOperator.GREATER_THAN, new CCodeIdentifier ("length"), new CCodeConstant ("0"));
+                       ccode.open_if (length_check);
+
                        var sizeof_call = new CCodeFunctionCall (new CCodeIdentifier ("sizeof"));
                        sizeof_call.add_argument (new CCodeIdentifier (get_ccode_name (array_type.element_type)));
                        var length_expr = new CCodeIdentifier ("length");
@@ -597,6 +612,9 @@ public class Vala.CCodeArrayModule : CCodeMethodCallModule {
 
                                ccode.add_return (dup_call);
                        }
+
+                       ccode.close ();
+                       ccode.add_return (new CCodeIdentifier ("NULL"));
                }
 
                // append to file
index 78c939a2feeec3bb9a6c4dda0aa95842e4b8c3db..263e8975e4c509a706ab9ca9addcf2adbc034c1b 100644 (file)
@@ -79,6 +79,7 @@ TESTS = \
        arrays/cast-silent-invalid.test \
        arrays/class-field-length-cname.vala \
        arrays/constant-element-access.vala \
+       arrays/empty-length-0.vala \
        arrays/expression-bracket.test \
        arrays/fixed-length-init0-not-allowed.vala \
        arrays/field-global-length-cname.vala \
@@ -949,6 +950,7 @@ LINUX_TESTS = \
 
 POSIX_TESTS = \
        basic-types/arrays.vala \
+       arrays/empty-length-0.vala \
        structs/struct_only.vala \
        delegates/delegate_only.vala \
        enums/enum_only.vala \
diff --git a/tests/arrays/empty-length-0.vala b/tests/arrays/empty-length-0.vala
new file mode 100644 (file)
index 0000000..8d64f30
--- /dev/null
@@ -0,0 +1,52 @@
+struct Manam {
+       string s;
+}
+
+string[] foo;
+int[] bar;
+Manam[] manam;
+
+string[] get_foo () {
+       return foo;
+}
+
+int[] get_bar () {
+       return bar;
+}
+
+Manam[] get_manam () {
+       return manam;
+}
+
+void main () {
+       {
+               foo = new string[0];
+               assert (foo != null);
+               assert (get_foo () != null);
+       }
+       {
+               foo = {};
+               assert (foo != null);
+               assert (get_foo () != null);
+       }
+       {
+               bar = new int[0];
+               //assert (bar != null);
+               assert (get_bar () == null);
+       }
+       {
+               bar = {};
+               //assert (bar != null);
+               assert (get_bar () == null);
+       }
+       {
+               manam = new Manam[0];
+               //assert (manam != null);
+               assert (get_manam () == null);
+       }
+       {
+               manam = {};
+               //assert (manam != null);
+               assert (get_manam () == null);
+       }
+}