Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

An infinite loop found in cJSON_DeleteItemFromObjectCaseSensitive #807

Open
PromptFuzz opened this issue Dec 6, 2023 · 2 comments
Open

Comments

@PromptFuzz
Copy link

Hi,
when fuzzing cJSON, there is a timeout reported by ASAN. There might is an infinite loop bug in cJSON_DeleteItemFromObjectCaseSensitive.

==617073== ERROR: libFuzzer: timeout after 241 seconds
    #0 0x5583f5cf2a41 in __sanitizer_print_stack_trace /work/llvm/llvm-project/compiler-rt/lib/asan/asan_stack.cpp:87:3
    #1 0x5583f5c0c808 in fuzzer::PrintStackTrace() /work/llvm/llvm-project/compiler-rt/lib/fuzzer/FuzzerUtil.cpp:210:5
    #2 0x5583f5befcd9 in fuzzer::Fuzzer::AlarmCallback() /work/llvm/llvm-project/compiler-rt/lib/fuzzer/FuzzerLoop.cpp:301:5
    #3 0x7fd7e37c041f  (/lib/x86_64-linux-gnu/libpthread.so.0 0x1441f) (BuildId: 7b4536f41cdaa5888408e82d0836e33dcf436466)
    #4 0x5583f5c7b995 in __interceptor_strcmp /work/llvm/llvm-project/compiler-rt/lib/asan/../sanitizer_common/sanitizer_common_interceptors.inc:527
    #5 0x5583f5d74174 in get_object_item cjson/src/cjson/cJSON.c:1892:83
    #6 0x5583f5d7809c in cJSON_GetObjectItemCaseSensitive /cjson/src/cjson/cJSON.c:1919:12
    #7 0x5583f5d7809c in cJSON_DetachItemFromObjectCaseSensitive /cjson/src/cjson/cJSON.c:2247:24
    #8 0x5583f5d7809c in cJSON_DeleteItemFromObjectCaseSensitive /cjson/src/cjson/cJSON.c:2259:18

My environment:
CentOS 5.4

PoC:
poc.tar.gz

@daschfg
Copy link

daschfg commented Dec 6, 2023

Interesting find.
Basically, whats causing the infinite loop here is a circular reference after adding the same item twice.

I boiled the POC down a bit:

cJSON* root = cJSON_CreateObject();
cJSON* item = cJSON_CreateNumber(42);

cJSON_AddItemToObject(root, "item1", item);
cJSON_AddItemToObject(root, "item2", item);  // Circular reference is created here

cJSON_Print(root);                           // This will enter an infinite loop

Specifically, the circular reference is created in suffix_object, which is called with prev and item being equal.
(https://github.com/DaveGamble/cJSON/blob/cb8693b058ba302f4829ec6d03f609ac6f848546/cJSON.c#L1928C13-L1928C19)

But aside from this analysis, I'm not sure what the best course of action on this would be.

@PeterAlfredLee
Copy link
Contributor

Adding the same item to object for more than one time is a broken use of cJSON_AddItemToObject. Simply doing same pointer check in suffix_object will not help much. POC to a similar problem:

    cJSON* root = cJSON_CreateObject();
    cJSON* item1 = cJSON_CreateNumber(42);
    cJSON* item2 = cJSON_CreateNumber(42);

    cJSON_AddItemToObject(root, "item1", item1);
    cJSON_AddItemToObject(root, "item2", item2);
    cJSON_AddItemToObject(root, "item3", item1); // circular reference

    cJSON_Print(root);

To prevent this, we need to check all items in a object/array if the added item already exist when adding a item to a object/array. No doubt this will cause performance problems.

I can't find a elegant enough solution. Ideas?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants