← All libraries
Parser · C
How to fuzz jq
jq processes untrusted JSON from the network — its query compiler is a hidden attack surface.
jq is ubiquitous in CI/CD pipelines and shell scripts that consume API responses, meaning it frequently processes untrusted JSON. Beyond the JSON parser, its filter compiler, bytecode interpreter, and recursive descent evaluator each represent distinct bug surfaces that coverage-guided fuzzing can map efficiently.
Common bug classes
- •Heap buffer overflow in filter lexer string escape handling
- •Stack overflow via mutually recursive jq function definitions
- •Use-after-free in backtracking path evaluator
- •Integer overflow in array index arithmetic on large inputs
- •Null dereference on missing object key in optional operator
Recommended setup
Fuzzers
- → AFL++
- → libFuzzer
Sanitizers
- → ASan
- → UBSan
Harness scaffold
#include <stdint.h>
#include <stddef.h>
#include <stdlib.h>
#include <string.h>
#include <jv.h>
#include <jq.h>
int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
jq_state *jq = jq_init();
if (!jq) return 0;
if (jq_compile(jq, ".")) {
jv input = jv_parse_sized((const char *)data, (int)size);
if (jv_is_valid(input)) {
jq_start(jq, input, 0);
jv result;
while (jv_is_valid(result = jq_next(jq)))
jv_free(result);
jv_free(result);
} else {
jv_free(input);
}
}
jq_teardown(&jq);
return 0;
}Save this as fuzz_target.cc, build with your compiler + sanitizer flags, and you have a working starting point.
Push the harness above + a Dockerfile. First month 50% off.