C'est à toi de savoir d'où vient les données.
Et si tu ne sais pas, imagine le pire. En informatique (et surtout en
sécurité informatique), le paranoïaque est encore optimiste.Du coup, j'aurais tendance à croire que ce genre de source passe
son temps à valider des données...
A valider les données extérieures, oui.
Au moment où tu es sûr que la ligne lue est conforme aux
spécifications.
Je dois dire que les expressions régulières/rationnelles seraient
parfaitement adaptées dans le cas présent : puisqu'on sait qu'il y a
exactement deux nombres entiers positifs sur chaque ligne, et que le
seul caractère possible est un espace, il suffit d'utiliser
l'expression "^ *([0-9]+) +([0-9]+) *$" et le tour est joué : soit la
ligne est conforme à cette expression, et les nombres sont 1 et 2,
soit la ligne n'est pas conforme, et le programme râle.
C'est différent : les données fournies à strcpy sont fournies par le
programme, pas lues depuis un fichier externe. Donc la fonction qui
appelle strcpy() doit faire les vérifications qu'elle juge utiles.
S'il est plus facile de faire un programme fiable en C++, ce langage
n'est pas sans ses pièges et comportements indéfinis. Une classe de
base sans destructeur virtuel vaut bien un char* utilisé sans rigueur.
Même sans attaques, si l'entrée n'est pas conforme aux spécifications,
ton programme doit l'indiquer, ne serait-ce que pour pouvoir déboguer
le programme qui crée cette entrée.
C'est à toi de savoir d'où vient les données.
Et si tu ne sais pas, imagine le pire. En informatique (et surtout en
sécurité informatique), le paranoïaque est encore optimiste.
Du coup, j'aurais tendance à croire que ce genre de source passe
son temps à valider des données...
A valider les données extérieures, oui.
Au moment où tu es sûr que la ligne lue est conforme aux
spécifications.
Je dois dire que les expressions régulières/rationnelles seraient
parfaitement adaptées dans le cas présent : puisqu'on sait qu'il y a
exactement deux nombres entiers positifs sur chaque ligne, et que le
seul caractère possible est un espace, il suffit d'utiliser
l'expression "^ *([0-9]+) +([0-9]+) *$" et le tour est joué : soit la
ligne est conforme à cette expression, et les nombres sont 1 et 2,
soit la ligne n'est pas conforme, et le programme râle.
C'est différent : les données fournies à strcpy sont fournies par le
programme, pas lues depuis un fichier externe. Donc la fonction qui
appelle strcpy() doit faire les vérifications qu'elle juge utiles.
S'il est plus facile de faire un programme fiable en C++, ce langage
n'est pas sans ses pièges et comportements indéfinis. Une classe de
base sans destructeur virtuel vaut bien un char* utilisé sans rigueur.
Même sans attaques, si l'entrée n'est pas conforme aux spécifications,
ton programme doit l'indiquer, ne serait-ce que pour pouvoir déboguer
le programme qui crée cette entrée.
C'est à toi de savoir d'où vient les données.
Et si tu ne sais pas, imagine le pire. En informatique (et surtout en
sécurité informatique), le paranoïaque est encore optimiste.Du coup, j'aurais tendance à croire que ce genre de source passe
son temps à valider des données...
A valider les données extérieures, oui.
Au moment où tu es sûr que la ligne lue est conforme aux
spécifications.
Je dois dire que les expressions régulières/rationnelles seraient
parfaitement adaptées dans le cas présent : puisqu'on sait qu'il y a
exactement deux nombres entiers positifs sur chaque ligne, et que le
seul caractère possible est un espace, il suffit d'utiliser
l'expression "^ *([0-9]+) +([0-9]+) *$" et le tour est joué : soit la
ligne est conforme à cette expression, et les nombres sont 1 et 2,
soit la ligne n'est pas conforme, et le programme râle.
C'est différent : les données fournies à strcpy sont fournies par le
programme, pas lues depuis un fichier externe. Donc la fonction qui
appelle strcpy() doit faire les vérifications qu'elle juge utiles.
S'il est plus facile de faire un programme fiable en C++, ce langage
n'est pas sans ses pièges et comportements indéfinis. Une classe de
base sans destructeur virtuel vaut bien un char* utilisé sans rigueur.
Même sans attaques, si l'entrée n'est pas conforme aux spécifications,
ton programme doit l'indiquer, ne serait-ce que pour pouvoir déboguer
le programme qui crée cette entrée.
Il ne faut jamais faire confiance aux données entrantes,
Jamais ?
Pour moi, ça dépend beaucoup d'où viennent les données entrantes.
En l'occurence ici, ce qui semble être un simple exercice, il ne doit
pas y avoir de trop grand danger.
pour éviter tout abus. Une grande partie des failles de sécurité
viennent justement du manque de rigueur dans la vérification de
l'input.
Il y a vraiment une faille de sécurite dans ce code ?
int v1, v2;
while( file >> v1 >> v2 )
;
En effet, comme le souligne drkm, il semble délicat de valider le
format en entrée du fichier mais à part ça.
Je ne suis pas spécialiste de le programmation en milieu 'hostile'
mais je ne suis pas sûr qu'il soit facile de trouver un fichier en
entrée permettant de prendre le contrôle de la machine ou autre.
Autant en C, il faut faire plus attention, autant en C++ je suis
beaucoup plus souple, les outils de la librairie C++ faisant le plus
gros du travail.
Il ne faut jamais faire confiance aux données entrantes,
Jamais ?
Pour moi, ça dépend beaucoup d'où viennent les données entrantes.
En l'occurence ici, ce qui semble être un simple exercice, il ne doit
pas y avoir de trop grand danger.
pour éviter tout abus. Une grande partie des failles de sécurité
viennent justement du manque de rigueur dans la vérification de
l'input.
Il y a vraiment une faille de sécurite dans ce code ?
int v1, v2;
while( file >> v1 >> v2 )
;
En effet, comme le souligne drkm, il semble délicat de valider le
format en entrée du fichier mais à part ça.
Je ne suis pas spécialiste de le programmation en milieu 'hostile'
mais je ne suis pas sûr qu'il soit facile de trouver un fichier en
entrée permettant de prendre le contrôle de la machine ou autre.
Autant en C, il faut faire plus attention, autant en C++ je suis
beaucoup plus souple, les outils de la librairie C++ faisant le plus
gros du travail.
Il ne faut jamais faire confiance aux données entrantes,
Jamais ?
Pour moi, ça dépend beaucoup d'où viennent les données entrantes.
En l'occurence ici, ce qui semble être un simple exercice, il ne doit
pas y avoir de trop grand danger.
pour éviter tout abus. Une grande partie des failles de sécurité
viennent justement du manque de rigueur dans la vérification de
l'input.
Il y a vraiment une faille de sécurite dans ce code ?
int v1, v2;
while( file >> v1 >> v2 )
;
En effet, comme le souligne drkm, il semble délicat de valider le
format en entrée du fichier mais à part ça.
Je ne suis pas spécialiste de le programmation en milieu 'hostile'
mais je ne suis pas sûr qu'il soit facile de trouver un fichier en
entrée permettant de prendre le contrôle de la machine ou autre.
Autant en C, il faut faire plus attention, autant en C++ je suis
beaucoup plus souple, les outils de la librairie C++ faisant le plus
gros du travail.
On Mon, 11 Oct 2004 22:23:55 +0200, David :
Je dois dire que les expressions régulières/rationnelles seraient
parfaitement adaptées dans le cas présent : puisqu'on sait qu'il y a
exactement deux nombres entiers positifs sur chaque ligne, et que le
seul caractère possible est un espace, il suffit d'utiliser
l'expression "^ *([0-9]+) +([0-9]+) *$" et le tour est joué : soit la
ligne est conforme à cette expression, et les nombres sont 1 et 2,
soit la ligne n'est pas conforme, et le programme râle.
Même sans attaques, si l'entrée n'est pas conforme aux spécifications,
ton programme doit l'indiquer, ne serait-ce que pour pouvoir déboguer
le programme qui crée cette entrée.
On Mon, 11 Oct 2004 22:23:55 +0200, David <dfleury2@libertysurf.fr>:
Je dois dire que les expressions régulières/rationnelles seraient
parfaitement adaptées dans le cas présent : puisqu'on sait qu'il y a
exactement deux nombres entiers positifs sur chaque ligne, et que le
seul caractère possible est un espace, il suffit d'utiliser
l'expression "^ *([0-9]+) +([0-9]+) *$" et le tour est joué : soit la
ligne est conforme à cette expression, et les nombres sont 1 et 2,
soit la ligne n'est pas conforme, et le programme râle.
Même sans attaques, si l'entrée n'est pas conforme aux spécifications,
ton programme doit l'indiquer, ne serait-ce que pour pouvoir déboguer
le programme qui crée cette entrée.
On Mon, 11 Oct 2004 22:23:55 +0200, David :
Je dois dire que les expressions régulières/rationnelles seraient
parfaitement adaptées dans le cas présent : puisqu'on sait qu'il y a
exactement deux nombres entiers positifs sur chaque ligne, et que le
seul caractère possible est un espace, il suffit d'utiliser
l'expression "^ *([0-9]+) +([0-9]+) *$" et le tour est joué : soit la
ligne est conforme à cette expression, et les nombres sont 1 et 2,
soit la ligne n'est pas conforme, et le programme râle.
Même sans attaques, si l'entrée n'est pas conforme aux spécifications,
ton programme doit l'indiquer, ne serait-ce que pour pouvoir déboguer
le programme qui crée cette entrée.
mais pour ce qui
est d'une simple validité de format de fichier, je
ne vois qu'un simple agrément de confort permettant
d'indiquer une erreur de l'utilisateur.
mais pour ce qui
est d'une simple validité de format de fichier, je
ne vois qu'un simple agrément de confort permettant
d'indiquer une erreur de l'utilisateur.
mais pour ce qui
est d'une simple validité de format de fichier, je
ne vois qu'un simple agrément de confort permettant
d'indiquer une erreur de l'utilisateur.
std::istringstream s( line ) ;
line >> i >> j >> std::ws ;
if ( ! line || line.peek() != EOF ) {
// erreur...
}
En fait, si quelque part il y a une ligne qui manque un nombre, si tu ne
vérifies pas ligne par ligne, tu ne détectes l'erreur qu'à la fin.
La question fondamentale, c'est qu'est-ce qu'on va faire avec les
erreurs qu'on détecte. Mon expérience suggère qu'on va afficher
l'erreur. Avec son numéro de ligne, pour que l'utilisateur peut le
rétrouver facilement. Dans ce cas-là, la lecture ligne par ligne est
tout à fait indiquée, pour faciliter aussi le comptage des lignes.
std::istringstream s( line ) ;
line >> i >> j >> std::ws ;
if ( ! line || line.peek() != EOF ) {
// erreur...
}
En fait, si quelque part il y a une ligne qui manque un nombre, si tu ne
vérifies pas ligne par ligne, tu ne détectes l'erreur qu'à la fin.
La question fondamentale, c'est qu'est-ce qu'on va faire avec les
erreurs qu'on détecte. Mon expérience suggère qu'on va afficher
l'erreur. Avec son numéro de ligne, pour que l'utilisateur peut le
rétrouver facilement. Dans ce cas-là, la lecture ligne par ligne est
tout à fait indiquée, pour faciliter aussi le comptage des lignes.
std::istringstream s( line ) ;
line >> i >> j >> std::ws ;
if ( ! line || line.peek() != EOF ) {
// erreur...
}
En fait, si quelque part il y a une ligne qui manque un nombre, si tu ne
vérifies pas ligne par ligne, tu ne détectes l'erreur qu'à la fin.
La question fondamentale, c'est qu'est-ce qu'on va faire avec les
erreurs qu'on détecte. Mon expérience suggère qu'on va afficher
l'erreur. Avec son numéro de ligne, pour que l'utilisateur peut le
rétrouver facilement. Dans ce cas-là, la lecture ligne par ligne est
tout à fait indiquée, pour faciliter aussi le comptage des lignes.
pour ce qui
est d'une simple validité de format de fichier, je
ne vois qu'un simple agrément de confort permettant
d'indiquer une erreur de l'utilisateur.
C'est différent : les données fournies à strcpy sont fournies par le
programme, pas lues depuis un fichier externe. Donc la fonction qui
appelle strcpy() doit faire les vérifications qu'elle juge utiles.
Je ne crois pas que je soit d'accord.
Je ne vois pas de différence, la validité des données
pourraient vérifiées aussi bien dans ce cas.
Si un programmeur utilise ma librairie, j'ai pas de raison
de faire confiance aux données qu'il passera en paramètre
de ma fonction, pas plus qu'un fichier que je lirais d'un flux
d'entrée.
pour ce qui
est d'une simple validité de format de fichier, je
ne vois qu'un simple agrément de confort permettant
d'indiquer une erreur de l'utilisateur.
C'est différent : les données fournies à strcpy sont fournies par le
programme, pas lues depuis un fichier externe. Donc la fonction qui
appelle strcpy() doit faire les vérifications qu'elle juge utiles.
Je ne crois pas que je soit d'accord.
Je ne vois pas de différence, la validité des données
pourraient vérifiées aussi bien dans ce cas.
Si un programmeur utilise ma librairie, j'ai pas de raison
de faire confiance aux données qu'il passera en paramètre
de ma fonction, pas plus qu'un fichier que je lirais d'un flux
d'entrée.
pour ce qui
est d'une simple validité de format de fichier, je
ne vois qu'un simple agrément de confort permettant
d'indiquer une erreur de l'utilisateur.
C'est différent : les données fournies à strcpy sont fournies par le
programme, pas lues depuis un fichier externe. Donc la fonction qui
appelle strcpy() doit faire les vérifications qu'elle juge utiles.
Je ne crois pas que je soit d'accord.
Je ne vois pas de différence, la validité des données
pourraient vérifiées aussi bien dans ce cas.
Si un programmeur utilise ma librairie, j'ai pas de raison
de faire confiance aux données qu'il passera en paramètre
de ma fonction, pas plus qu'un fichier que je lirais d'un flux
d'entrée.
Il ne faut jamais faire confiance aux données entrantes,
Jamais ?
Jamais.
Danger, ça dépend de quoi. « Garbage in, garbage out », comme on dit. Si
le fichier d'entrée n'est pas du bon format, c'est qu'il est erroné.
Garbage, donc. Un bon programme le reconnaît, et signale l'erreur.
Tu ne programmes pas sous Windows, in sur un système Unix ? Tu ne lis
jamais de fichiers ?
À vrai dire, à part une meilleur gestion des types, je ne vois pas la
différence. On a même réinventer gets (>> vers un char*).
Il ne faut jamais faire confiance aux données entrantes,
Jamais ?
Jamais.
Danger, ça dépend de quoi. « Garbage in, garbage out », comme on dit. Si
le fichier d'entrée n'est pas du bon format, c'est qu'il est erroné.
Garbage, donc. Un bon programme le reconnaît, et signale l'erreur.
Tu ne programmes pas sous Windows, in sur un système Unix ? Tu ne lis
jamais de fichiers ?
À vrai dire, à part une meilleur gestion des types, je ne vois pas la
différence. On a même réinventer gets (>> vers un char*).
Il ne faut jamais faire confiance aux données entrantes,
Jamais ?
Jamais.
Danger, ça dépend de quoi. « Garbage in, garbage out », comme on dit. Si
le fichier d'entrée n'est pas du bon format, c'est qu'il est erroné.
Garbage, donc. Un bon programme le reconnaît, et signale l'erreur.
Tu ne programmes pas sous Windows, in sur un système Unix ? Tu ne lis
jamais de fichiers ?
À vrai dire, à part une meilleur gestion des types, je ne vois pas la
différence. On a même réinventer gets (>> vers un char*).
La situation est tout de même différente
Une fonction de
bibliothèque peut se décharger de responsabiltés sur son utilisateur.
Si ce dernier ne remplit pas le contrat d'utilisation, tant pis pour
lui.
Mais je vois mal un programme faire la même chose : « il y a moyen
d'obtenir un buffer overflow, mais j'indique dans mes préconditions
que vous ne pouvez pas utiliser ce type d'entrée, donc tout va bien ».
La situation est tout de même différente
Une fonction de
bibliothèque peut se décharger de responsabiltés sur son utilisateur.
Si ce dernier ne remplit pas le contrat d'utilisation, tant pis pour
lui.
Mais je vois mal un programme faire la même chose : « il y a moyen
d'obtenir un buffer overflow, mais j'indique dans mes préconditions
que vous ne pouvez pas utiliser ce type d'entrée, donc tout va bien ».
La situation est tout de même différente
Une fonction de
bibliothèque peut se décharger de responsabiltés sur son utilisateur.
Si ce dernier ne remplit pas le contrat d'utilisation, tant pis pour
lui.
Mais je vois mal un programme faire la même chose : « il y a moyen
d'obtenir un buffer overflow, mais j'indique dans mes préconditions
que vous ne pouvez pas utiliser ce type d'entrée, donc tout va bien ».
Une fonction de
bibliothèque peut se décharger de responsabiltés sur son utilisateur.
Si ce dernier ne remplit pas le contrat d'utilisation, tant pis pour
lui.
Mais je vois mal un programme faire la même chose : « il y a moyen
d'obtenir un buffer overflow, mais j'indique dans mes préconditions
que vous ne pouvez pas utiliser ce type d'entrée, donc tout va bien ».
Sur cet exemple, je n'ai pas eu un exemple de buffer overflow.
Une fonction de
bibliothèque peut se décharger de responsabiltés sur son utilisateur.
Si ce dernier ne remplit pas le contrat d'utilisation, tant pis pour
lui.
Mais je vois mal un programme faire la même chose : « il y a moyen
d'obtenir un buffer overflow, mais j'indique dans mes préconditions
que vous ne pouvez pas utiliser ce type d'entrée, donc tout va bien ».
Sur cet exemple, je n'ai pas eu un exemple de buffer overflow.
Une fonction de
bibliothèque peut se décharger de responsabiltés sur son utilisateur.
Si ce dernier ne remplit pas le contrat d'utilisation, tant pis pour
lui.
Mais je vois mal un programme faire la même chose : « il y a moyen
d'obtenir un buffer overflow, mais j'indique dans mes préconditions
que vous ne pouvez pas utiliser ce type d'entrée, donc tout va bien ».
Sur cet exemple, je n'ai pas eu un exemple de buffer overflow.
Il ne faut jamais faire confiance aux données entrantes,
Jamais ?
Jamais.
Ma confiance me perdra ;-)Danger, ça dépend de quoi. « Garbage in, garbage out », comme on
dit. Si le fichier d'entrée n'est pas du bon format, c'est qu'il est
erroné. Garbage, donc. Un bon programme le reconnaît, et signale
l'erreur.
Le "Garbage In, Garbage Out" me va bien. Si l'utilsateur n'est pas
capable de fournir un fichier en entrée, pourquoi serait-il capable de
comprendre le fichier de sortie (qu'il soit bon ou mauvais) ?
Tu ne programmes pas sous Windows, in sur un système Unix ? Tu ne
lis jamais de fichiers ?
Si, je passe pas mal de temps à ça. Mes les fichiers reçus
ne sont pas là pour faire planter le traitement.
Mais je vérifie les données fonctionnelles, pas le format du fichier.
Si je reçois en fichier posant un pb sur le format de fichier, je me
pose d'abord la question sur le programme qui m'a généré le fichier.
Ce ne sont jamais des fichiers écris à la main (ce qui simplifie le
problème).
À vrai dire, à part une meilleur gestion des types, je ne vois pas
la différence. On a même réinventer gets (>> vers un char*).
l'équivalent d'un :
std::string line;
while( getline( file, line ) )
;
en C est vraiment hors de portée d'un simple débutant.
Il ne faut jamais faire confiance aux données entrantes,
Jamais ?
Jamais.
Ma confiance me perdra ;-)
Danger, ça dépend de quoi. « Garbage in, garbage out », comme on
dit. Si le fichier d'entrée n'est pas du bon format, c'est qu'il est
erroné. Garbage, donc. Un bon programme le reconnaît, et signale
l'erreur.
Le "Garbage In, Garbage Out" me va bien. Si l'utilsateur n'est pas
capable de fournir un fichier en entrée, pourquoi serait-il capable de
comprendre le fichier de sortie (qu'il soit bon ou mauvais) ?
Tu ne programmes pas sous Windows, in sur un système Unix ? Tu ne
lis jamais de fichiers ?
Si, je passe pas mal de temps à ça. Mes les fichiers reçus
ne sont pas là pour faire planter le traitement.
Mais je vérifie les données fonctionnelles, pas le format du fichier.
Si je reçois en fichier posant un pb sur le format de fichier, je me
pose d'abord la question sur le programme qui m'a généré le fichier.
Ce ne sont jamais des fichiers écris à la main (ce qui simplifie le
problème).
À vrai dire, à part une meilleur gestion des types, je ne vois pas
la différence. On a même réinventer gets (>> vers un char*).
l'équivalent d'un :
std::string line;
while( getline( file, line ) )
;
en C est vraiment hors de portée d'un simple débutant.
Il ne faut jamais faire confiance aux données entrantes,
Jamais ?
Jamais.
Ma confiance me perdra ;-)Danger, ça dépend de quoi. « Garbage in, garbage out », comme on
dit. Si le fichier d'entrée n'est pas du bon format, c'est qu'il est
erroné. Garbage, donc. Un bon programme le reconnaît, et signale
l'erreur.
Le "Garbage In, Garbage Out" me va bien. Si l'utilsateur n'est pas
capable de fournir un fichier en entrée, pourquoi serait-il capable de
comprendre le fichier de sortie (qu'il soit bon ou mauvais) ?
Tu ne programmes pas sous Windows, in sur un système Unix ? Tu ne
lis jamais de fichiers ?
Si, je passe pas mal de temps à ça. Mes les fichiers reçus
ne sont pas là pour faire planter le traitement.
Mais je vérifie les données fonctionnelles, pas le format du fichier.
Si je reçois en fichier posant un pb sur le format de fichier, je me
pose d'abord la question sur le programme qui m'a généré le fichier.
Ce ne sont jamais des fichiers écris à la main (ce qui simplifie le
problème).
À vrai dire, à part une meilleur gestion des types, je ne vois pas
la différence. On a même réinventer gets (>> vers un char*).
l'équivalent d'un :
std::string line;
while( getline( file, line ) )
;
en C est vraiment hors de portée d'un simple débutant.