Skip to content

Commit e199071

Browse files
authored
Fix UB when using zero-sized allocations together with pcrel relocs (#10347)
1 parent 132a490 commit e199071

File tree

1 file changed

+17
-12
lines changed

1 file changed

+17
-12
lines changed

cranelift/jit/src/backend.rs

Lines changed: 17 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -867,23 +867,24 @@ impl Module for JITModule {
867867
align,
868868
} = data;
869869

870-
let size = init.size();
871-
let ptr = if size == 0 {
872-
// Return a correctly aligned non-null pointer to avoid UB in write_bytes and
873-
// copy_nonoverlapping.
874-
usize::try_from(align.unwrap_or(WRITABLE_DATA_ALIGNMENT)).unwrap() as *mut u8
875-
} else if decl.writable {
870+
// Make sure to allocate at least 1 byte. Allocating 0 bytes is UB. Previously a dummy
871+
// value was used, however as it turns out this will cause pc-relative relocations to
872+
// fail on architectures where pc-relative offsets are range restricted as the dummy
873+
// value is not close enough to the code that has the pc-relative relocation.
874+
let alloc_size = std::cmp::max(init.size(), 1);
875+
876+
let ptr = if decl.writable {
876877
self.memory
877878
.writable
878-
.allocate(size, align.unwrap_or(WRITABLE_DATA_ALIGNMENT))
879+
.allocate(alloc_size, align.unwrap_or(WRITABLE_DATA_ALIGNMENT))
879880
.map_err(|e| ModuleError::Allocation {
880881
message: "unable to alloc writable data",
881882
err: e,
882883
})?
883884
} else {
884885
self.memory
885886
.readonly
886-
.allocate(size, align.unwrap_or(READONLY_DATA_ALIGNMENT))
887+
.allocate(alloc_size, align.unwrap_or(READONLY_DATA_ALIGNMENT))
887888
.map_err(|e| ModuleError::Allocation {
888889
message: "unable to alloc readonly data",
889890
err: e,
@@ -894,7 +895,7 @@ impl Module for JITModule {
894895
// FIXME pass a Layout to allocate and only compute the layout once.
895896
std::alloc::handle_alloc_error(
896897
std::alloc::Layout::from_size_align(
897-
size,
898+
alloc_size,
898899
align.unwrap_or(READONLY_DATA_ALIGNMENT).try_into().unwrap(),
899900
)
900901
.unwrap(),
@@ -905,12 +906,12 @@ impl Module for JITModule {
905906
Init::Uninitialized => {
906907
panic!("data is not initialized yet");
907908
}
908-
Init::Zeros { .. } => {
909+
Init::Zeros { size } => {
909910
unsafe { ptr::write_bytes(ptr, 0, size) };
910911
}
911912
Init::Bytes { ref contents } => {
912913
let src = contents.as_ptr();
913-
unsafe { ptr::copy_nonoverlapping(src, ptr, size) };
914+
unsafe { ptr::copy_nonoverlapping(src, ptr, contents.len()) };
914915
}
915916
}
916917

@@ -921,7 +922,11 @@ impl Module for JITModule {
921922
};
922923
let relocs = data.all_relocs(pointer_reloc).collect::<Vec<_>>();
923924

924-
self.compiled_data_objects[id] = Some(CompiledBlob { ptr, size, relocs });
925+
self.compiled_data_objects[id] = Some(CompiledBlob {
926+
ptr,
927+
size: init.size(),
928+
relocs,
929+
});
925930
self.data_objects_to_finalize.push(id);
926931
if self.isa.flags().is_pic() {
927932
self.pending_got_updates.push(GotUpdate {

0 commit comments

Comments
 (0)