Cyclone (limbaj de programare)

Cyclone
Cyclone
Apărut în2002  (2002)
Proiectat deAT&T Labs
Tiparestrict, static
Influențat deC
InfluențeRust
Prezență onlinecyclone.thelanguage.org

Cyclone este destinată să fie un dialect sigur al limbajului C. Cyclone este proiectat pentru a evita depășirile buffer și alte vulnerabilități care sunt posibile în programele C, fără a pierde puterea și comoditatea lui C ca instrument de programare a sistemului.

Dezvoltarea Cyclone a fost inițiată ca un proiect comun al AT&T Labs Research și al grupului Greg Morrisett de la Cornell în 2001. Versiunea 1.0 a fost lansată pe 8 mai 2006.

Scopul și istoricul proiectului

Scopul principal al dezvoltării este de a face programele C mai protejate de erori și vulnerabilități, cum ar fi influxul de buffer infinit, cu o pierdere minimă de eficiență și cu continuitate. Ideea este de a lua mijloacele de protecție eficientă de la limbile de nivel înalt și de a le pune în aplicare într-un limbaj de nivel inferior.

Elementele de bază ale dezvoltării au fost elaborate de Dan Grossman, Trevor Jim și Greg Morrisett de la Universitatea Cornell în proiectarea și implementarea limbajului de asamblare TAL[1] (Typed Assembly Language) cu tastare strictă.

Versiunea compilatorului 1.0 a fost lansată pe 8 mai 2006. Se aplică termenilor GNU GPL versiunea 2.0. În prezent, proiectul este închis oficial cu formularea «obiectivele de cercetare realizate». Unele idei de design sunt folosite în limba de programare Rust.

Prezentarea limbajului

Cyclone se deosebește de C în primul rând prin scrierea mai strictă și dacă este necesar, introducerea controalelor runtime, de exemplu, respectarea limitelor matricei. Lucrarea cu indicii a fost extinsă și formalizată semnificativ, dar tehnicile de aritmetică a pointerilor care sunt familiare programatorilor C continuă să funcționeze. Limbajul a adăugat multe caracteristici convenabile din C++, C99 și GCC. A fost introdus un nou tip de date @tagged union — un analog al c-union, care păstrează informații despre tipul de date pe care îl stochează în prezent.

Cele mai mari inovații sunt legate de ideile împrumutate de lucru cu tipurile de date din limbajul ML. Este un sistem flexibil de tiparizare statică care facilitează descrierea diferitelor structuri recursive (liste, arbori etc.) și permite utilizarea polimorfismului și a programării generalizate. Programatorul poate controla complet procesul de potrivire a tipului. Cyclone acceptă inferența de tip.

Noua limbă este foarte apropiată de C, ceea ce permite cu un efort minim să transferați aplicațiile scrise în C la ea. Pana în prezent, creatorii Cyclone au reușit să dezvolte un server web simplu, care în opinia lor, este complet imun la erorile și vulnerabilitățile obișnuite.

Tipuri de pointeri

Cyclone implementează trei tipuri de pointer:

  • * (tip normal)
  • @ (Niciodată-NULL pointer), and
  • ? (singurul tip cu aritmetică pointer permis)

Scopul introducerii acestor noi tipuri de indicatori este de a evita problemele obișnuite atunci când folosiți indicii. Luați de exemplu o funcție, numită foo care ia un pointer la un int:

 int foo(int *);

Deși persoana care a scris funcția foo ar fi putut introduce cecuri NULL, să presupunem că, din motive de performanță, nu au făcut-o. Pentru a evita astfel de probleme, Cyclone introduce tipul de @ pointer, care nu poate fi niciodată NULL. Astfel, versiunea "sigură" a foo ar fi:

 int foo(int @);

Acest lucru îi spune compilatorului Cyclone că argumentul pentru foo nu ar trebui să fie niciodată NULL, evitând comportamentul nedefinit. Schimbarea simplă de la * la @ salvează programatorul de la faptul că trebuie să scrie verificări NULL, iar sistemul de operare să nu trebuiască să tragă dereferențele indicatorului NULL. Această limită suplimentară, totuși, poate fi un obstacol destul de mare pentru majoritatea programatorilor C, care sunt obișnuiți să-și poată manipula direct indicii cu aritmetica. Deși acest lucru este de dorit, poate duce la depășiri de buffer și la alte greșeli de tip "off-by-one". Pentru a evita acest lucru,? tipul de pointer este delimitat de o legatură cunoscută, de dimensiunea matricei. Luați, de exemplu, o funcție simplă strlen, scrisă în C:

 int strlen(const char *s)
 {
     int iter = 0;
     if (s == NULL)
        return 0;
     while (s[iter] != '\0') {
        iter++;
     }
     return iter;
 }

Această funcție presupune că șirul introdus este terminat de NULL ('\0'). Cu toate acestea, ce s-ar întâmpla dacă char buf[6] = {'h','e','l','l','o','!'}; au fost transmise acestui șir? Acest lucru este perfect legal în C, dar ar provoca strlen iterarea prin memorie neapărat asociată cu sirul s. Există funcții, cum ar fi strnlen, care pot fi utilizate pentru a evita astfel de probleme, însă aceste funcții nu sunt standard la fiecare implementare a ANSI C. Versiunea Cyclone a strlen nu este atât de diferită de versiunea C:

 int strlen(const char ? s)
 {
    int iter, n = s.size;
    if (s == NULL)
       return 0;
    for (iter = 0; iter < n; iter++, s++) {
       if (*s == '\0')
          return iter;
    }
    return n;
 }

Aici, strlen se limitează la lungimea matricei care îi este trecută, astfel încât nu trece peste lungimea reală. Fiecare dintre tipurile de tip pointer poate fi difuzat în condiții de siguranță pentru fiecare dintre celelalte, iar matricele și șirurile sunt distribuite automat ? de compilator.

Disponibilitatea indicatorilor și a analizei regiunilor

Luați în considerare următorul cod, în C:

 char *itoa(int i)
 {
    char buf[20];
    sprintf(buf,"%d",i);
    return buf;
 }

Funcția itoa alocă o mulțime de caractere buf pe stivă și returnează un pointer la începutul lui buf. Cu toate acestea, memoria folosită în stivă pentru buf este dealocată atunci când funcția revine, astfel încât valoarea returnată nu poate fi folosită în siguranță în afara funcției. În timp ce gcc și alți compilatori vor avertiza despre un astfel de cod, în mod obișnuit vor fi compilate fără avertismente:

 char *itoa(int i)
 {
    char buf[20], *z;
    sprintf(buf,"%d",i);
    z = buf;
    return z;
 }

gcc poate produce avertismente pentru un astfel de cod ca efect secundar al opțiunii -O2 sau -O3, dar nu există garanții că toate astfel de erori vor fi detectate. Cyclone face analize regionale ale fiecărui segment de cod, împiedicând afișarea indicatoarelor, cum ar fi cel returnat din această versiune de itoa. Toate variabilele locale într-un anumit domeniu de aplicare sunt considerate a fi parte a aceleiași regiuni, separate de halda sau de orice altă regiune locală. Astfel, atunci când analizăm itoa, compilatorul Cyclone va vedea că z este un pointer în stack-ul local și va raporta o eroare.

Note

Legături externe