Hacktoberfest 2026: những issue maintainer đã đánh dấu cho tháng Mười, đang mở và phù hợp người mới. Xem issue Hacktoberfest

[cJSON_Utils] decode_pointer_inplace off-by-one causes incorrect decoding of "~1" (JSON Pointer)

Đang mở
#977 0 bình luận 0 reaction 0 người được giao Xem trên GitHub

Chưa có ai nhận issue này.

Đánh giá

Độ khó
2/5
Thời gian dự kiến
1-3 giờ
Mức phù hợp với người mới
55/100
Loại issue
Lỗi
Độ rõ ràng
Đặc tả rõ ràng
Mức độ hoạt động
Đình trệ
Công nghệ
c
Lĩnh vực
backend

Hướng nghiên cứu

Bắt đầu trong cJSON_Utils.c, tại decode_pointer_inplace(), khoảng dòng 370, và so sánh cách xử lý 1 của nó với bản tái hiện được cung cấp. Biên dịch và chạy poc_decode_pointer.c bằng lệnh gcc được ghi trong tài liệu, sau đó xác minh rằng việc áp dụng /a1b cập nhật khóa "a/b" hiện có thành 2 mà không tạo "a~/".

Do mô hình lập chỉ mục viết ra từ nội dung của issue.

Mô tả

Description

decode_pointer_inplace() (used by JSON Patch helpers) writes decoded slashes to decoded_string[1] instead of the current output slot. As a result, pointers containing ~1 are decoded incorrectly during patch application—values are written under mutated object keys like "a~/" instead of the intended "a/b". The function reports success even though it corrupted the object.

Reproduction steps
  1. Clone cJSON (current master).
  2. Drop the PoC below into poc_decode_pointer.c at repo root.
  3. Build and run:
    cd cJSON
    gcc -std=c99 -Wall -Wextra poc_decode_pointer.c cJSON.c cJSON_Utils.c -o poc_decode_pointer
    ./poc_decode_pointer
    
PoC source
#include <stdio.h>
#include <stdlib.h>

#include "cJSON.h"
#include "cJSON_Utils.h"

static void print_json(const char *label, cJSON *item)
{
    char *rendered = cJSON_PrintUnformatted(item);
    if (rendered == NULL)
    {
        fprintf(stderr, "%s: <print error>\n", label);
        return;
    }

    printf("%s: %s\n", label, rendered);
    cJSON_free(rendered);
}

int main(void)
{
    const char *document_text = "{\"a/b\":1}";
    const char *patch_text = "[{\"op\":\"add\",\"path\":\"/a~1b\",\"value\":2}]";
    cJSON *document = NULL;
    cJSON *patches = NULL;
    cJSON *value = NULL;
    int status = 0;

    document = cJSON_Parse(document_text);
    patches = cJSON_Parse(patch_text);
    if ((document == NULL) || (patches == NULL))
    {
        fprintf(stderr, "failed to parse JSON input\n");
        goto cleanup;
    }

    print_json("Original document", document);
    print_json("Patch", patches);

    status = cJSONUtils_ApplyPatches(document, patches);
    printf("cJSONUtils_ApplyPatches returned %d\n", status);

    print_json("Document after patch", document);

    value = cJSON_GetObjectItemCaseSensitive(document, "a/b");
    if (value != NULL)
    {
        printf("a/b = %d\n", value->valueint);
    }
    else
    {
        printf("a/b key is missing!\n");
    }

    value = cJSON_GetObjectItemCaseSensitive(document, "a~/");
    if (value != NULL)
    {
        printf("Corrupted key a~/ = %d\n", value->valueint);
    }

cleanup:
    if (document != NULL)
    {
        cJSON_Delete(document);
    }
    if (patches != NULL)
    {
        cJSON_Delete(patches);
    }

    return status;
}
PoC Output
zc@docker:~/cJSON$ ./poc_decode_pointer 
Original document: {"a/b":1}
Patch: [{"op":"add","path":"/a~1b","value":2}]
cJSONUtils_ApplyPatches returned 0
Document after patch: {"a/b":1,"a~/":2}
a/b = 1
Corrupted key a~/ = 2
Expected vs. actual results
  • Expected: Applying the patch that targets /a~1b updates key "a/b" to 2.
  • Actual: cJSONUtils_ApplyPatches returns success but leaves "a/b" unchanged and inserts a new key "a~/" with value 2, proving the decoded pointer got corrupted.
Suggested fix

In decode_pointer_inplace() (around line 370), write the decoded slash to decoded_string[0] and ensure the output pointer only advances once per decoded character:

diff --git a/cJSON_Utils.c b/cJSON_Utils.c
index 8fa24f8..8a3d881 100644
--- a/cJSON_Utils.c
+++ b/cJSON_Utils.c
@@ -374,7 +374,7 @@ static void decode_pointer_inplace(unsigned char
*string)
             }
             else if (string[1] == '1')
             {
-                decoded_string[1] = '/';
+                decoded_string[0] = '/';
             }
             else
             {
@@ -383,7 +383,10 @@ static void decode_pointer_inplace(unsigned char
*string)
             }

             string++;
+            continue;
         }
+
+        decoded_string[0] = string[0];
     }

     decoded_string[0] = '\0';

This change keeps the decoded pointer aligned with the output buffer so /a~1b resolves to "a/b" during JSON Patch operations.

Output after fix
zc@docker:~/cJSON$ ./poc_decode_pointer 
Original document: {"a/b":1}
Patch: [{"op":"add","path":"/a~1b","value":2}]
cJSONUtils_ApplyPatches returned 0
Document after patch: {"a/b":2}
a/b = 2
Ngôn ngữ chính
C
Star
13k
Fork
3.5k
Chỉ số merge pull request
Không có pull request nào được merge trong 30 ngày

Chuẩn bị môi trường

Bắt đầu từ đâu

  1. Đọc hết issue, rồi đọc hướng dẫn đóng góp của dự án.
  2. Bình luận trên issue rằng bạn sẽ nhận — tránh hai người làm cùng một việc.
  3. Fork repository và làm thay đổi trên một nhánh.
  4. Mở pull request có tham chiếu số hiệu của issue.

Issue khác của DaveGamble/cJSON

Tất cả issue của DaveGamble/cJSON

Issue tương tự

Thêm issue về C

Nhận issue mới trong hộp thư của bạn

Bản tóm tắt ngắn những issue GitHub phù hợp với người mới.