From a7ae552851d02842a9d91aec52611f98e35d4d86 Mon Sep 17 00:00:00 2001 From: Heikki Linnakangas Date: Fri, 4 Jun 2021 23:05:28 +0300 Subject: [PATCH] Use rust memoffset crate to replace C offsetof(). Cherry-picked from Eric's PR #208 --- Cargo.lock | 10 ++++++++++ postgres_ffi/Cargo.toml | 1 + postgres_ffi/build.rs | 1 - postgres_ffi/pg_control_ffi.h | 7 ------- postgres_ffi/src/controlfile_utils.rs | 19 ++++++++++++------- 5 files changed, 23 insertions(+), 15 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 72e34638cf..d3cf801ede 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -928,6 +928,15 @@ version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b16bd47d9e329435e309c58469fe0791c2d0d1ba96ec0954152a5ae2b04387dc" +[[package]] +name = "memoffset" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59accc507f1338036a0477ef61afdae33cde60840f4dfe481319ce3ad116ddf9" +dependencies = [ + "autocfg", +] + [[package]] name = "mime" version = "0.3.16" @@ -1364,6 +1373,7 @@ dependencies = [ "hex", "lazy_static", "log", + "memoffset", "rand", "regex", "thiserror", diff --git a/postgres_ffi/Cargo.toml b/postgres_ffi/Cargo.toml index 0c829d4b7f..d9d522b5b9 100644 --- a/postgres_ffi/Cargo.toml +++ b/postgres_ffi/Cargo.toml @@ -17,6 +17,7 @@ crc32c = "0.6.0" hex = "0.4.3" lazy_static = "1.4" log = "0.4.14" +memoffset = "0.6.2" thiserror = "1.0" workspace_hack = { path = "../workspace_hack" } diff --git a/postgres_ffi/build.rs b/postgres_ffi/build.rs index d1df770d51..7207ca67bd 100644 --- a/postgres_ffi/build.rs +++ b/postgres_ffi/build.rs @@ -25,7 +25,6 @@ fn main() { // .whitelist_type("ControlFileData") .whitelist_var("PG_CONTROL_FILE_SIZE") - .whitelist_var("PG_CONTROLFILEDATA_OFFSETOF_CRC") .whitelist_type("DBState") // // Path the server include dir. It is in tmp_install/include/server, if you did diff --git a/postgres_ffi/pg_control_ffi.h b/postgres_ffi/pg_control_ffi.h index 805ccfa724..d6f13be0d0 100644 --- a/postgres_ffi/pg_control_ffi.h +++ b/postgres_ffi/pg_control_ffi.h @@ -6,10 +6,3 @@ */ #include "c.h" #include "catalog/pg_control.h" - -/* - * PostgreSQL uses "offsetof(ControlFileData, crc)" in multiple places to get the - * size of the control file up to the CRC, which is the last field, but there is - * no constant for it. We also need it in the Rust code. - */ -const uint32 PG_CONTROLFILEDATA_OFFSETOF_CRC = offsetof(ControlFileData, crc); diff --git a/postgres_ffi/src/controlfile_utils.rs b/postgres_ffi/src/controlfile_utils.rs index d6c625c296..2e0db3dab8 100644 --- a/postgres_ffi/src/controlfile_utils.rs +++ b/postgres_ffi/src/controlfile_utils.rs @@ -23,15 +23,20 @@ //! information. You can use PostgreSQL's pg_controldata utility to view its //! contents. //! -use crate::{ControlFileData, PG_CONTROLFILEDATA_OFFSETOF_CRC, PG_CONTROL_FILE_SIZE}; +use crate::{ControlFileData, PG_CONTROL_FILE_SIZE}; use anyhow::{bail, Result}; use bytes::{Bytes, BytesMut}; -// sizeof(ControlFileData) +/// Equivalent to sizeof(ControlFileData) in C const SIZEOF_CONTROLDATA: usize = std::mem::size_of::(); -// offsetof(ControlFileData, crc) -const OFFSETOF_CRC: usize = PG_CONTROLFILEDATA_OFFSETOF_CRC as usize; + +/// Compute the offset of the `crc` field within the `ControlFileData` struct. +/// Equivalent to offsetof(ControlFileData, crc) in C. +// Someday this can be const when the right compiler features land. +fn pg_control_crc_offset() -> usize { + memoffset::offset_of!(ControlFileData, crc) +} /// @@ -47,6 +52,7 @@ pub fn decode_pg_control(buf: &[u8]) -> Result { } // Compute the expected CRC of the content. + let OFFSETOF_CRC = pg_control_crc_offset(); let expectedcrc = crc32c::crc32c(&buf[0..OFFSETOF_CRC]); // Convert the slice into an array of the right size, and use `transmute` to @@ -104,9 +110,8 @@ pub fn encode_pg_control(controlfile: &ControlFileData) -> Bytes { unsafe { std::mem::transmute::(*controlfile) }; // Recompute the CRC - let mut data_without_crc: [u8; OFFSETOF_CRC] = [0u8; OFFSETOF_CRC]; - data_without_crc.copy_from_slice(&b[0..OFFSETOF_CRC]); - let newcrc = crc32c::crc32c(&data_without_crc); + let OFFSETOF_CRC = pg_control_crc_offset(); + let newcrc = crc32c::crc32c(&b[0..OFFSETOF_CRC]); let mut buf = BytesMut::with_capacity(PG_CONTROL_FILE_SIZE as usize); buf.extend_from_slice(&b[0..OFFSETOF_CRC]);