From 2e0e8337833ad5433966fbc69b7a2d950e5f2a60 Mon Sep 17 00:00:00 2001 From: iliasabk <286468824+iliasabk@users.noreply.github.com> Date: Fri, 18 Sep 2026 02:43:33 +0200 Subject: [PATCH] replace_item_in_object: fix use-after-free when key aliases item name MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit cJSON_ReplaceItemInObject() freed replacement->string before duplicating the string argument. When the caller passes the item's own name as the key (e.g. moving an item between objects under the same name), cJSON_strdup() read the freed buffer. Duplicate the key into new_key first, then release the old name — same ordering fix as 22a7d04 applied to add_item_to_object(). Also use new_key for the object lookup, since the original pointer may dangle after the free. Fixes #1081 --- cJSON.c | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/cJSON.c b/cJSON.c index 88c2d95b..3f8b16d3 100644 --- a/cJSON.c +++ b/cJSON.c @@ -2426,25 +2426,30 @@ CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemInArray(cJSON *array, int which, cJSON static cJSON_bool replace_item_in_object(cJSON *object, const char *string, cJSON *replacement, cJSON_bool case_sensitive) { + char *new_key = NULL; + if ((replacement == NULL) || (string == NULL)) { return false; } + /* duplicate the key before freeing the old one: string may alias replacement->string */ + new_key = (char*)cJSON_strdup((const unsigned char*)string, &global_hooks); + if (new_key == NULL) + { + return false; + } + /* replace the name in the replacement */ if (!(replacement->type & cJSON_StringIsConst) && (replacement->string != NULL)) { cJSON_free(replacement->string); } - replacement->string = (char*)cJSON_strdup((const unsigned char*)string, &global_hooks); - if (replacement->string == NULL) - { - return false; - } + replacement->string = new_key; replacement->type &= ~cJSON_StringIsConst; - return cJSON_ReplaceItemViaPointer(object, get_object_item(object, string, case_sensitive), replacement); + return cJSON_ReplaceItemViaPointer(object, get_object_item(object, new_key, case_sensitive), replacement); } CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemInObject(cJSON *object, const char *string, cJSON *newitem)