diff --git a/rust/hg-cpython/src/cindex.rs b/rust/hg-cpython/src/cindex.rs --- a/rust/hg-cpython/src/cindex.rs +++ b/rust/hg-cpython/src/cindex.rs @@ -16,7 +16,7 @@ }; use hg::revlog::{Node, RevlogIndex}; use hg::{Graph, GraphError, Revision, WORKING_DIRECTORY_REVISION}; -use libc::c_int; +use libc::{c_int, ssize_t}; const REVLOG_CABI_VERSION: c_int = 2; @@ -24,10 +24,10 @@ pub struct Revlog_CAPI { abi_version: c_int, index_length: - unsafe extern "C" fn(index: *mut revlog_capi::RawPyObject) -> c_int, + unsafe extern "C" fn(index: *mut revlog_capi::RawPyObject) -> ssize_t, index_node: unsafe extern "C" fn( index: *mut revlog_capi::RawPyObject, - rev: c_int, + rev: ssize_t, ) -> *const Node, index_parents: unsafe extern "C" fn( index: *mut revlog_capi::RawPyObject, @@ -157,7 +157,7 @@ fn node(&self, rev: Revision) -> Option<&Node> { let raw = unsafe { - (self.capi.index_node)(self.index.as_ptr(), rev as c_int) + (self.capi.index_node)(self.index.as_ptr(), rev as ssize_t) }; if raw.is_null() { None diff --git a/tests/test-persistent-nodemap.t b/tests/test-persistent-nodemap.t --- a/tests/test-persistent-nodemap.t +++ b/tests/test-persistent-nodemap.t @@ -33,10 +33,18 @@ #if rust -Reported bug: some Rust code panics when handling the null revision +Regression test for a previous bug in Rust/C FFI for the `Revlog_CAPI` capsule: +in places where `mercurial/cext/revlog.c` function signatures use `Py_ssize_t` +(64 bits on Linux x86_64), corresponding declarations in `rust/hg-cpython/src/cindex.rs` +incorrectly used `libc::c_int` (32 bits). +As a result, -1 passed from Rust for the null revision became 4294967295 in C. - $ hg log -r 00000000 2>&1 | grep panicked - thread '' panicked at 'called `Option::unwrap()` on a `None` value', hg-cpython/src/revlog.rs:* (glob) + $ hg log -r 00000000 + changeset: -1:000000000000 + tag: tip + user: + date: Thu Jan 01 00:00:00 1970 +0000 + #endif