Skip to content

Go source does not reproduce the bundled gomtp.dylib #15

Description

@aj0413

Summary

The Go source currently committed under ffi/kalam/native cannot reproduce the precompiled lib/gomtp.dylib shipped with SwiftMTP v1.2.4.

The dylib implements a newer multi-device backend API and additional USB synchronization logic that are absent from the repository source. This prevents contributors from auditing, debugging, or rebuilding the backend used by the application.

Evidence

The generated header declares this API:

extern void FetchAvailableDevices(on_cb_result_t* onDonePtr);
extern void Initialize(char* initInputJson, on_cb_result_t* onDonePtr);
extern void CancelTransfer(char* cancelTransferInputJson, on_cb_result_t* onDonePtr);
extern void Dispose(char* deviceInputJson, on_cb_result_t* onDonePtr);

However, the checked-in Go source has an older API:

//export Initialize
func Initialize(onDonePtr *C.on_cb_result_t)

It does not contain implementations for FetchAvailableDevices, CancelTransfer, or InitializeByDeviceId.

Static inspection of lib/gomtp.dylib shows that the compiled backend contains:

main.FetchAvailableDevices
main.CancelTransfer
main.getContainer
main.containersMap
main.containersLock
main.libusbGlobalLock
main.libusbContextLock
main.libusbLocked
github.com/ganeshrvel/go-mtpx.InitializeByDeviceId

It also contains behavior and diagnostic strings absent from the source:

FetchAvailableDevices: USB busy, returning %d cached devices
FetchAvailableDevices: Merging active device from cache: %s
FetchAvailableDevices: Cached device %s is stale
USB diag: device may be occupied by other processes

Example inspection command:

nm -arch arm64 -nm lib/gomtp.dylib |
  grep -E 'FetchAvailableDevices|CancelTransfer|containersMap|libusbLocked'

The binary reports that it was built with Go 1.26.1:

strings -arch arm64 lib/gomtp.dylib | grep 'go1\.'

The repository artifact at v1.2.4 has SHA-256:

ff774eb9bbab4f149c78d2890a81adc1e607d9e12d3816a52c4beadb9ad1bc1e

Build-script mismatch

ffi/kalam/native/scripts/build.sh still produces:

lib/kalam.dylib
lib/kalam.h

Xcode instead links:

lib/gomtp.dylib
lib/gomtp.h

Therefore, running the documented build script does not recreate the backend used by the application.

Git history indicates that a precompiled kalam.dylib was added and updated directly. Commit be9a80f later renamed that artifact to gomtp.dylib, but the corresponding newer Go source was not committed.

Dependency mismatch

The binary identifies these pinned modules:

github.com/ganeshrvel/go-mtpfs v1.0.4-0.20240426083057-1c3302b3c476
github.com/ganeshrvel/go-mtpx v0.0.0-20240426092756-18f12db021cc
github.com/ganeshrvel/usb v0.0.0-20210103155855-14d96f5ae403

However, the compiled go-mtpfs includes a custom getUSBOccupyingPIDs implementation not present in the pinned upstream source. This suggests that locally modified dependency source was used without recording it through a committed fork, vendor directory, or replace directive.

Why this matters

This currently prevents contributors from:

  • Rebuilding the application entirely from source.
  • Auditing the exact USB and filesystem behavior being distributed.
  • Fixing backend defects and validating that the fix reaches the release.
  • Reproducing the generated gomtp.h.
  • Verifying dependency patches.
  • Producing deterministic release artifacts.

It also affects an observed connection bug. Static analysis indicates that the compiled busy-device path can serialize a nil device slice as:

{"data": null}

The Swift frontend expects an array and reports:

MTPManager: Failed to decode available devices payload

Without the matching Go source, this cannot be corrected at its origin.

Requested resolution

Please consider:

  1. Committing the exact Go source used to build the current gomtp.dylib.
  2. Publishing any locally modified dependency forks or vendored patches.
  3. Updating go.mod with the actual dependency revisions or replace directives.
  4. Updating the build script to generate lib/gomtp.dylib and lib/gomtp.h.
  5. Documenting the required Go, SDK, macOS deployment target, and libusb versions.
  6. Adding a CI check that builds the dylib and verifies its exported symbols against gomtp.h.
  7. Rebuilding the checked-in binary from the committed source.

This issue is about source and release reproducibility; it is not an assertion that the existing binary is malicious.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions