strcpy sur un char[1] ???

Le
Alain Montfranc
Bonjour

Dans un code source je trouve cela :

struct NAME
{
struct NAME * next;
char name[1];
};

puis :

strcpy(p->name, dp2->d_name);

Il me semble que strcpy copie jusqu'au premier ? A moins que la
chaine soit vide, ce genre de truc va forcément "déborder", non et
corrompre la stack ?
Vidéos High-Tech et Jeu Vidéo
Téléchargements
Vos réponses Page 1 / 2
Gagnez chaque mois un abonnement Premium avec GNT : Inscrivez-vous !
Trier par : date / pertinence
JKB
Le #16738071
Le 06-09-2008, à propos de
strcpy sur un char[1] ???,
Alain Montfranc écrivait dans fr.comp.lang.c :
Bonjour



Rebonjour ;-)

Dans un code source je trouve cela :

struct NAME
{
struct NAME * next;
char name[1];
};

puis :

strcpy(p->name, dp2->d_name);



Des noms, des noms, des noms ! ;-)

Il me semble que strcpy copie jusqu'au premier ? A moins que la
chaine soit vide, ce genre de truc va forcément "déborder", non et
corrompre la stack ?



Oui. Je site :

La fonction strcpy() copie la chaîne pointée par src, y compris le car
actère nul (« ») final dans la chaîne pointée par dest.

Ça déborde dès que la chaine source est de taille strictement supérieure
à 0

JKB

--
Le cerveau, c'est un véritable scandale écologique. Il représente 2% de notre
masse corporelle, mais disperse à lui seul 25% de l'énergie que nous
consommons tous les jours.
Erwan David
Le #16738061
Alain Montfranc
Bonjour

Dans un code source je trouve cela :

struct NAME
{
struct NAME * next;
char name[1];
};

puis :

strcpy(p->name, dp2->d_name);

Il me semble que strcpy copie jusqu'au premier ? A moins que la
chaine soit vide, ce genre de truc va forcément "déborder", non et
corrompre la stack ?



Tout dépend de comment a été alloué p.

--
Le travail n'est pas une bonne chose. Si ça l'était,
les riches l'auraient accaparé
Alain Montfranc
Le #16738331
Erwan David a écrit
Alain Montfranc
Bonjour

Dans un code source je trouve cela :

struct NAME
{
struct NAME * next;
char name[1];
};

puis :

strcpy(p->name, dp2->d_name);

Il me semble que strcpy copie jusqu'au premier ? A moins que la
chaine soit vide, ce genre de truc va forcément "déborder", non et
corrompre la stack ?



Tout dépend de comment a été alloué p.



Par un malloc. Ca change quoi ?
Alain Montfranc
Le #16738321
JKB a écrit
Le 06-09-2008, à propos de
strcpy sur un char[1] ???,
Alain Montfranc écrivait dans fr.comp.lang.c :
Bonjour



Rebonjour ;-)

Dans un code source je trouve cela :

struct NAME
{
struct NAME * next;
char name[1];
};

puis :

strcpy(p->name, dp2->d_name);



Des noms, des noms, des noms ! ;-)



openqm, version gpl


Il me semble que strcpy copie jusqu'au premier ? A moins que la
chaine soit vide, ce genre de truc va forcément "déborder", non et
corrompre la stack ?



Oui. Je site :

La fonction strcpy() copie la chaîne pointée par src, y compris le car
actère nul (« ») final dans la chaîne pointée par dest.

Ça déborde dès que la chaine source est de taille strictement supérieure
à 0

JKB



beurk quoi...
Erwan David
Le #16738451
Alain Montfranc
Erwan David a écrit
Alain Montfranc
Bonjour

Dans un code source je trouve cela :

struct NAME
{
struct NAME * next;
char name[1];
};

puis :

strcpy(p->name, dp2->d_name);

Il me semble que strcpy copie jusqu'au premier ? A moins que la
chaine soit vide, ce genre de truc va forcément "déborder", non et
corrompre la stack ?



Tout dépend de comment a été alloué p.



Par un malloc. Ca change quoi ?



malloc avec quelle taille ? C'est une technique classique en C pré 99
d'avoir une structure qui déclare un dernier composant qui est un
tableau de taille 1, mais la taille allouée est celle qu'il faut.



--
Le travail n'est pas une bonne chose. Si ça l'était,
les riches l'auraient accaparé
Alain Montfranc
Le #16738641
Erwan David a écrit
Alain Montfranc
Erwan David a écrit
Alain Montfranc
Bonjour

Dans un code source je trouve cela :

struct NAME
{
struct NAME * next;
char name[1];
};

puis :

strcpy(p->name, dp2->d_name);

Il me semble que strcpy copie jusqu'au premier ? A moins que la
chaine soit vide, ce genre de truc va forcément "déborder", non et
corrompre la stack ?



Tout dépend de comment a été alloué p.



Par un malloc. Ca change quoi ?



malloc avec quelle taille ? C'est une technique classique en C pré 99
d'avoir une structure qui déclare un dernier composant qui est un
tableau de taille 1, mais la taille allouée est celle qu'il faut.



ok
Antoine Leca
Le #16762061
En news:, JKB va escriure:
Le 06-09-2008, à propos de strcpy sur un char[1] ???,
Alain Montfranc écrivait dans fr.comp.lang.c :
struct NAME { struct NAME * next; char name[1]; };
strcpy(p->name, dp2->d_name);
Il me semble que strcpy copie jusqu'au premier ?



Oui. Je site :
La fonction strcpy() copie la chaîne pointée par src, y
compris le car actère nul (« ») final dans la chaîne
pointée par dest.



Et...

Ça déborde dès que la chaine source est de taille strictement
supérieure à 0




Cela ne déborde que si la chaîne finale (la vraie, pas la déclaration) a une
taille réservée inférieure à la taille réelle (strlen+1) de la chaîne
origine.

Et en C, du fait de l'équivalence pointeur-tableau, la déclaration
« visible » d'un tableau n'est pas forcément la déclaration réelle, en
particulier en ce qui concerne la taille du tableau.


Antoine
JKB
Le #16762051
Le 09-09-2008, à propos de
Re: strcpy sur un char[1] ???,
Antoine Leca écrivait dans fr.comp.lang.c :
En news:, JKB va escriure:
Le 06-09-2008, à propos de strcpy sur un char[1] ???,
Alain Montfranc écrivait dans fr.comp.lang.c :
struct NAME { struct NAME * next; char name[1]; };
strcpy(p->name, dp2->d_name);
Il me semble que strcpy copie jusqu'au premier ?



Oui. Je site :
La fonction strcpy() copie la chaîne pointée par src, y
compris le car actère nul (« ») final dans la chaîne
pointée par dest.



Et...

Ça déborde dès que la chaine source est de taille strictement
supérieure à 0




Cela ne déborde que si la chaîne finale (la vraie, pas la déclaration) a une
taille réservée inférieure à la taille réelle (strlen+1) de la chaîne
origine.

Et en C, du fait de l'équivalence pointeur-tableau, la déclaration
« visible » d'un tableau n'est pas forcément la déclaration réelle, en
particulier en ce qui concerne la taille du tableau.



Nous sommes d'accord, mais je réagissais avec le source sous les
yeux (ce fil est issu d'une discussion avec un psychopathe sur un
autre forum). Dans le code en question, une structure est déclarée,
et _jamais_ on ne contrôle que le strcpy ne va pas écraser quelque
chose.

Cordialement,

JKB

--
Le cerveau, c'est un véritable scandale écologique. Il représente 2% de notre
masse corporelle, mais disperse à lui seul 25% de l'énergie que nous
consommons tous les jours.
Antoine Leca
Le #16763241
En news:, JKB va escriure:
Antoine Leca écrivait dans fr.comp.lang.c :
Et en C, du fait de l'équivalence pointeur-tableau, la déclaration
« visible » d'un tableau n'est pas forcément la déclaration réelle,
en particulier en ce qui concerne la taille du tableau.



Nous sommes d'accord, mais je réagissais avec le source sous les
yeux [...]. Dans le code en question, une structure est déclarée,
et _jamais_ on ne contrôle que le strcpy ne va pas écraser quelque
chose.



Avec strcpy tout seul, il est virtuellement impossible de contrôler que tu
ne vas pas écraser quelque chose.

