Skip to content

hashify::tiny_set! causes build to be not reproducible #4

@nmeum

Description

@nmeum

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions