@@ -289,13 +289,33 @@ interp_prev_ins (InterpInst *ins)
289289 return ins ;
290290}
291291
292+ static gboolean
293+ check_stack_helper (TransformData * td , int n )
294+ {
295+ int stack_size = GPTRDIFF_TO_INT (td -> sp - td -> stack );
296+ if (stack_size < n ) {
297+ td -> has_invalid_code = TRUE;
298+ return FALSE;
299+ }
300+ return TRUE;
301+ }
302+
292303#define CHECK_STACK (td , n ) \
293304 do { \
294- guint stack_size = GPTRDIFF_TO_UINT ((td)->sp - (td)->stack); \
295- if (stack_size < (n)) \
296- g_warning ("%s.%s: not enough values (%d < %d) on stack at %04x", \
297- m_class_get_name ((td)->method->klass), (td)->method->name, \
298- stack_size, n, (td)->ip - (td)->il_code); \
305+ if (!check_stack_helper (td, n)) \
306+ goto exit; \
307+ } while (0)
308+
309+ #define CHECK_STACK_RET_VOID (td , n ) \
310+ do { \
311+ if (!check_stack_helper (td, n)) \
312+ return; \
313+ } while (0)
314+
315+ #define CHECK_STACK_RET (td , n , ret ) \
316+ do { \
317+ if (!check_stack_helper (td, n)) \
318+ return ret; \
299319 } while (0)
300320
301321#define ENSURE_STACK_SIZE (td , size ) \
@@ -876,9 +896,9 @@ handle_branch (TransformData *td, int long_op, int offset)
876896static void
877897one_arg_branch (TransformData * td , int mint_op , int offset , int inst_size )
878898{
899+ CHECK_STACK_RET_VOID (td , 1 );
879900 int type = td -> sp [-1 ].type == STACK_TYPE_O || td -> sp [-1 ].type == STACK_TYPE_MP ? STACK_TYPE_I : td -> sp [-1 ].type ;
880901 int long_op = mint_op + type - STACK_TYPE_I4 ;
881- CHECK_STACK (td , 1 );
882902 -- td -> sp ;
883903 if (offset ) {
884904 handle_branch (td , long_op , offset + inst_size );
@@ -905,9 +925,9 @@ interp_add_conv (TransformData *td, StackInfo *sp, InterpInst *prev_ins, int typ
905925static void
906926two_arg_branch (TransformData * td , int mint_op , int offset , int inst_size )
907927{
928+ CHECK_STACK_RET_VOID (td , 2 );
908929 int type1 = td -> sp [-1 ].type == STACK_TYPE_O || td -> sp [-1 ].type == STACK_TYPE_MP ? STACK_TYPE_I : td -> sp [-1 ].type ;
909930 int type2 = td -> sp [-2 ].type == STACK_TYPE_O || td -> sp [-2 ].type == STACK_TYPE_MP ? STACK_TYPE_I : td -> sp [-2 ].type ;
910- CHECK_STACK (td , 2 );
911931
912932 if (type1 == STACK_TYPE_I4 && type2 == STACK_TYPE_I8 ) {
913933 // The il instruction starts with the actual branch, and not with the conversion opcodes
@@ -939,8 +959,8 @@ two_arg_branch(TransformData *td, int mint_op, int offset, int inst_size)
939959static void
940960unary_arith_op (TransformData * td , int mint_op )
941961{
962+ CHECK_STACK_RET_VOID (td , 1 );
942963 int op = mint_op + td -> sp [-1 ].type - STACK_TYPE_I4 ;
943- CHECK_STACK (td , 1 );
944964 td -> sp -- ;
945965 interp_add_ins (td , op );
946966 interp_ins_set_sreg (td -> last_ins , td -> sp [0 ].local );
@@ -951,6 +971,7 @@ unary_arith_op(TransformData *td, int mint_op)
951971static void
952972binary_arith_op (TransformData * td , int mint_op )
953973{
974+ CHECK_STACK_RET_VOID (td , 2 );
954975 int type1 = td -> sp [-2 ].type ;
955976 int type2 = td -> sp [-1 ].type ;
956977 int op ;
@@ -982,7 +1003,6 @@ binary_arith_op(TransformData *td, int mint_op)
9821003 td -> ip - td -> il_code , mono_interp_opname (mint_op ), type1 , type2 );
9831004 }
9841005 op = mint_op + type1 - STACK_TYPE_I4 ;
985- CHECK_STACK (td , 2 );
9861006 td -> sp -= 2 ;
9871007 interp_add_ins (td , op );
9881008 interp_ins_set_sregs2 (td -> last_ins , td -> sp [0 ].local , td -> sp [1 ].local );
@@ -993,8 +1013,8 @@ binary_arith_op(TransformData *td, int mint_op)
9931013static void
9941014shift_op (TransformData * td , int mint_op )
9951015{
1016+ CHECK_STACK_RET_VOID (td , 2 );
9961017 int op = mint_op + td -> sp [-2 ].type - STACK_TYPE_I4 ;
997- CHECK_STACK (td , 2 );
9981018 if (td -> sp [-1 ].type != STACK_TYPE_I4 ) {
9991019 g_warning ("%s.%s: shift type mismatch %d" ,
10001020 m_class_get_name (td -> method -> klass ), td -> method -> name ,
@@ -1083,7 +1103,7 @@ store_arg(TransformData *td, int n)
10831103{
10841104 gint32 size = 0 ;
10851105 int mt ;
1086- CHECK_STACK (td , 1 );
1106+ CHECK_STACK_RET_VOID (td , 1 );
10871107 MonoType * type ;
10881108
10891109 type = get_arg_type_exact (td , n , & mt );
@@ -1131,7 +1151,7 @@ static void
11311151store_local (TransformData * td , int local )
11321152{
11331153 int mt = td -> locals [local ].mt ;
1134- CHECK_STACK (td , 1 );
1154+ CHECK_STACK_RET_VOID (td , 1 );
11351155#if SIZEOF_VOID_P == 8
11361156 // nint and int32 can be used interchangeably. Add implicit conversions.
11371157 if (td -> sp [-1 ].type == STACK_TYPE_I4 && stack_type [mt ] == STACK_TYPE_I8 )
@@ -3121,7 +3141,7 @@ interp_transform_call (TransformData *td, MonoMethod *method, MonoMethod *target
31213141
31223142 if (target_method == NULL ) {
31233143 if (calli ) {
3124- CHECK_STACK (td , 1 );
3144+ CHECK_STACK_RET (td , 1 , FALSE );
31253145 if (method -> wrapper_type != MONO_WRAPPER_NONE )
31263146 csignature = (MonoMethodSignature * )mono_method_get_wrapper_data (method , token );
31273147 else {
@@ -3289,7 +3309,7 @@ interp_transform_call (TransformData *td, MonoMethod *method, MonoMethod *target
32893309 need_null_check = TRUE;
32903310 }
32913311
3292- CHECK_STACK (td , csignature -> param_count + csignature -> hasthis );
3312+ CHECK_STACK_RET (td , csignature -> param_count + csignature -> hasthis , FALSE );
32933313 if (tailcall && !td -> gen_sdb_seq_points && !calli && op == -1 &&
32943314 (target_method -> flags & METHOD_ATTRIBUTE_PINVOKE_IMPL ) == 0 &&
32953315 (target_method -> iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL ) == 0 &&
@@ -4312,7 +4332,7 @@ initialize_clause_bblocks (TransformData *td)
43124332static void
43134333handle_ldind (TransformData * td , int op , int type , gboolean * volatile_ )
43144334{
4315- CHECK_STACK (td , 1 );
4335+ CHECK_STACK_RET_VOID (td , 1 );
43164336 interp_add_ins (td , op );
43174337 td -> sp -- ;
43184338 interp_ins_set_sreg (td -> last_ins , td -> sp [0 ].local );
@@ -4329,7 +4349,7 @@ handle_ldind (TransformData *td, int op, int type, gboolean *volatile_)
43294349static void
43304350handle_stind (TransformData * td , int op , gboolean * volatile_ )
43314351{
4332- CHECK_STACK (td , 2 );
4352+ CHECK_STACK_RET_VOID (td , 2 );
43334353 if (* volatile_ ) {
43344354 interp_emit_memory_barrier (td , MONO_MEMORY_BARRIER_REL );
43354355 * volatile_ = FALSE;
@@ -4344,7 +4364,7 @@ handle_stind (TransformData *td, int op, gboolean *volatile_)
43444364static void
43454365handle_ldelem (TransformData * td , int op , int type )
43464366{
4347- CHECK_STACK (td , 2 );
4367+ CHECK_STACK_RET_VOID (td , 2 );
43484368 ENSURE_I4 (td , 1 );
43494369 interp_add_ins (td , op );
43504370 td -> sp -= 2 ;
@@ -4357,7 +4377,7 @@ handle_ldelem (TransformData *td, int op, int type)
43574377static void
43584378handle_stelem (TransformData * td , int op )
43594379{
4360- CHECK_STACK (td , 3 );
4380+ CHECK_STACK_RET_VOID (td , 3 );
43614381 ENSURE_I4 (td , 2 );
43624382 interp_add_ins (td , op );
43634383 td -> sp -= 3 ;
@@ -4578,7 +4598,9 @@ generate_code (TransformData *td, MonoMethod *method, MonoMethodHeader *header,
45784598
45794599 td -> dont_inline = g_list_prepend (td -> dont_inline , method );
45804600 while (td -> ip < end ) {
4581- g_assert (td -> sp >= td -> stack );
4601+ // Check here for every opcode to avoid code bloat
4602+ if (td -> has_invalid_code )
4603+ goto exit ;
45824604 in_offset = GPTRDIFF_TO_INT (td -> ip - header -> code );
45834605 if (!inlining )
45844606 td -> current_il_offset = in_offset ;
@@ -7750,6 +7772,8 @@ generate_code (TransformData *td, MonoMethod *method, MonoMethodHeader *header,
77507772 return ret ;
77517773exit :
77527774 ret = FALSE;
7775+ if (td -> has_invalid_code )
7776+ mono_error_set_generic_error (error , "System" , "InvalidProgramException" , "" );
77537777 goto exit_ret ;
77547778}
77557779
0 commit comments