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.46.11~19 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=b763b94e5d1a613c4c010249a395787255096425;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 afa30692e..828c37f74 100644 --- a/codegen/valaccodearraymodule.vala +++ b/codegen/valaccodearraymodule.vala @@ -521,12 +521,20 @@ public class Vala.CCodeArrayModule : CCodeMethodCallModule { gnew.add_argument (new CCodeIdentifier (get_ccode_name (array_type.element_type))); 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.data_type != null && array_type.element_type.data_type.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); + // 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); @@ -540,7 +548,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 dup_call = new CCodeFunctionCall (new CCodeIdentifier ("g_memdup")); dup_call.add_argument (new CCodeIdentifier ("self")); @@ -549,6 +564,9 @@ public class Vala.CCodeArrayModule : CCodeMethodCallModule { dup_call.add_argument (new CCodeBinaryExpression (CCodeBinaryOperator.MUL, new CCodeIdentifier ("length"), sizeof_call)); 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 3e63794f7..5663d7678 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 \ 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); + } +}