Lectura y escritura fuera de límites en qsort() de glibc

Una lectura y escritura fuera de límites recientemente identificada en `qsort()` de glibc aparece solo cuando los programas le pasan una función de comparación “mala”, como una que desborda al restar enteros o viola las reglas de ordenación con flotantes y NaN. Los comentaristas debaten si esto es realmente una vulnerabilidad de seguridad en glibc o simplemente comportamiento indefinido causado por código incorrecto del llamador, y si merece un CVE dada su rareza y dificultad de explotación. El hilo se amplía hacia una comparación de las culturas de seguridad en C/C++ frente a Rust y otros lenguajes, discutiendo cuánto deben defender las bibliotecas contra el uso indebido frente a preservar rendimiento y simplicidad.

Naturaleza del error de qsort

  • El error es una lectura/escritura fuera de límites en qsort de glibc cuando la llamada suministra una función de comparación no transitiva (con errores).
  • Muchos lo ven como “error del usuario” (parámetro inválido), análogo a llamar a memcpy con punteros incorrectos, pero aun así coinciden en que corregir las comprobaciones de límites es una buena práctica defensiva.
  • Otros subrayan que la implementación “obvia” del comparador (a - b) es sutilmente incorrecta debido al desbordamiento entero, así que esto no es puramente un caso extremo exótico.

“Lo estás usando mal” vs vulnerabilidad de seguridad

  • Un bando argumenta que esto es principalmente un error en el código de la aplicación, ya que los estándares exigen explícitamente un orden total; el comportamiento indefinido recae en quien llama.
  • Otro bando dice que, si un uso indebido común puede causar corrupción de memoria, eso es un problema legítimo de seguridad y merece un CVE para la implementación de la biblioteca también.
  • Hay críticas hacia la actitud de “como es UB, vale cualquier cosa” en la cultura de C/C++, en contraste con normas más defensivas en otros entornos.

Comparadores, NaN y coma flotante

  • Ordenar flotantes con NaN o infinitos mal gestionados puede violar los requisitos del comparador, provocando fallos o comportamientos incorrectos.
  • Los ejemplos muestran cómo los NaN rompen la reflexividad y la transitividad, confundiendo a los algoritmos de ordenación. Algunos sugieren que intentar ordenar NaN es, en sí mismo, normalmente un error lógico.

Culturas de seguridad del lenguaje y desbordamiento entero

  • Se cita Rust como ejemplo de tratar los casos de “lo estás usando mal” como problemas de seguridad: los comparadores defectuosos pueden dar resultados erróneos pero no UB; traits como Ord son seguros, con “unsafe traits” separados para invariantes que pueden causar UB si se rompen.
  • Discusión sobre el manejo del desbordamiento:
    • Operaciones comprobadas/saturadas/por envoltura en Rust y comportamiento de depuración frente a compilación de रिलीज़.
    • Desbordamiento con signo en C/C++ como UB; el wraparound sin signo a menudo no es lo que los programadores pretenden.
    • Ada, Pascal y WUFFS como ejemplos de lenguajes o DSL que codifican rangos/refinamientos para mayor seguridad.

Rendimiento y alternativas a qsort

  • qsort se describe como relativamente lento; para código de alto rendimiento se recomienda std::sort de C++ o bibliotecas especializadas, a veces mediante un envoltorio fino de C++ invocable desde C.
  • Algunos se preocupan por el coste de rendimiento de comprobaciones de seguridad adicionales; otros argumentan que el coste suele ser insignificante.

Explotabilidad, CVE y puntuación

  • Se debate la explotabilidad: requiere un comparador ya defectuoso y, a menudo, un contexto privilegiado (por ejemplo, setuid-root); en el hilo no se conocen explotaciones reales.
  • Hay opiniones encontradas sobre si debe emitirse un CVE:
    • A favor: anima a los usuarios a auditar comparadores y actualizar.
    • En contra: los CVE son costosos para entornos regulados y deberían reservarse para problemas claramente explotables.
  • Frustración más amplia con las puntuaciones CVSS: algunos errores graves y fácilmente explotables obtienen puntuaciones bajas, mientras que errores impracticables de tipo DoS reciben puntuaciones altas, dificultando la priorización.