kstenerud / KSCrash

The Ultimate iOS Crash Reporter
MIT License
4.23k stars 705 forks source link

Replace `sprintf` with `snprintf` #523

Closed GLinnik21 closed 2 months ago

GLinnik21 commented 2 months ago

We've identified an issue in versions 1.x.x where crashes occasionally occur during the JSON serialization of crash reports. The problem appears to be a potential buffer overflow vulnerability in our floating point value handling.

One of the functions affected is: https://github.com/kstenerud/KSCrash/blob/8cc2170a9d3bc7775b71311bff231e600ca1349e/Sources/KSCrashRecordingCore/KSJSONCodec.c#L275-L282

This function uses sprintf, which lacks bounds checking and could lead to buffer overflows. To address this, we propose replacing sprintf with snprintf. This change would provide proper bounds checking and prevent potential buffer overflows.

Here's the proposed modification:

int ksjson_addFloatingPointElement(KSJSONEncodeContext* const context, const char* const name, double value)
{
    int result = ksjson_beginElement(context, name);
    unlikely_if(result != KSJSON_OK) { return result; }
    char buff[30];
    int written = snprintf(buff, sizeof(buff), "%lg", value);
    if (written < 0 || written >= sizeof(buff)) {
        // Handle error or truncation
        return KSJSON_ERROR_INVALID_DATA;
    }
    return addJSONData(context, buff, written);
}

It's important to note that this is only one of several places where sprintf is used. We should conduct a thorough review of the codebase and replace all instances of sprintf with safer alternatives like snprintf to prevent similar vulnerabilities elsewhere.

For context, here's a stack trace from one of the crashes:

Crashed: ExceptionHandler
0  libsystem_kernel.dylib         0x7578 __pthread_kill + 8
1  libsystem_pthread.dylib        0x7118 pthread_kill + 268
2  libsystem_c.dylib              0x1d178 abort + 180
3  libsystem_malloc.dylib         0x1e0e4 malloc_vreport + 908
4  libsystem_malloc.dylib         0x1e38c malloc_zone_error + 104
5  libsystem_malloc.dylib         0x18658 nanov2_guard_corruption_detected + 44
6  libsystem_malloc.dylib         0x16810 nanov2_free_definite_size + 402
7  libsystem_c.dylib              0xd9d4 __Balloc_D2A + 244
8  libsystem_c.dylib              0x12b60 __d2b_D2A + 56
9  libsystem_c.dylib              0x10e10 __dtoa + 236
10 libsystem_c.dylib              0x2b54 __vfprintf + 2500
11 libsystem_c.dylib              0x1f74 _vsnprintf + 224
12 libsystem_c.dylib              0xa954 __sprintf_chk + 60
13 CrashReporter                  0x4d4ec json_addFloatingPointElement + 80
14 CrashReporter                  0x43c44 saveState + 192
15 CrashReporter                  0x440d8 crashstate_notifyAppCrash + 56
16 CrashReporter                  0x403f0 onCrash + 52
17 CrashReporter                  0x43924 cm_handleException + 148
18 CrashReporter                  0x454c4 handleExceptions + 708
19 libsystem_pthread.dylib        0x16b8 *pthread*start + 148
20 libsystem_pthread.dylib        0xb88 thread_start + 8