-
Notifications
You must be signed in to change notification settings - Fork 3.2k
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
Possibly serious bugs in add_item_to_array in 1.7.13 #499
Comments
I see that in 1.7.13 there is a changelog note, "Improve performance of adding item to array.". This seems to have been implemented by "abusing" the "prev" pointer in an attempt to turn the double-linked list into a circular buffer, creating an infinite loop on prev, and redefining the meaning of prev for cJSON_Array in the data structure documentation. That documentation has been static for many years and likely relied upon by many developers. For most of history:
New for 1.7.13:
You need to dereference what was previously a null pointer to test if you're at the start. This is IMO a really bad design choice. If it's important to provide fast access to the end of the double-linked list, why not add a new member to the cJSON structure that points to it, and maintain full backwards compatibility/semantics, as well as the normall expected behavior of a double-linked list? |
@SLDiggie Thanks your reporting, the reason why the tail node is not added in the cJSON struct is that we value space very much, as you said, which is not a good choice, as you said. I'll release a new version to fix these problems before the end of September. |
@Alanscut Just to be clear, I'm not only reporting the design issue, but the changes in cJSON 1.7.13 also seem to create the potential for use after free vulnerabilities (might be a crash and/or security issue), erroneous document output, and DOS (infinite loops). IMO you ought to be considering reverting some of these. I made a small sample function to help illustrate, hopefully that's useful to you. None of these problems happen against 1.7.12. `
} |
IMHO, we can improve efficiency safely in the current way, but I have to admit that this is not a conventional approach. Even if we change it to a full double linked list, the second problem you mentioned above still exists. So, would you prefer to add a node to cJSON struct to record the tail node? |
From 1.7.12 -> 1.7.13 this code was changed in add_item_to_array:
`
static cJSON_bool add_item_to_array(cJSON *array, cJSON *item)
{
cJSON *child = NULL;
}
`
->
`
static cJSON_bool add_item_to_array(cJSON *array, cJSON *item)
{
cJSON *child = NULL;
}
`
The new code seems very strange:
If array has no child, the old code assigns the new item as the child. The new code for some reason also sets the new item's prev pointer to point at itself. If prev is traversed, that is an infinite loop.
In the old code, to add a new item to the end of a child, the code follows the pointers chain to all the next child items, then adds the new item at the end. The new code seems to make two errors:
(1) Assuming child must be the first child item in array, if the new code sees a prev pointer on this first child it tries to add the new item to it, i.e. before the first child. You end up in a situation where you can't start at the first child and follow Next to the new element, you instead have to start at the first child then go Prev then go Next. A result of this is that code that traverses the pointers via Next doesn't see all of the values. For example, print() will not include them. We run into this bug when constructing an object tree with more than one item in the array with cJSON, only in 1.7.13.
(2) If child->prev is null it makes the old last item's prev point at the new item. The old last item's next ALSO points at the last item (due to suffix_object). Traversing prev for the last two items will now infinitely loop between the last two items.
These seem like serious issues, as you end up with potential infinite loops and values you expect missing from the output when you build a document tree with cJSON, even though no errors are returned.
The text was updated successfully, but these errors were encountered: