ParseCore — Análisis de Cobertura de Fuzzing
Campaña: semanas 1–3  ·  Generado: 2026-06-16  ·  CULTIVA IA / Seguridad
libFuzzer AFL++ cargo-fuzz 2 Bloqueadores

Estado de la campaña

📦
Corpus
generado
🔨
Build con
instrumentación
Ejecución
corpus
📊
Análisis
cobertura ←
🔍
Identificar
bloqueadores
📖
Diccionarios
/ seeds
🔄
Siguiente
campaña

Resumen ejecutivo

Cobertura SUT C++ (líneas)
61.4%
Campaña 1→2: +8.3 pp
Cobertura SUT Rust (líneas)
34.2%
Plateau detectado — sin avance
Casos en corpus total
15.847
libFuzzer 12.341 + AFL++ 3.506
Magic values detectados
2
Bloquean ~22% del código C++

Cobertura por archivo — C++ (libFuzzer + LLVM)

Método: Compilación con -fprofile-instr-generate -fcoverage-mapping, ejecución sobre corpus completo, procesado con llvm-profdata merge + llvm-cov report. Harness excluido con -ignore-filename-regex='harness.cc|execute-rt.cc'.
src/parser_core.cc C++ 63.7%
617 / 968 líneas·342 / 512 ramas·89 / 121 funciones
src/format_handlers/json_handler.cc C++ 82.1%
329 / 401 líneas·198 / 234 ramas·41 / 48 funciones
src/format_handlers/xml_handler.cc C++ 55.3%
214 / 387 líneas·102 / 201 ramas·28 / 52 funciones
src/format_handlers/pdf_handler.cc C++ 29.4%
98 / 333 líneas·41 / 187 ramas·11 / 37 funciones
src/format_handlers/csv_handler.cc C++ 91.8%
179 / 195 líneas·88 / 97 ramas·22 / 24 funciones
src/validators/schema_validator.cc C++ 48.6%
171 / 352 líneas·87 / 198 ramas·19 / 41 funciones

Cobertura diferencial — Campaña 1 vs Campaña 2

Evolución por módulo (líneas %)
parser_core.cc
55.1% 63.7% ▲ +8.6 pp
json_handler.cc
76.4% 82.1% ▲ +5.7 pp
xml_handler.cc
54.8% 55.3% ▲ +0.5 pp
pdf_handler.cc
29.4% 29.4% — plateau
csv_handler.cc
88.2% 91.8% ▲ +3.6 pp
schema_validator.cc
51.0% 48.6% ▼ −2.4 pp
Diagnóstico de tendencias
xml_handler.cc
Plateau — magic value sospechado
pdf_handler.cc
Plateau — magic header 0x25504446
schema_validator.cc
Regresión — cambio en harness excluye paths
json_handler.cc
Buen progreso — seeds JSON bien formados
csv_handler.cc
Casi saturado — 92%, rendimiento decreciente
Campaña 1 usaba cobertura de libFuzzer runtime (47%) — infla harness. Cobertura real SUT con llvm-cov: 53.1% → 61.4%.

Bloqueadores detectados — Magic Values

