Now when a compiler runs printf("%s", text);, it would look into the stack and go to the address 5054. However what about printf(text)? How does it access the address of 5054 to print "%s" which after printing might result to a segmentation fault?
Non è così. Nel caso in cui l'utente immetta "% s" come input, ci saranno due stringhe in posizioni diverse, entrambe contenenti "% s": la costante di stringa dal secondo printf
, e text
array di caratteri contenenti l'input dell'utente.
Ecco cosa sta succedendo in modo più dettagliato:
printf("%s", text);
In questo caso, il primo argomento è una costante di stringa. Quindi, il compilatore crea una stringa contenente "% s" e la aggiunge a una tabella di costanti di stringa da qualche parte in memoria (diciamo all'indirizzo 5054). Quando viene chiamato questo printf
, l'indirizzo della costante di stringa (5054) viene posizionato nello stack, insieme all'indirizzo della matrice text
. (L'ordine in cui vengono inseriti nello stack dipende dall'ordine push dell'argomento, ma di solito è da destra a sinistra). Quindi l'indirizzo di esecuzione corrente viene posto nello stack o in un registro speciale (in modo che la CPU possa tornare dalla funzione) e la CPU salta all'indirizzo della funzione printf
. La funzione printf
valuta la stringa di formattazione e quando trova% s, appare sullo stack per il secondo argomento (l'indirizzo della stringa text
) e lo stampa.
printf(text);
In questo esempio, solo l'indirizzo dell'argomento di testo viene inserito nello stack. Quindi l'indirizzo di esecuzione viene salvato e la CPU salta all'indirizzo della funzione printf
, come prima. L'indirizzo della costante di stringa (5054) non è posizionato sullo stack, perché non c'è una costante di stringa nell'elenco di argomenti della funzione.
In questo caso, la funzione printf
valuta la stringa di formattazione, e quando trova% s che l'utente ha inserito, cerca lo stack per il secondo argomento, ma non ce n'è uno, quindi qualsiasi cosa fosse attiva lo stack verrà letto, trattato come l'indirizzo di una stringa, de-referenziato per stamparlo e probabilmente si verificherà un errore di segmentazione.
printf
è una funzione Variadic , il che significa che può richiedere un numero variabile di argomenti. Si basa sull'analisi di runtime della stringa di formattazione per determinare quanti argomenti (dovrebbero) sono stati passati ad esso. Questo è ciò che rende vulnerabile ai dati dannosi: il contenuto della stringa di formattazione non corrisponde al numero di argomenti effettivamente passati.