Repository navigation
fix: make builds reproducible by moving rust-i18n to 3.1.5 - #65
animeshchaudhri merged 1 commit into
Conversation
Two release builds of the same commit produce different binaries.
rust-i18n-macro 3.1.2 writes out the translation tables of the editor
widget's i18n! call by iterating a HashMap, whose seed is random in
every process, so each build compiles them in a different order.
3.1.3 and later iterate a BTreeMap.
A plain cargo update cannot reach 3.1.3: proc-macro-crate 2.0.2 pins
toml_datetime exactly, below what newer rust-i18n's toml needs.
num_enum_derive accepts proc-macro-crate 3, already in the lock, so
the change is
cargo update -p proc-macro-crate@2.0.2
cargo update -p rust-i18n
Lock-only. The runtime rust-i18n crate is identical from 3.1.2 to
3.1.5, and rust-i18n-support changes only in the locale loader the
macro runs at compile time. The update also drops serde_yml and
libyml, which cargo audit reports as unsound (RUSTSEC-2025-0068,
RUSTSEC-2025-0067).
|
@barnumbirr Really interesting find. This is especially important for security as Rustman grows. Thanks for the detailed investigation. Merging this! Also did you use any tool for figuring what was different for LTO for both builds or just the sha hash ? |
|
Thanks! No dedicated tool, mostly hashes and comparing the right files. I noticed it because debrebuild, which rebuilds a Debian package and compares it with the published one, reported only Diffing the final binaries didn't get far. With LTO and What found it was comparing the intermediate artifacts instead of the binary: two builds from a clean for n in 1 2; do
rm -rf target
cargo build --release --locked -q
(cd target/release/deps && sha256sum *.rlib *.rmeta | sort -k2) > /tmp/rlibs-$n.txt
done
diff /tmp/rlibs-1.txt /tmp/rlibs-2.txtOnly diffoscope, from the Reproducible Builds project, is the usual tool for looking inside two differing builds, but I didn't need it here. On security: I've opened #66 for the four advisories |
Two release builds of the same commit produce different binaries. The cause is rust-i18n-macro 3.1.2, which writes out the translation tables of the editor widget's
i18n!call by iterating aHashMap. Its seed is random in every process, so every build compiles the tables in a different order, and with LTO the rest of the binary shifts around them. rust-i18n fixed this in 3.1.3 ("ReplaceHashMapwithBTreeMapto remove non-determinism in build", longbridge/rust-i18n#104), but the lock is still on 3.1.2.A plain
cargo update -p rust-i18ncannot move it:proc-macro-crate2.0.2 pinstoml_datetime = "=0.6.3", below what the toml in newer rust-i18n needs.num_enum_deriveacceptsproc-macro-crateup to 3, and 3.5.0 is already in the lock, so the change is:It only touches
Cargo.lock:rust-i18n,rust-i18n-macroandrust-i18n-supportgo from 3.1.2 to 3.1.5. The runtimerust-i18ncrate is identical between the two;rust-i18n-supportchanges only in the locale loader that the macro runs at compile time.toml0.7.8 to 0.8.23, withtoml_edit,toml_datetime,winnowand a newtoml_write, all reached only through the macro at compile time.proc-macro-crate2.0.2,serde_ymlandlibymlare removed. The last two clear twocargo auditwarnings, RUSTSEC-2025-0068 and RUSTSEC-2025-0067 (unsound, unmaintained); rust-i18n 3.1.4 had already moved toserde_yamlover earlier concerns aboutserde_yml(Concerns with serde_yml rustsec/advisory-db#2212).Testing
cargo build --release, twice per tree from a clean target at the same path, Rust 1.98.1: on master the two binaries differ (3de8eb66…andd0bb5bf4…, 23,495,224 and 23,495,480 bytes); with this change both arecec019ef….--no-default-featuresbuild, comparing every crate's.rliband.rmetabetween two builds foundiced_code_editorthe only crate that differed. With this change they all match.cargo test: 139 passed and 3 ignored with default features, 131 and 3 with--no-default-features, the same as master.cargo check --all-targets --target x86_64-pc-windows-gnupasses with master's one warning (APP_IDis never used).rust-versionfloors are the same 21 as on master, so this change does not raise it.Not tested on macOS.