Skip to content

integer: use type-generic overflow intrinsics for size_t - #7406

Open
msuozzo wants to merge 1 commit into
libgit2:mainfrom
msuozzo:push-nqzwyvnntryt
Open

msuozzo wants to merge 1 commit into
libgit2:mainfrom
msuozzo:push-nqzwyvnntryt

Conversation

@msuozzo

@msuozzo msuozzo commented Oct 11, 2026

Copy link
Copy Markdown
Contributor

This fixes wasm32 (WASI, Emscripten) where size_t is unsigned long
while SIZE_MAX == UINT_MAX. Previously, git__add_sizet_overflow
passed a size_t * to __builtin_uadd_overflow, which takes an
unsigned int *. Clang 22 and later upgrade this to an error so every
file that checks an allocation size fails to build.

msuozzo added a commit to msuozzo/git2-rs that referenced this pull request Oct 11, 2026
Build the vendored libgit2 for `target_os = "wasi"` (tested on
wasm32-wasip1; wasip2 is untested). There is no system libgit2 to link
against, so WASI always builds the vendored copy. In git2, path
conversions accept WASI's `OsStr`, and `Repository::open_ext` and
`discover_path` join ceiling directories themselves, since std's
`env::join_paths` is unsupported on WASI.

WASI preview 1 lacks several things libgit2's unix build assumes:

- mmap: build with `NO_MMAP`, so pack windows are read into memory.
- threads: leave `GIT_THREADS` undefined, and reject the -threads
  targets, where git2's `Send` types could then race inside libgit2.
- network connections: replace `streams/socket.c` with a stream that
  always fails, and reject the `https` and `ssh` features.
- user and process identity: wasi/compat.c defines getuid and friends
  (uid 0, pid 1). wasi-libc has no pwd.h, so wasi/include/pwd.h
  provides one; libgit2 only consults it when setuid, so the home
  directory comes from $HOME.

On wasm32, `size_t` is `unsigned long` but `SIZE_MAX == UINT_MAX`, so
libgit2's `integer.h` passes a `size_t *` to `__builtin_uadd_overflow`.
The types have the same width, so clang's error is downgraded for WASI
as a stopgap until libgit2 uses the type-generic builtins
(libgit2/libgit2#7406).

Add a CI job that builds for wasm32-wasip1 with wasi-sdk.
This fixes wasm32 (WASI, Emscripten) where `size_t` is `unsigned long`
while `SIZE_MAX == UINT_MAX`. Previously, `git__add_sizet_overflow`
passed a `size_t *` to `__builtin_uadd_overflow`, which takes an
`unsigned int *`. Clang 22 and later upgrade this to an error so every
file that checks an allocation size fails to build.
msuozzo added a commit to msuozzo/git2-rs that referenced this pull request Oct 12, 2026
Build the vendored libgit2 for `target_os = "wasi"` (tested on
wasm32-wasip1; wasip2 is untested). There is no system libgit2 to link
against, so WASI always builds the vendored copy. In git2, path
conversions accept WASI's `OsStr`, and `Repository::open_ext` and
`discover_path` join ceiling directories themselves, since std's
`env::join_paths` is unsupported on WASI.

WASI preview 1 lacks several things libgit2's unix build assumes:

- mmap: build with `NO_MMAP`, so pack windows are read into memory.
- threads: leave `GIT_THREADS` undefined, and reject the -threads
  targets, where git2's `Send` types could then race inside libgit2.
- network connections: replace `streams/socket.c` with a stream that
  always fails, and reject the `https` and `ssh` features.
- user and process identity: wasi/compat.c defines getuid and friends
  (uid 0, pid 1). wasi-libc has no pwd.h, so wasi/include/pwd.h
  provides one; libgit2 only consults it when setuid, so the home
  directory comes from $HOME.

On wasm32, `size_t` is `unsigned long` but `SIZE_MAX == UINT_MAX`, so
libgit2's `integer.h` passes a `size_t *` to `__builtin_uadd_overflow`.
The types have the same width, so clang's error is downgraded for WASI
as a stopgap until libgit2 uses the type-generic builtins
(libgit2/libgit2#7406).

libz-sys before 1.1.30 builds zlib for WASI without default allocators
(rust-lang/libz-sys#273), so every object read fails. Require 1.1.30.

Add a CI job that builds for wasm32-wasip1 with wasi-sdk and runs the
tests under wasmtime. MSRV only builds: before Rust 1.94, std on WASI
can't canonicalize paths and its remove_dir_all fails on what the
tests create. For the tests:

- std has no temporary directory on WASI, so tests create theirs with
  `test::tempdir()`, which points tempfile at /tmp there, as tempfile's
  own tests do. The runner preopens /tmp.
- Test helpers with only unix and windows variants (`realpath`,
  `ostr_to_cstr`, file URLs, the symlink in `repo_status`) now cover
  WASI, and `search_path` joins paths itself.
- Skipped on WASI: `compile_fail` (trybuild runs cargo),
  `non_utf8_branch` (WASI paths are UTF-8), and two tests that remove
  directories through paths ending in a slash, which wasmtime rejects
  (bytecodealliance/wasmtime#11524).

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant