]> git.ipfire.org Git - thirdparty/vala.git/commitdiff
codegen: Check vfunc of abstract/virtual methods for NULL before using it
authorRico Tzschichholz <ricotz@ubuntu.com>
Wed, 15 Apr 2020 14:24:10 +0000 (16:24 +0200)
committerRico Tzschichholz <ricotz@ubuntu.com>
Wed, 15 Apr 2020 15:51:41 +0000 (17:51 +0200)
Fixes https://gitlab.gnome.org/GNOME/vala/issues/153

codegen/valaccodemethodmodule.vala

index 03b382ac4ba1667aad5879ad4bd449256bc481d8..55d29ff975855891667e4ec97903af0d81bd5fca 100644 (file)
@@ -1068,15 +1068,11 @@ public abstract class Vala.CCodeMethodModule : CCodeStructModule {
 
                CCodeExpression vcast;
                if (m.parent_symbol is Interface) {
-                       var iface = (Interface) m.parent_symbol;
-
-                       vcast = new CCodeFunctionCall (new CCodeIdentifier (get_ccode_interface_get_function (iface)));
-                       ((CCodeFunctionCall) vcast).add_argument (new CCodeIdentifier ("self"));
+                       vcast = new CCodeIdentifier ("_iface_");
                } else {
                        var cl = (Class) m.parent_symbol;
                        if (!cl.is_compact) {
-                               vcast = new CCodeFunctionCall (new CCodeIdentifier (get_ccode_class_get_function (cl)));
-                               ((CCodeFunctionCall) vcast).add_argument (new CCodeIdentifier ("self"));
+                               vcast = new CCodeIdentifier ("_klass_");
                        } else {
                                vcast = new CCodeIdentifier ("self");
                        }
@@ -1095,7 +1091,7 @@ public abstract class Vala.CCodeMethodModule : CCodeStructModule {
 
                push_function (vfunc);
 
-               if (context.assert && m.return_type.type_symbol is Struct && ((Struct) m.return_type.type_symbol).is_simple_type () && default_value_for_type (m.return_type, false) == null) {
+               if (m.return_type.is_non_null_simple_type () && default_value_for_type (m.return_type, false) == null) {
                        // the type check will use the result variable
                        var vardecl = new CCodeVariableDeclarator ("result", default_value_for_type (m.return_type, true));
                        vardecl.init0 = true;
@@ -1109,6 +1105,26 @@ public abstract class Vala.CCodeMethodModule : CCodeStructModule {
                        create_precondition_statement (m, return_type, precondition);
                }
 
+               if (m.parent_symbol is Interface) {
+                       var iface = (Interface) m.parent_symbol;
+
+                       var vcastcall = new CCodeFunctionCall (new CCodeIdentifier (get_ccode_interface_get_function (iface)));
+                       ((CCodeFunctionCall) vcastcall).add_argument (new CCodeIdentifier ("self"));
+                       ccode.add_declaration ("%s*".printf (get_ccode_type_name (iface)), new CCodeVariableDeclarator ("_iface_"));
+                       ccode.add_assignment (vcast, vcastcall);
+               } else {
+                       var cl = (Class) m.parent_symbol;
+                       if (!cl.is_compact) {
+                               var vcastcall = new CCodeFunctionCall (new CCodeIdentifier (get_ccode_class_get_function (cl)));
+                               ((CCodeFunctionCall) vcastcall).add_argument (new CCodeIdentifier ("self"));
+                               ccode.add_declaration ("%sClass*".printf (get_ccode_name (cl)), new CCodeVariableDeclarator ("_klass_"));
+                               ccode.add_assignment (vcast, vcastcall);
+                       }
+               }
+
+               // check if vfunc pointer is properly set
+               ccode.open_if (vcall.call);
+
                if (return_type is VoidType || return_type.is_real_non_null_struct_type ()) {
                        ccode.add_expression (vcall);
                } else if (m.get_postconditions ().size == 0) {
@@ -1130,6 +1146,14 @@ public abstract class Vala.CCodeMethodModule : CCodeStructModule {
                        }
                }
 
+               ccode.close ();
+
+               if (m.return_type.is_non_null_simple_type () && default_value_for_type (m.return_type, false) == null) {
+                       ccode.add_return (new CCodeIdentifier ("result"));
+               } else if (!(return_type is VoidType)) {
+                       ccode.add_return (default_value_for_type (return_type, false, true));
+               }
+
                if (m.printf_format) {
                        vfunc.modifiers |= CCodeModifiers.PRINTF;
                } else if (m.scanf_format) {