Quali sono i vantaggi in termini di sicurezza di un sistema di tipi?

46

In JavaScript: The Good Parts di Douglas Crockford, menziona nel suo capitolo sull'eredità,

The other benefit of classical inheritance is that it includes the specification of a system of types. This mostly frees the programmer from having to write explicit casting operations, which is a very good thing because when casting, the safety benefits of a type system are lost.

Quindi, prima di tutto, cos'è effettivamente la sicurezza? protezione contro la corruzione dei dati, hacker, malfunzionamenti del sistema, ecc.?

Quali sono i vantaggi in termini di sicurezza di un sistema di tipi? Che cosa rende un sistema di tipi diverso che gli consente di fornire questi vantaggi in termini di sicurezza?

    
posta MistakesWereMade 24.10.2013 - 19:31
fonte

8 risposte

81

I sistemi di tipi evitano errori

I sistemi di tipo eliminano i programmi illegali. Considera il seguente codice Python.

 a = 'foo'
 b = True
 c = a / b

In Python, questo programma fallisce; lancia un'eccezione. In un linguaggio come Java, C #, Haskell , qualunque cosa, questo non è nemmeno un programma legale. Evitate completamente questi errori perché semplicemente non sono possibili nel set di programmi di input.

Allo stesso modo, un sistema di tipo migliore esclude più errori. Se passiamo a sistemi di tipo super avanzati possiamo dire cose del genere:

 Definition divide x (y : {x : integer | x /= 0}) = x / y

Ora il sistema di tipi garantisce che non vi siano errori di divisione per 0.

Che tipo di errori

Ecco un breve elenco di ciò che gli errori possono impedire ai sistemi di tipo

  1. Errori fuori range
  2. Iniezione SQL
  3. Generalizzazione di 2, molti problemi di sicurezza (quali controllo dell'inquinamento si trovano in Perl )
  4. Errori fuori sequenza (dimenticando di chiamare init)
  5. Forzare un sottoinsieme di valori da utilizzare (ad esempio, solo numeri interi maggiori di 0)
  6. Nefarious kittens (Sì, era uno scherzo)
  7. Errori di perdita di precisione
  8. Errori di memoria transazionale software (STM) (questo richiede purezza, che richiede anche tipi)
  9. Generalizzazione di 8, controllo degli effetti collaterali
  10. Invarianti su strutture dati (è un albero binario bilanciato?)
  11. Dimentica un'eccezione o lancia quella sbagliata

E ricorda, questo è anche al momento compilazione . Non è necessario scrivere test con copertura del 100% del codice per controllare semplicemente gli errori di tipo, il compilatore lo fa per te:)

Case study: calcolo lambda tipizzato

Bene, esaminiamo il più semplice dei sistemi di tutti i tipi, semplicemente calcolo lambda tipizzato .

Fondamentalmente ci sono due tipi,

Type = Unit | Type -> Type

E tutti i termini sono variabili, lambda o applicazione. Sulla base di questo, possiamo dimostrare che qualsiasi programma ben scritto termina. Non c'è mai una situazione in cui il programma si bloccherà o si interromperà per sempre. Questo non è dimostrabile nel normale calcolo lambda perché, beh, non è vero.

Pensa a questo, possiamo usare i sistemi di tipi per garantire che il nostro programma non si interrompa per sempre, piuttosto bello vero?

Deviazione in tipi dinamici

I sistemi di tipi dinamici possono offrire garanzie identiche come sistemi di tipo statico, ma in fase di esecuzione anziché in fase di compilazione. In realtà, dal momento che è runtime, puoi effettivamente offrire più informazioni. Tuttavia, si perdono alcune garanzie, in particolare per quanto riguarda le proprietà statiche come la terminazione.

Quindi i tipi dinamici non escludono determinati programmi, ma indirizzano programmi malformati a azioni ben definite, come l'eccezione di lancio.

TLDR

Quindi il lungo e il corto di esso, è che i sistemi di tipi escludono certi programmi. Molti programmi sono interrotti in qualche modo, quindi con i sistemi di tipi evitiamo questi programmi guasti.

    
risposta data 24.10.2013 - 19:58
fonte
16

La realtà stessa è scritta. Non è possibile aggiungere lunghezze ai pesi. E mentre puoi aggiungere piedini ai metri (entrambi sono unità di lunghezza), dovresti ridimensionare almeno uno dei due. Non riuscendo a farlo, puoi mandare in crash la tua missione su Marte, letteralmente.

In un sistema typesafe, l'aggiunta di due lunghezze espresse in unità diverse sarebbe stata un errore o avrebbe causato un cast automatico.

    
risposta data 25.10.2013 - 08:54
fonte
15

Un sistema di tipo ti aiuta ad evitare errori di codifica semplici, o piuttosto permette al compilatore di rilevare quegli errori per te.

Ad esempio, in JavaScript e Python, spesso il problema seguente viene rilevato solo in fase di esecuzione e, in base alla qualità del test, la rarità della condizione può effettivamente arrivare alla produzione:

if (someRareCondition)
     a = 1
else
     a = {1, 2, 3}

// 10 lines below
k = a.length

Mentre un linguaggio strongmente tipizzato ti costringerà a dichiarare esplicitamente che a è un array e non ti permetterà di assegnare un intero. In questo modo, non c'è alcuna possibilità che a non abbia length - anche nei casi più rari.

    
risposta data 24.10.2013 - 20:14
fonte
5

Quanto prima nel ciclo di sviluppo del software è possibile rilevare un errore, tanto meno è costoso da risolvere. Considera un errore che causa la perdita dei dati del tuo cliente più grande o di tutti i tuoi clienti. Un tale errore potrebbe essere la fine della tua azienda se viene catturata solo dopo che i clienti reali hanno perso i dati! È chiaramente meno costoso trovare e correggere questo bug prima di spostarlo in produzione.

Anche per gli errori meno costosi, vengono spesi più tempo ed energia se i tester sono coinvolti rispetto a quando i programmatori possono trovarli e ripararli. È più economico se non viene controllato nel controllo del codice sorgente dove altri programmatori possono creare software basato su di esso. La sicurezza del tipo previene alcune classi di errori anche dalla compilazione, eliminando così quasi l'intero costo potenziale di tali errori.

Ma non è tutta la storia. Come qualcuno che programma in un linguaggio dinamico ti dirà, alcune volte è bello se il tuo programma si compila in modo da poter provare una parte di esso senza ottenere ogni piccolo dettaglio per risolverlo. C'è un compromesso tra sicurezza e convenienza. I test unitari possono mitigare parte del rischio di usare un linguaggio dinamico, ma scrivere e mantenere buoni test unitari ha il suo costo che può essere più alto di quello di usare un linguaggio sicuro per il tipo.

Se stai sperimentando, se il tuo codice sarà usato una sola volta (come un rapporto una tantum), se sei in una situazione in cui non ti preoccuperai di scrivere comunque un test unitario, allora un linguaggio dinamico è probabilmente perfetto per te. Se si dispone di un'applicazione di grandi dimensioni e si desidera modificare una parte senza interrompere il resto, digitare la sicurezza è un salvataggio. I tipi di errori di sicurezza sono esattamente il tipo di errori che gli umani tendono a ignorare o sbagliare durante il refactoring.

    
risposta data 24.10.2013 - 21:49
fonte
4

Introduzione

La sicurezza del tipo può essere ottenuta con linguaggi tipicamente statici (compilati, di tipo statico) e / o runtime (valutati, dinamici). Secondo Wikipedia un '... sistema di tipo strong è descritto come uno in cui non vi è alcuna possibilità di un errore di tipo runtime non controllato (ed Luca Cardelli). In altri scritti, l'assenza di errori di run-time non controllati viene definita sicurezza o sicurezza del tipo ... '

Sicurezza: controllo del tipo statico

Classicamente, la sicurezza di tipo è stata sinonimo di tipizzazione statica, in linguaggi come C, C ++ e Haskell, che sono progettati per rilevare errori di corrispondenza di tipo quando vengono compilati. Ciò ha il vantaggio di evitare condizioni potenzialmente indefinite o soggette a errori quando il programma viene eseguito. Questo può essere inestimabile quando c'è il rischio che i tipi di puntatori possano essere erroneamente abbinati, ad esempio, una situazione che potrebbe portare a conseguenze catastrofiche se non rilevata. In questo senso la tipizzazione statica è considerata sinonimo di sicurezza della memoria.

La tipizzazione statica è non completamente sicura ma migliora la sicurezza , tuttavia. Anche i sistemi tipizzati staticamente possono avere conseguenze catastrofiche. Molti esperti ritengono che sia possibile utilizzare la tipizzazione statica per scrivere sistemi più robusti e meno soggetti a errori (mission critical).

Le lingue tipizzate staticamente possono contribuire a ridurre il rischio di perdita di dati o perdita di precisione nel lavoro numerico, che può verificarsi a causa di errata corrispondenza o troncamento integrale di float o mis-matching e float.

C'è un vantaggio nell'uso di linguaggi tipizzati staticamente per efficienza e velocità di esecuzione. Il runtime beneficia di non dover determinare i tipi durante l'esecuzione.

Sicurezza: controllo del tipo di runtime

Erlang, ad esempio, è di tipo dichiarativo, digita dinamicamente il linguaggio controllato che viene eseguito su una macchina virtuale. Il codice di Erlang può essere compilato in byte. Erlang è considerato forse il più importante linguaggio mission-critical, tollerante ai guasti disponibile, ed è stato riferito che Erlang ha una affidabilità di nove 9 (99.9999999% o non più di 31.5 msecs all'anno).

Alcune lingue, come Common Lisp, non sono tipizzate staticamente, ma possono essere dichiarate se lo si desidera, il che può aiutare a migliorare la velocità e l'efficienza. È anche da notare che molti dei linguaggi interpretati più ampiamente usati, come Python, sono, sotto il ciclo di valutazione, scritti in linguaggi tipizzati staticamente come C o C ++. Sia Commom Lisp che Python sono considerati sicuri rispetto alla definizione precedente.

    
risposta data 24.10.2013 - 21:09
fonte
1

the safety benefits of a type system are lost.

So first of all, what actually is safety? protection against data corruption, or hackers, or system malfunctions, etc.?

What are the safety benefits of a type system? What makes a type system different that allows it to provide these safety benefits?

Mi sento come se i sistemi di tipo avessero una visione così negativa. Un sistema di tipo riguarda più la garanzia che l'assenza di errori. Quest'ultimo è una conseguenza del sistema di tipi. Un sistema di tipi per un linguaggio di programmazione è un modo per produrre, in fase di compilazione, una prova che un programma soddisfa un qualche tipo di specifica.

Il tipo di specifica che si può codificare come tipo dipende dalla lingua, o più direttamente, dal punto di vista del sistema di tipi della lingua.

Il tipo più basilare di specifiche è una garanzia sul comportamento di input / output delle funzioni e sulla validità dell'interno di un corpo di una funzione. Considera un'intestazione di funzione

f : (Int,Int) -> String

Un buon sistema di tipi si assicurerà che f sia applicato solo agli oggetti che produrranno una coppia di Int quando valuterà, e garantisce che f produrrà sempre una stringa.

Alcune istruzioni in una lingua, come if-then blocks, non hanno un comportamento di input / output; qui il sistema tipo garantisce che ogni dichiarazione o dichiarazione nel blocco è valida; questo vale per le operazioni sugli oggetti del tipo corretto. Queste garanzie sono componibili.

Inoltre, questo fornisce una sorta di condizione di sicurezza della memoria. La citazione che hai a che fare riguarda il casting. In alcuni casi, il casting va bene, come il casting di un Int a 32 bit a un Int a 64 bit. Tuttavia, generalmente, si blocca il sistema di tipi.

Si consideri

Foo x = new Foo(3,4,5,6);
f((Int)x,(Int)x);

A causa del casting, x è trasformato in un Int, quindi tecnicamente il precedente controllo del tipo; tuttavia, sconfigge davvero lo scopo di typechecking.

Una cosa che potrebbe rendere un sistema di tipo diverso e migliore è dissuadere i cast (A) x dove x prima che il caso sia di tipo B, a meno che B non sia un sottotipo (o subobject) di A. Le idee della teoria di sottotipizzazione sono state utilizzato in sicurezza per rimuovere la possibilità di attacchi con overflow / underflow interi.

Riepilogo

Un sistema di tipi è un modo per dimostrare che un programma soddisfa un qualche tipo di specifica. I vantaggi che un sistema di tipi può fornire dipendono dalla forza del sistema di tipi utilizzato.

    
risposta data 12.12.2013 - 09:29
fonte
1

Un vantaggio non ancora menzionato per un sistema di tipi è incentrato sul fatto che molti programmi sono letti più di quanto siano scritti, e in molti casi un sistema di tipi può consentire di specificare molte informazioni in un modo che è conciso e può essere facilmente digerito da qualcuno che legge il codice. Mentre i tipi di parametri non prendono il posto dei commenti descrittivi, la maggior parte delle persone lo troverà più veloce da leggere: "int Distance;" o Distance As Int32 che leggere "La distanza deve essere un numero intero +/- 2147483647"; le frazioni passate possono produrre risultati incoerenti. "Inoltre, i tipi di parametri possono aiutare a ridurre il divario tra ciò che una determinata implementazione di API fa, rispetto a ciò su cui i chiamanti possono fare affidamento.Ad esempio, se una particolare implementazione Javascript di un'API utilizza i suoi parametri in un modo che costringono qualsiasi stringa alla forma numerica, potrebbe non essere chiaro se ai chiamanti è permesso fare affidamento su tale comportamento, o se altre implementazioni dell'API potrebbero funzionare male se date stringhe Avere un metodo il cui parametro è specificato come Double renderebbe chiaro che qualsiasi valore stringa deve essere forzato dal chiamante prima di essere passato, avendo un metodo con un sovraccarico che accetta Double e un altro che accetta String renderebbe più chiaro che i chiamanti che tengono stringhe sarebbero consentiti per passarli come tali.

    
risposta data 28.03.2015 - 19:00
fonte
0

So first of all, what actually is safety? Protection against data corruption, or hackers, or system malfunctions, etc.?

Tutte le altre risposte e altro. In generale, "type safety" significa semplicemente che nessuno dei programmi compilati da un compilatore conterrà errori di tipo.

Ora, che cos'è un errore di tipo? In linea di principio, è possibile specificare qualsiasi proprietà indesiderata come errore di tipo, e alcuni sistemi di tipi saranno in grado di garantire staticamente che nessun programma abbia tale errore.

Per "proprietà" sopra, intendo un tipo di proposizione logica che si applica al tuo programma, ad esempio, "tutti gli indici sono entro i limiti dell'array". Altri tipi di proprietà includono "tutti i puntatori differiti sono validi", "questo programma non esegue alcun I / O" o "questo programma esegue solo I / O su / dev / null", ecc. Quasi ogni tipo di la proprietà può essere specificata e il tipo controllato in questo modo, a seconda dell'espressività del tuo sistema di tipi.

I sistemi di tipi dipendenti sono tra i più generici di sistemi di tipi, tramite i quali è possibile applicare praticamente qualsiasi proprietà che ti piace. Tuttavia, non è necessariamente facile farlo, poiché le proprietà sofisticate sono soggette a incompletezza per gentile concessione di Gödel .

    
risposta data 25.10.2013 - 03:16
fonte

Leggi altre domande sui tag