-
-
Notifications
You must be signed in to change notification settings - Fork 5
Description
I was debugging a reproducible build failure in pimsync [1] [2]. pimsync uses hashify indirectly through mail-parser, which then uses hashify.
In this context, reproducible build means that the compiler output is deterministic. Hence, if I run the build twice I get the same binary. This is important for verifying binaries provided, for example, by Linux distributions. For more information refer to the reproducible builds website: https://reproducible-builds.org/.
Problem
The underlying problem is hashify::tiny_set!, which is a proc_macro that is used by mail-parser. Unfortunately, this macro makes the compiler output non-deterministic as it iterates over a HashMap. The Rust standard library documentation clearly states that HashMap iteration occurs in ”arbitrary order”. Therefore, the compiler output is non-deterministic.
Reproducing the Problem
Use the following commands:
$ cat src/lib.rs
pub fn is_re_prefix(prefix: &str) -> bool {
hashify::tiny_set! {prefix.as_bytes(),
"re",
"res",
"sv",
"antw",
"ref",
"aw",
"απ",
"השב",
"vá",
"r",
"rif",
"bls",
"odp",
"ynt",
"atb",
"رد",
"回复",
"转发",
}
}
$ cargo build --release && mv target target.1
$ cargo build --release && mv target target.2
$ md5sum target.?/release/*.rlib
b1baf6bbdba2e06c5b5cd2fcc0e604d0 target.1/release/librepro.rlib
359d5e96fb9d38c3280a4fe761d9ee12 target.2/release/librepro.rlib
This builds a library with a function using hashify::tiny_set! twice. As we can see in the md5sum output, the resulting .rlib file is not identical, but should be as otherwise its build not reproducible.
For more information refer to the following write-up: https://notes.8pit.net/notes/iqfs.html.