Domanda

EDIT: ho aggiunto la fonte per l'esempio.

Mi sono imbattuto questo esempio:

char source[MAX] = "123456789";
char source1[MAX] = "123456789";
char destination[MAX] = "abcdefg";
char destination1[MAX] = "abcdefg";
char *return_string;
int index = 5;

/* This is how strcpy works */
printf("destination is originally = '%s'\n", destination);
return_string = strcpy(destination, source);
printf("after strcpy, dest becomes '%s'\n\n", destination);

/* This is how strncpy works */
printf( "destination1 is originally = '%s'\n", destination1 );
return_string = strncpy( destination1, source1, index );
printf( "After strncpy, destination1 becomes '%s'\n", destination1 );

Che ha prodotto questo output:

destination is originally = 'abcdefg'
After strcpy, destination becomes '123456789'

destination1 is originally = 'abcdefg'
After strncpy, destination1 becomes '12345fg'

Il che mi fa chiedere perché qualcuno vorrebbe questo effetto. Sembra che sarebbe confuso. Questo programma mi fa pensare che potresti praticamente copiare sul nome di qualcuno (ad es. Tom Brokaw) con Tom Bro763.

Quali sono i vantaggi dell'utilizzo strncpy() Sopra strcpy()?

È stato utile?

Soluzione

strncpy Combatti l'overflow del buffer richiedendo di metterci una lunghezza. strcpy Dipende da un trailing \0, che potrebbe non verificarsi sempre.

In secondo luogo, perché hai scelto di copiare solo 5 caratteri su 7 caratteri è al di là di me, ma produce comportamenti previsti. Sta solo copiando il primo n personaggi, dove n è il terzo argomento.

Il n Le funzioni sono tutte utilizzate come codifica difensiva contro gli overflow del buffer. Si prega di usarli al posto delle funzioni più vecchie, come strcpy.

Altri suggerimenti

Il strncpy() La funzione è stata progettata pensando a un problema molto particolare: manipolando le stringhe memorizzate alla maniera delle voci di directory UNIX originali. Questi utilizzavano un array di dimensioni fisse e un NUL-terminatore veniva utilizzato solo se il nome file era più corto dell'array.

Questo è ciò che c'è dietro le due stranezze di strncpy():

  • Non mette un NUL-terminatore sulla destinazione se è completamente riempito; e
  • Riempi sempre completamente la destinazione, se necessario.

Per un "più sicuro strcpy()", Stai meglio usando strncat() così:

if (dest_size > 0)
{
    dest[0] = '\0';
    strncat(dest, source, dest_size - 1);
}

Ciò terminerà sempre il risultato e non copierà più del necessario.

Mentre conosco l'intento dietro strncpy, non è davvero una buona funzione. Evitare entrambi. Raymond Chen spiega.

Personalmente, la mia conclusione è semplicemente da evitare strncpy E tutti i suoi amici se hai a che fare con stringhe di terminazione null. Nonostante lo "STR" nel nome, queste funzioni non producono stringhe terminate nulle. Convertono una stringa con terminazione nulla in un buffer di caratteri grezzi. Usandoli in cui è prevista una stringa con terminazione nullo poiché il secondo buffer è semplice. Non solo non riesci a ottenere una corretta risoluzione nulla se la fonte è troppo lunga, ma se la fonte è breve si ottiene imbottitura nulla inutile.

Guarda anche Perché Strncpy è insicuro?

Strncpy non è più sicuro di strcpy, scambia solo un tipo di bug con un altro. In C, quando si maneggia le corde C, è necessario conoscere le dimensioni dei buffer, non c'è modo di aggirarlo. Strncpy era giustificato per la cosa della directory menzionata da altri, ma per il resto, non dovresti mai usarlo:

  • Se conosci la lunghezza della tua stringa e buffer, perché usare strncpy? È uno spreco di potenza di calcolo nella migliore delle ipotesi (aggiungendo inutile 0)
  • Se non conosci le lunghezze, rischi di troncare silenziosamente le stringhe, il che non è molto meglio di un overflow tampone

Quello che stai cercando è la funzione strlcpy() che termina sempre la stringa con 0 e inizializza il buffer. È anche in grado di rilevare overflow. L'unico problema, non è (davvero) portatile ed è presente solo su alcuni sistemi (BSD, Solaris). Il problema con questa funzione è che apre un'altra lattina di vermi come si può vedere dalle discussioni suhttp://en.wikipedia.org/wiki/strlcpy

La mia opinione personale è che è molto più utile di strncpy() e strcpy(). Ha prestazioni migliori ed è un buon compagno snprintf(). Per piattaforme che non lo hanno, è relativamente facile da implementare. (Per la fase di sviluppo di un'applicazione, sostituisco queste due funzioni (snprintf() e strlcpy()) con una versione di intrappolamento che aborta brutalmente il programma su overflow o troncati del buffer. Ciò consente di catturare rapidamente i peggiori trasgressori. Soprattutto se lavori su una base di codice da qualcun altro.

MODIFICARE: strlcpy() può essere implementato facilmente:

size_t strlcpy(char *dst, const char *src, size_t dstsize)
{
  size_t len = strlen(src);
  if(dstsize) {
    size_t bl = (len < dstsize-1 ? len : dstsize-1);
    ((char*)memcpy(dst, src, bl))[bl] = 0;
  }
  return len;
}

Il strncpy() La funzione è quella più sicura: è necessario passare la massima lunghezza che il buffer di destinazione può accettare. Altrimenti potrebbe accadere che la stringa di origine non sia terminata correttamente 0, nel qual caso il strcpy() La funzione potrebbe scrivere più caratteri a destinazione, corrompendo tutto ciò che è nella memoria dopo il buffer di destinazione. Questo è il problema del buffer-overrun utilizzato in molti exploit

Anche per le funzioni API POSIX come read() che non mette la terminazione 0 nel buffer, ma restituisce il numero di byte letti, metterai manualmente lo 0 o lo copierai usando strncpy().

Nel tuo codice di esempio, index in realtà non è un indice, ma a count - racconta quanti personaggi al massimo da copiare dall'origine a destinazione. Se non esiste un byte nullo tra i primi n byte di origine, la stringa inserita a destinazione non verrà terminata nulla

strncpy riempie la destinazione con ' 0' per la dimensione della sorgente, anche se la dimensione della destinazione è più piccola ....

MANPAGE:

Se la lunghezza di SRC è inferiore a n, strncpy () imbevra il resto di DEST con byte null.

E non solo il resto ... anche dopo questo fino a quando non vengono raggiunti i personaggi. E così ottieni un overflow ... (vedi l'implementazione della pagina Man)

Questo può essere usato in molti altri scenari, in cui è necessario copiare solo una parte della stringa originale nella destinazione. Usando strncpy () è possibile copiare una parte limitata della stringa originale rispetto a strcpy (). Vedo che il codice che hai messo viene da publib.boulder.ibm.com.

Dipende dal nostro requisito. Per gli utenti di Windows

Usiamo strncpy ogni volta che non vogliamo copiare l'intera stringa o vogliamo copiare solo n numero di caratteri. Ma Strcpy copia l'intera stringa incluso il carattere null terminale.

Questi collegamenti ti aiuteranno di più a conoscere Strcpy e Strncpy e dove possiamo usare.

su strcpy

su strncpy

La strncpy è una versione più sicura di strcpy in realtà non dovresti mai usare strcpy perché la sua potenziale vulnerabilità di overflow del buffer che ti rende vulnerabile il sistema a tutti i tipi di attacchi

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top