[interp] Stack corruption running full AOT interpreter using ValueTuple. (#31790)
authormonojenkins <jo.shields+jenkins@xamarin.com>
Wed, 5 Feb 2020 22:35:05 +0000 (17:35 -0500)
committerGitHub <noreply@github.com>
Wed, 5 Feb 2020 22:35:05 +0000 (17:35 -0500)
Calling a method compiled using full AOT from interpreter can lead to stack corruption if signature include a ValueTuple without fields on compilers where MONO_ZERO_LEN_ARRAY is not 0 (msvc, clang). This is due to doing memset on memory allocated using MONO_SIZEOF_GENERIC_INST but
then memset using sizeof (MonoGenericInst). Fix makes sure we allocate and memset the same size of memory since otherwise it will lead to an overwrite of allocated memory when type_argc is 0.

The repro is a little tricky since the called method needs to be in a full AOT assembly and then called from an interpreted assembly:

If this is included in a full AOT:ed assembly.

```
public class StackOverwrite
{
        [MethodImpl(MethodImplOptions.NoInlining)]
        static public ValueTuple trashStack()
        {
            return ValueTuple.Create();
        }
}
```

and this is run under interpreter using --ful-aot-interp:

```
class Program
{
        static int Main(string[] args)
        {
            var test = StackOverwrite.trashStack();
            return 0;
        }
}
```

It will corrupt the stack before applying the fix.

Thanks @buggeststar for bring the issue to our attention and assisting narrow down repro on how to trigger the issues.

Co-authored-by: Johan Lorensson <lateralusx.github@gmail.com>
src/mono/mono/metadata/icall.c
src/mono/mono/metadata/metadata.c

index e3357c0..3ed967a 100644 (file)
@@ -6823,7 +6823,7 @@ get_generic_inst_from_array_handle (MonoArrayHandle type_args)
        int size = MONO_SIZEOF_GENERIC_INST + type_argc * sizeof (MonoType *);
 
        MonoGenericInst *ginst = (MonoGenericInst *)g_alloca (size);
-       memset (ginst, 0, sizeof (MonoGenericInst));
+       memset (ginst, 0, MONO_SIZEOF_GENERIC_INST);
        ginst->type_argc = type_argc;
        for (int i = 0; i < type_argc; i++) {
                MONO_HANDLE_ARRAY_GETVAL (ginst->type_argv[i], type_args, MonoType*, i);
index 9cb701e..1b001d0 100644 (file)
@@ -3386,7 +3386,7 @@ mono_metadata_get_generic_inst (int type_argc, MonoType **type_argv)
        is_open = (i < type_argc);
 
        ginst = (MonoGenericInst *)g_alloca (size);
-       memset (ginst, 0, sizeof (MonoGenericInst));
+       memset (ginst, 0, MONO_SIZEOF_GENERIC_INST);
        ginst->is_open = is_open;
        ginst->type_argc = type_argc;
        memcpy (ginst->type_argv, type_argv, type_argc * sizeof (MonoType *));