From 25c2be0ff477c5bd6c71f4dc598d7a94c08bb724 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Fri, 16 Mar 2012 14:28:45 +0100 Subject: [PATCH] Forbid boxed ifaces with self types or generic methods in bounded params They are a soundness hole. Closes #1994 --- src/rustc/middle/trans/base.rs | 10 ++++----- src/rustc/middle/trans/impl.rs | 11 ++++++---- src/rustc/middle/typeck.rs | 37 +++++++++++++++++++++++++--------- 3 files changed, 39 insertions(+), 19 deletions(-) diff --git a/src/rustc/middle/trans/base.rs b/src/rustc/middle/trans/base.rs index 23fc3f69e961..c2cb142b46e2 100644 --- a/src/rustc/middle/trans/base.rs +++ b/src/rustc/middle/trans/base.rs @@ -2668,12 +2668,12 @@ fn invoke_(bcx: block, llfn: ValueRef, llargs: [ValueRef], // cleanups to run if bcx.unreachable { ret bcx; } let normal_bcx = sub_block(bcx, "normal return"); - /*std::io::println("fn: " + lib::llvm::type_to_str(bcx.ccx().tn, - val_ty(llfn))); + /*io::println("fn: " + lib::llvm::type_to_str(bcx.ccx().tn, + val_ty(llfn))); for a in llargs { - std::io::println(" a: " + lib::llvm::type_to_str(bcx.ccx().tn, - val_ty(a))); - }*/ + io::println(" a: " + lib::llvm::type_to_str(bcx.ccx().tn, + val_ty(a))); + }// */ invoker(bcx, llfn, llargs, normal_bcx.llbb, get_landing_pad(bcx)); ret normal_bcx; } diff --git a/src/rustc/middle/trans/impl.rs b/src/rustc/middle/trans/impl.rs index f706c0b0471a..f4620677701d 100644 --- a/src/rustc/middle/trans/impl.rs +++ b/src/rustc/middle/trans/impl.rs @@ -115,9 +115,12 @@ fn trans_monomorphized_callee(bcx: block, callee_id: ast::node_id, let ty_substs = impl_substs + vec::tailn(node_substs, node_substs.len() - n_m_tps); let {bcx, val} = trans_self_arg(bcx, base); - {env: self_env(val, node_id_type(bcx, base.id), none) - with lval_static_fn_inner(bcx, mth_id, callee_id, ty_substs, - some(sub_origins))} + let lval = lval_static_fn_inner(bcx, mth_id, callee_id, ty_substs, + some(sub_origins)); + {env: self_env(val, node_id_type(bcx, base.id), none), + val: PointerCast(bcx, lval.val, T_ptr(type_of_fn_from_ty( + ccx, node_id_type(bcx, callee_id)))) + with lval} } typeck::vtable_iface(iid, tps) { trans_iface_callee(bcx, base, callee_id, n_method) @@ -236,7 +239,7 @@ fn make_impl_vtable(ccx: @crate_ctxt, impl_id: ast::def_id, substs: [ty::t], let fty = ty::substitute_type_params(tcx, substs, ty::mk_fn(tcx, im.fty)); if (*im.tps).len() > 0u || ty::type_has_vars(fty) { - C_null(type_of_fn_from_ty(ccx, fty)) + C_null(T_ptr(T_nil())) } else { let m_id = method_with_name(ccx, impl_id, im.ident); if has_tps { diff --git a/src/rustc/middle/typeck.rs b/src/rustc/middle/typeck.rs index e518704b1b39..ff38e998461b 100644 --- a/src/rustc/middle/typeck.rs +++ b/src/rustc/middle/typeck.rs @@ -1782,7 +1782,7 @@ fn lookup_method(fcx: @fn_ctxt, expr: @ast::expr, node_id: ast::node_id, some({method_ty: fty, n_tps: method_n_tps, substs, origin, self_sub}) { let tcx = fcx.ccx.tcx; let substs = substs, n_tps = vec::len(substs), n_tys = vec::len(tps); - let has_self = ty::type_has_params(fty); + let has_self = ty::type_has_vars(fty); if method_n_tps + n_tps > 0u { if n_tys == 0u || n_tys != method_n_tps { if n_tys != 0u { @@ -3335,15 +3335,16 @@ mod vtable { } fn lookup_vtables(fcx: @fn_ctxt, isc: resolve::iscopes, sp: span, - bounds: @[ty::param_bounds], tys: [ty::t]) - -> vtable_res { + bounds: @[ty::param_bounds], tys: [ty::t], + allow_unsafe: bool) -> vtable_res { let tcx = fcx.ccx.tcx, result = [], i = 0u; for ty in tys { for bound in *bounds[i] { alt bound { ty::bound_iface(i_ty) { let i_ty = ty::substitute_type_params(tcx, tys, i_ty); - result += [lookup_vtable(fcx, isc, sp, ty, i_ty)]; + result += [lookup_vtable(fcx, isc, sp, ty, i_ty, + allow_unsafe)]; } _ {} } @@ -3354,7 +3355,8 @@ mod vtable { } fn lookup_vtable(fcx: @fn_ctxt, isc: resolve::iscopes, sp: span, - ty: ty::t, iface_ty: ty::t) -> vtable_origin { + ty: ty::t, iface_ty: ty::t, allow_unsafe: bool) + -> vtable_origin { let tcx = fcx.ccx.tcx; let (iface_id, iface_tps) = alt check ty::get(iface_ty).struct { ty::ty_iface(did, tps) { (did, tps) } @@ -3378,6 +3380,20 @@ mod vtable { } } ty::ty_iface(did, tps) if iface_id == did { + if !allow_unsafe { + for m in *ty::iface_methods(tcx, did) { + if ty::type_has_vars(ty::mk_fn(tcx, m.fty)) { + tcx.sess.span_err( + sp, "a boxed iface with self types may not be \ + passed as a bounded type"); + } else if (*m.tps).len() > 0u { + tcx.sess.span_err( + sp, "a boxed iface with generic methods may not \ + be passed as a bounded type"); + + } + } + } ret vtable_iface(did, tps); } _ { @@ -3410,8 +3426,8 @@ mod vtable { im.did); let params = vec::map(vars, {|t| fixup_ty(fcx, sp, t)}); - let subres = lookup_vtables(fcx, isc, sp, - im_bs, params); + let subres = lookup_vtables( + fcx, isc, sp, im_bs, params, false); found = some(vtable_static(im.did, params, subres)); } @@ -3469,7 +3485,7 @@ mod vtable { if has_iface_bounds(*item_ty.bounds) { let impls = cx.impl_map.get(ex.id); cx.vtable_map.insert(ex.id, lookup_vtables( - fcx, impls, ex.span, item_ty.bounds, ts)); + fcx, impls, ex.span, item_ty.bounds, ts, false)); } } _ {} @@ -3490,7 +3506,7 @@ mod vtable { let ts = ty::node_id_to_type_params(cx.tcx, callee_id); let iscs = cx.impl_map.get(ex.id); cx.vtable_map.insert(callee_id, lookup_vtables( - fcx, iscs, ex.span, bounds, ts)); + fcx, iscs, ex.span, bounds, ts, false)); } } _ {} @@ -3502,7 +3518,8 @@ mod vtable { ty::ty_iface(_, _) { let impls = cx.impl_map.get(ex.id); let vtable = lookup_vtable(fcx, impls, ex.span, - expr_ty(cx.tcx, src), target_ty); + expr_ty(cx.tcx, src), target_ty, + true); cx.vtable_map.insert(ex.id, @[vtable]); } _ {}