2013-03-05 14 views
7

Mi sembra che le persone, soprattutto quando imparano il linguaggio di programmazione C, stiano ancora utilizzando la funzione gets per leggere i dati da stdin. Nonostante che ora è stato rimosso dallo standard C11, e un disclaimer sul cppreference legge:È stato sempre utile?

La ottiene (funzione) non esegue il controllo dei limiti, pertanto, questa funzione è estremamente vulnerabile al buffer overflow attacchi. Non è possibile utilizzare in modo sicuro (a meno che il programma non sia eseguito in un ambiente che limita ciò che può apparire su stdin). Per questo motivo, la funzione ha deprecato nella terza rettifica allo standard C99 e rimosso completamente nello standard C11. fgets() e gets_s() sono le sostituzioni consigliate da .

Non utilizzare mai gets().

Tuttavia, sembra che questo non sia un nuovo problema che ha prodotto filosofie di programmazione più moderne. Sarebbe sempre stato interrotto e avrebbe causato l'arresto anomalo dei programmi e non vedo cosa si possa intendere per "ambiente che limita ciò che può apparire su stdin".

Quindi, era sempre utile in passato? O qual è la ragione per cui è stata aggiunta agli standard precedenti e alle versioni pre-standard di C?


(1) ... o almeno modificati per avere un parametro aggiuntivo che indica la lunghezza massima di leggere. Sto chiedendo comunque della vecchia firma, ricevendo solo un puntatore.

+2

Da [le FAQ] (http://stackoverflow.com/faq) * "Dovresti solo porre domande pratiche e di risposta ** basate sui problemi reali che stai affrontando ** ..." * (la mia enfasi). –

+0

???? http://stackoverflow.com/questions/3302255/c-scanf-vs-gets-vs-fgets –

+1

@TJCrowder - dice anche "problemi che sono unici per la professione di programmatore", non chiederei sull'utilizzo dell'API al di fuori della professione di programmazione – Mike

risposta

5

Sì, è stato utile e "estremamente vulnerabile agli attacchi di buffer-overflow" allo stesso tempo.

sarebbe sempre stata rotta e hanno causato programmi di crash e non vedo cosa potrebbe essere inteso da un "ambiente che limita ciò che può apparire su stdin".

No, gets non ha causato l'arresto anomalo dei programmi. È principalmente un problema di sicurezza. Si può leggere su attacchi di tipo buffer overflow here

vedere anche questa domanda: Why is the gets function so dangerous that it should not be used?

+1

Come implicitamente affermato nel PO, queste sono contraddizioni. Se esimo il mio programma per bufferare i sovraccarichi chiamando 'gets', allora è distintamente ** non ** utile. La domanda chiede se ci fossero delle protezioni aggiuntive o, in caso contrario, perché "get" è stato definito com'era. – bitmask

+2

@bitmask Per me "utile" significa che può aiutare a raggiungere alcune funzionalità utili per l'utente. Un programma può essere utile e non sicuro allo stesso tempo ... – lbalazscs

+1

C è stato progettato negli anni '70. Allora, i sistemi in rete erano l'eccezione della norma e la sicurezza non era considerata importante come oggi. I dati sono stati generalmente considerati affidabili come il software. – Philipp

0

Gets è ancora utile per la prototipazione. È veloce da scrivere e produce risultati attesi per il programmatore, che è orientato a risolvere un problema a portata di mano invece di provare a far crollare il proprio programma.

+0

'fgets' è veloce da scrivere, davvero. Fornire le dimensioni del buffer e lo standard input FILE non è tanto un ostacolo. – bitmask

+0

@ bitmask: Il fastidio è dover usare strlen per trovare la nuova riga in modo che possa essere eliminata. – supercat

5

Quando si esaminano i resti dei primi giorni di C, è necessario considerare lo sfondo storico.

Il linguaggio C è stato progettato negli anni '70. Allora, i sistemi in rete erano l'eccezione della norma e la sicurezza non era considerata importante come oggi. I sistemi raramente funzionavano su dati di terze parti non attendibili. E anche quando lo facevano, non era considerato un grosso rischio. La tecnologia dell'informazione era ancora nella sua fase iniziale. Nessuno si è reso conto di quanto possano essere sensibili i sistemi informatici.

CPU time, d'altra parte, era prezioso.I programmi dovevano essere il più efficienti possibile.

Ecco perché la maggior parte delle funzioni della libreria C standard non esegue il controllo dei vincoli. Le prestazioni avevano una priorità molto più alta della sicurezza. Quando hai richiesto la sicurezza, dovevi convalidare i tuoi dati prima del inserendolo nel tuo programma.

Ma oggi, nel 21 ° secolo, in cui tutti i sistemi di computer sono interconnessi, tutti i sistemi informatici elaborano costantemente informazioni provenienti da origini non attendibili o addirittura sconosciute e l'hacking è un'industria da miliardi di dollari, la sicurezza è diventata la priorità numero uno per ogni programma informatico .

+0

Non stavo parlando di sicurezza nel senso attuale, ma piuttosto di robustezza. Ma il tuo argomento di velocità è molto buono, che potrebbe avere la precedenza su * sia * sicurezza e robustezza. – bitmask

2

Quando gets è stato inventato, pochissimi programmi dovevano essere in grado di accettare grandi quantità di input da fonti inaffidabili. gets è adeguato per un input limitato da un utente cooperante. Questo utente fornisce "l'ambiente che limita ciò che può apparire", non digitando molto su ogni riga. Potresti praticamente contare su un utente seduto a un terminale per non digitare centinaia di byte di dati in un prompt "y/n". Se hanno convogliato un grosso file nel tuo programma, quando il tuo programma non è stato progettato per questo, beh, hanno ottenuto risultati negativi.

I programmi che hanno dovuto gestire input arbitrari non hanno utilizzato gets.

Ora, l'input malevolo è comune nella pratica ed è più dannoso poiché esistono strumenti e tecniche che consentono agli aggressori di trasformare facilmente i buffer overflow a loro vantaggio. Un utente esperto che digita al prompt è un caso di nicchia. Inoltre, la contabilizzazione di input dannosi è ampiamente utilizzata come buona tecnica per garantire che il software sia robusto contro input inaspettati che lo non è stato inteso come attacco. Praticamente tutti i programmi dovrebbero gestire input arbitrari. Quindi gets è chiaramente inadeguato.