Skip to content

Fix private module loophole in the 'private type in public item' check #23290

New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

Merged
merged 1 commit into from
Mar 18, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions src/librustc/session/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -736,8 +736,8 @@ mod opt {
use getopts;
use super::RustcOptGroup;

type R = RustcOptGroup;
type S<'a> = &'a str;
pub type R = RustcOptGroup;
pub type S<'a> = &'a str;

fn stable(g: getopts::OptGroup) -> R { RustcOptGroup::stable(g) }
fn unstable(g: getopts::OptGroup) -> R { RustcOptGroup::unstable(g) }
Expand Down
50 changes: 32 additions & 18 deletions src/librustc_privacy/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1186,6 +1186,7 @@ impl<'a, 'tcx> VisiblePrivateTypesVisitor<'a, 'tcx> {
if !is_local(did) {
return false
}

// .. and it corresponds to a private type in the AST (this returns
// None for type parameters)
match self.tcx.map.find(did.node) {
Expand All @@ -1206,12 +1207,15 @@ impl<'a, 'tcx> VisiblePrivateTypesVisitor<'a, 'tcx> {
if !self.tcx.sess.features.borrow().visible_private_types &&
self.path_is_private_type(trait_ref.trait_ref.ref_id) {
let span = trait_ref.trait_ref.path.span;
self.tcx.sess.span_err(span,
"private trait in exported type \
parameter bound");
self.tcx.sess.span_err(span, "private trait in exported type \
parameter bound");
}
}
}

fn item_is_public(&self, id: &ast::NodeId, vis: ast::Visibility) -> bool {
self.exported_items.contains(id) || vis == ast::Public
}
}

impl<'a, 'b, 'tcx, 'v> Visitor<'v> for CheckTypeForPrivatenessVisitor<'a, 'b, 'tcx> {
Expand Down Expand Up @@ -1259,7 +1263,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for VisiblePrivateTypesVisitor<'a, 'tcx> {
// error messages without (too many) false positives
// (i.e. we could just return here to not check them at
// all, or some worse estimation of whether an impl is
// publicly visible.
// publicly visible).
ast::ItemImpl(_, _, ref g, ref trait_ref, ref self_, ref impl_items) => {
// `impl [... for] Private` is never visible.
let self_contains_private;
Expand Down Expand Up @@ -1321,7 +1325,22 @@ impl<'a, 'tcx, 'v> Visitor<'v> for VisiblePrivateTypesVisitor<'a, 'tcx> {
match *trait_ref {
None => {
for impl_item in impl_items {
visit::walk_impl_item(self, impl_item);
// This is where we choose whether to walk down
// further into the impl to check its items. We
// should only walk into public items so that we
// don't erroneously report errors for private
// types in private items.
match impl_item.node {
ast::MethodImplItem(..)
if self.item_is_public(&impl_item.id, impl_item.vis) =>
{
visit::walk_impl_item(self, impl_item)
}
ast::TypeImplItem(..) => {
visit::walk_impl_item(self, impl_item)
}
_ => {}
}
}
}
Some(ref tr) => {
Expand Down Expand Up @@ -1360,7 +1379,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for VisiblePrivateTypesVisitor<'a, 'tcx> {
match impl_item.node {
ast::MethodImplItem(ref sig, _) => {
if sig.explicit_self.node == ast::SelfStatic &&
self.exported_items.contains(&impl_item.id) {
self.item_is_public(&impl_item.id, impl_item.vis) {
found_pub_static = true;
visit::walk_impl_item(self, impl_item);
}
Expand All @@ -1381,15 +1400,18 @@ impl<'a, 'tcx, 'v> Visitor<'v> for VisiblePrivateTypesVisitor<'a, 'tcx> {
ast::ItemTy(..) => return,

// not at all public, so we don't care
_ if !self.exported_items.contains(&item.id) => return,
_ if !self.item_is_public(&item.id, item.vis) => {
return;
}

_ => {}
}

// we've carefully constructed it so that if we're here, then
// We've carefully constructed it so that if we're here, then
// any `visit_ty`'s will be called on things that are in
// public signatures, i.e. things that we're interested in for
// this visitor.
debug!("VisiblePrivateTypesVisitor entering item {:?}", item);
visit::walk_item(self, item);
}

Expand Down Expand Up @@ -1420,20 +1442,12 @@ impl<'a, 'tcx, 'v> Visitor<'v> for VisiblePrivateTypesVisitor<'a, 'tcx> {
}
}

fn visit_fn(&mut self, fk: visit::FnKind<'v>, fd: &'v ast::FnDecl,
b: &'v ast::Block, s: Span, id: ast::NodeId) {
// needs special handling for methods.
if self.exported_items.contains(&id) {
visit::walk_fn(self, fk, fd, b, s);
}
}

fn visit_ty(&mut self, t: &ast::Ty) {
debug!("VisiblePrivateTypesVisitor checking ty {:?}", t);
if let ast::TyPath(_, ref p) = t.node {
if !self.tcx.sess.features.borrow().visible_private_types &&
self.path_is_private_type(t.id) {
self.tcx.sess.span_err(p.span,
"private type in exported type signature");
self.tcx.sess.span_err(p.span, "private type in exported type signature");
}
}
visit::walk_ty(self, t)
Expand Down
6 changes: 3 additions & 3 deletions src/librustc_resolve/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -382,7 +382,7 @@ enum ModuleKind {
}

/// One node in the tree of modules.
struct Module {
pub struct Module {
parent_link: ParentLink,
def_id: Cell<Option<DefId>>,
kind: Cell<ModuleKind>,
Expand Down Expand Up @@ -491,7 +491,7 @@ struct ValueNsDef {
// Records the definitions (at most one for each namespace) that a name is
// bound to.
#[derive(Debug)]
struct NameBindings {
pub struct NameBindings {
type_def: RefCell<Option<TypeNsDef>>, //< Meaning in type namespace.
value_def: RefCell<Option<ValueNsDef>>, //< Meaning in value namespace.
}
Expand Down Expand Up @@ -767,7 +767,7 @@ impl PrimitiveTypeTable {
}

/// The main resolver class.
struct Resolver<'a, 'tcx:'a> {
pub struct Resolver<'a, 'tcx:'a> {
session: &'a Session,

ast_map: &'a ast_map::Map<'tcx>,
Expand Down
2 changes: 1 addition & 1 deletion src/librustc_trans/trans/base.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1464,7 +1464,7 @@ pub fn arg_kind<'a, 'tcx>(cx: &FunctionContext<'a, 'tcx>, t: Ty<'tcx>)
}

// work around bizarre resolve errors
type RvalueDatum<'tcx> = datum::Datum<'tcx, datum::Rvalue>;
pub type RvalueDatum<'tcx> = datum::Datum<'tcx, datum::Rvalue>;

// create_datums_for_fn_args: creates rvalue datums for each of the
// incoming function arguments. These will later be stored into
Expand Down
2 changes: 1 addition & 1 deletion src/librustc_trans/trans/common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -378,7 +378,7 @@ pub fn validate_substs(substs: &Substs) {

// work around bizarre resolve errors
type RvalueDatum<'tcx> = datum::Datum<'tcx, datum::Rvalue>;
type LvalueDatum<'tcx> = datum::Datum<'tcx, datum::Lvalue>;
pub type LvalueDatum<'tcx> = datum::Datum<'tcx, datum::Lvalue>;

// Function context. Every LLVM function we create will have one of
// these.
Expand Down
2 changes: 1 addition & 1 deletion src/librustc_typeck/check/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -195,7 +195,7 @@ type DeferredCallResolutionHandler<'tcx> = Box<DeferredCallResolution<'tcx>+'tcx
/// When type-checking an expression, we propagate downward
/// whatever type hint we are able in the form of an `Expectation`.
#[derive(Copy)]
enum Expectation<'tcx> {
pub enum Expectation<'tcx> {
/// We know nothing about what type this expression should have.
NoExpectation,

Expand Down
2 changes: 1 addition & 1 deletion src/librustc_typeck/check/regionck.rs
Original file line number Diff line number Diff line change
Expand Up @@ -178,7 +178,7 @@ pub struct Rcx<'a, 'tcx: 'a> {

}

struct RepeatingScope(ast::NodeId);
pub struct RepeatingScope(ast::NodeId);
pub enum SubjectNode { Subject(ast::NodeId), None }

impl<'a, 'tcx> Rcx<'a, 'tcx> {
Expand Down
4 changes: 2 additions & 2 deletions src/librustc_typeck/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -128,12 +128,12 @@ mod constrained_type_params;
mod coherence;
mod variance;

struct TypeAndSubsts<'tcx> {
pub struct TypeAndSubsts<'tcx> {
pub substs: subst::Substs<'tcx>,
pub ty: Ty<'tcx>,
}

struct CrateCtxt<'a, 'tcx: 'a> {
pub struct CrateCtxt<'a, 'tcx: 'a> {
// A mapping from method call sites to traits that have that method.
trait_map: ty::TraitMap,
/// A vector of every trait accessible in the whole crate
Expand Down
6 changes: 3 additions & 3 deletions src/libstd/sys/unix/stack_overflow.rs
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@ mod imp {
munmap(handler._data, SIGSTKSZ);
}

type sighandler_t = *mut libc::c_void;
pub type sighandler_t = *mut libc::c_void;

#[cfg(any(all(target_os = "linux", target_arch = "x86"), // may not match
all(target_os = "linux", target_arch = "x86_64"),
Expand All @@ -156,7 +156,7 @@ mod imp {
target_os = "android"))] // may not match
mod signal {
use libc;
use super::sighandler_t;
pub use super::sighandler_t;

pub static SA_ONSTACK: libc::c_int = 0x08000000;
pub static SA_SIGINFO: libc::c_int = 0x00000004;
Expand Down Expand Up @@ -210,7 +210,7 @@ mod imp {
target_os = "openbsd"))]
mod signal {
use libc;
use super::sighandler_t;
pub use super::sighandler_t;

pub const SA_ONSTACK: libc::c_int = 0x0001;
pub const SA_SIGINFO: libc::c_int = 0x0040;
Expand Down
2 changes: 1 addition & 1 deletion src/libstd/sys/windows/backtrace.rs
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ struct ADDRESS64 {
Mode: ADDRESS_MODE,
}

struct STACKFRAME64 {
pub struct STACKFRAME64 {
AddrPC: ADDRESS64,
AddrReturn: ADDRESS64,
AddrFrame: ADDRESS64,
Expand Down
28 changes: 28 additions & 0 deletions src/test/compile-fail/priv_in_pub_sig_priv_mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

// Test that we properly check for private types in public signatures, even
// inside a private module (#22261).

mod a {
struct Priv;

pub fn expose_a() -> Priv { //~Error: private type in exported type signature
panic!();
}

mod b {
pub fn expose_b() -> super::Priv { //~Error: private type in exported type signature
panic!();
}
}
}

pub fn main() {}
31 changes: 0 additions & 31 deletions src/test/run-pass/export-unexported-dep.rs

This file was deleted.

2 changes: 1 addition & 1 deletion src/test/run-pass/issue-15774.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
#![deny(warnings)]
#![allow(unused_imports)]

enum Foo { A }
pub enum Foo { A }
mod bar {
pub fn normal(x: ::Foo) {
use Foo::A;
Expand Down