Neues von MISRA Amendement 3 zu MISRA C:2012 veröffentlicht

Von Frank Büchner* Lesedauer: 11 min

Anbieter zum Thema

Die MISRA-Richtlinien sind wohl die bekanntesten Kodiervorgaben für die Programmiersprache C. Das liegt nicht zuletzt daran, dass die Ursprünge dieser Richtlinien bis ins Jahr 1990 zurückreichen und die Richtlinien seitdem immer wieder korrigiert und erweitert wurden. Kürzlich wurde ein weiteres Amendement veröffentlicht: Amendement 3. Was ist darin neu?

Die ursprüngliche Richtlinie MISRA C:2012 [MISRA3] enthält 159 Vorgaben.
Die ursprüngliche Richtlinie MISRA C:2012 [MISRA3] enthält 159 Vorgaben.
(Bild: / CC0)

Die Geschichte von MISRA („The Motor Industry Software Reliable Association“) beginnt im Jahr 1990 als Teil des von der Regierung von Großbritannien geförderten Projekts „SafeIT“. Heute wird MISRA vom „The MISRA Consortium Limited“ verwaltet, mit Sitz in Norwich, Großbritannien. Deshalb sind die Preise für die Richtlinien die man über die Internet-Seite des Consortiums [MISRA] beziehen kann, auch in GBP angegeben.

Die erste MISRA-Richtlinie für die Programmiersprache C [MISRA1] erschien im April 1998. Laut Titel war sie explizit für Software in Fahrzeugen gedacht. Aber die Absicht der Richtlinie, der Programmiersprache C etwas von ihrer Gefährlichkeit zu nehmen, war natürlich auch in anderen Anwendungsbereichen sinnvoll, beispielsweise in Industrieanwendungen oder der Medizintechnik. Die zweite Ausgabe der Richtlinie von 2004 [MISRA2], war dann schon allgemeiner für sicherheitskritische Systeme gedacht.

Die aktuelle Richtlinie MISRA C:2012 [MISRA3] enthält ursprünglich 159 Vorgaben. Diese setzen sich zusammen aus 16 Direktiven und 143 Regeln. Direktiven sind Vorgaben, bei denen es nicht möglich ist, eine vollständige Beschreibung anzugeben, so dass immer eine gewisse Unsicherheit besteht, was die Einhaltung bzw. Verletzung der Direktive nun genau bedeutet. Deshalb können statische Analyse-Werkzeuge hier nur unterstützen.

Auch reicht der Programmcode allein zur Prüfung von Direktiven normalerweise nicht aus, es werden Zusatzinformationen wie beispielsweise Anforderungs- oder Design-Dokumente benötigt, welche üblicherweise durch ein Review geprüft werden müssen, weil statische Analyse-Werkzeuge hier an ihre Grenzen stoßen. Dies trifft beispielsweise bei Direktive 1.1 zu, nach der durch die Implementierung festgelegtes Verhalten dokumentiert und verstanden sein muss. Wie soll ein Werkzeug beurteilen, ob solches Verhalten von den Entwicklern verstanden ist? Ähnlich verhält es sich bei Direktive 3.1, nach der jedweder Code auf dokumentierte Anforderungen zurückgeführt werden können muss.

Für Regeln hingegen ist der Programmcode (gegebenenfalls mit zusätzliche Informationen wie beispielsweise die Anzahl der Bits in einem Integer) ausreichend für die Untersuchung, ob eine Regel verletzt wurde oder nicht. Zur Prüfung von Regeln sind statische Analysewerkzeuge prinzipiell geeignet und werden üblicherweise auch dafür verwendet. Das heißt jedoch nicht, dass Werkzeuge für jede Regel auch in jedem Fall korrekt entscheiden können, ob die Regel verletzt ist oder nicht. Das ist ein prinzipielles Problem der Informatik (Halteproblem) und hängt nicht vom Werkzeug ab. In der Richtlinie ist für jede MISRA-Regel angegeben, ob sie entscheidbar ist oder nicht. Unglücklicherweise sind interessante Regeln unentscheidbar, beispielsweise Regel 9.1, bei der es darum geht, ob eine Stackvariable vor Verwendung initialisiert wurde oder nicht. Die Verwendung einer uninitialisierten Variablen ist undefiniertes Verhalten und muss vermieden werden.

Im Mai 2016 kamen durch Amendment 1 [MISRA-AMD1] (AMD1) weitere 14 Vorgaben hinzu (1 Direktive + 13 Regeln), insgesamt waren es damit 173 Vorgaben. Diese 14 zusätzlichen Vorgaben adressieren speziell Security. Eine bestehende Regel (21.8) wird durch AMD1 geändert.

Bis zu diesem Zeitpunkt adressierten die MISRA-Vorgaben lediglich die Sprachstandards C90 und C99. Im Februar 2020 wurden durch Amendment 2 [MISRA-AMD2] begonnen, die Richtlinie für den Sprachstandard C11 zu aktualisieren. Dies betraf viele Vorgaben, wenn auch oft nur formal. Außerdem kamen noch zwei weitere Regeln hinzu. Damit gab es insgesamt 175 Vorgaben.

Amendment 3

Amendment 3 [MISRA-AMD3] (AMD3) setzt die Aktualisierung der Vorgaben für den Sprachstandard C11 fort und bezieht auch C18 mit ein (Bild 1). C18 entspricht C11 mit Ausnahme von Korrekturen. Wenn im folgenden C11 steht, ist damit immer auch C18 einbezogen.

Bild 1: Durch Amendements kommen auch neue Direktiven und Regeln hinzu.
Bild 1: Durch Amendements kommen auch neue Direktiven und Regeln hinzu.
(Bild: Hitex GmbH)

Mit AMD3 kamen eine Direktive und 23 Regeln neu hinzu. Zudem wurden 3 bestehende Direktiven und 9 bestehende Regeln verändert.

AMD3 erlaubt mit Einschränkung die folgenden drei Funktionalitäten von C11:
(1) No-return-Funktionen (Schlüsselwort _Noreturn, Header <stdnoreturn.h>)
(2) Ausrichtung von Objekten (Schlüsselwort alignas, Header <stdalign.h>)
(3) Typ-generische Ausdrücke (Schlüsselwort _Generic).

Ferner gibt es weiterführende Anleitung zur Verwendung der folgenden drei Funktionalitäten (die es schon in C99 gab):
(a) Typ-generische mathematische Macros (tgmath.h)
(b) Fließkommazahlen (Vergleiche, Not-a-number (NaN) und unendlich (INF))
(c) komplexe Zahlen.

Jetzt Newsletter abonnieren

Verpassen Sie nicht unsere besten Inhalte

Mit Klick auf „Newsletter abonnieren“ erkläre ich mich mit der Verarbeitung und Nutzung meiner Daten gemäß Einwilligungserklärung (bitte aufklappen für Details) einverstanden und akzeptiere die Nutzungsbedingungen. Weitere Informationen finde ich in unserer Datenschutzerklärung.

Aufklappen für Details zu Ihrer Einwilligung

Schlussendlich verbietet AMD3 die Nutzung von Funktionalitäten, die der C Sprachstandard als veraltet erklärt.

No-return-Funktionen

No-return-Funktionen wurden in C11 eingeführt und sind Funktionen, die mit dem Schlüsselwort _Noreturn deklariert sind, das angibt, dass solche Funktionen nicht zu ihrem Aufrufer zurückkehren. Hiermit befassen sich drei neue Regeln (Regel 17.9 bis 17.11), die einfach zu verstehen sind, da sie einfach die „vernünftige“ Verwendung dieses Schlüsselworts fordern.

Bild 3: Das statische Analyse-Werkzeug ECLAIR (V3.13) zeigt eine Verletzung der Regel 17.9 aus AMD3.
Bild 3: Das statische Analyse-Werkzeug ECLAIR (V3.13) zeigt eine Verletzung der Regel 17.9 aus AMD3.
(Bild: Hitex GmbH)

Regel 17.9 fordert, dass eine No-return-Funktion nicht zu der aufrufenden Funktion zurückkehren darf, denn dies wäre undefiniertes Verhalten und alles mögliche Schlimme kann passieren, beispielsweise Abstürze. Leider ist diese wichtige Regel unentscheidbar (Bild 3). Regel 17.10 fordert, dass eine No-return-Funktion void sein muss, d.h. keinen Rückgabendatentyp haben darf. Regel 17.11 fordert, dass eine Funktion, die nicht zum Aufrufer zurückkehrt, als No-return-Funktion deklariert sein soll. Da es das Schlüsselwort _Noreturn erst ab C11 gibt, gelten diese drei Regeln natürlich nur ab dieser Sprachversion.

Dokumenttypen

Bild 2: MISRA-Dokumente mit Bezug zu MISRA C:2012
Bild 2: MISRA-Dokumente mit Bezug zu MISRA C:2012
(Bild: Hitex GmbH)

Seit dem Erscheinen der Richtlinie MISRA C:2012 im März hat MISRA verschiedenste Dokumenttypen mit Bezug zu dieser Richtlinie veröffentlicht (Bild 2).
Die Dokumente sind kostenlos im Internet von www.mirsa.org.uk erhältlich.

Amendements
Amendements verändern und erweitern die (Ur-) Richtlinie (siehe Bild 1).

Addendums
Addendums verändern die Richtlinie nicht. Die drei bisherigen Addenden vergleichen die Vorgaben in MISRA C:2012 mit den Vorgaben in anderen Richtlinien oder Standards. Addendum 1 vergleicht mit MISRA C:2004 [MISRA2]; Addendum 2 vergleicht mit C secure [17961]; Addendum 3 vergleicht mit CERT [CERT].

Compliance
Diese Dokumente zeigen (beispielhaft) auf, wie man vorgehen muss und welche Dokumente empfehlenswert sind, um MISRA-Compliance zu erhalten.

Permits
Dieses Dokument zeigt Situationen, bei denen es vernünftig und notwendig ist, eine Regelverletzung zu akzeptieren. Dies gilt beispielsweise für defensiven Code, der unter normalen Umständen nicht erreichbar ist (was eine Verletzung von Regel 2.1 ist), was aber toleriert werden muss, wenn man sich beispielsweise vor Datenkorruption schützen will. Permits stehen in Zusammenhang mit den Compliance-Dokumenten.

Technical Corrigendums
Technical Corrigendums korrigieren die Richtlinie, beispielsweise wenn der Begriff „Deklaration“ mit dem Begriff „Definition“ verwechselt wurde. TCs können aber auch Klarstellungen sein, zum Beispiel auf die Frage „Gilt die Regel auch in diesem Spezialfall?“

Ausrichtung von Objekten

In C11 wurde das Schlüsselwort _Alignas eingeführt. Damit kann man explizit die Ausrichtung von Variablen und Typen festlegen, um schnellere Zugriffe zu ermöglichen. In C++ lautet das korrespondierende Schlüsselwort alignas, und damit man einheitliche Schlüsselworte in C und C++ verwenden kann, gibt es für C den Header <stdalign.h>, in dem alignas zu _Alignas definiert wird. Die Beispiele in AMD3 verwenden durchgehend alignas. Drei neue Regeln 8.15 bis 8.17 befassen sich mit der Ausrichtung von Objekten. Diese Regeln verlangen, dass die Ausrichtung von Objekten „vernünftig“ erfolgt.

Regel 8.15 fordert, dass alle Deklarationen und die Definition eines Objekts die gleiche Ausrichtung haben müssen. Wird diese Regel verletzt, entsteht undefiniertes Verhalten, was unbedingt vermieden werden muss. Diese Regel ist natürlich auch eingehalten, wenn für alle Deklarationen und die Definition eines Objekts keine explizite Ausrichtung angegeben ist.

Regel 8.16 gilt die Ausrichtung mit dem Wert null, die nicht vorkommen soll. Diese Ausrichtung wird immer ignoriert, und könnte ausdrücken, dass im betreffenden Fall die Ausrichtung nicht wichtig ist. Regel 8.16 rät, dies über den Präprozessor zu bewirken.

Regel 8.17 fordert, dass nur eine Ausrichtung für ein Objekt angegeben werden sollte. C11 erlaubt mehrere Ausrichtungen für ein Objekt anzugeben, von denen dann die strengste Ausrichtung verwendet wird.

Typ-generische Ausdrücke

Abhängig vom Typ einer Variablen wird aus einer Liste ein Ausdruck, der auch eine Funktion sein kann, ausgewählt. Die Liste kann auch einen default enthalten. Dies wurde in C11 für das Programmieren mit dem Schlüsselwort _Generic zugänglich gemacht. Dadurch erhält C11 eine Art Typ-Polymorphismus. Für die Typ-generischen Ausdrücke wurden in AMD3 acht neue Regeln eingeführt, die einen eigenen Regelabschnitt bilden: Regel 23.1 bis 23.8.

Regel 23.1 fordert, dass eine generische Auswahl nur aus einem Macro heraus erfolgen sollte, denn wenn es direkt geschieht, ist der Typ bereits bekannt und die Auswahl überflüssig. Wenn die generische Auswahl dennoch direkt geschieht, darf der Auswahl-Ausdruck keine Seiteneffekte enthalten, denn diese würden nicht evaluiert. Letzteres besagt Regel 23.2.

Regel 23.3 besagt, dass die Auswahlliste mindestens eine Auswahl beinhalten sollte, die nicht default ist. Ansonsten macht die Auswahl keinen Sinn und ist wahrscheinlich so nicht gewollt. Nach Regel 23.4 dürfen nicht alle Typen vorkommen, da der Auswahl-Ausdruck in ein lvalue umgewandelt wird. Hätte man beispielsweise einen Array-Typ oder einen Funktionstyp in der Auswahlliste, könnte dieser nie ausgewählt werden. Deshalb sind manche Typen verboten.

Regel 23.5 verlangt, dass die die generische Auswahl nicht von impliziten Pointer-Typ-Konvertierungen abhängen sollte. Regel 23.6 verlangt, dass der Auswahl-Ausdruck einen essentiellen Typ haben muss, der passend zu seinem Standard-Typ ist. Diese Regel bezieht sich auf das essentielle Typ-System der MISRA-Richtlinien. Dieses Typ-System darf nicht verletzt werden.

Regel 23.7 sagt, dass eine generische Auswahl aus einem Macro heraus das Argument (nur) einmal evaluieren sollte. Das sollte für alle Auswahlmöglichkeiten gelten, d.h. es soll keine Auswahl geben, die einmal evaluiert wird und eine andere, die das nicht wird.

Regel 23.8 fordert, dass default in der Auswahlliste entweder als erster oder als letzter Eintrag in der Auswahlliste stehen muss. Damit kann man einfacher sehen, ob es einen solchen Eintrag gibt oder nicht. Die Regel kann natürlich nur verletzt werden, wenn es überhaupt einen default gibt.

Weitere Neuerungen durch AMD3

Durch AMD3 kommen außerdem neu hinzu: Direktive 4.15 und die Regeln 1.5, 6.3, 7.5, 17.12, 17.13, 18.9, 21.22, 21.23, 21.24.

Die neue Direktive 4.15 fordert, dass die Auswertung von floating-point Ausdrücken nicht zur unentdeckten Erzeugung von unendlich (INF) oder Not-a-number (NaN) führt. Gilt bereits für C90.

