Pourquoi utiliser asprintf() au lieu de sprintf()?
Je vais avoir du mal à comprendre pourquoi vous avez besoin de asprintf.
Ici, dans le manuel il est dit
Les fonctions
asprintf()
etvasprintf()
sont des analogues desprintf(3)
et
vsprintf(3)
, sauf qu'ils allouent une chaîne assez grand pour contenir
la sortie y compris l'octet nul final, et retourne un pointeur
par l'intermédiaire du premier argument. Ce pointeur doit être transmis à
free(3)
pour libérer le stockage alloué lorsqu'il n'est plus nécessaire.
Donc, voici l'exemple que j'essaie de comprendre:
asprintf(&buffer, "/bin/echo %s is cool", getenv("USER"));
Quelle est la différence si le tampon alloue une chaîne assez grand vs dire char* = (string)
asprintf()
etvasprintf()
sont des extensions GNU. Ajout de la GNU tag.- Hmm, je me demande si le demandeur est en train de faire les exercices ici: exploit-exercises.com/nebula/level02?
- Un très bon billet de blog sur ce sujet peuvent être trouvées ici: gestion de la mémoire-en-c-et-auto ... btw. le complet blog vaut la peine de lire
Vous devez vous connecter pour publier un commentaire.
Si vous utilisez
sprintf()
ouvsprintf()
, vous devez allouer un tampon en premier, et vous devez être sûr que le tampon est assez grand pour contenir ce que sprintf écrit. Sinonsprintf()
seront heureux de vous écraser toute la mémoire au-delà de la fin de la mémoire tampon.... écrit le '6' et la résiliation de
null
au-delà de la fin de l'espace alloué àx
, soit corrompre une autre variable, ou de provoquer une erreur de segmentation.Si vous avez de la chance, il va piétiner sur la mémoire entre les blocs alloués, et ne ferait pas de mal, cette fois. Cela conduit à des bugs -- le plus dur genre à diagnostiquer. C'est bien d'utiliser un outil comme ElectricFence que les causes des dépassements à l'échec-rapide.
Un non-utilisateur malveillant qui offre une très longs entrée, pourrait provoquer le programme à se comporter de manière inattendue. Un utilisateur malveillant pourrait exploiter ceci comme un moyen d'obtenir leur propre code exécutable dans le système.
Un garde contre c'est d'utiliser
snprintf()
, qui tronque la chaîne à la longueur maximale que vous fournissez.La valeur de retour
size
est la longueur que aurait été écrit si l'espace était disponible -- n'incluant pas la valeur null.Dans ce cas, si
size
est supérieur ou égal à 5, alors vous savez que la troncature s'est produite - et si vous ne voulez pas de troncature, vous pouvez affecter une nouvelle chaîne et essayersnprintf()
de nouveau.(c'est un assez naïve de l'algorithme, mais il illustre bien le propos)
asprintf()
fait tout cela en une seule étape, pour vous - calcule la longueur de la chaîne, alloue que la quantité de mémoire et écrit de la chaîne en elle.Dans tous les cas, une fois que vous avez fini avec
x
vous avez besoin de le sortir, ou vous avez une fuite de mémoire:asprintf()
est implicitemalloc()
, donc vous devez vérifier qu'il a travaillé, comme vous le feriez avecmalloc()
ou tout autre système d'appel.Noter que
asprintf()
fait partie de la GNU et BSD extensions pour libc - vous ne pouvez pas être sûr qu'il sera disponible dans toutes les C de l'environnement.sprintf()
etsnprintf()
font partie de la norme POSIX et C99 normes.malloc
(et sa famille) en C.size
est les caractères écrits sans valeur null, ne devriez-vous pas realloc(size+1) * sizeof(char)
?asprintf
est utile. L'ancienne méthode est très facile à visser en place.malloc()
snprintf
extrait de: 1. Vous souhaitez passer BUF_LEN pour la première snprintf(), pas 5! 2. Ce que vous devez fairex = realloc(x, (size + 1))
! realloc accepte un pointeur, pas un pointeur vers un pointeur! 3. La deuxième snprintf appel doit être (taille+1), et non pas 5!L'avantage est la sécurité.
De nombreux programmes ont permis à système exploite à se produire en ayant programmeur-fourni tampons débordé quand il est rempli avec les données fournies par les utilisateurs.
Avoir
asprintf
allouer de la mémoire tampon pour vous des garanties qui ne peuvent pas arriver.Cependant, vous doit vérifier la valeur de retour de
asprintf
pour s'assurer que l'allocation de mémoire réellement réussi. Voir http://blogs.23.nu/ilja/2006/10/antville-12995/sprintf
vous êtes forcé d'écrire votre propre fonction qui fait cela de toute façon, maintenant que vous avez tout enveloppé dans un seul prêt-à-fonction, au détriment de la portabilité.