MISRA — ghidul de programare sigură în C

MISRA e cel mai cunoscut set de reguli de programare sigură pentru C și C++.

Ce este MISRA?

MISRA (Motor Industry Software Reliability Association) e un consorțiu britanic fondat în 1990 care publică ghiduri de programare sigură. Cel mai cunoscut: MISRA C — un set de ~150 de reguli care interzic constructe periculoase din limbajul C.

Nu e un compilator, nu e un tool — e un document care spune „fă așa, nu face așa". Respectarea lui se verifică cu tool-uri automate (lintere).

Inițial creat pentru industria auto, MISRA e azi standard și în:

  • Avionică (DO-178B/C)
  • Medical (IEC 62304)
  • Feroviar (EN 50128)
  • Industrial (IEC 61508)

Structura regulilor

MISRA C:2012 are 3 categorii de reguli și 2 tipuri:

Categorii

| Categorie | Obligație | Exemple | |---|---|---| | Mandatory | Trebuie respectată obligatoriu | Fără excepții | | Required | Trebuie respectată, dar poți cere derogare motivată | Majoritatea regulilor | | Advisory | Recomandată, nerespectarea nu încalcă standardul | Bune practici |

Tipuri

| Tip | Ce verifică | |---|---| | Directive | Proces / organizare (ex: "documentați deciziile") | | Rule | Cod concret (ex: "nu folosi goto") |

Număr de reguli pe versiune

| Versiune | Reguli | |---|---| | MISRA C:1998 | ~93 | | MISRA C:2004 | ~121 | | MISRA C:2012 | ~143 | | MISRA C:2023 | ~150 (revizia 3) | | MISRA C++:2008 | ~228 | | MISRA C++:2023 | ~200 |

Exemple de reguli — pe categorii

Direcții de siguranță

Câteva reguli iconice, grupate pe ce previn:

| Problemă | MISRA | Ce interzice | |---|---|---| | Buffer overflow | Regula 18.1 | Pointeri la array-uri fără limită | | Use-after-free | Regula 18.6 | Acces după free() | | Null pointer | Regula 16.7 | Dereferențiere fără verificare | | Întregi | 10.1-10.4 | Conversii implicite între tipuri | | Bucle | 14.1-15.7 | Bucle infinite fără ieșire, goto, longjmp | | Memorie | 21.1-21.12 | malloc/free interzis (doar pool-uri) | | Evaluare | 13.1-13.6 | Efecte secundare în expresii | | Preprocesor | 20.1-20.14 | #undef, #include condiționat periculos |

Câteva reguli celebre

Regula 14.1 — Bucle trebuie să aibă un contor și o condiție clară:

// ❌ MISRA: bucle infinite fără ieșire explicită
for (;;) { }  // permis doar cu break explicit

// ❌ MISRA: modificarea contorului în corp
for (i = 0; i < n; i++) {
    i = i + 2;  // periculos, greu de urmărit
}

// ✅ MISRA
for (i = 0; i < n; i++) {
    if (cond) break;
}

Regula 16.7 — Pointerii se verifică înainte de folosire:

// ❌ MISRA
void process(int *p) {
    *p = 5;  // p poate fi NULL
}

// ✅ MISRA
void process(int *p) {
    if (p != NULL) {
        *p = 5;
    }
}

Regula 21.3 — Eroare: alocare dinamică interzisă:

// ❌ MISRA
int *buf = malloc(100);

// ✅ MISRA (alocare statică)
int buf[100];

Multe sisteme critice nu permit malloc — odată ce resursele sunt alocate la pornire, nu se mai alocă nimic dinamic pentru a evita fragmentarea heap-ului sau epuizarea memoriei.

Reguli de notare

Regula 8.3 — Toate funcțiile trebuie declarate înainte de folosire:

// ❌ MISRA — foo() e apelat înainte de declarație
void bar() { foo(); }
void foo() { }

// ✅ MISRA
void foo(void);  // declarație
void bar(void) { foo(); }
void foo(void) { }

MISRA în practică

Workflow tipic

1. Scrii cod C (respectând conștient regulile)
2. Rulezi un tool static (PC-lint, SonarQube, Coverity)
3. Tool-ul raportează încălcări → le repari
4. Pentru încălcările justificate, scrii derogare
5. Prezinți raportul de conformitate auditorului
6. Auditorul acceptă sau cere corecții

Tool-uri de verificare

| Tool | Gratis? | Acoperire MISRA | |---|---|---| | PC-lint / FlexeLint | ❌ | Aproape completă | | SonarQube | Parțial (community) | ~80% | | Coverity | ❌ | ~90% | | CppCheck | ✅ | ~50% | | Astree | ❌ | Completă (și runtime) | | Polyspace | ❌ | Completă |

MISRA și limbajul C

C e un limbaj periculos din punct de vedere al siguranței. MISRA încearcă să-l facă sigur prin reguli, dar:

┌────────────────────────────────────────────┐
│  C standard                                │
│  (poți face orice, inclusiv prostii)       │
├────────────────────────────────────────────┤
│  MISRA C                                   │
│  (interzice ~20% din C, previne ~90%       │
│   din bug-urile comune)                    │
├────────────────────────────────────────────┤
│  Tool-uri statice                           │
│  (verifică automat regulile)               │
└────────────────────────────────────────────┘

MISRA vs Rust

O comparație directă:

| Caracteristică | MISRA (C) | Rust | |---|---|---| | Buffer overflow | Regula manuală + tool | Imposibil la compilare | | Use-after-free | Regula manuală + tool | Imposibil (borrow checker) | | Null pointer | Verificare manuală | Opțional (Option<T>) | | Alocare dinamică | Interzisă (regula) | Sigură prin tipuri (Box, Vec) | | Cost | Document £50 + tool $1k-50k/an | Gratis | | Aplicare | Tool extern, post-factum | Compilatorul o face automat | | Reguli de învățat | ~150 | ~30 (concepte Rust) |

Un program respectă MISRA nu pentru că e corect — ci pentru că e mai puțin probabil să aibă bug-uri. Un program în Rust e corect din punct de vedere al memoriei — garantat de compilator.

Critici

MISRA nu e lipsit de controverse:

  1. Costul documentației — ghidul oficial nu e gratuit (spre deosebire de SEI CERT C de la CMU, care e gratis și acoperă același domeniu)
  2. Falsă siguranță — un cod poate fi MISRA-compliant și tot plin de bug-uri logice. MISRA nu previne greșeli de algoritm
  3. Tool-urile sunt scumpe — verificarea MISRA e dominată de tool-uri comerciale scumpe, ceea ce exclude echipele mici
  4. Birocrație — derogările, auditurile și documentația adaugă costuri semnificative fără a îmbunătăți neapărat calitatea codului

Concluzie

MISRA e un standard matur și respectat în industriile critice. Dacă scrii C pentru un airbag sau un sistem de frânare, vei respecta MISRA pentru că clientul și auditorul cer asta. Nu e perfect, dar e cea mai bună soluție disponibilă pentru C în siguranță.

Rust e promițător, dar realitatea e nuanțată:

| Nevoie | Ce alegi | |---|---| | Certificare formală (DO-178C, ISO 26262) | C + MISRA + tool-uri scumpe | | Produs mai sigur, fără certificare | Rust e o alternativă excelentă | | Toolchain certificat | Există pentru C (GCC), nu pentru Rust (rustc/LLVM) | | Cost | MISRA: document £50 + tool $1k-50k/an; Rust: gratis |

Rust atinge siguranța memoriei mai bine decât MISRA + C, dar certificarea safety-critical cere mai mult decât siguranța memoriei: traceabilitate, acoperire MC/DC, toolchain calificat — domenii unde C și MISRA au decenii de precedent.