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

fix insufficient check in cJSON_DetachItemViaPointer #722

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

hopper-vul
Copy link
Contributor

cJSON_DetachItemViaPointer() will crash if the detached item has field prev is null. The common suitation scenario is the detached item is created by cJSON_Create* APIs and directly pass it to cJSON_DetachItemViaPointer(object, item) call without adding item to object previously. Then the cJSON_DetachItemViaPointer() will crash because it does not check whether the passed item has valid prev field.

As detach a non-existent item is an undesirable behavior, instead of raising an uneasy core dump, this commit adds the NULL check of item->prev in cJSON_DetachItemViaPointer and return NULL to inform user such unexpect behavior (as user will routinely free/handle the detached resources later).

Signed-off-by: hopper-vul hopper.vul@gmail.com

cJSON_DetachItemViaPointer() will crash if the detached item has field `prev` is null.
The common suitation scenario is the detached item is created by cJSON_Create* APIs
and directly pass it to cJSON_DetachItemViaPointer(object, item) call without adding
item to object previously. Then the cJSON_DetachItemViaPointer() will crash because
it does not check whether the passed item has valid `prev` field.

As detach a non-existent item is an undesirable behavior, instead of raising an uneasy core dump,
this commit adds the NULL check of `item->prev` in cJSON_DetachItemViaPointer
and return NULL to inform user such unexpect behavior (as user will routinely free/handle the
detached resources later).

Signed-off-by: hopper-vul <hopper.vul@gmail.com>
@hopper-vul
Copy link
Contributor Author

The smallest case is

#include "cJSON.h"
  
int main(){
        cJSON *object = cJSON_CreateObject();
        cJSON *item = cJSON_CreateObject();
        cJSON *deatch = cJSON_DetachItemViaPointer(object, item); //core dump!
        if (deatch == NULL)
                cJSON_Delete(item);
        cJSON_Delete(object);
        return 0;
}

@hopper-vul
Copy link
Contributor Author

@Alanscut @FSMaxB Hi, could you please review this PR? I'm looking forward to your feedback.

Thanks.

@Alanscut
Copy link
Collaborator

Alanscut commented Jul 1, 2023

I think the null check of item-prev should be at the place it's visited.

Just think about this scenario:
When item == parent->child, it means item is the first child of parent. In this case, the item->prev is NULL cause it's the first item. In your implementation this will return NULL and it's not what we are expected.

@@ -2186,7 +2186,7 @@ CJSON_PUBLIC(cJSON*) cJSON_AddArrayToObject(cJSON * const object, const char * c

CJSON_PUBLIC(cJSON *) cJSON_DetachItemViaPointer(cJSON *parent, cJSON * const item)
{
if ((parent == NULL) || (item == NULL))
if ((parent == NULL) || (item == NULL) || (item->prev == NULL))
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I prefer adding this null check to the place where item->prev is used instead of here.
I mean:

    if (item != parent->child)
    {
        if (item->prev == NULL)
        {
            return NULL;
        }
        /* not the first element */
        item->prev->next = item->next;
    }

@MSQFIGHTING
Copy link

I think the null check of item-prev should be at the place it's visited.

Just think about this scenario: When item == parent->child, it means item is the first child of parent. In this case, the item->prev is NULL cause it's the first item. In your implementation this will return NULL and it's not what we are expected.
Hi, when i see the readme , i found that if "item == parent->child", the item->prev will be the last object of his parent object and the item->prev->next will be NULL

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

Successfully merging this pull request may close these issues.

3 participants