Si dovrebbe mai uso gets
(o scanf
con una dimensione di stringa illimitata) dal momento che si apre fino a buffer overflow. Utilizzare lo fgets
con un handle stdin
poiché consente di limitare i dati che verranno inseriti nel buffer.
Ecco un piccolo frammento che uso per ingresso di linea da parte dell'utente:
#include <stdio.h>
#include <string.h>
#define OK 0
#define NO_INPUT 1
#define TOO_LONG 2
static int getLine (char *prmpt, char *buff, size_t sz) {
int ch, extra;
// Get line with buffer overrun protection.
if (prmpt != NULL) {
printf ("%s", prmpt);
fflush (stdout);
}
if (fgets (buff, sz, stdin) == NULL)
return NO_INPUT;
// If it was too long, there'll be no newline. In that case, we flush
// to end of line so that excess doesn't affect the next call.
if (buff[strlen(buff)-1] != '\n') {
extra = 0;
while (((ch = getchar()) != '\n') && (ch != EOF))
extra = 1;
return (extra == 1) ? TOO_LONG : OK;
}
// Otherwise remove newline and give string back to caller.
buff[strlen(buff)-1] = '\0';
return OK;
}
Questo mi permette di impostare la dimensione massima, in grado di rilevare se viene inserito troppi dati sulla linea, e sarà svuotare il resto della linea e quindi non influisce sulla successiva operazione di input.
È possibile testare con qualcosa di simile:
// Test program for getLine().
int main (void) {
int rc;
char buff[10];
rc = getLine ("Enter string> ", buff, sizeof(buff));
if (rc == NO_INPUT) {
// Extra NL since my system doesn't output that on EOF.
printf ("\nNo input\n");
return 1;
}
if (rc == TOO_LONG) {
printf ("Input too long [%s]\n", buff);
return 1;
}
printf ("OK [%s]\n", buff);
return 0;
}
non le librerie di sistema che implementano scanf impediscono l'overflow del comando (ho capito che all'interno del programma se lo sviluppatore non ha verificato l'input ci potrebbe essere un overflow, ma la libreria di sistema è sicura giusto?). – Marm0t
No, se si 'scanf ("% s ")' in un buffer da 20 byte e l'utente inserisce una riga da 40 byte, si è in stato di hosed. L'intero punto di 'scanf' è formattato per la scansione e c'è poco più _unformatted_ dell'input dell'utente :-) – paxdiablo
@ Marm0t - Pensa in questo modo considerando la seguente domanda: in che modo l'implementazione previene un overflow se tutto ciò che ottiene è un puntatore a una porzione di memoria (tipizzata come un char *) 'senza alcun parametro che indichi l'implementazione sulla dimensione del buffer di destinazione'? –