quickjs-tart

quickjs-based runtime for wallet-core logic
Log | Files | Refs | README | LICENSE

fuzz_json.c (4117B)


      1 // Copyright 2025 Google LLC
      2 // Fuzz target for QuickJS JSON operations
      3 
      4 #include "quickjs.h"
      5 #include "quickjs-libc.h"
      6 #include <stdint.h>
      7 #include <stdlib.h>
      8 #include <string.h>
      9 #include <stdio.h>
     10 
     11 int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
     12     if (size < 1) return 0;
     13     
     14     JSRuntime* rt = JS_NewRuntime();
     15     if (!rt) return 0;
     16     
     17     JSContext* ctx = JS_NewContext(rt);
     18     if (!ctx) {
     19         JS_FreeRuntime(rt);
     20         return 0;
     21     }
     22     
     23     char* input = malloc(size + 1);
     24     if (!input) {
     25         JS_FreeContext(ctx);
     26         JS_FreeRuntime(rt);
     27         return 0;
     28     }
     29     memcpy(input, data, size);
     30     input[size] = '\0';
     31     
     32     char parse_script[8192];
     33     snprintf(parse_script, sizeof(parse_script), 
     34              "JSON.parse(JSON.stringify(%s))", input);
     35     
     36     JSValue parse_result = JS_Eval(ctx, parse_script, strlen(parse_script), 
     37                                     "<json-fuzz>", 0);
     38     
     39     if (JS_IsException(parse_result)) {
     40         JS_GetException(ctx);
     41     } else {
     42         JS_FreeValue(ctx, parse_result);
     43     }
     44     
     45     char direct_parse[16384];
     46     snprintf(direct_parse, sizeof(direct_parse), "JSON.parse('");
     47     
     48     size_t script_len = strlen(direct_parse);
     49     for (size_t i = 0; i < size && script_len < sizeof(direct_parse) - 20; i++) {
     50         char c = input[i];
     51         if (c == '\\' || c == '\'') {
     52             direct_parse[script_len++] = '\\';
     53         }
     54         if (c >= 32 && c < 127) {
     55             direct_parse[script_len++] = c;
     56         }
     57     }
     58     strcat(direct_parse + script_len, "');");
     59     
     60     JSValue direct_result = JS_Eval(ctx, direct_parse, strlen(direct_parse), 
     61                                      "<json-direct>", 0);
     62     if (JS_IsException(direct_result)) {
     63         JS_GetException(ctx);
     64     } else {
     65         JS_FreeValue(ctx, direct_result);
     66     }
     67     
     68     char stringify_script[8192];
     69     snprintf(stringify_script, sizeof(stringify_script),
     70              "var obj = { data: %s, num: 123, str: 'test', bool: true, nullv: null, "
     71              "arr: [1,2,3], nested: { a: 1 } }; JSON.stringify(obj);",
     72              input);
     73     
     74     JSValue stringify_result = JS_Eval(ctx, stringify_script, 
     75                                         strlen(stringify_script), "<json-stringify>", 0);
     76     if (JS_IsException(stringify_result)) {
     77         JS_GetException(ctx);
     78     } else {
     79         const char* str = JS_ToCString(ctx, stringify_result);
     80         if (str) {
     81             JS_FreeCString(ctx, str);
     82         }
     83         JS_FreeValue(ctx, stringify_result);
     84     }
     85     
     86     const char* spacing_tests[] = {
     87         "JSON.stringify({a:1,b:2})",
     88         "JSON.stringify({a:1,b:2}, null, 2)",
     89         "JSON.stringify({a:1,b:2}, null, '  ')",
     90         "JSON.stringify([1,2,3])",
     91         "JSON.stringify(null)",
     92         "JSON.stringify(undefined)",
     93         "JSON.stringify(123)",
     94         "JSON.stringify('string')",
     95         "JSON.stringify(true)",
     96     };
     97     
     98     for (size_t i = 0; i < sizeof(spacing_tests) / sizeof(spacing_tests[0]); i++) {
     99         JSValue r = JS_Eval(ctx, spacing_tests[i], strlen(spacing_tests[i]), 
    100                             "<json-test>", 0);
    101         if (!JS_IsException(r)) {
    102             JS_FreeValue(ctx, r);
    103         } else {
    104             JS_GetException(ctx);
    105         }
    106     }
    107     
    108     const char* reviver_test = "JSON.parse('{\"a\":1,\"b\":2}', function(k,v) { return v; })";
    109     JSValue reviver_result = JS_Eval(ctx, reviver_test, strlen(reviver_test), 
    110                                        "<json-reviver>", 0);
    111     if (!JS_IsException(reviver_result)) {
    112         JS_FreeValue(ctx, reviver_result);
    113     } else {
    114         JS_GetException(ctx);
    115     }
    116     
    117     const char* replacer_test = "JSON.stringify({a:1,b:2}, function(k,v) { return v; })";
    118     JSValue replacer_result = JS_Eval(ctx, replacer_test, strlen(replacer_test),
    119                                        "<json-replacer>", 0);
    120     if (!JS_IsException(replacer_result)) {
    121         JS_FreeValue(ctx, replacer_result);
    122     } else {
    123         JS_GetException(ctx);
    124     }
    125     
    126     free(input);
    127     JS_FreeContext(ctx);
    128     JS_FreeRuntime(rt);
    129     
    130     return 0;
    131 }