Die neue Regel 1.5 verbietet die Benutzung von Sprachfunktionalitäten, die der C Sprachstandard (in Anhang F) als veraltet erklärt. Gilt bereits für C99.

Die neue Regel 6.3 verbietet Bitfelder als Element einer union, denn hier ist das Verhalten durch die Implementierung definiert. Gilt bereits für C90.

Die neue Regel 7.5 fordert, dass das Argument eines Integer Constant Macro (wie beispielsweise UNIT32_C) eine geeignete Form hat. Das Argument muss ein Integer ohne Suffix sein und der Wert des Arguments darf nicht größer sein als durch den Macro-Namen angegeben wird. Ansonsten entsteht undefiniertes Verhalten. Gilt bereits für C99.

Die neue Regel 17.12 verlangt, dass Funktionsnamen entweder eine nachgestellte Parameterliste (in Klammern) haben sollen oder ein vorangestelltes ‚&‘. Denn bei einem Funktionsnamen mit keinem von beiden ist unklar, ob wirklich die Adresse der Funktion gemeint ist oder ob die Parameterliste vergessen wurde. Dies soll die Wartbarkeit der Software verbessern und gilt bereits für C90.

Die neue Regel 17.13 verlangt, dass ein Funktionstyp keine Typqualifizierer (wie const, volatile, restrict oder _Atomic) haben darf, denn dies erzeugt undefiniertes Verhalten. Gilt bereits für C90.

Die neue Regel 18.9 steigt in die Tiefen der Programmiersprache C und soll, vereinfacht gesagt, Pointer auf Objekte mit begrenzter Lebenszeit vermeiden. Gilt bereits für C90.

Die neue Regeln 21.22 und 21.23 betreffen die Argumente der Typ-generischen Macros aus dem Header <tgmath.h>. Sie müssen den richtigen essentiellen Typ bzw. den gleichen Standard-Typ haben. Gilt bereits für C99.

Die neue Regel 21.24 verbietet die Benutzung von rand() und srand(), weil es keine Garantie für die Qualität der Zufallszahlen gibt. Gilt bereits für C90.

Änderungen durch AMD3

AMD3 verändert drei bestehende Direktiven (Direktive 4.6, 4.9 und 4.11) und 9 bestehende Regeln (Regel 1.4, 10.1, 10.3, 10.4, 10.5, 10.7, 10.8, 21.11, 21.12).

Direktive 4.6 wird für complex float erweitert. Direktive 4.9 erlaubt nun _Generic als funktions-ähnliches Macro. Direktive 4.11 wird zum Thema Präzision der trigonometrischen periodischen Funktionen im Header <math.h> erweitert. Regel 1.4 erlaubt nun die Verwendung der Schlüsselworte _Generic, _Noreturn und _Alignas, da diese in AMD3 nun explizit behandelt werden. Der Behandlung von „complex floating“ gelten die angeführten Regeln 10.x, die auch das essentielle Typ-Modell von MISRA betreffen. Die Regel 21.11 stuft die Verwendung des Headers <tgmath.h> neu ein und die Regel 21.12 macht eine Neueinstufung für den Header <fenv.h>.

AMD3 aktualisiert auch Addendum 3

Im Januar 2018 wurde Addendum 3 [MISRA-AD3] veröffentlicht. In Addendum 3 wird die Abdeckung von MISRA C:2012 (mit Amendment 1) zum SEI CERT C Coding Standard (Edition von 2016) [CERT] für das sichere („secure“) Programmieren diskutiert, mit dem Ergebnis, dass von den 99 Vorgaben 80 mehr oder weniger gut abgedeckt sind (d.h. manche nur partiell). Durch AMD3 werden weitere 4 Vorgaben aus CERT abgedeckt, so dass nun 84 der 99 Vorgaben abgedeckt sind. Beispielsweise befassen sich zwei der bisher nicht abgedeckten Vorgaben aus CERT (MSC30-C und MSC32-C) mit Zufallszahlen, die nun durch die neue Regel 21.24 aus AMD3, die rand() und srand() verbietet, abgedeckt sind. Somit ist die Überdeckung zwischen den „Safety“-Vorgaben aus MISRA und den „Security“-Vorgaben aus CERT weiter verbessert.

