From: Rico Tzschichholz Date: Sun, 24 May 2020 17:25:41 +0000 (+0200) Subject: codegen: Improve array-dup-wrapper for empty arrays X-Git-Tag: 0.49.1~117 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=48679761c7298f14bdab9c6ea3bd4c48db192cf5;p=thirdparty%2Fvala.git codegen: Improve array-dup-wrapper for empty arrays Guard against negative lengths and consistently return NULL if allocated size would be 0. See https://gitlab.gnome.org/GNOME/vala/issues/999 --- diff --git a/codegen/valaccodearraymodule.vala b/codegen/valaccodearraymodule.vala index 5fa9ea23d..0192f2cc9 100644 --- a/codegen/valaccodearraymodule.vala +++ b/codegen/valaccodearraymodule.vala @@ -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 diff --git a/tests/Makefile.am b/tests/Makefile.am index 78c939a2f..263e8975e 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -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 index 000000000..8d64f304a --- /dev/null +++ b/tests/arrays/empty-length-0.vala @@ -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); + } +}