Quizás todos los desarrolladores de software de microcontroladores han escuchado sobre estándares especiales de codificación para ayudar a mejorar la seguridad y portabilidad del código. Una de esas normas es MISRA. En este artículo, veremos más de cerca qué es este estándar, su concepto y cómo usarlo en sus proyectos.
Muchos de nuestros lectores han escuchado que PVS-Studio admite la clasificación de sus advertencias de acuerdo con el estándar MISRA. Por el momento, PVS-Studio
cubre más de 100 reglas MISRA C: 2012 y MISRA C ++: 2008.
Este artículo tiene como objetivo matar tres pájaros de un tiro:
- Indica qué es MISRA para aquellos que aún no están familiarizados con este estándar;
- Recordar al mundo del desarrollo integrado lo que podemos hacer;
- Ayude a los nuevos empleados de nuestra empresa, que también desarrollarán nuestro analizador MISRA en el futuro, a familiarizarse completamente con él.
Espero poder hacerlo interesante. ¡Entonces vamos!
La historia de misra
La historia de MISRA comenzó hace mucho tiempo. En aquel entonces, a principios de la década de 1990, el programa gubernamental "Safe IT" del Reino Unido proporcionó fondos para varios proyectos relacionados de alguna manera con la seguridad de los sistemas electrónicos. El proyecto MISRA (Asociación de Fiabilidad de Software de la Industria del Motor) se fundó para crear una guía para el desarrollo de software de microcontroladores en vehículos terrestres, principalmente en automóviles.
Tras recibir fondos del estado, el equipo de MISRA se hizo cargo del trabajo y, en noviembre de 1994, lanzó su primera guía: "
Directrices de desarrollo para software basado en vehículos ". Esta guía aún no se ha vinculado a un lenguaje específico, pero debo admitir que el trabajo se ha realizado de manera impresionante y se ha referido, probablemente, a todos los aspectos concebibles del desarrollo de software integrado. Por cierto, recientemente los desarrolladores de esta guía
han celebrado el 25 aniversario de una fecha tan importante para ellos.
Cuando terminaron los fondos del estado, los miembros de MISRA decidieron continuar trabajando juntos de manera informal, ya que continúa hasta nuestros días. En términos generales, MISRA (como organización) es una comunidad de partes interesadas de diversas industrias automotrices y aeronáuticas. Ahora estas fiestas son:
- Bentley automóviles
- Ford Motor Company
- Jaguar land rover
- Sistemas diésel de Delphi
- HORIBA MIRA
- Protean electric
- Servicios de ingeniería de Visteon
- La universidad de leeds
- Ricardo reino unido
- ZF TRW
Jugadores de mercado muy fuertes, ¿no? No es sorprendente que su primer estándar relacionado con el lenguaje, MISRA C, se haya convertido en un lugar común entre los desarrolladores de sistemas integrados críticos. Un poco más tarde, apareció MISRA C ++. Gradualmente, las versiones de los estándares se han actualizado y refinado para cubrir las nuevas características de los idiomas. Al momento de escribir este artículo, las versiones actuales son MISRA C: 2012 y MISRA C ++: 2008.
Concepto principal y ejemplos de reglas.
Las características más distintivas de MISRA son su increíble atención a los detalles y su meticulosidad extrema para garantizar la seguridad. Los autores no solo recopilaron todas las deficiencias de C y C ++ en un solo lugar (como, por ejemplo, los autores de CERT), sino que también elaboraron cuidadosamente los estándares internacionales de estos lenguajes y escribieron todas las formas de cometer un error. Después, agregaron reglas sobre la legibilidad del código para asegurar el código limpio contra un nuevo error.
Para comprender la escala de seriedad, veamos algunas reglas tomadas del estándar.
Por un lado, hay reglas decentes y valiosas que siempre deben seguirse, sin importar para qué sea su proyecto. En su mayor parte, están diseñados para eliminar el comportamiento indefinido / no especificado / definido por la implementación. Por ejemplo:
- No use el valor de una variable no inicializada
- No use el puntero para ARCHIVAR después de que se cierre la transmisión
- Todas las funciones no nulas deben devolver un valor.
- Los contadores de bucle no deben ser del tipo de punto flotante
- y otros
Por otro lado, hay reglas, cuyos beneficios no son difíciles de entender, pero que (desde el punto de vista de los proyectos ordinarios) se pueden violar ocasionalmente:
- No uses goto y longjmp
- Cada cambio debe terminar con la etiqueta predeterminada
- No escriba código inalcanzable
- No uses funciones variadas
- No use aritmética de direcciones (excepto [] y ++ )
- ...
Tales reglas tampoco son malas, y combinadas con las anteriores, ya dan un aumento tangible a la seguridad, pero ¿es esto suficiente para sistemas integrados altamente confiables? Se utilizan no solo en la industria automotriz, sino también en las industrias de aviación, aeroespacial, militar y medicina.
No queremos que ninguna máquina de rayos X
irradie pacientes con una dosis de 20,000 rads debido a un error de software, por lo que las reglas habituales "cotidianas" no son suficientes. Con vidas humanas y mucho dinero en juego, la meticulosidad es indispensable. Aquí es donde entran en juego el resto de las reglas de MISRA:
- El sufijo 'L' en el literal siempre debe ser mayúscula (la letra minúscula 'l' se puede confundir con 1)
- No use el operador "coma" (aumenta la posibilidad de cometer un error)
- No use la recursividad (una pila pequeña de microcontroladores puede desbordarse fácilmente)
- Los cuerpos de las declaraciones si , de lo contrario , para , while , do , switch deben estar entre paréntesis (potencialmente puede cometer un error cuando el código está alineado incorrectamente )
- No use memoria dinámica (porque existe la posibilidad de no liberarla del montón, especialmente en microcontroladores)
- ... y muchas, muchas de estas reglas.
A menudo sucede que las personas que se encuentran por primera vez con MISRA tienen la impresión de que el propósito de la norma es "prohibir esto y prohibir aquello". De hecho, es así, pero solo hasta cierto punto.
Por un lado, el estándar tiene muchas de esas reglas, pero no está destinado a prohibirlo todo, pero por otro lado, enumera todas las formas de violar la seguridad del código. Para la mayoría de las reglas, usted elige si necesita seguirlas o no. Explicaré este caso con más detalle.
En MISRA C, las reglas se dividen en tres categorías principales: obligatorio, obligatorio y consultivo. Son obligatorias las reglas que no se pueden romper bajo ningún pretexto. Por ejemplo, esta sección incluye la regla: "no use el valor de una variable no iniciada". Las reglas requeridas son menos estrictas: permiten la posibilidad de rechazo, pero solo si estas desviaciones se documentan cuidadosamente y se justifican por escrito. El resto de las reglas entran en la categoría de Asesoría, que no son obligatorias.
MISRA C ++ tiene algunas diferencias: no hay una categoría obligatoria, y la mayoría de las reglas pertenecen a la categoría requerida. Por lo tanto, de hecho, tiene derecho a romper cualquier regla, simplemente no olvide comentar todas las desviaciones. También existe la categoría Documento: estas son reglas obligatorias (no se permiten desviaciones) relacionadas con prácticas generales como "Cada uso del ensamblador debe estar documentado" o "Una biblioteca incluida debe cumplir con MISRA C ++".
Otros asuntos
De hecho, MISRA no se trata solo de un conjunto de reglas. De hecho, es una guía para escribir código seguro para microcontroladores, por lo que está lleno de cosas buenas. Echemos un vistazo en profundidad a ellos.
En primer lugar, el estándar contiene una descripción bastante completa de la historia de fondo: por qué se creó el estándar, por qué se eligió C o C ++, los pros y los contras de estos lenguajes.
Todos conocemos muy bien los méritos de estos idiomas. Así como también somos conscientes de sus deficiencias :) Alto nivel de complejidad, especificación estándar incompleta y sintaxis que permiten cometer fácilmente un error y luego buscarlo durante siglos, todo esto no puede dejar de mencionarse. Por ejemplo, podría escribir esto accidentalmente:
for (int i = 0; i < n; ++i); { do_something(); }
Después de todo, existe la posibilidad de que una persona no note
un punto y
coma extra , ¿verdad? Otra opción es escribir el código de la
siguiente manera :
void SpendTime(bool doWantToKillPeople) { if (doWantToKillPeople = true) { StartNuclearWar(); } else { PlayComputerGames(); } }
Es bueno que tanto el
primer como el
segundo caso puedan ser fácilmente detectados por las reglas MISRA (1 - MISRA C: 13.4 / MISRA C ++: 6.2.1; 2 - MISRA C: 13.4 / MISRA C ++: 6.2.1).
El estándar contiene una descripción de los problemas y consejos sobre lo que uno debe saber antes de asumir una tarea determinada: cómo configurar el proceso de desarrollo de acuerdo con MISRA; cómo usar analizadores estáticos para verificar el cumplimiento del código; qué documentos hay que mantener, cómo completarlos, etc.
Los apéndices al final también incluyen: una breve lista y un resumen de las reglas, una pequeña lista de vulnerabilidades de C / C ++, un ejemplo de documentación de desviación de reglas y algunas listas de verificación que ayudan a resolver toda esta burocracia.
Como puede ver, MISRA no es solo un conjunto de reglas, sino casi una infraestructura completa para escribir código seguro para sistemas integrados.
Uso en tus proyectos
Imagina la escena: vas a escribir un programa para un sistema incrustado tan necesario y responsable. O ya tiene un programa, pero necesita "portarlo" a MISRA. Entonces, ¿cómo verifica que su código cumpla con el estándar? ¿Realmente tienes que hacerlo manualmente?
La verificación manual del código es una tarea incómoda e incluso potencialmente imposible. No solo cada revisor tiene que examinar cuidadosamente cada línea de código, sino que también se debe conocer el estándar casi de memoria. Loco
Por lo tanto, los propios desarrolladores de MISRA recomiendan el uso de análisis estático para probar su código. Después de todo, de hecho, el análisis estático es un proceso automatizado de revisión de código. Simplemente ejecute el analizador en su programa y, en unos minutos, obtendrá un informe de posibles violaciones del estándar. Eso es lo que necesitas, ¿no? Todo lo que tiene que hacer es revisar el registro y corregir las advertencias.
La siguiente pregunta es: ¿en qué punto debemos comenzar a usar MISRA? La respuesta es simple: cuanto antes mejor. Idealmente, antes de comenzar a escribir código, porque MISRA asume que sigue el estándar para todo el ciclo de vida de su código.
Bueno, no siempre es posible escribir de acuerdo con MISRA desde el principio. Por ejemplo, a menudo ocurre que el proyecto ya se ha implementado parcial o completamente, pero luego el cliente quería que el proyecto cumpliera con el estándar. En este caso, tendrá que lidiar con una refactorización exhaustiva del código existente.
Ahí es donde surge la trampa. Incluso diría que aparece una roca submarina. ¿Qué sucede si toma un analizador estático y verifica el proyecto "ordinario" para cumplir con el estándar MISRA? Spoiler: puede que tengas miedo.
Correcto, el ejemplo en la imagen es exagerado. Muestra el resultado de verificar un proyecto bastante grande que en realidad no estaba destinado a trabajar en microcontroladores. Sin embargo, al verificar el código ya existente, es posible que reciba una, dos, tres o incluso diez mil advertencias del analizador. Las nuevas advertencias, emitidas para código nuevo o modificado, simplemente se perderán en este gran grupo de advertencias.
Entonces, ¿qué puedes hacer al respecto? ¿Realmente tiene que posponer todas las tareas y hacer todo lo posible para arreglar viejas advertencias?
Como desarrolladores del analizador estático, sabemos que aparecen muchas advertencias después de la verificación. Por lo tanto, desarrollamos la solución, que puede ayudar a utilizar el analizador de inmediato sin detener el trabajo. Esta solución se llama "suprimir base".
Las bases de supresión representan el mecanismo PVS-Studio que le permite suprimir masivamente los mensajes del analizador. Si revisa un proyecto por primera vez y recibe varios miles de advertencias, solo necesita agregarlas en una base de supresión y la próxima ejecución le dará cero advertencias.
De esta manera, puede continuar escribiendo y cambiando el código de manera normal, y al hacerlo, recibirá mensajes solo sobre errores que se acaban de realizar en el proyecto. Por lo tanto, obtendrá el mayor beneficio del analizador aquí y ahora, sin ser distraído por rastrillar errores antiguos. Unos pocos clics, ¡y el analizador se incorpora a su desarrollo! Puede leer las instrucciones detalladas sobre cómo hacer esto
aquí .
Probablemente se preguntará: "Espere, ¿qué pasa con las advertencias ocultas?" La respuesta es bastante simple: no se olvide de ellas y corríjalas por etapas fáciles. Por ejemplo, puede cargar la base de supresión en el sistema de control de versiones y permitir solo las confirmaciones que no aumentan el número de advertencias. Por lo tanto, poco a poco su "roca subacuática" se desgastará tarde o temprano sin dejar rastro.
Bien, el analizador ahora se adoptó con éxito y estamos listos para continuar. ¿Qué hacer a continuación? La respuesta es evidente: ¡trabaje con el código! Pero, ¿qué se necesita para poder declarar el cumplimiento de la norma? ¿Cómo demuestras que tu proyecto cumple con MISRA?
De hecho, no hay un "certificado" especial de que su código corresponde a MISRA. Como estipula el estándar, el seguimiento del cumplimiento debe ser realizado por dos partes: el cliente del software y el proveedor del software. El proveedor desarrolla software que cumple con el estándar y completa los documentos necesarios. El cliente, a su vez, debe asegurarse de que los datos de estos documentos sean verdaderos.
Si desarrolla software para usted, la responsabilidad de cumplir con el estándar solo recaerá sobre sus hombros :)
En general, para demostrar el cumplimiento de su proyecto, necesitará documentos de respaldo. La lista de documentos que los desarrolladores de proyectos deben preparar puede variar, pero MISRA ofrece algunos conjuntos como referencia. Echemos un vistazo más de cerca a este conjunto.
Necesitará estas cosas para solicitar el cumplimiento estándar:
- El proyecto en sí, cuyo código cumple con las reglas obligatorias y obligatorias
- Plan de aplicación de la guía
- Documentación sobre todas las advertencias del compilador y el analizador estático.
- Documentación para todas las desviaciones de las Reglas requeridas
- Resumen de cumplimiento de la directriz
El primero es un plan de aplicación de la guía. Esta es su tabla más importante y contiene referencias a todos los demás documentos. En su primera columna hay una lista de reglas MISRA, en el resto, se observa si hubo alguna desviación de esas reglas. Esta tabla se ve así:
El estándar recomienda construir su proyecto con varios compiladores, así como usar dos o más analizadores estáticos para probar el cumplimiento de su código. Si el compilador o el analizador emite una advertencia relacionada con las reglas, debe anotarla en la tabla y documentar los siguientes puntos: por qué la advertencia no puede repararse, si es falsa o no, etc.
Si un analizador estático no puede verificar una de las reglas, debe realizar una revisión manual del código. Este procedimiento también debe documentarse, después de lo cual se debe agregar un enlace a esa documentación al plan de cumplimiento.
Si el compilador o el analizador estático resulta ser correcto, o si hay infracciones válidas de las reglas durante el proceso de revisión del código, debe corregirlas o documentarlas. Nuevamente, adjuntando el enlace a la documentación en la tabla.
Por lo tanto, un plan de cumplimiento es un documento que proporcionará documentación para cualquier desviación identificada en su código.
Veamos brevemente documentar directamente las desviaciones de las reglas. Como mencioné, dicha documentación solo es necesaria para las Reglas requeridas, ya que las reglas obligatorias no se pueden violar y las Reglas de asesoramiento se pueden violar sin ninguna documentación.
Si elige desviarse de la regla, la documentación debe incluir:
- El número de la regla violada.
- La ubicación exacta de la desviación.
- La validez de la desviación.
- Prueba de que la desviación no compromete la seguridad
- Posibles consecuencias para el usuario.
Como puede ver, este enfoque de la documentación le hace preguntarse seriamente si la violación vale la pena. Esto se hizo específicamente para no sentir el deseo de violar las reglas requeridas :)
Ahora sobre el resumen del cumplimiento de las normas. Este documento, quizás, será el más fácil de completar:
La columna central se llena antes de comenzar a trabajar con el código, y la correcta, después de que su proyecto esté listo.
Aquí hay una pregunta razonable: ¿por qué deberían especificarse las categorías de reglas, si ya están especificadas en el estándar mismo? El hecho es que el estándar permite "promover" una regla en una categoría más estricta. Por ejemplo, un cliente puede pedirle que clasifique una regla de asesoramiento. Dicha "promoción" debe realizarse antes de trabajar con el código, y el resumen del cumplimiento de las reglas le permite anotarlo explícitamente.
En cuanto a la última columna, es bastante simple: solo debe tener en cuenta si se está utilizando la regla y, de ser así, si hay desviaciones de la misma.
Se necesita toda esta tabla para que pueda ver rápidamente qué prioridades tienen las reglas y si el código las cumple. Si de repente le interesa saber la causa exacta de la desviación, siempre puede recurrir al plan de cumplimiento y encontrar la documentación que necesita.
Entonces escribiste el código cuidadosamente siguiendo las reglas de MISRA. Ha realizado un plan de cumplimiento y documentado todo lo que podría documentarse, y ha completado sus hojas de vida de cumplimiento. Si este es el caso, entonces tienes un código muy limpio, muy legible y muy confiable que ahora odias :)
¿Dónde vivirá su programa ahora? En un dispositivo de resonancia magnética? ¿En un sensor de velocidad ordinario o en el sistema de control de algún satélite espacial? Sí, has pasado por un camino burocrático serio, pero eso no es gran cosa. Cuando se trata de vidas humanas reales, siempre debes ser escrupuloso.
Si se las arregló y logró llegar al final victorioso, entonces lo felicito sinceramente: usted escribe un código seguro de alta calidad. Gracias
El futuro de las normas.
Para el final, me gustaría detenerme en el futuro de los estándares.
Ahora Misra vive y evoluciona. Por ejemplo, "The MISRA C: 2012 Third Edition (First Revision)" es una edición revisada y ampliada con nuevas reglas anunciadas a principios de 2019. Al mismo tiempo, el próximo lanzamiento de "MISRA C: 2012 Enmienda 2 - C11 Core ”, que es un estándar revisado del año 2012, fue anunciado. Este documento incluirá reglas que cubren por primera vez las versiones en lenguaje C de los años 2011 y 2018.
MISRA C ++ sigue evolucionando también. Como saben, el último estándar de MISRA C ++ está fechado en 2008, por lo que la versión más antigua del lenguaje que cubre es C ++ 03. Debido a esto, hay otro estándar similar a MISRA, y se llama AUTOSAR C ++. Originalmente fue pensado como una continuación de MISRA C ++ y estaba destinado a cubrir versiones posteriores del lenguaje. A diferencia de su cerebro, AUTOSAR C ++ se actualiza dos veces al año y actualmente es compatible con C ++ 14. Nuevas actualizaciones de C ++ 17 y luego C ++ 20 aún están por llegar.
¿Por qué comencé a hablar de algún otro estándar? El hecho es que hace poco menos de un año, ambas organizaciones anunciaron que fusionarían sus estándares en uno solo. MISRA C ++ y AUTOSAR C ++ se convertirán en un estándar único y, a partir de ahora, evolucionarán juntos. Creo que son buenas noticias para los desarrolladores que escriben para microcontroladores en C ++, y no menos buenas para los desarrolladores de analizadores estáticos. ¡Hay mucho más por hacer! :)
Conclusión
Hoy, con suerte, aprendió mucho sobre MISRA: leyó la historia de su origen, estudió los ejemplos de reglas y el concepto del estándar, consideró todo lo que necesitará para usar MISRA en sus proyectos e incluso tuvo una visión del futuro. ¡Espero que ahora comprenda mejor qué es MISRA y cómo cocinarlo!
En la vieja tradición, dejaré aquí un enlace a nuestro analizador estático PVS-Studio. Es capaz de encontrar no solo desviaciones del estándar MISRA, sino también
una gran variedad de errores y vulnerabilidades. Si está interesado en probar PVS-Studio usted mismo,
descargue la versión demo y verifique su proyecto.
Ahí es donde termina mi artículo. ¡Les deseo a todos los lectores una feliz Navidad y felices fiestas de Año Nuevo!