Buscar/Encontrar errores reales en parches de sistemas de bajo nivel, sin quejas de estilo

Encontrar errores reales en parches de sistemas de bajo nivel, sin quejas de estilo

Úsalo al revisar parches de sistemas de bajo nivel, como drivers o bibliotecas de red. Sigue la memoria, los locks y las rutas de error, revisa enteros, hilos, criptografía y cambios de API, e informa solo de fallos corregibles; el estilo, solo si está muy seguro.

Para usar estas reglas de IA
## Informar de posibles errores aun con dudas y del estilo solo con mucha seguridad Considera los defectos de corrección como los hallazgos más valiosos. Informa de un posible error de corrección cuando la confianza sea del 50 por ciento o más, e indica la incertidumbre si las pruebas están incompletas. Merece la pena señalar un posible acceso tras liberación, una fuga de recursos, una condición de carrera o una vulneración de límites, aunque se necesite confirmación adicional. Aplica un umbral diferente a los hallazgos de estilo, formato y proceso: - Informa de ellos únicamente cuando la confianza supere el 80 por ciento. - Omite todo aquello que finalmente juzgues correcto, aceptable o inofensivo. - Nunca plantees una preocupación para luego contradecirla en el mismo hallazgo. - Siempre que sea posible, limita cada comentario a una frase que indique una acción. Revisa cada parche por su propio comportamiento. No deduzcas de una diferencia aislada el orden de una serie de parches, las dependencias de compilación entre parches ni las circunstancias del colaborador. Dentro de una serie, omite los parches sin problemas en lugar de resumirlos como libres de incidencias. ## Seguir las reservas de memoria y las rutas de error en busca de fugas y usos indebidos Para cada asignación, descriptor abierto, bloqueo adquirido u objeto parcialmente inicializado, rastrea todas las ramas posteriores. Comprueba que los retornos anticipados y las etiquetas de limpieza mantengan una liberación equilibrada, el orden correcto y los códigos de error. Da prioridad a: - Accesos después de la liberación, liberaciones dobles, desreferencias nulas y lecturas alcanzables de datos sin inicializar. - Fugas de memoria, descriptores, conexiones de red, bloqueos o miembros construidos parcialmente. - Ausencia de comprobaciones de error en operaciones que realmente pueden fallar. - Valores de retorno incorrectos, estado de error descartado, condiciones invertidas y límites desplazados en una unidad. - Un valor sobrescrito incondicionalmente antes de su primera lectura. - Reutilización de un mismo contador de bucle en bucles anidados. - Acumulación de un contador que asigna una muestra en lugar de sumarla. Distingue los contadores incrementales de los medidores y de las asignaciones iniciales. No señales un retorno sin comprobar solo porque una función devuelve un entero cuando la plataforma compatible documenta que esa llamada no puede fallar con argumentos válidos. ## Comprobar anchos de enteros y tamaños de paquetes Revisa las operaciones aritméticas según la anchura de los operandos, no solo según la anchura del destino: - Ensancha al menos un operando antes de multiplicar cuando el resultado necesite un tipo más ancho. - Antes de desplazar hacia una máscara de bits ancha, utiliza un literal u operando tan ancho como el destino. - Ensancha los valores sin signo estrechos antes de un desplazamiento utilizado en aritmética de punteros o en un resultado ancho. - No modifiques los desplazamientos con resultado estrecho si cabe todo su intervalo y no interviene un contexto más ancho. - Limita cada recorrido de cadenas o índices controlado por entradas del sistema invitado, paquetes, dispositivos o la API. Respeta la propiedad al liberar lotes de objetos de paquetes o descriptores. Una operación masiva que presupone un único asignador o grupo de memoria no es segura para matrices cuyos elementos pueden proceder de distintos orígenes; utiliza una ruta de liberación que tenga en cuenta el grupo de memoria, salvo que el contrato de la ruta rápida demuestre una propiedad uniforme. Mantén el tamaño de la carga útil del protocolo separado del tamaño total de la trama. Calcula la sobrecarga del entramado a partir de las capacidades del dispositivo en vez de usar una constante universal y, tras la configuración, lee la configuración actual canónica en lugar de un campo de solicitud obsoleto. Cuando una trama no quepa en un solo búfer de recepción, la implementación debe habilitar una ruta multisegmento compatible o rechazar la configuración. Vuelve a comprobarlo durante la configuración inicial, la preparación de las colas y los cambios de tamaño en tiempo de ejecución, y selecciona la función de recepción a partir tanto del modo configurado como del requisito real de tamaño. ## Comprobar que los datos compartidos usan atómicos o locks, no volatile No aceptes `volatile` como sincronización entre hilos. El estado mutable compartido requiere operaciones atómicas o un bloqueo adecuado; `volatile` solo restringe los accesos del compilador y no aporta atomicidad ni orden de memoria. Elige el orden más débil que mantenga la corrección: - Orden relajado para estadísticas y marcas independientes que no publican datos relacionados. - Almacenamientos con liberación y cargas con adquisición para relaciones de publicación y consumo. - Orden de adquisición y liberación para operaciones de lectura, modificación y escritura que consumen y publican estado. - Consistencia secuencial únicamente cuando varias operaciones atómicas independientes necesiten un solo orden global. Prefiere especificar el orden en la operación atómica antes que usar una barrera independiente. Una barrera solo es adecuada cuando debe ordenar un grupo mayor de accesos no atómicos. Permite `volatile` para registros de hardware y otros accesos dirigidos realmente a dispositivos. En los mútex, las condiciones, las barreras o los bloqueos de lectura y escritura situados en memoria compartida entre procesos, exige una inicialización compartida entre procesos; no la exijas para memoria privada de un proceso. Prefiere primitivas de sincronización diseñadas para memoria compartida cuando su comportamiento de espera se ajuste al caso de uso. ## Revisar la criptografía solo si el parche maneja claves o secretos Aplica comprobaciones criptográficas únicamente cuando el parche gestione claves, valores de un solo uso, material de autenticación o código de protocolos de seguridad. - Compara las etiquetas de autenticación, resúmenes, MAC o valores de integridad influidos por un atacante mediante una primitiva de igualdad en tiempo constante. - Conserva la semántica de igualdad al sustituir una comparación ordinaria de bytes. - Borra las claves, las programaciones expandidas de claves, los secretos de sesión y materiales similares con una operación que no pueda eliminarse por optimización antes de liberarlos. - Genera claves, vectores de inicialización y valores de un solo uso mediante una fuente aleatoria criptográficamente segura. No señales las comparaciones ordinarias de identificadores de algoritmos, longitudes, capacidades o claves de búsqueda. No afirmes que se reutiliza un valor de un solo uso basándote en un parche estático cuando esa reutilización es una propiedad del tiempo de ejecución que la diferencia no puede demostrar. ## Mantener simple la API de la biblioteca y versionar los cambios de ABI incompatibles Diseña una biblioteca reutilizable como un servicio similar a un compilador: crea un identificador de acceso, proporciona la entrada, recibe una salida estructurada y deja que quien llama decida qué sucede después. Evita el estado de instancia única y las tablas de retrollamadas que obligan a quien llama a convertirse en el motor de la biblioteca. Para las retrollamadas públicas y los modelos de datos: - Prefiere un solo parámetro de retrollamada a una tabla de operaciones extensa. - Considera más de cinco retrollamadas como una advertencia para rediseñar y más de veinte como un error de diseño de la API. - Documenta la propiedad, la vida útil, los valores de retorno y el comportamiento ante fallos de las retrollamadas. - No utilices retrollamadas sin valor de retorno para operaciones que puedan fallar. - Prefiere registros etiquetados extensibles a una enumeración creciente combinada con una unión también creciente. Todo lo que se instale como cabecera forma parte de la API pública, con independencia de su etiqueta. Explicita la propiedad y la vida útil de los búferes, especialmente cuando se trate de almacenamiento estático interno. El código nuevo no debe introducir interfaces obsoletas. Para marcar una interfaz como obsoleta no deben quedar usuarios dentro del árbol, y se necesitan documentación de publicación, una ruta de migración y una anotación visible para el compilador. Coloca las anotaciones públicas, experimentales e internas exactamente donde las espere la cadena de herramientas, exporta los símbolos desde las definiciones del código fuente y utiliza el versionado de la ABI para cambios incompatibles en firmas estables. Nunca solicites editar manualmente los mapas de símbolos generados. ## Dejar el estilo mecánico a las herramientas y revisar lo que ellas no ven Deja que los formateadores, las herramientas de parches semánticos y los scripts de validación del repositorio se ocupen de las sustituciones mecánicas. Utiliza la revisión humana o mediante IA para los casos que esas herramientas no puedan comprender. Comprueba las reglas establecidas del proyecto sobre sangría, finales de línea, grupos de inclusiones, llaves, disposición de funciones, identificadores y prefijos de espacios de nombres. Exige prefijos únicos en los símbolos de bibliotecas o controladores visibles externamente para evitar colisiones en el enlace estático. Utiliza terminología inclusiva. Prefiere tipos booleanos reales para estados de verdadero o falso, pero conserva los enteros para códigos de error o valores con varios estados y evita cambios de tipo ajenos en código consolidado. Mantén constantes las tablas de despacho de funciones en tiempo de compilación, salvo que el registro en tiempo de ejecución o la detección de capacidades las modifiquen. Ajusta las primitivas de asignación y copia a la ruta de datos: - Utiliza una asignación ordinaria en el montón para los datos generales de control. - Utiliza una asignación visible para el dispositivo, consciente de NUMA e inicializada a cero para DMA, colas o datos entre procesos. - Utiliza la copia masiva optimizada solo cuando beneficie a la ruta rápida y se cumpla su contrato. Los comentarios deben explicar las restricciones y la intención, no repetir el código. ## Actualizar las pruebas y la documentación junto con cada cambio de código Cada confirmación de cambios debe poder compilarse de forma independiente, pero quien revise solo un parche no debe especular sobre el orden de la serie. Valida con los compiladores, destinos, opciones y scripts de compilación compatibles con el proyecto. Añade pruebas específicas para los comportamientos nuevos y las API públicas. Utiliza las aserciones de pruebas funcionales y el ejecutor de conjuntos del repositorio, registra con precisión los requisitos del entorno y proporciona al menos una implementación para cada API nueva dirigida a dispositivos. Actualiza el código y la documentación de forma atómica: - Documenta las API públicas y los cambios importantes visibles para el usuario. - Mantén las matrices de funcionalidades y la documentación de operaciones coherentes con la implementación. - Actualiza únicamente las notas de la versión actual para las API públicas, los controladores nuevos o los cambios de comportamiento significativos. - No exijas notas de versión para cambios limitados a pruebas o a la implementación interna. - Prefiere listas de definiciones en documentación estructurada cuando cada elemento sea un término acompañado de una descripción sustancial; conserva listas sencillas para elementos breves y procedimientos. Aplica el formateador del lenguaje de compilación y las reglas de ordenación que utilice el repositorio. Valida Python con el formateador y la política de longitud de línea designados. ## Aplicar las reglas de ramas estables solo cuando el destino sea estable Utiliza reglas estrictas de versiones estables únicamente cuando la rama o la versión de destino esté identificada expresamente como estable. En ese caso, permite solo correcciones de errores: ninguna funcionalidad nueva, API pública, modificación de la ABI, símbolo, opción de configuración ni refactorización ajena. Exige que una retroportación haga referencia a la corrección original y siga la convención de notificación de versiones estables del proyecto. Considera una limpieza extensa alrededor de una corrección pequeña como una advertencia, pues aumenta el riesgo de la retroportación. Si no se especifica ninguna versión, presupón que se trata de la rama principal de desarrollo, donde las funcionalidades y API nuevas pueden ser válidas. Nunca apliques prohibiciones exclusivas de versiones estables solo porque el repositorio también mantenga ramas estables. ## Dar arreglos concretos y repasar los hallazgos dos veces antes de enviar Clasifica como errores los defectos confirmados de seguridad de memoria, sincronización, límites, limpieza, criptografía, ABI y compilación. Utiliza advertencias para pruebas o documentación ausentes, una forma inadecuada de la API, incorporación de elementos obsoletos, uso incorrecto de la asignación y problemas de mantenibilidad con alta confianza. No informes de: - Omisiones en mapas generados, detalles de derechos de autor o formato de confirmaciones que ya sean responsabilidad de las herramientas de validación. - Usos correctos de `volatile` con hardware, bloqueos privados de un proceso, recepción multisegmento o macros de prueba actuales. - Peticiones vagas de verificar algo sin pruebas de que sea incorrecto. - Parches sin problemas, fallos especulativos entre parches u observaciones sin una medida correctiva. Para cada problema real, indica primero el problema, explica el impacto solo cuando no sea evidente y proporciona una corrección concreta o una orientación para el código. Antes de enviar el resultado, realiza dos revisiones separadas: 1. Revisión de corrección: recupera los hallazgos plausibles de corrección que se descartaron sin pruebas y confirma que se rastrearon las rutas de recursos, la vida útil, los límites y la propagación de errores. 2. Revisión de falsos positivos: elimina todos los elementos de estilo o proceso que el propio análisis consideró aceptables, correctos o inofensivos. Una lista de hallazgos vacía después de estas revisiones es válida. No inventes comentarios para rellenarla.