Skip to content

git_repository_open, given a nonexistent path, trashes pthread_self on macOS/ARM64 #6871

@OneSadCookie

Description

@OneSadCookie

Reproduction steps

#include <git2.h>
#include <pthread.h>
#include <stdio.h>

int main(int argc, char const * const *argv) {
    if (argc < 2) {
        fprintf(stderr, "Pass a path to a directory for git_repository_open\n");
        return 1;
    }
    char const *path = argv[1];
    
    printf("before git_repository_open: pthread_self: %p\n", pthread_self());

    git_repository *repo = NULL;
    int err = git_repository_open(&repo, path);
    if (err == 0) {
        printf("git_repository_open succeeded: %p\n", repo);
    } else {
        printf("git_repository_open failed: %d\n", err);
    }

    printf("after git_repository_open: pthread_self: %p\n", pthread_self());
    exit(0);
}

I'm using the libgit2 from homebrew, but the version Apple ships with Xcode also has the problem:

cc \
    -I/opt/homebrew/include \
    main.c \
    /opt/homebrew/lib/libgit2.a \
    /opt/homebrew/lib/libssh2.a \
    /opt/homebrew/lib/libcrypto.a \
    -lz -liconv \
    -framework Security -framework Foundation

Running the test program on /usr succeeds, but on /foo fails:

$ lldb a.out 
(lldb) target create "a.out"
Current executable set to '/Users/<me>/.../Libgit2NukesPthreadSelf/a.out' (arm64).
(lldb) r /usr
Process 73772 launched: '/Users/<me>/.../Libgit2NukesPthreadSelf/a.out' (arm64)
before git_repository_open: pthread_self: 0x1fa3fcf40
git_repository_open failed: -1
after git_repository_open: pthread_self: 0x1fa3fcf40
Process 73772 exited with status = 0 (0x00000000) 

(lldb) r /foo
Process 73796 launched: '/Users/<me>/.../Libgit2NukesPthreadSelf/a.out' (arm64)
before git_repository_open: pthread_self: 0x1fa3fcf40
git_repository_open failed: -3
Process 73796 stopped
* thread #1, queue = 'com.apple.main-thread', stop reason = EXC_BREAKPOINT (code=1, subcode=0x1925a973c)
    frame #0: 0x00000001925a973c libsystem_pthread.dylib`pthread_self + 56
libsystem_pthread.dylib`pthread_self:
->  0x1925a973c <+56>: brk    #0xc473
    0x1925a9740 <+60>: cmp    x16, x0
    0x1925a9744 <+64>: b.ne   0x1925a9750    ; <+76>
    0x1925a9748 <+68>: ldp    x29, x30, [sp], #0x10
Target 0: (a.out) stopped.
(lldb) bt
* thread #1, queue = 'com.apple.main-thread', stop reason = EXC_BREAKPOINT (code=1, subcode=0x1925a973c)
  * frame #0: 0x00000001925a973c libsystem_pthread.dylib`pthread_self + 56
    frame #1: 0x00000001000020e0 a.out`main + 224
    frame #2: 0x0000000192223154 dyld`start + 2476

Expected behavior

git_repository_open should not trash memory

Actual behavior

Pretty sure git_repository_open is trashing memory! At the least, it's somehow triggering pthread_self's internal safety check, probably this one: https://github.com/apple/darwin-libpthread/blob/main/src/inline_internal.h#L177

Version of libgit2 (release number or SHA1)

1.8.1

Operating system(s) tested

macOS Sonoma 14.6.1

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