Skip to content

Commit ef0505f

Browse files
committed
[mono][interp] Don't do sign extension when called from gsharedvt_in_sig
Those wrappers use the real type as the return, so sign extension shouldn't be needed and it wouldn't be safe, because the wrapper passes the address of the return var of the actual type. Attemptying to sign extend could overflow the storage of this var.
1 parent 533d1f9 commit ef0505f

File tree

1 file changed

+11
-2
lines changed

1 file changed

+11
-2
lines changed

src/mono/mono/mini/interp/interp.c

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2395,8 +2395,17 @@ interp_entry (InterpEntryData *data)
23952395

23962396
// The return value is at the bottom of the stack, after the locals space
23972397
type = rmethod->rtype;
2398-
if (type->type != MONO_TYPE_VOID)
2399-
stackval_to_data_sign_ext (type, frame.stack, data->res, FALSE);
2398+
if (type->type != MONO_TYPE_VOID) {
2399+
// interp entry is called either from a interp_in wrapper or a gsharedvt_in_sig wrapper
2400+
// interp_in wrappers always return intptr (they are more aggresively shared) while the
2401+
// gsharedvt_in_sig wrapper returns the actual type. This check follows the logic in
2402+
// interp_create_method_pointer_llvmonly and interp_create_method_pointer so we do the
2403+
// return sign extension only when called from the interp_in wrapper.
2404+
if (!mono_llvm_only || sig->param_count > MAX_INTERP_ENTRY_ARGS)
2405+
stackval_to_data_sign_ext (type, frame.stack, data->res, FALSE);
2406+
else
2407+
stackval_to_data (type, frame.stack, data->res, FALSE);
2408+
}
24002409
}
24012410

24022411
static void

0 commit comments

Comments
 (0)