Safer FFI initialization with MaybeUninit

Also corrects some deprecated trait object syntax and relaxes the
documented Go version requirement.

Change-Id: Ia0ec8ec8922f217b718afdff479e9d6df456347c
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 0833fd9..16da6f2 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -19,6 +19,8 @@
 ### Changed
 - `build.rs` implements symbol name scraping natively, and no longer relies on
   BoringSSL's `read_symbols.go`.
+- Minimum required Rust version raised to 1.36
+- Minimum required Go version lowered to 1.10
 
 ### Fixed
 - `build.rs` no longer respects `$GOPATH`, instead it always uses the
diff --git a/README.md b/README.md
index 0ac5ed6..7c9a9cc 100644
--- a/README.md
+++ b/README.md
@@ -18,6 +18,8 @@
 
 ## Dependencies
 
+Rust 1.36 or newer is required.
+
 Mundane vendors a copy of the BoringSSL source, so BoringSSL does not need to be
 installed locally in order to build. However, the BoringSSL build system has the
 following dependencies:
@@ -29,7 +31,7 @@
   makes compilation significantly faster; if both are present, Ninja will be
   used. On Windows, Ninja is required.
 - A C++ compiler
-- Go 1.11 or later
+- Go 1.10 or later
 - To build the x86 and x86_64 assembly, your assembler must support AVX2
   instructions and `MOVBE`. If using GNU binutils, you must have 2.22 or later.
 
diff --git a/build/obj.rs b/build/obj.rs
index 9df92a2..98feddf 100644
--- a/build/obj.rs
+++ b/build/obj.rs
@@ -15,13 +15,13 @@
 use std::error;
 
 /// List symbols exported by the file (expected to be either a static library or an object file).
-pub fn exported_symbols(file: &str) -> Result<BTreeSet<String>, Box<error::Error>> {
+pub fn exported_symbols(file: &str) -> Result<BTreeSet<String>, Box<dyn error::Error>> {
     let mut bytes = Vec::new();
     File::open(file)?.read_to_end(&mut bytes)?;
     binary_exported_symbols(&bytes)
 }
 
-fn binary_exported_symbols(bytes: &[u8]) -> Result<BTreeSet<String>, Box<error::Error>> {
+fn binary_exported_symbols(bytes: &[u8]) -> Result<BTreeSet<String>, Box<dyn error::Error>> {
     let mut symbols = BTreeSet::new();
     match goblin::Object::parse(bytes)? {
         goblin::Object::Archive(archive) => {
diff --git a/src/boringssl/mod.rs b/src/boringssl/mod.rs
index 4ae02f6..b51a979 100644
--- a/src/boringssl/mod.rs
+++ b/src/boringssl/mod.rs
@@ -98,7 +98,8 @@
 use std::fmt::{self, Debug, Display, Formatter};
 use std::num::NonZeroUsize;
 use std::os::raw::{c_char, c_int, c_uint, c_void};
-use std::{mem, ptr, slice};
+use std::mem::MaybeUninit;
+use std::{ptr, slice};
 
 use boringssl::abort::UnwrapAbort;
 use boringssl::raw::{
@@ -130,9 +131,9 @@
     #[must_use]
     pub fn cbb_new(initial_capacity: usize) -> Result<CStackWrapper<CBB>, BoringError> {
         unsafe {
-            let mut cbb = mem::uninitialized();
-            CBB_init(&mut cbb, initial_capacity)?;
-            Ok(CStackWrapper::new(cbb))
+            let mut cbb = MaybeUninit::uninit();
+            CBB_init(cbb.as_mut_ptr(), initial_capacity)?;
+            Ok(CStackWrapper::new(cbb.assume_init()))
         }
     }
 
@@ -184,9 +185,9 @@
         with_cbs: F,
     ) -> O {
         unsafe {
-            let mut cbs = mem::uninitialized();
-            CBS_init(&mut cbs, bytes.as_ptr(), bytes.len());
-            let mut cbs = CStackWrapper::new(cbs);
+            let mut cbs = MaybeUninit::uninit();
+            CBS_init(cbs.as_mut_ptr(), bytes.as_ptr(), bytes.len());
+            let mut cbs = CStackWrapper::new(cbs.assume_init());
             with_cbs(&mut cbs)
         }
     }
@@ -475,9 +476,9 @@
     #[must_use]
     pub fn sha384_new() -> CStackWrapper<SHA512_CTX> {
         unsafe {
-            let mut ctx = mem::uninitialized();
-            SHA384_Init(&mut ctx);
-            CStackWrapper::new(ctx)
+            let mut ctx = MaybeUninit::uninit();
+            SHA384_Init(ctx.as_mut_ptr());
+            CStackWrapper::new(ctx.assume_init())
         }
     }
 }
@@ -527,10 +528,10 @@
         md: &CRef<'static, EVP_MD>,
     ) -> Result<CStackWrapper<HMAC_CTX>, BoringError> {
         unsafe {
-            let mut ctx = mem::uninitialized();
-            HMAC_CTX_init(&mut ctx);
-            HMAC_Init_ex(&mut ctx, key.as_ptr() as *const c_void, key.len(), md.as_const())?;
-            Ok(CStackWrapper::new(ctx))
+            let mut ctx = MaybeUninit::uninit();
+            HMAC_CTX_init(ctx.as_mut_ptr());
+            HMAC_Init_ex(ctx.as_mut_ptr(), key.as_ptr() as *const c_void, key.len(), md.as_const())?;
+            Ok(CStackWrapper::new(ctx.assume_init()))
         }
     }
 
@@ -762,7 +763,7 @@
                 &mut self,
             ) -> [u8; ::boringssl::ffi::$digest_len as usize] {
                 unsafe {
-                    let mut md: [u8; ::boringssl::ffi::$digest_len as usize] = mem::uninitialized();
+                    let mut md = MaybeUninit::<[u8; ::boringssl::ffi::$digest_len as usize]>::uninit();
                     // SHA1_Final promises to return 1. SHA256_Final,
                     // SHA384_Final, and SHA512_Final all document that they
                     // only fail due to programmer error. The only input to the
@@ -773,8 +774,8 @@
                     // here.
                     //
                     // TODO(joshlf): Figure out how XXX_Final can fail.
-                    ::boringssl::raw::$final_raw((&mut md[..]).as_mut_ptr(), self.as_mut()).unwrap_abort();
-                    md
+                    ::boringssl::raw::$final_raw(md.as_mut_ptr() as _, self.as_mut()).unwrap_abort();
+                    md.assume_init()
                 }
             }
         }
diff --git a/src/boringssl/wrapper.rs b/src/boringssl/wrapper.rs
index 3b6ac46..a6953b9 100644
--- a/src/boringssl/wrapper.rs
+++ b/src/boringssl/wrapper.rs
@@ -5,7 +5,7 @@
 // https://opensource.org/licenses/MIT.
 
 use std::marker::PhantomData;
-use std::mem;
+use std::mem::{self, MaybeUninit};
 use std::ptr::NonNull;
 
 /// A trait that can be used to ensure that users of the boringssl module can't
@@ -338,9 +338,9 @@
     // CStackWrapper::new).
     fn default() -> CStackWrapper<C> {
         unsafe {
-            let mut obj: C = mem::uninitialized();
-            C::init(&mut obj);
-            CStackWrapper { obj, _no_sync: PhantomData }
+            let mut obj = MaybeUninit::<C>::uninit();
+            C::init(obj.as_mut_ptr());
+            CStackWrapper { obj: obj.assume_init(), _no_sync: PhantomData }
         }
     }
 }