Stack-overflow via deep JSON array nesting under ASan+-O0, below CJSON_NESTING_LIMIT
Nadie ha tomado este issue todavía.
Evaluación
- Dificultad
- 2/5
- Tiempo estimado
- 1-3 horas
- Aptitud para principiantes
- 68/100
- Tipo de issue
- Documentación
- Claridad
- Bastante claro
- Estado de actividad
- Activo
- Stack tecnológico
- c
- Área
- documentation
Línea de trabajo
Empieza en cJSON.c localizando CJSON_NESTING_LIMIT y la documentación o los comentarios existentes al respecto. Revisa el reproducer del sanitizer y los detalles de compilación reportados; después, documenta que la profundidad de anidamiento segura efectiva depende de la configuración de compilación, especialmente con -O0 y ASan; el trabajo estará hecho cuando la documentación del límite deje clara esta expectativa para quienes usan fuzzing y sanitizers.
Escrito por el modelo de indexación a partir del texto del issue.
Descripción
Summary
Under an ASan + -O0 build (the standard configuration for fuzzing/CI sanitizer runs), a deeply nested JSON array triggers a native stack overflow before CJSON_NESTING_LIMIT (1000) is ever reached, because the limit bounds the number of recursive parser calls but not the size of each call's stack frame, and ASan instrumentation plus disabled optimization inflate that frame size substantially.
This is not an exploitable issue in a normal optimized release build (verified below) — filing this as a robustness/documentation note, not a security report.
Repro
Minimized input: a JSON value consisting of 755 consecutive [ bytes, no closing brackets, no other content.
$ ./cjson_asan_o0 < deepnest_755.json
==PID==ERROR: AddressSanitizer: stack-overflow on address 0x...
<empty stack>
SUMMARY: AddressSanitizer: stack-overflow
(No symbolized backtrace — ASan's own crash-reporting code cannot run once the stack is this exhausted, which is typical for pure stack-overflow crashes as opposed to heap-buffer-overflow.)
Build used to reproduce: cJSON.c compiled with -O0 -fsanitize=address -g, default thread/process stack size (8 MiB on the Linux machine used here). Binary search found the exact boundary on that machine: 754 levels of [ is parsed/rejected cleanly (cJSON_ParseWithLength returns NULL), 755 crashes.
Why the existing limit does not catch it here
CJSON_NESTING_LIMIT counts recursive calls, not stack bytes consumed. Under -O0, every local gets its own stack slot (no register allocation), and ASan adds redzone padding around each stack allocation. The combined per-call frame size under this build is large enough that the process stack is exhausted well before the 1000-call counter would reject the input.
Confirms it is release-build-safe
The same inputs (780, 1000, 1500, 5000, 50000 levels of [) were tested against an identical harness built -O2, no sanitizers: all are rejected cleanly, exit code 0, no crash, in every case. The nesting limit does its job as documented in a normal build; the gap only appears under sanitizer instrumentation.
Suggested fix
Options, roughly in order of effort:
- Note in the
CJSON_NESTING_LIMITdocumentation that the effective safe depth is build-configuration-dependent (much lower under-O0/ASan/MSan than in an optimized release build), so people fuzzing or testing cJSON with sanitizers know a stack-overflow at a shallower depth than 1000 is expected, not a new bug. - Optionally lower the default limit, or make it configurable relative to a measured/available stack size, if protecting sanitizer/debug builds against this specific crash is a goal.
Happy to share the exact harness and inputs if useful. Reported by an independent fuzzing exercise, no CVE requested given the release-build behavior is correct.
- Lenguaje dominante
- C
- Estrellas
- 13k
- Forks
- 3.5k
- Métricas de merge de PR
- Sin PR fusionados en 30 d
Preparar el entorno
- Sin Dockerfile ni archivo de Docker Compose
- Sin plantilla de pull request
- Leer la guía de contribución
Primeros pasos
- Lee el issue completo y luego la guía de contribución del proyecto.
- Comenta en el issue que vas a ocuparte — evita que dos personas hagan lo mismo.
- Haz un fork del repositorio y trabaja en una rama.
- Abre un pull request que haga referencia al número del issue.
Más de DaveGamble/cJSON
-
Dificultad 2/5 1-3 horas Aptitud para principiantes 86/100
DaveGamble/cJSON#1094 ·
-
Dificultad 2/5 1-3 horas Aptitud para principiantes 82/100
DaveGamble/cJSON#1082 ·
-
Dificultad 2/5 1-3 horas Aptitud para principiantes 82/100
DaveGamble/cJSON#1081 ·
-
Dificultad 2/5 1-3 horas Aptitud para principiantes 78/100
DaveGamble/cJSON#1074 ·
-
Dificultad 2/5 1-3 horas Aptitud para principiantes 78/100
DaveGamble/cJSON#1071 ·
Todos los issues de DaveGamble/cJSON
Issues similares
-
Dificultad 2/5 1-3 horas Aptitud para principiantes 84/100
darktable-org/darktable#22455 · 1 comentario ·
Los mantenedores suelen responder en 1 día
-
area:ci kind:gate-defect
Dificultad 2/5 1-3 horas Aptitud para principiantes 84/100
InauguralSystems/EigenScript#1448 ·
Los mantenedores suelen responder en 1 día
-
Dificultad 2/5 1-3 horas Aptitud para principiantes 78/100
BasedHardware/omi#20084 ·
Los mantenedores suelen responder en 1 día
-
Dificultad 2/5 1-3 horas Aptitud para principiantes 64/100
raspberrypi/pico-sdk#3225 · 1 comentario ·
Los mantenedores suelen responder en 1 día
-
Dificultad 2/5 1-3 horas Aptitud para principiantes 78/100