🚫
Magic Header PDF — 0x25504446 ("%PDF")
src/format_handlers/pdf_handler.cc · líneas 87–95 · NUNCA ejecutadas
CRÍTICO
85 bool PDFHandler::parse(const uint8_t *buf, size_t sz) { 86 if (sz < 4) return false; 87 uint32_t magic = *(uint32_t*)buf; // 0 executions 88 if (magic != 0x25504446) return false; // BLOQUEA todo el módulo PDF 89 return parseHeader(buf + 4, sz - 4); 90 }
Solución: Añadir entrada al diccionario de fuzzing: "\x25\x50\x44\x46" (bytes de "%PDF"). Seed mínimo: 4 bytes con el magic.
Magic Namespace XML — string literal "PCORE_DOC_V2"
src/format_handlers/xml_handler.cc · líneas 143–151 · 0 ejecuciones
MODERADO
141 XmlDoc* XmlHandler::validateNamespace(const char *ns) { 142 std::string input(ns); 143 if (input.substr(0,12) != "PCORE_DOC_V2") { // 0 hits 144 throw InvalidNamespace("Expected PCORE_DOC_V2"); 145 } 146 return parseXmlDoc(ns + 12); 147 }
Solución: Añadir "PCORE_DOC_V2" al diccionario. Considerar seed XML con xmlns correcto para desbloquear parsing completo.

Cobertura Rust — cargo-fuzz · fuzz_json_validator

src/lib.rs Rust PLATEAU
Cobertura líneas 34.2%
412 / 1.204 líneas·187 / 608 ramas·38 / 97 funciones
Módulos cubiertos:
json::parser61%
json::validator18%
schema::loader12%
error::reporter78%
Diagnóstico y acciones Rust
Causa del plateau:
El harness solo invoca json::parser::from_bytes(). El módulo json::validator requiere schema pre-cargado via schema::loader::load_file() que el harness no inicializa. 82% del código de validación inaccesible.
Comando de cobertura usado: cargo +nightly fuzz coverage fuzz_json_validator
Acción recomendada:
Reescribir harness para inicializar schema embebido antes de llamar al validator. Ver patrón "lazy_static! schema" en Rust.

Anti-patrones detectados en esta campaña

Anti-patrón ¿Presente? Impacto Acción correctiva
Usar cobertura reportada por libFuzzer (runtime 47%) para comparaciones SI — Campaña 1 Inflaba cobertura en ~6 pp con código de harness Migrado a llvm-cov con -ignore-filename-regex
No filtrar harness de reportes SI — Campaña 1 harness.cc y execute-rt.cc sumaban cobertura artificial Corregido en campaña 2
Ignorar inputs que crashean al generar cobertura NO execute-rt.cc implementa fork()
No rastrear cobertura a lo largo del tiempo SI Sin baseline de campaña 1 no se detecta regresión schema_validator Archivar .profdata con timestamp en CI
Mezclar instrumentación LLVM y GCC NO Solo LLVM/clang en todos los targets
Harness Rust sin inicializar dependencias necesarias SI — fuzz_json_validator Bloquea 66% del código Rust — causa del plateau Reescribir harness con schema embebido

Recomendaciones priorizadas

1
Añadir magic values al diccionario de PDF y XML
ALTA
Los dos bloqueadores detectados impiden que el fuzzer explore el 29% restante de pdf_handler y el 45% de xml_handler. Impacto inmediato alto.
# pdf.dict "\x25\x50\x44\x46" # xml.dict "PCORE_DOC_V2"
2
Reescribir harness Rust fuzz_json_validator con schema embebido
ALTA
El módulo json::validator (18% cobertura) requiere schema pre-cargado. Sin él, el fuzzer nunca alcanza la lógica de validación real.
// harness.rs — añadir antes de fuzz loop let schema = Schema::from_bytes(include_bytes!("../fixtures/base.schema.json"))?;
3
Investigar regresión en schema_validator.cc (−2.4 pp)
MEDIA
La cobertura bajó de 51% a 48.6% en campaña 2. Revisar si un cambio en el harness eliminó paths de validación. Comparar .profdata con diff.
llvm-cov show ./fuzz_exec -instr-profile=campaign2.profdata \ -instr-profile=campaign1.profdata -show-line-counts-or-regions \ src/validators/schema_validator.cc
4
Automatizar cobertura en CI tras cada campaña nocturna
MEDIA
Archivar .profdata con timestamp, generar reporte HTML y publicar en dashboard interno. Detectar regresiones automáticamente.
llvm-profdata merge -sparse fuzz.profraw -o coverage-$(date +%Y%m%d).profdata
5
Crear seeds PDF mínimos válidos para pdf_handler
BAJA
CSV alcanzó 92% con buenos seeds estructurados. Aplicar misma estrategia a PDF: corpus de PDFs mínimos válidos (~100 casos) para desbloquear 70%+ restante.
# Seed mínimo PDF: 4 bytes magic + header básico printf '\x25\x50\x44\x46-1.4\n' > corpus/seed_minimal.pdf