logo Homepage
+  NewbieContest
|-+  Programmation» Langages compilés» [C/C++] sockets et strcat()
Username:
Password:
Pages: [1]
  Imprimer  
Auteur Fil de discussion: [C/C++] sockets et strcat()  (Lu 3873 fois)
lilxam
Profil challenge

Classement : 130/54314

Membre Complet
***
Hors ligne Hors ligne
Messages: 154


Voir le profil WWW
« le: 26 Janvier 2007 à 20:48:11 »

Bonjout tout le monde. Bon voilà j'ai deux questions en C/C++.
     La premiere, je ne trouve pas comment executer une commande MS-DOS à partir du client sur le serveur avec les sockets. Un peu comme avec netcat l'option -e.
     La seconde, j'ai quelques probleme avec la fonction strcat() que je n'arrive pas à résoudre.
Avec ce code tout marche :

     char chaine1[100] = "hello";
     char chaine2[] = " world";
     strcat (chaine1, chaine2);
     cout <<"Chaine1 : " <<chaine1;

Parcontre, si je définis les chaines autrement j'obtient des resultats pas très convaiquant...
Code :
    char chaine1[]="";
    cout <<"chaine1 : ";
    cin >> chaine1;

    char chaine2[]="";
    cout <<"chaine2 : ";
    cin >> chaine2;
    strcat(chaine1, chaine2);
    cout <<"resultat : "<<chaine1;
Et là ...le resultat me renvoi un peu n'importe quoi, les caracteres pas dans l'ordre par exemple.

Donc voici mes deux problemes, j'espère avoir été clair.
Journalisée

Pourquoi faire simple quand on peut faire compliquer ?
_o_
Relecteur

Profil challenge

Classement : 42/54314

Membre Héroïque
*
Hors ligne Hors ligne
Messages: 1258


Voir le profil
« #1 le: 27 Janvier 2007 à 00:33:50 »

Citation de: lilxam
[SNIP]
    char chaine1[]="";
    cout <<"chaine1 : ";
    cin >> chaine1;
[SNIP]

Et là ...le resultat me renvoi un peu n'importe quoi, les caracteres pas dans l'ordre par exemple.
Tu as du bol. Sur le linux que j'ai sous la main, c'est segmentation fault direct. Et pourquoi donc ? Rien à voir avec strcat  : http://www.eskimo.com/~scs/cclass/notes/sx4aa.html

Citation
if the dimension is omitted, it is inferred from the size of the string initializer.
Autrement dit, la ligne char chaine1[]=""; ne fait qu'allouer un tableau de... 0 caractères (ou peut-être un quand même, pour loger le zéro teminal). Lorsque l'on tente de rentrer quelque chose là dedans, boum ! Un buffer overflow.

Tu as juste la chance d'avoir un compilo ou un os assez laxiste qui ne le signale pas. Tu jardines donc joyeusement dans la mémoire avec tes saisies et ton strcat et le résultat est... imprévisible.

Donc, un tableau de caractères statiques demande au moins une taille maximum. Et qui plus est, puisqu'on est sur NC, on n'oublie pas d'utiliser des fonctions de manipulations de chaîne robustes, pour éviter les buffer-overflows, soit, dans notre cas : strncat (méfiance avec ces trucs là, ça ne règle pas tous les problèmes, cf. le strncpy de la plupart des Unix, qui dans un cas particulier, omet le caractère terminal à la fin de la copie ! Un comble.)

