Fix leaks in mono_lookup_internal_call_full_with_flags, for lack of destructors....
authorJay Krell <jaykrell@microsoft.com>
Wed, 17 Jul 2019 19:09:19 +0000 (12:09 -0700)
committerRyan Lucia <rylucia@microsoft.com>
Wed, 17 Jul 2019 19:09:18 +0000 (12:09 -0700)
* Fix leaks in mono_lookup_internal_call_full_with_flags, for lack of C++ destructors.

* Initialize `sigstart` also.

Commit migrated from https://github.com/mono/mono/commit/e2ce0a16a61a02511728d217d92156691dc42289

src/mono/mono/metadata/icall.c

index 52e31ef..fad6653 100644 (file)
@@ -8972,12 +8972,13 @@ no_icall_table (void)
 gconstpointer
 mono_lookup_internal_call_full_with_flags (MonoMethod *method, gboolean warn_on_missing, guint32 *flags)
 {
-       char *sigstart;
-       char *tmpsig;
+       char *sigstart = NULL;
+       char *tmpsig = NULL;
        char mname [2048];
-       char *classname;
+       char *classname = NULL;
        int typelen = 0, mlen, siglen;
-       gconstpointer res;
+       gconstpointer res = NULL;
+       gboolean locked = FALSE;
 
        g_assert (method != NULL);
 
@@ -8987,20 +8988,20 @@ mono_lookup_internal_call_full_with_flags (MonoMethod *method, gboolean warn_on_
        if (m_class_get_nested_in (method->klass)) {
                int pos = concat_class_name (mname, sizeof (mname)-2, m_class_get_nested_in (method->klass));
                if (!pos)
-                       return NULL;
+                       goto exit;
 
                mname [pos++] = '/';
                mname [pos] = 0;
 
                typelen = concat_class_name (mname+pos, sizeof (mname)-pos-1, method->klass);
                if (!typelen)
-                       return NULL;
+                       goto exit;
 
                typelen += pos;
        } else {
                typelen = concat_class_name (mname, sizeof (mname), method->klass);
                if (!typelen)
-                       return NULL;
+                       goto exit;
        }
 
        classname = g_strdup (mname);
@@ -9015,21 +9016,22 @@ mono_lookup_internal_call_full_with_flags (MonoMethod *method, gboolean warn_on_
 
        tmpsig = mono_signature_get_desc (mono_method_signature_internal (method), TRUE);
        siglen = strlen (tmpsig);
-       if (typelen + mlen + siglen + 6 > sizeof (mname)) {
-               g_free (classname);
-               return NULL;
-       }
+       if (typelen + mlen + siglen + 6 > sizeof (mname))
+               goto exit;
+
        sigstart [0] = '(';
        memcpy (sigstart + 1, tmpsig, siglen);
        sigstart [siglen + 1] = ')';
        sigstart [siglen + 2] = 0;
-       g_free (tmpsig);
 
        /* mono_marshal_get_native_wrapper () depends on this */
-       if (method->klass == mono_defaults.string_class && !strcmp (method->name, ".ctor"))
-               return (gconstpointer)ves_icall_System_String_ctor_RedirectToCreateString;
+       if (method->klass == mono_defaults.string_class && !strcmp (method->name, ".ctor")) {
+               res = (gconstpointer)ves_icall_System_String_ctor_RedirectToCreateString;
+               goto exit;
+       }
 
        mono_icall_lock ();
+       locked = TRUE;
 
        res = g_hash_table_lookup (icall_hash, mname);
        if (res) {
@@ -9037,9 +9039,7 @@ mono_lookup_internal_call_full_with_flags (MonoMethod *method, gboolean warn_on_
                if (flags)
                        *flags = value->flags;
                res = value->method;
-               mono_icall_unlock ();
-               g_free (classname);
-               return res;
+               goto exit;
        }
 
        /* try without signature */
@@ -9050,16 +9050,13 @@ mono_lookup_internal_call_full_with_flags (MonoMethod *method, gboolean warn_on_
                if (flags)
                        *flags = value->flags;
                res = value->method;
-               mono_icall_unlock ();
-               g_free (classname);
-               return res;
+               goto exit;
        }
 
        if (!icall_table) {
-               mono_icall_unlock ();
-               g_free (classname);
                /* Fail only when the result is actually used */
-               return (gconstpointer)no_icall_table;
+               res = (gconstpointer)no_icall_table;
+               goto exit;
        } else {
                gboolean uses_handles = FALSE;
                g_assert (icall_table->lookup);
@@ -9067,10 +9064,10 @@ mono_lookup_internal_call_full_with_flags (MonoMethod *method, gboolean warn_on_
                if (res && flags && uses_handles)
                        *flags = *flags | MONO_ICALL_FLAGS_USES_HANDLES;
                mono_icall_unlock ();
-               g_free (classname);
+               locked = FALSE;
 
                if (res)
-                       return res;
+                       goto exit;
 
                if (warn_on_missing) {
                        g_warning ("cant resolve internal call to \"%s\" (tested without signature also)", mname);
@@ -9082,8 +9079,15 @@ mono_lookup_internal_call_full_with_flags (MonoMethod *method, gboolean warn_on_
                        g_print ("and you need to fix your mono install first.\n");
                }
 
-               return NULL;
+               res = NULL;
        }
+
+exit:
+       if (locked)
+               mono_icall_unlock ();
+       g_free (classname);
+       g_free (tmpsig);
+       return res;
 }
 
 /**