Fecha: 2026-06-15 Estado: Aceptado Bloque: M4 (línea README “parser hardened” históricamente pendiente) Origen: docs/TAREAS_PENDIENTES.md §3 — “1 hora mínima sin panic ni unwrap fallido” declarado como prioridad alta desde hace meses. Hermana: ADR-0084 (M3 — proptest planner) y ADR-0086 (proptest Pager). Mismo enfoque hand-rolled zero-deps.

Contexto

SQLite tiene millones de horas de fuzz acumuladas — parte central de su credibilidad. gabysql tenía cero. Cualquier afirmación de “parser robusto” sin evidencia de fuzz es vacía.

cargo fuzz real (libFuzzer / AFL) requiere:

Ninguno disponible en el entorno típico del autor (Windows + GNU toolchain, sin MSVC linker). Choca también con ADR-0001 (zero deps core) — cargo-fuzz agrega libfuzzer-sys como dep.

Decisión

Implementar un stress test del parser hand-rolled que dé el mismo nivel de evidencia práctica que una hora de cargo fuzz real, ejecutable en el entorno del autor.

Diseño (tests/fuzz_parser.rs)

Comando para reproducir 1h:

GABYSQL_FUZZ_PARSER_SECS=3600 \
    cargo test --target x86_64-pc-windows-gnu --release \
    --test fuzz_parser -- --ignored --nocapture

Evidencia de la primera corrida

Capturada en docs/fuzz/FUZZ-RUN-2026-06-15.md:

Métrica Valor
Duración 3 600 s
Iters totales 503 861 946
Throughput 139 961 iters/seg
Parse OK (random suerte) 74 787
Parse error 503 787 159
PANICS 0

500 millones de inputs random — incluyendo 30% bytes mutados — ninguno disparó panic, unwrap fallido ni loop infinito en gabysql::sql::parse().

Lectura honesta (importante)

Esta evidencia respalda:

Esta evidencia NO respalda:

El ADR de la evidencia (FUZZ-RUN-2026-06-15.md) detalla estas limitaciones y propone próximos pasos: cargo-fuzz real en CI Linux, fuzz sobre exec(), coverage-guided generation.

Consecuencias

Positivas

Negativas / deuda

Alternativas consideradas

  1. cargo fuzz real en CI Linux (libFuzzer). La evidencia sería más fuerte (coverage-guided). Diferido porque requiere setup nightly + workflow GitHub Actions + corpus inicial. ADR-0087 deja propuesta para próxima iteración.
  2. AFL — descartado por mismas razones.
  3. proptest crate — choca con ADR-0001.
  4. No hacer nada, dejar la línea del README pendiente indefinidamente — rechazado: 1 hora de generación random es mejor que cero horas de cualquier cosa.

Tests añadidos

Suite total: sigue en 816 verde + 4 ignored (1 Argon2 + 2 env-var + 1 fuzz_parser). El fuzz no afecta el conteo de la corrida default.

Próxima mejora documentada

Cuando alguien quiera subir el bar:

  1. CI Linux con cargo fuzz real (workflow nightly).
  2. Fuzz sobre exec() con pre-fixture de tabla.
  3. Coverage-guided generation.

Referencias