Fix pointer provenance in const rust with zero sized type enum variants (#3532)

This commit is contained in:
Evan Almloff authored and GitHub committed 2025-01-10 13:01:15 -08:00
1 parent c4b5e7dbf1
commit 2924ec4678
1 file changed
+15 -8
+15 -8
View File
@@ -64,7 +64,11 @@ impl EnumLayout {
i += 1; i += 1;
} }
let variants_offset = (discriminant.size / max_align) + max_align; let variants_offset_raw = discriminant.size;
let padding = (max_align - (variants_offset_raw % max_align)) % max_align;
let variants_offset = variants_offset_raw + padding;
assert!(variants_offset % max_align == 0);
Self { Self {
size, size,
@@ -588,7 +592,7 @@ const fn serialize_const_struct(
while i < layout.data.len() { while i < layout.data.len() {
// Serialize the field at the offset pointer in the struct // Serialize the field at the offset pointer in the struct
let StructFieldLayout { offset, layout } = &layout.data[i]; let StructFieldLayout { offset, layout } = &layout.data[i];
let field = unsafe { ptr.byte_add(*offset) }; let field = ptr.wrapping_byte_add(*offset as _);
to = serialize_const_ptr(field, to, layout); to = serialize_const_ptr(field, to, layout);
i += 1; i += 1;
} }
@@ -610,11 +614,11 @@ const fn serialize_const_enum(
let byte = if cfg!(target_endian = "big") { let byte = if cfg!(target_endian = "big") {
unsafe { unsafe {
byte_ptr byte_ptr
.byte_add(layout.discriminant.size - offset - 1) .wrapping_byte_add((layout.discriminant.size - offset - 1) as _)
.read() .read()
} }
} else { } else {
unsafe { byte_ptr.byte_add(offset).read() } unsafe { byte_ptr.wrapping_byte_add(offset as _).read() }
}; };
to = to.push(byte); to = to.push(byte);
discriminant |= (byte as u32) << (offset * 8); discriminant |= (byte as u32) << (offset * 8);
@@ -626,7 +630,7 @@ const fn serialize_const_enum(
// If the variant is the discriminated one, serialize it // If the variant is the discriminated one, serialize it
let EnumVariant { tag, data, .. } = &layout.variants[i]; let EnumVariant { tag, data, .. } = &layout.variants[i];
if discriminant == *tag { if discriminant == *tag {
let data_ptr = unsafe { ptr.byte_add(layout.variants_offset) }; let data_ptr = ptr.wrapping_byte_offset(layout.variants_offset as _);
to = serialize_const_struct(data_ptr, to, data); to = serialize_const_struct(data_ptr, to, data);
break; break;
} }
@@ -646,9 +650,12 @@ const fn serialize_const_primitive(
while offset < layout.size { while offset < layout.size {
// If the bytes are reversed, walk backwards from the end of the number when pushing bytes // If the bytes are reversed, walk backwards from the end of the number when pushing bytes
if cfg!(any(target_endian = "big", feature = "test-big-endian")) { if cfg!(any(target_endian = "big", feature = "test-big-endian")) {
to = to.push(unsafe { ptr.byte_add(layout.size - offset - 1).read() }); to = to.push(unsafe {
ptr.wrapping_byte_offset((layout.size - offset - 1) as _)
.read()
});
} else { } else {
to = to.push(unsafe { ptr.byte_add(offset).read() }); to = to.push(unsafe { ptr.wrapping_byte_offset(offset as _).read() });
} }
offset += 1; offset += 1;
} }
@@ -664,7 +671,7 @@ const fn serialize_const_list(
let len = layout.len; let len = layout.len;
let mut i = 0; let mut i = 0;
while i < len { while i < len {
let field = unsafe { ptr.byte_add(i * layout.item_layout.size()) }; let field = ptr.wrapping_byte_offset((i * layout.item_layout.size()) as _);
to = serialize_const_ptr(field, to, layout.item_layout); to = serialize_const_ptr(field, to, layout.item_layout);
i += 1; i += 1;
} }