macOS weird crash in [NSString stringWithUTF8String:]

Viewed 241

We started seeing crashes that happen when our app starts. I wasn't able to reproduce it, and it happens only to a few users.

The exception is:

Exception Type: EXC_BAD_ACCESS (SIGBUS) Exception Codes: 0x00000000 at 0x0000000105e1f32c Crashed Thread: 8

stack here

Thread 8 Crashed:
0   libsystem_platform.dylib        0x00007fff203b56f8 _os_semaphore_wait.cold.1 + 129
1   libsystem_malloc.dylib          0x00007fff20193793 szone_malloc_should_clear + 66
2   libsystem_malloc.dylib          0x00007fff201aceb7 _malloc_zone_calloc + 59
3   CoreFoundation                  0x00007fff203e7b0a _CFRuntimeCreateInstance + 290
4   CoreFoundation                  0x00007fff203e7289 __CFStringCreateImmutableFunnel3 + 2099
5   CoreFoundation                  0x00007fff203f34fe CFStringCreateWithBytes + 27
6   Foundation                      0x00007fff210eadbe +[NSString stringWithUTF8String:] + 68
7   MyApp                     0x0000000104551576 +[Utility getCommandLine:] + 934

source code here

+ (void)getCommandLine:(LCProcessInfo*)process
{
    int mib[3], argmax, nargs, c = 0;
    char *procargs, *cp, *sp, *np;
    size_t size;
    
    mib[0] = CTL_KERN;
    mib[1] = KERN_ARGMAX;
    size = sizeof(argmax);
    if (sysctl(mib, 2, &argmax, &size, NULL, 0) == -1)
    {
        ERROR(@"sysctl() of KERN_ARGMAX has failed.");
        return;
    }
    
    procargs = malloc(argmax);
    if (procargs == NULL)
    {
        ERROR(@"malloc() has failed");
        return;
    }
    
    mib[0] = CTL_KERN;
    mib[1] = KERN_PROCARGS2;
    mib[2] = (int)process.pid;
    
    size = argmax;
    if (sysctl(mib, 3, procargs, &size, NULL, 0) == -1)
    {
        // Failure here means it's a system process.
        process.commandLine = [NSString stringWithFormat:@"(%@)", process.name];
        goto exit;
    }
    
    memcpy(&nargs, procargs, sizeof(nargs));
    cp = procargs + sizeof(nargs);
    
    for (; cp < &procargs[size]; cp++)
    {
        if (*cp == '\0')
        {
            break;
        }
    }
    
    if (cp == &procargs[size])
    {
        goto exit;;
    }
    
    // Skip trailing '\0' characters.
    for (; cp < &procargs[size]; cp++)
    {
        if (*cp != '\0')
        {
            break;
        }
    }
    
    if (cp == &procargs[size])
    {
        goto exit;
    }
    
    // Save where argv[0] string starts.
    sp = cp;
    
    /*
     * Iterate through the '\0'-terminated strings and convert '\0' to ' '
     * until a string is found that has a '=' character in it (or there are
     * no more strings in procargs).  There is no way to deterministically
     * know where the command arguments end and the environment strings
     * start, which is why the '=' character is searched for as a heuristic.
     */
    for (np = NULL; c < nargs && cp < &procargs[size]; cp++) {
        if (*cp == '\0') {
            c++;
            if (np != NULL) {
                /* Convert previous '\0'. */
                *np = ' ';
            }
            /* Note location of current '\0'. */
            np = cp;
        }
    }
    
    /*
     * sp points to the beginning of the arguments/environment string, and
     * np should point to the '\0' terminator for the string.
     */
    if (np == NULL || np == sp) {
        /* Empty or unterminated string. */
        goto exit;
    }
    
    /* Make a copy of the string. */
    process.commandLine = [NSString stringWithUTF8Strin:sp];
    
exit:
    /* Clean up. */
    free(procargs);
}

Would appreciate any help to understand what's can cause this kind of crash.

1 Answers

Look at the value of sp before you call this. I expect there's a bug in how you advance cp. You probably advance it too far. I would suspect problems in your = searching heuristic.

If sp is NULL, this will crash.

nullTerminatedCString

A NULL-terminated C array of bytes in UTF-8 encoding. This value must not be NULL.

Important

Raises an exception if nullTerminatedCString is NULL.

Related