]> git.lizzy.rs Git - rust.git/commitdiff
Fix codegen with explicit allocation byte access
authorAndreas Molzer <andreas.molzer@gmx.de>
Wed, 14 Aug 2019 02:40:03 +0000 (04:40 +0200)
committerAndreas Molzer <andreas.molzer@gmx.de>
Wed, 21 Aug 2019 08:55:16 +0000 (10:55 +0200)
src/librustc_codegen_llvm/consts.rs

index 0077df3cf5eea191dcbc475038ab32a5055b62d7..26eb870cfc0d422ab8e5c99511f42ddc29c97a9c 100644 (file)
@@ -35,11 +35,21 @@ pub fn const_alloc_to_llvm(cx: &CodegenCx<'ll, '_>, alloc: &Allocation) -> &'ll
         assert_eq!(offset as usize as u64, offset);
         let offset = offset as usize;
         if offset > next_offset {
-            llvals.push(cx.const_bytes(&alloc.bytes[next_offset..offset]));
+            // This `inspect` is okay since we have check that it is not within a relocation, it is
+            // within the bounds of the allocation, and it doesn't affect interpreter execution (we
+            // inspect the result after interpreter execution). Any undef byte is replaced with
+            // some arbitrary byte value.
+            //
+            // FIXME: relay undef bytes to codegen as undef const bytes
+            let bytes = alloc.inspect_with_undef_and_ptr_outside_interpreter(next_offset..offset);
+            llvals.push(cx.const_bytes(bytes));
         }
         let ptr_offset = read_target_uint(
             dl.endian,
-            &alloc.bytes[offset..(offset + pointer_size)],
+            // This `inspect` is okay since it is within the bounds of the allocation, it doesn't
+            // affect interpreter execution (we inspect the result after interpreter execution),
+            // and we properly interpret the relocation as a relocation pointer offset.
+            alloc.inspect_with_undef_and_ptr_outside_interpreter(offset..(offset + pointer_size)),
         ).expect("const_alloc_to_llvm: could not read relocation pointer") as u64;
         llvals.push(cx.scalar_to_backend(
             Pointer::new(alloc_id, Size::from_bytes(ptr_offset)).into(),
@@ -51,8 +61,16 @@ pub fn const_alloc_to_llvm(cx: &CodegenCx<'ll, '_>, alloc: &Allocation) -> &'ll
         ));
         next_offset = offset + pointer_size;
     }
-    if alloc.bytes.len() >= next_offset {
-        llvals.push(cx.const_bytes(&alloc.bytes[next_offset ..]));
+    if alloc.len() >= next_offset {
+        let range = next_offset..alloc.len();
+        // This `inspect` is okay since we have check that it is after all relocations, it is
+        // within the bounds of the allocation, and it doesn't affect interpreter execution (we
+        // inspect the result after interpreter execution). Any undef byte is replaced with some
+        // arbitrary byte value.
+        //
+        // FIXME: relay undef bytes to codegen as undef const bytes
+        let bytes = alloc.inspect_with_undef_and_ptr_outside_interpreter(range);
+        llvals.push(cx.const_bytes(bytes));
     }
 
     cx.const_struct(&llvals, true)
@@ -437,7 +455,23 @@ fn codegen_static(
                 //
                 // We could remove this hack whenever we decide to drop macOS 10.10 support.
                 if self.tcx.sess.target.target.options.is_like_osx {
-                    let sect_name = if alloc.bytes.iter().all(|b| *b == 0) {
+                    assert_eq!(alloc.relocations.len(), 0);
+
+                    let is_zeroed = {
+                        // Treats undefined bytes as if they were defined with the byte value that
+                        // happens to be currently assigned in mir. This is valid since reading
+                        // undef bytes may yield arbitrary values.
+                        //
+                        // FIXME: ignore undef bytes even with representation `!= 0`.
+                        //
+                        // The `inspect` method is okay here because we checked relocations, and
+                        // because we are doing this access to inspect the final interpreter state
+                        // (not as part of the interpreter execution).
+                        alloc.inspect_with_undef_and_ptr_outside_interpreter(0..alloc.len())
+                            .iter()
+                            .all(|b| *b == 0)
+                    };
+                    let sect_name = if is_zeroed {
                         CStr::from_bytes_with_nul_unchecked(b"__DATA,__thread_bss\0")
                     } else {
                         CStr::from_bytes_with_nul_unchecked(b"__DATA,__thread_data\0")
@@ -456,10 +490,17 @@ fn codegen_static(
                         section.as_str().as_ptr() as *const _,
                         section.as_str().len() as c_uint,
                     );
+                    assert!(alloc.relocations.is_empty());
+
+                    // The `inspect` method is okay here because we checked relocations, and
+                    // because we are doing this access to inspect the final interpreter state (not
+                    // as part of the interpreter execution).
+                    let bytes = alloc.inspect_with_undef_and_ptr_outside_interpreter(
+                        0..alloc.len());
                     let alloc = llvm::LLVMMDStringInContext(
                         self.llcx,
-                        alloc.bytes.as_ptr() as *const _,
-                        alloc.bytes.len() as c_uint,
+                        bytes.as_ptr() as *const _,
+                        bytes.len() as c_uint,
                     );
                     let data = [section, alloc];
                     let meta = llvm::LLVMMDNodeInContext(self.llcx, data.as_ptr(), 2);