Problème, la logique de nommage de la norme semble proposer strncpy quand tu
veux contrôler, et pour des raisons historiques strncpy n'a pas cette
fonction ; il faudrait utiliser strlcpy qui n'est pas normalisée, ou
snprintf qui est d'une part C99 et d'autre part demande plus de ressources,
ou sprintf(,"%.*s",) qui demande aussi beaucoup de ressources et n'est pas
facile à relire car ce n'est pas « idiomatique »¹, ou strcpy_s qui est la
réponse officielle du comité mais n'est pas très répandue, voire strncpy_s
qui cumule tous les inconvénients : 4 arguments, sémantique différente à la
fois de strncpy et de strlcpy, peu utilisée, possibilité de mettre en jeu un
mécanisme d'exception à rebond multiple, fonction des implémentations et
potentiellement différent à la fois de signal/raise et de setjmp/longjmp.


Par ailleurs, et c'était mon propos ci-dessus, lorsque tu utilises
fct_qui_modifie_arg1(p->name, ...), la structure qui est déclarée pour &p
importe peu, c'est la structure réellement utilisée pour l'allocation qui
importe (le C a une règle spéciale pour permettre justement ce genre
d'utilisation); note bien que dans le cas d'une allocation dynamique, même
la déclaration utilisée pour l'allocation de la structure qui va être passée
ensuite dans le pointeur p [ouf!] n'importe pas vraiment, c'est en fait le
paramètre passé à malloc/calloc/realloc ou équivalent qui va déterminer
indirectement la taille des éléments de la structure.


Antoine
__________
¹: Techniquement c'est-à-dire dans le respect strict de la norme, s[n]printf
sont de plus limitées à des chaînes de 4095 caractères avec C99, voire 509
en C90.
JKB
Le #16763471
Le 09-09-2008, à propos de
Re: strcpy sur un char[1] ???,
Antoine Leca écrivait dans fr.comp.lang.c :
En news:, JKB va escriure:
Antoine Leca écrivait dans fr.comp.lang.c :
Et en C, du fait de l'équivalence pointeur-tableau, la déclaration
« visible » d'un tableau n'est pas forcément la déclaration réelle,
en particulier en ce qui concerne la taille du tableau.



Nous sommes d'accord, mais je réagissais avec le source sous les
yeux [...]. Dans le code en question, une structure est déclarée,
et _jamais_ on ne contrôle que le strcpy ne va pas écraser quelque
chose.



Avec strcpy tout seul, il est virtuellement impossible de contrôler que tu
ne vas pas écraser quelque chose.



Je sais bien, on contrôle les longueurs _avant_ d'appliquer le
strcpy. Ce qui n'est pas fait dans le code dont on parle.

Problème, la logique de nommage de la norme semble proposer strncpy quand tu
veux contrôler, et pour des raisons historiques strncpy n'a pas cette
fonction ; il faudrait utiliser strlcpy qui n'est pas normalisée, ou
snprintf qui est d'une part C99 et d'autre part demande plus de ressources,
ou sprintf(,"%.*s",) qui demande aussi beaucoup de ressources et n'est pas
facile à relire car ce n'est pas « idiomatique »¹, ou strcpy_s qui est la
réponse officielle du comité mais n'est pas très répandue, voire strncpy_s
qui cumule tous les inconvénients : 4 arguments, sémantique différente à la
fois de strncpy et de strlcpy, peu utilisée, possibilité de mettre en jeu un
mécanisme d'exception à rebond multiple, fonction des implémentations et
potentiellement différent à la fois de signal/raise et de setjmp/longjmp.


Par ailleurs, et c'était mon propos ci-dessus, lorsque tu utilises
fct_qui_modifie_arg1(p->name, ...), la structure qui est déclarée pour &p
importe peu, c'est la structure réellement utilisée pour l'allocation qui
importe (le C a une règle spéciale pour permettre justement ce genre
d'utilisation); note bien que dans le cas d'une allocation dynamique, même
la déclaration utilisée pour l'allocation de la structure qui va être passée
ensuite dans le pointeur p [ouf!] n'importe pas vraiment, c'est en fait le
paramètre passé à malloc/calloc/realloc ou équivalent qui va déterminer
indirectement la taille des éléments de la structure.



Nous sommes bien d'accord. Sauf que dans le cas présent, on alloue
une structure d'une certaine taille et on écrit brutalement
derrière. C'est assez casse-gueule comme manipulation. Note que je
ne parle que du code en question et non de la programmation C en
général.

Cordialement,

JKB

--
Le cerveau, c'est un véritable scandale écologique. Il représente 2% de notre
masse corporelle, mais disperse à lui seul 25% de l'énergie que nous
consommons tous les jours.
Publicité
Poster une réponse
Anonyme