Für wen ist AMD3 wichtig?

Jeder, der sicherheitskritische Software entwickelt, sollte die MISRA-Richtlinien anwenden. Selbstverständlich sollte jeder, der den Sprachstandard C11 verwendet, AMD3 benutzen. Aber auch für Anwender von C90 oder C99 ist AMD3 wichtig, denn die neue Direktive 4.15 sowie sechs der neuen Regeln gelten bereits für C90 und weitere vier der neuen Regeln gelten ab C99.

Fazit

Die MISRA-Richtlinien sind lebendig und werden ständig angepasst und erweitert. Viele Zusatzdokumente erläutern und komplettieren die eigentlichen Richtlinien (siehe Bild 2). AMD3 ist ein weiterer Schritt auf diesem Weg. Allerdings ist mit AMD3 die Aktualisierung für C11 noch nicht zu Ende, es fehlen noch die Themen „threads“ und „atomics“. Dies wird in Amendement 4 behandelt, erschienen im März 2023. (mbf)

Literatur- und Quellenverzeichnis

[17961] ISO/IEC TS 17961:2013, Information technology — Programming languages, their environments & system software interfaces — C Secure Coding Rules. Geneva, Switzerland: ISO/IEC, Nov. 2013.

[CERT] SEI CERT C Coding Standard: Rules for Developing Safe, Reliable, and Secure Systems, 2016th ed. Software Engineering, Carnegie Mellon University, 2016.

[MISRA] www.misra.org.uk

[MISRA1] MISRA C:1998, Guidelines for the use of the C language in vehicle-based software, Horiba Mira Limited, UK, April 1998.

[MISRA2] MISRA C:2004, Guidelines for the use of the C language in critical systems, Horiba Mira Limited, UK, Edition 2, Oktober 2004.

[MISRA3] MISRA C:2012, Guidelines for the use of the C language in critical systems, Mira Limited, UK, Edition 3, März 2013.

[MISRA-AMD1] MISRA C:2012 Amendment 1 — Additional security guidelines for MISRA C:2012. Horiba Mira Limited, UK, Apr. 2016.

[MISRA-AMD2] MISRA C:2012 Amendment 2 — Updates for ISO/IEC 9899:2011 Core functionality. Horiba Mira Limited, UK, Feb. 2020.

[MISRA-AMD3] MISRA C:2012 Amendment 3 — Updates for ISO/IEC 9899:2011/2018 Phase 2. The MISRA Consortium Limited, UK, Okt. 2022.

[MISRA-AD2] MISRA C:2012 Addendum 2 — Coverage of MISRA C:2012 (including Amendment 1) against ISO/IEC TS 17961:2013 “C Secure”, 2nd ed. Horiba Mira Limited, UK, Jan. 2018.

[MISRA-AD3] MISRA C:2012 Addendum 3 — Coverage of MISRA C:2012 (including Amendment 1) against CERT C 2016 Edition. Horiba Mira Limited, UK, Jan. 2018.

[ECLAIR] Statisches Analysewerkzeug von BUGSENG, mehr Info: www.hitex.de/eclair

Der Autor

(Bild: Hitex)

Frank Büchner hat ein Diplom in Informatik von der Technischen Hochschule Karlsruhe, heute KIT. Seit vielen Jahren widmet er sich dem Thema Testen und Software-Qualität. Momentan arbeitet er als „Principal Engineer Software Quality“ bei der Fa. Hitex GmbH in Karlsruhe.

(ID:49320769)