diff --git a/src/liblibc/lib.rs b/src/liblibc/lib.rs index 1bc64ffcc92ae..21313858f8812 100644 --- a/src/liblibc/lib.rs +++ b/src/liblibc/lib.rs @@ -78,6 +78,7 @@ #![allow(non_uppercase_statics)] #![allow(missing_doc)] #![allow(uppercase_variables)] +#![warn(repr_c_implicit_padding)] #[cfg(test)] extern crate std; #[cfg(test)] extern crate test; @@ -369,6 +370,7 @@ pub mod types { pub type pthread_t = c_ulong; + #[repr(C)] pub struct glob_t { pub gl_pathc: size_t, pub gl_pathv: *mut *mut c_char, @@ -381,11 +383,13 @@ pub mod types { pub __unused5: *mut c_void, } + #[repr(C)] pub struct timeval { pub tv_sec: time_t, pub tv_usec: suseconds_t, } + #[repr(C)] pub struct timespec { pub tv_sec: time_t, pub tv_nsec: c_long, @@ -402,24 +406,30 @@ pub mod types { pub type sa_family_t = u16; pub type in_port_t = u16; pub type in_addr_t = u32; + #[repr(C)] pub struct sockaddr { pub sa_family: sa_family_t, pub sa_data: [u8, ..14], } + #[repr(C)] pub struct sockaddr_storage { pub ss_family: sa_family_t, + pub __ss_pad1: [u8, ..6], pub __ss_align: i64, pub __ss_pad2: [u8, ..112], } + #[repr(C)] pub struct sockaddr_in { pub sin_family: sa_family_t, pub sin_port: in_port_t, pub sin_addr: in_addr, pub sin_zero: [u8, ..8], } + #[repr(C)] pub struct in_addr { pub s_addr: in_addr_t, } + #[repr(C)] pub struct sockaddr_in6 { pub sin6_family: sa_family_t, pub sin6_port: in_port_t, @@ -427,23 +437,28 @@ pub mod types { pub sin6_addr: in6_addr, pub sin6_scope_id: u32, } + #[repr(C)] pub struct in6_addr { pub s6_addr: [u16, ..8] } + #[repr(C)] pub struct ip_mreq { pub imr_multiaddr: in_addr, pub imr_interface: in_addr, } + #[repr(C)] pub struct ip6_mreq { pub ipv6mr_multiaddr: in6_addr, pub ipv6mr_interface: c_uint, } + #[repr(C)] pub struct addrinfo { pub ai_flags: c_int, pub ai_family: c_int, pub ai_socktype: c_int, pub ai_protocol: c_int, pub ai_addrlen: socklen_t, + pub __padding: [u8, ..4], #[cfg(target_os = "linux")] pub ai_addr: *mut sockaddr, @@ -459,6 +474,7 @@ pub mod types { pub ai_next: *mut addrinfo, } + #[repr(C)] pub struct sockaddr_un { pub sun_family: sa_family_t, pub sun_path: [c_char, ..108] @@ -618,6 +634,7 @@ pub mod types { pub type blksize_t = i32; pub type blkcnt_t = i32; + #[repr(C)] pub struct stat { pub st_dev: c_ulong, pub st_pad1: [c_long, ..3], @@ -641,11 +658,13 @@ pub mod types { pub st_pad5: [c_long, ..14], } + #[repr(C)] pub struct utimbuf { pub actime: time_t, pub modtime: time_t, } + #[repr(C)] pub struct pthread_attr_t { pub __size: [u32, ..9] } @@ -702,6 +721,7 @@ pub mod types { pub type nlink_t = u64; pub type blksize_t = i64; pub type blkcnt_t = i64; + #[repr(C)] pub struct stat { pub st_dev: dev_t, pub st_ino: ino_t, @@ -723,11 +743,13 @@ pub mod types { pub __unused: [c_long, ..3], } + #[repr(C)] pub struct utimbuf { pub actime: time_t, pub modtime: time_t, } + #[repr(C)] pub struct pthread_attr_t { pub __size: [u64, ..7] } @@ -752,6 +774,7 @@ pub mod types { pub type pthread_t = uintptr_t; + #[repr(C)] pub struct glob_t { pub gl_pathc: size_t, pub __unused1: size_t, @@ -768,11 +791,13 @@ pub mod types { pub __unused8: *mut c_void, } + #[repr(C)] pub struct timeval { pub tv_sec: time_t, pub tv_usec: suseconds_t, } + #[repr(C)] pub struct timespec { pub tv_sec: time_t, pub tv_nsec: c_long, @@ -789,11 +814,13 @@ pub mod types { pub type sa_family_t = u8; pub type in_port_t = u16; pub type in_addr_t = u32; + #[repr(C)] pub struct sockaddr { pub sa_len: u8, pub sa_family: sa_family_t, pub sa_data: [u8, ..14], } + #[repr(C)] pub struct sockaddr_storage { pub ss_len: u8, pub ss_family: sa_family_t, @@ -801,6 +828,7 @@ pub mod types { pub __ss_align: i64, pub __ss_pad2: [u8, ..112], } + #[repr(C)] pub struct sockaddr_in { pub sin_len: u8, pub sin_family: sa_family_t, @@ -808,9 +836,11 @@ pub mod types { pub sin_addr: in_addr, pub sin_zero: [u8, ..8], } + #[repr(C)] pub struct in_addr { pub s_addr: in_addr_t, } + #[repr(C)] pub struct sockaddr_in6 { pub sin6_len: u8, pub sin6_family: sa_family_t, @@ -819,17 +849,21 @@ pub mod types { pub sin6_addr: in6_addr, pub sin6_scope_id: u32, } + #[repr(C)] pub struct in6_addr { pub s6_addr: [u16, ..8] } + #[repr(C)] pub struct ip_mreq { pub imr_multiaddr: in_addr, pub imr_interface: in_addr, } + #[repr(C)] pub struct ip6_mreq { pub ipv6mr_multiaddr: in6_addr, pub ipv6mr_interface: c_uint, } + #[repr(C)] pub struct addrinfo { pub ai_flags: c_int, pub ai_family: c_int, @@ -840,6 +874,7 @@ pub mod types { pub ai_addr: *mut sockaddr, pub ai_next: *mut addrinfo, } + #[repr(C)] pub struct sockaddr_un { pub sun_len: u8, pub sun_family: sa_family_t, @@ -898,6 +933,7 @@ pub mod types { pub type blksize_t = i64; pub type blkcnt_t = i64; pub type fflags_t = u32; + #[repr(C)] pub struct stat { pub st_dev: dev_t, pub st_ino: ino_t, @@ -923,6 +959,7 @@ pub mod types { pub __unused: [uint8_t, ..2], } + #[repr(C)] pub struct utimbuf { pub actime: time_t, pub modtime: time_t, @@ -950,6 +987,7 @@ pub mod types { pub type pthread_t = uintptr_t; + #[repr(C)] pub struct glob_t { pub gl_pathc: size_t, pub __unused1: size_t, @@ -966,11 +1004,13 @@ pub mod types { pub __unused8: *mut c_void, } + #[repr(C)] pub struct timeval { pub tv_sec: time_t, pub tv_usec: suseconds_t, } + #[repr(C)] pub struct timespec { pub tv_sec: time_t, pub tv_nsec: c_long, @@ -987,11 +1027,13 @@ pub mod types { pub type sa_family_t = u8; pub type in_port_t = u16; pub type in_addr_t = u32; + #[repr(C)] pub struct sockaddr { pub sa_len: u8, pub sa_family: sa_family_t, pub sa_data: [u8, ..14], } + #[repr(C)] pub struct sockaddr_storage { pub ss_len: u8, pub ss_family: sa_family_t, @@ -999,6 +1041,7 @@ pub mod types { pub __ss_align: i64, pub __ss_pad2: [u8, ..112], } + #[repr(C)] pub struct sockaddr_in { pub sin_len: u8, pub sin_family: sa_family_t, @@ -1006,9 +1049,11 @@ pub mod types { pub sin_addr: in_addr, pub sin_zero: [u8, ..8], } + #[repr(C)] pub struct in_addr { pub s_addr: in_addr_t, } + #[repr(C)] pub struct sockaddr_in6 { pub sin6_len: u8, pub sin6_family: sa_family_t, @@ -1017,17 +1062,21 @@ pub mod types { pub sin6_addr: in6_addr, pub sin6_scope_id: u32, } + #[repr(C)] pub struct in6_addr { pub s6_addr: [u16, ..8] } + #[repr(C)] pub struct ip_mreq { pub imr_multiaddr: in_addr, pub imr_interface: in_addr, } + #[repr(C)] pub struct ip6_mreq { pub ipv6mr_multiaddr: in6_addr, pub ipv6mr_interface: c_uint, } + #[repr(C)] pub struct addrinfo { pub ai_flags: c_int, pub ai_family: c_int, @@ -1038,6 +1087,7 @@ pub mod types { pub ai_addr: *mut sockaddr, pub ai_next: *mut addrinfo, } + #[repr(C)] pub struct sockaddr_un { pub sun_len: u8, pub sun_family: sa_family_t, @@ -1098,6 +1148,7 @@ pub mod types { pub type blkcnt_t = i64; pub type fflags_t = u32; + #[repr(C)] pub struct stat { pub st_ino: ino_t, pub st_nlink: nlink_t, @@ -1122,6 +1173,7 @@ pub mod types { pub st_qspare1: int64_t, pub st_qspare2: int64_t, } + #[repr(C)] pub struct utimbuf { pub actime: time_t, pub modtime: time_t, @@ -1150,6 +1202,7 @@ pub mod types { // pub Note: this is the struct called stat64 in win32. Not stat, // nor stati64. + #[repr(C)] pub struct stat { pub st_dev: dev_t, pub st_ino: ino_t, @@ -1165,16 +1218,19 @@ pub mod types { } // note that this is called utimbuf64 in win32 + #[repr(C)] pub struct utimbuf { pub actime: time64_t, pub modtime: time64_t, } + #[repr(C)] pub struct timeval { pub tv_sec: time_t, pub tv_usec: suseconds_t, } + #[repr(C)] pub struct timespec { pub tv_sec: time_t, pub tv_nsec: c_long, @@ -1191,24 +1247,29 @@ pub mod types { pub type sa_family_t = u16; pub type in_port_t = u16; pub type in_addr_t = u32; + #[repr(C)] pub struct sockaddr { pub sa_family: sa_family_t, pub sa_data: [u8, ..14], } + #[repr(C)] pub struct sockaddr_storage { pub ss_family: sa_family_t, pub __ss_align: i64, pub __ss_pad2: [u8, ..112], } + #[repr(C)] pub struct sockaddr_in { pub sin_family: sa_family_t, pub sin_port: in_port_t, pub sin_addr: in_addr, pub sin_zero: [u8, ..8], } + #[repr(C)] pub struct in_addr { pub s_addr: in_addr_t, } + #[repr(C)] pub struct sockaddr_in6 { pub sin6_family: sa_family_t, pub sin6_port: in_port_t, @@ -1216,17 +1277,21 @@ pub mod types { pub sin6_addr: in6_addr, pub sin6_scope_id: u32, } + #[repr(C)] pub struct in6_addr { pub s6_addr: [u16, ..8] } + #[repr(C)] pub struct ip_mreq { pub imr_multiaddr: in_addr, pub imr_interface: in_addr, } + #[repr(C)] pub struct ip6_mreq { pub ipv6mr_multiaddr: in6_addr, pub ipv6mr_interface: c_uint, } + #[repr(C)] pub struct addrinfo { pub ai_flags: c_int, pub ai_family: c_int, @@ -1237,6 +1302,7 @@ pub mod types { pub ai_addr: *mut sockaddr, pub ai_next: *mut addrinfo, } + #[repr(C)] pub struct sockaddr_un { pub sun_family: sa_family_t, pub sun_path: [c_char, ..108] @@ -1356,6 +1422,7 @@ pub mod types { pub type LPWCH = *mut WCHAR; pub type LPCH = *mut CHAR; + #[repr(C)] pub struct SECURITY_ATTRIBUTES { pub nLength: DWORD, pub lpSecurityDescriptor: LPVOID, @@ -1379,6 +1446,7 @@ pub mod types { pub type time64_t = i64; pub type int64 = i64; + #[repr(C)] pub struct STARTUPINFO { pub cb: DWORD, pub lpReserved: LPWSTR, @@ -1401,6 +1469,7 @@ pub mod types { } pub type LPSTARTUPINFO = *mut STARTUPINFO; + #[repr(C)] pub struct PROCESS_INFORMATION { pub hProcess: HANDLE, pub hThread: HANDLE, @@ -1409,6 +1478,7 @@ pub mod types { } pub type LPPROCESS_INFORMATION = *mut PROCESS_INFORMATION; + #[repr(C)] pub struct SYSTEM_INFO { pub wProcessorArchitecture: WORD, pub wReserved: WORD, @@ -1424,6 +1494,7 @@ pub mod types { } pub type LPSYSTEM_INFO = *mut SYSTEM_INFO; + #[repr(C)] pub struct MEMORY_BASIC_INFORMATION { pub BaseAddress: LPVOID, pub AllocationBase: LPVOID, @@ -1435,6 +1506,7 @@ pub mod types { } pub type LPMEMORY_BASIC_INFORMATION = *mut MEMORY_BASIC_INFORMATION; + #[repr(C)] pub struct OVERLAPPED { pub Internal: *mut c_ulong, pub InternalHigh: *mut c_ulong, @@ -1445,6 +1517,7 @@ pub mod types { pub type LPOVERLAPPED = *mut OVERLAPPED; + #[repr(C)] pub struct FILETIME { pub dwLowDateTime: DWORD, pub dwHighDateTime: DWORD, @@ -1452,6 +1525,7 @@ pub mod types { pub type LPFILETIME = *mut FILETIME; + #[repr(C)] pub struct GUID { pub Data1: DWORD, pub Data2: WORD, @@ -1459,6 +1533,7 @@ pub mod types { pub Data4: [BYTE, ..8], } + #[repr(C)] pub struct WSAPROTOCOLCHAIN { pub ChainLen: c_int, pub ChainEntries: [DWORD, ..MAX_PROTOCOL_CHAIN], @@ -1466,6 +1541,7 @@ pub mod types { pub type LPWSAPROTOCOLCHAIN = *mut WSAPROTOCOLCHAIN; + #[repr(C)] pub struct WSAPROTOCOL_INFO { pub dwServiceFlags1: DWORD, pub dwServiceFlags2: DWORD, @@ -1508,6 +1584,7 @@ pub mod types { pub type pthread_t = uintptr_t; + #[repr(C)] pub struct glob_t { pub gl_pathc: size_t, pub __unused1: c_int, @@ -1524,11 +1601,13 @@ pub mod types { pub __unused8: *mut c_void, } + #[repr(C)] pub struct timeval { pub tv_sec: time_t, pub tv_usec: suseconds_t, } + #[repr(C)] pub struct timespec { pub tv_sec: time_t, pub tv_nsec: c_long, @@ -1546,11 +1625,13 @@ pub mod types { pub type sa_family_t = u8; pub type in_port_t = u16; pub type in_addr_t = u32; + #[repr(C)] pub struct sockaddr { pub sa_len: u8, pub sa_family: sa_family_t, pub sa_data: [u8, ..14], } + #[repr(C)] pub struct sockaddr_storage { pub ss_len: u8, pub ss_family: sa_family_t, @@ -1558,6 +1639,7 @@ pub mod types { pub __ss_align: i64, pub __ss_pad2: [u8, ..112], } + #[repr(C)] pub struct sockaddr_in { pub sin_len: u8, pub sin_family: sa_family_t, @@ -1565,9 +1647,11 @@ pub mod types { pub sin_addr: in_addr, pub sin_zero: [u8, ..8], } + #[repr(C)] pub struct in_addr { pub s_addr: in_addr_t, } + #[repr(C)] pub struct sockaddr_in6 { pub sin6_len: u8, pub sin6_family: sa_family_t, @@ -1576,17 +1660,21 @@ pub mod types { pub sin6_addr: in6_addr, pub sin6_scope_id: u32, } + #[repr(C)] pub struct in6_addr { pub s6_addr: [u16, ..8] } + #[repr(C)] pub struct ip_mreq { pub imr_multiaddr: in_addr, pub imr_interface: in_addr, } + #[repr(C)] pub struct ip6_mreq { pub ipv6mr_multiaddr: in6_addr, pub ipv6mr_interface: c_uint, } + #[repr(C)] pub struct addrinfo { pub ai_flags: c_int, pub ai_family: c_int, @@ -1597,6 +1685,7 @@ pub mod types { pub ai_addr: *mut sockaddr, pub ai_next: *mut addrinfo, } + #[repr(C)] pub struct sockaddr_un { pub sun_len: u8, pub sun_family: sa_family_t, @@ -1654,6 +1743,7 @@ pub mod types { pub type blksize_t = i64; pub type blkcnt_t = i32; + #[repr(C)] pub struct stat { pub st_dev: dev_t, pub st_mode: mode_t, @@ -1679,11 +1769,13 @@ pub mod types { pub st_qspare: [int64_t, ..2], } + #[repr(C)] pub struct utimbuf { pub actime: time_t, pub modtime: time_t, } + #[repr(C)] pub struct pthread_attr_t { pub __sig: c_long, pub __opaque: [c_char, ..36] @@ -1694,6 +1786,7 @@ pub mod types { pub mod bsd44 { } pub mod extra { + #[repr(C)] pub struct mach_timebase_info { pub numer: u32, pub denom: u32, @@ -1752,6 +1845,7 @@ pub mod types { pub type blksize_t = i64; pub type blkcnt_t = i32; + #[repr(C)] pub struct stat { pub st_dev: dev_t, pub st_mode: mode_t, @@ -1777,11 +1871,13 @@ pub mod types { pub st_qspare: [int64_t, ..2], } + #[repr(C)] pub struct utimbuf { pub actime: time_t, pub modtime: time_t, } + #[repr(C)] pub struct pthread_attr_t { pub __sig: c_long, pub __opaque: [c_char, ..56] @@ -1792,6 +1888,7 @@ pub mod types { pub mod bsd44 { } pub mod extra { + #[repr(C)] pub struct mach_timebase_info { pub numer: u32, pub denom: u32, diff --git a/src/libnative/io/addrinfo.rs b/src/libnative/io/addrinfo.rs index 7a07b6221277f..99a484075185e 100644 --- a/src/libnative/io/addrinfo.rs +++ b/src/libnative/io/addrinfo.rs @@ -40,7 +40,8 @@ impl GetAddrInfoRequest { ai_addrlen: 0, ai_canonname: mut_null(), ai_addr: mut_null(), - ai_next: mut_null() + ai_next: mut_null(), + __padding: [0, ..4] } }); diff --git a/src/librustc/lint/builtin.rs b/src/librustc/lint/builtin.rs index 1667f2b6d5f0a..646ce73fe3e7f 100644 --- a/src/librustc/lint/builtin.rs +++ b/src/librustc/lint/builtin.rs @@ -1536,6 +1536,9 @@ declare_lint!(pub UNKNOWN_CRATE_TYPE, Deny, declare_lint!(pub VARIANT_SIZE_DIFFERENCE, Allow, "detects enums with widely varying variant sizes") +declare_lint!(pub REPR_C_IMPLICIT_PADDING, Allow, + "detects implicit padding, which cannot be memset reliably, in C structures") + /// Does nothing as a lint pass, but registers some `Lint`s /// which are used by other parts of the compiler. pub struct HardwiredLints; @@ -1554,7 +1557,8 @@ impl LintPass for HardwiredLints { WARNINGS, UNKNOWN_FEATURES, UNKNOWN_CRATE_TYPE, - VARIANT_SIZE_DIFFERENCE + VARIANT_SIZE_DIFFERENCE, + REPR_C_IMPLICIT_PADDING ) } } diff --git a/src/librustc/lint/context.rs b/src/librustc/lint/context.rs index 7d9ec29d70144..5c2fce2c21722 100644 --- a/src/librustc/lint/context.rs +++ b/src/librustc/lint/context.rs @@ -638,6 +638,16 @@ impl LintPass for GatherNodeLevels { _ => { } } }, + ast::ItemStruct(..) => { + let lint_id = LintId::of(builtin::REPR_C_IMPLICIT_PADDING); + match cx.lints.get_level_source(lint_id) { + lvlsrc @ (lvl, _) if lvl != Allow => { + cx.node_levels.borrow_mut() + .insert((it.id, lint_id), lvlsrc); + }, + _ => { } + } + } _ => { } } } diff --git a/src/librustc/middle/trans/base.rs b/src/librustc/middle/trans/base.rs index f1e84b8da8105..9ee62c1f3a2c5 100644 --- a/src/librustc/middle/trans/base.rs +++ b/src/librustc/middle/trans/base.rs @@ -1908,6 +1908,29 @@ fn enum_variant_size_lint(ccx: &CrateContext, enum_def: &ast::EnumDef, sp: Span, } } +fn struct_repr_padding_lint(ccx: &CrateContext, struct_def: &ast::StructDef, id: ast::NodeId) { + let levels = ccx.tcx.node_lint_levels.borrow(); + let lint_id = lint::LintId::of(lint::builtin::REPR_C_IMPLICIT_PADDING); + let lvlsrc = match levels.find(&(id, lint_id)) { + None | Some(&(lint::Allow, _)) => return, + Some(&lvlsrc) => lvlsrc, + }; + + let mut total_size = 0; + for field in struct_def.fields.iter() { + let align = llalign_of_min(ccx, sizing_type_of(ccx, + ty::node_id_to_type(&ccx.tcx, field.node.id))); + if total_size % align != 0 { + lint::raw_emit_lint(&ccx.tcx().sess, lint::builtin::REPR_C_IMPLICIT_PADDING, + lvlsrc, Some(field.span), + format!("field expects alignment of {} bytes, but is being \ + inserted after {}", align, total_size).as_slice()); + } + total_size += llsize_of_real(ccx, sizing_type_of(ccx, + ty::node_id_to_type(&ccx.tcx, field.node.id))); + } +} + pub struct TransItemVisitor<'a> { pub ccx: &'a CrateContext, } @@ -1977,6 +2000,14 @@ pub fn trans_item(ccx: &CrateContext, item: &ast::Item) { ast::ItemForeignMod(ref foreign_mod) => { foreign::trans_foreign_mod(ccx, foreign_mod); } + ast::ItemStruct(ref struct_definition, _) => { + // Only run the struct padding lint if we have #[repr(C)] + if item.attrs.iter().fold(attr::ReprAny, |acc, attr| { + attr::find_repr_attr(ccx.tcx.sess.diagnostic(), attr, acc) + }) == attr::ReprExtern { + struct_repr_padding_lint(ccx, &**struct_definition, item.id); + } + } ast::ItemTrait(..) => { // Inside of this trait definition, we won't be actually translating any // functions, but the trait still needs to be walked. Otherwise default diff --git a/src/librustuv/addrinfo.rs b/src/librustuv/addrinfo.rs index 6eaab1c096170..7a940bc0e45e1 100644 --- a/src/librustuv/addrinfo.rs +++ b/src/librustuv/addrinfo.rs @@ -65,6 +65,7 @@ impl GetAddrInfoRequest { ai_canonname: mut_null(), ai_addr: mut_null(), ai_next: mut_null(), + __padding: [0, ..4] } }); let hint_ptr = hint.as_ref().map_or(null(), |x| {