Quant à savoir comment limiter le nombre de caractères saisis sur le cin pour éviter de déborder les chaînes en paramètres, ça, je ne sais pas, je connais très peu le C++...  (http://forum.hardware.fr/images/perso/spamafote.gif)
Journalisée

Les épreuves de hack de NC sont trop faciles ? Et pourtant ! Bienvenue dans la vraie vie : http://thedailywtf.com/Articles/So-You-Hacked-Our-Site!.aspx
Invit
Invité
« #2 le: 27 Janvier 2007 à 02:45:12 »

On ne peut pas parser cin à priori, ça fait partie des choses à pas utiliser en général, enfin... D'un point de vue sécurité c'est complètement aléatoire en tout cas, au même titre qu'un gets (char *) en C.
Ca revient à se poser la question si on fait confiance aux données entrantes ou pas, en théorie jamais (et en théorie encore plus théorique, même pas au sein de tes propres fonctions dans ton programme, tu check tout le temps).

Edith:
Au temps pour moi, après recherche on peut parser cin avec les manipulateurs de iomanip
http://cowww.epfl.ch/infgmel/miniref/miniref-flots.html

Citation
string code;
cin >> setw(5) >> code;

Lit uniquement 5 caractères.
Evidemment on parle en C++ là, en C on aura :
Code:
char code[6];                          // les données sont initialisées à 0 implicitement
fscanf (stdin, "%5s", code);      // on récupère 5 octets
Journalisée
neoflo
Profil challenge

Classement : 8124/54314

Membre Complet
***
Hors ligne Hors ligne
Messages: 171


Voir le profil WWW
« #3 le: 27 Janvier 2007 à 10:37:21 »

Citation de: BufferBob
char code[6];                          // les données sont initialisées à 0 implicitement
Ceci est faux. Le tableau est passé sur la pile (ce qui fait juste changer le pointeur de pile) mais n'initialises pas toutes les données sur la pile à 0.

Code:
#include <stdio.h>
#include <stdlib.h>

void f(void)
{
  int tab[5];
  int i;
  for(i = 0; i<5;i++)
    printf("%d ", tab[i]);

  tab[4] = 2;
  printf("\n");
}


int main(void)
{
  f();
  f();
 return 0;
}
Tu pourras constater que les résultats ne valent pas tous le temps 0. Tu pourras même constater qu'au deuxième appel de f. on retrouve tab[4] qui affiche 2 car la pile est exactement dans la même configuration qu'avant (et elle n'a pas été effacée)

L'exécution me donne :
Code:
2009118740 4013192 4013104 8 2009116333
2009118740 4013192 4013104 8 2
Mais ceci dépend de la configuration de la pile au moment de l'appel évidemment.
Journalisée

neoflo
Profil challenge

Classement : 8124/54314

Membre Complet
***
Hors ligne Hors ligne
Messages: 171


Voir le profil WWW
« #4 le: 27 Janvier 2007 à 10:51:45 »

Chose amusante (mais ça peut vite changer) , le code :

Code:
#include <stdio.h>
#include <stdlib.h>

void salut(void)
{
 char tab[5] =  {'s', 'a','l','u', 't'};
 tab[0] = 's';
}

void g(void)
{
char tab[5];
int i;
for(i = 0; i<5; i++)
  printf("%c", tab[i]);

 printf("\n");
}

int main()
{
 salut();
 g();

return 0;
}
Affiche salut
Journalisée

lilxam
Profil challenge

Classement : 130/54314

Membre Complet
***
Hors ligne Hors ligne
Messages: 154


Voir le profil WWW
« #5 le: 27 Janvier 2007 à 11:07:30 »

Ok merci pour vos réponses
Journalisée

Pourquoi faire simple quand on peut faire compliquer ?
Invit
Invité
« #6 le: 27 Janvier 2007 à 14:22:52 »

Citation de: neoflo
Ceci est faux. Le tableau est passé sur la pile (ce qui fait juste changer le pointeur de pile) mais n'initialises pas toutes les données sur la pile à 0.
Ma foi, au temps pour moi (bis), je rectifie donc le code;
Code:
char code[6];

memset (code, 0, 6);             // on trouvera d'autres solutions pour mettre à 0, une boucle for() ou un appel à bzero() sous BSD..
fscanf (stdin, "%5s", code);
ou encore
Code:
char *code = (char *) calloc (6, sizeof (char));       // les données sont allouées dynamiquement (sur le tas), calloc() initialise à 0.
fscanf (stdin, "%5s", code);
En plus c'est erreur vraiment idiote, un truc que je savais, mais j'ai lu ça y'a pas longtemps je sais plus où, un article très sérieux ou un livre de référence sur le C, ça m'a induit en erreur sans réelle bonne raison et j'ai pas tilté du tout que le gars disait n'importe quoi
Journalisée
Pages: [1]
  Imprimer  
 
Aller à: