Pour commencer, j'ai l'impression qu'il y a des soucis potentiels/
théoriques de portabilité, par exemple :
/* Return 1 if condition is true, 0 otherwise */
int ct_isnonzero_u32(uint32_t x)
{
return (x|-x)>>31;
}
On va dire qu'on se limite aux plateformes où uint32_t existe, de toutes
façons si c'est pas le cas ça se verra vite à la compilation :)
Pour commencer, j'ai l'impression qu'il y a des soucis potentiels/
théoriques de portabilité, par exemple :
/* Return 1 if condition is true, 0 otherwise */
int ct_isnonzero_u32(uint32_t x)
{
return (x|-x)>>31;
}
On va dire qu'on se limite aux plateformes où uint32_t existe, de toutes
façons si c'est pas le cas ça se verra vite à la compilation :)
Pour commencer, j'ai l'impression qu'il y a des soucis potentiels/
théoriques de portabilité, par exemple :
/* Return 1 if condition is true, 0 otherwise */
int ct_isnonzero_u32(uint32_t x)
{
return (x|-x)>>31;
}
On va dire qu'on se limite aux plateformes où uint32_t existe, de toutes
façons si c'est pas le cas ça se verra vite à la compilation :)
On va dire qu'on se limite aux plateformes où uint32_t existe, de
toutes façons si c'est pas le cas ça se verra vite à la compilation
:)
/* Return 1 if condition is true, 0 otherwise */
int ct_isnonzero_u32(uint32_t x) { return (x|-x)>>31; }
Imaginons par contre que le compilo ait choisit des int de 64 bits.
[...] une des options raisonnables pour une implémentation (propager
le bit de signe) ne donne pas le résultat attendu
Bien sûr la seule solution sûre, c'est d'écrire les parties critiques
en assembleur directement,
On va dire qu'on se limite aux plateformes où uint32_t existe, de
toutes façons si c'est pas le cas ça se verra vite à la compilation
:)
/* Return 1 if condition is true, 0 otherwise */
int ct_isnonzero_u32(uint32_t x) { return (x|-x)>>31; }
Imaginons par contre que le compilo ait choisit des int de 64 bits.
[...] une des options raisonnables pour une implémentation (propager
le bit de signe) ne donne pas le résultat attendu
Bien sûr la seule solution sûre, c'est d'écrire les parties critiques
en assembleur directement,
On va dire qu'on se limite aux plateformes où uint32_t existe, de
toutes façons si c'est pas le cas ça se verra vite à la compilation
:)
/* Return 1 if condition is true, 0 otherwise */
int ct_isnonzero_u32(uint32_t x) { return (x|-x)>>31; }
Imaginons par contre que le compilo ait choisit des int de 64 bits.
[...] une des options raisonnables pour une implémentation (propager
le bit de signe) ne donne pas le résultat attendu
Bien sûr la seule solution sûre, c'est d'écrire les parties critiques
en assembleur directement,
Le 13/03/2015 00:33Z, Manuel Pégourié-Gonnard écrivit :On va dire qu'on se limite aux plateformes où uint32_t existe, de
toutes façons si c'est pas le cas ça se verra vite à la compilation :)
Et les techniques pour éviter les fuites d'information en fonction du
temps d'exécution sur les PDP-10 ou les Univac avec des char de 9 bits,
je ne sais pas si c'est ce qui importe le plus...
/* Return 1 if condition is true, 0 otherwise */
int ct_isnonzero_u32(uint32_t x) { return (x|-x)>>31; }
Imaginons par contre que le compilo ait choisit des int de 64 bits.
[...] une des options raisonnables pour une implémentation (propager le
bit de signe) ne donne pas le résultat attendu
Bah, c'est comme d'habitude en fait. Tu rajoutes du code pour traiter un
(supposé) problème, et au passage tu rajoutes de bogues.
Là où c'est plus inquiétant, c'est qu'un texte de prescription sur la
sûreté (ou la sécurité) ne soit pas un tant soit peu sérieux sur ce
risque, alors que par exemple cela fait maintenant 18 ans que les RFC de
l'IETF doivent nécessairement inclure un alinéa sur l'impact prçu en
terme de sécurité des prescriptions du texte...
Bien sûr la seule solution sûre, c'est d'écrire les parties critiques
en assembleur directement,
Même pas. Cf. Ken Thomson, "Reflection on trusting trust." Si tu ne fais
pas confiance au compilateur C, pourquoi diable devrais-tu faire
confiance à l'assembleur ?
Et si tu écris le programme toi-même en langage machine, et que tu le
programmes aux clés, qu'est-ce qui te dit que le micro-programme du
silicium ne va pas lui-même faire ses propres modifications, par exemple
réorganiser tes décalages soigneusement réarrangé, repérer que tout cela
revient à juste tester si x (OK, le registre 8) vaut ou pas zéro, et
reprogrammer par exemple en un saut prédictif au niveau de l'appel de
cette fonction ?
:-)
Le 13/03/2015 00:33Z, Manuel Pégourié-Gonnard écrivit :
On va dire qu'on se limite aux plateformes où uint32_t existe, de
toutes façons si c'est pas le cas ça se verra vite à la compilation :)
Et les techniques pour éviter les fuites d'information en fonction du
temps d'exécution sur les PDP-10 ou les Univac avec des char de 9 bits,
je ne sais pas si c'est ce qui importe le plus...
/* Return 1 if condition is true, 0 otherwise */
int ct_isnonzero_u32(uint32_t x) { return (x|-x)>>31; }
Imaginons par contre que le compilo ait choisit des int de 64 bits.
[...] une des options raisonnables pour une implémentation (propager le
bit de signe) ne donne pas le résultat attendu
Bah, c'est comme d'habitude en fait. Tu rajoutes du code pour traiter un
(supposé) problème, et au passage tu rajoutes de bogues.
Là où c'est plus inquiétant, c'est qu'un texte de prescription sur la
sûreté (ou la sécurité) ne soit pas un tant soit peu sérieux sur ce
risque, alors que par exemple cela fait maintenant 18 ans que les RFC de
l'IETF doivent nécessairement inclure un alinéa sur l'impact prçu en
terme de sécurité des prescriptions du texte...
Bien sûr la seule solution sûre, c'est d'écrire les parties critiques
en assembleur directement,
Même pas. Cf. Ken Thomson, "Reflection on trusting trust." Si tu ne fais
pas confiance au compilateur C, pourquoi diable devrais-tu faire
confiance à l'assembleur ?
Et si tu écris le programme toi-même en langage machine, et que tu le
programmes aux clés, qu'est-ce qui te dit que le micro-programme du
silicium ne va pas lui-même faire ses propres modifications, par exemple
réorganiser tes décalages soigneusement réarrangé, repérer que tout cela
revient à juste tester si x (OK, le registre 8) vaut ou pas zéro, et
reprogrammer par exemple en un saut prédictif au niveau de l'appel de
cette fonction ?
:-)
Le 13/03/2015 00:33Z, Manuel Pégourié-Gonnard écrivit :On va dire qu'on se limite aux plateformes où uint32_t existe, de
toutes façons si c'est pas le cas ça se verra vite à la compilation :)
Et les techniques pour éviter les fuites d'information en fonction du
temps d'exécution sur les PDP-10 ou les Univac avec des char de 9 bits,
je ne sais pas si c'est ce qui importe le plus...
/* Return 1 if condition is true, 0 otherwise */
int ct_isnonzero_u32(uint32_t x) { return (x|-x)>>31; }
Imaginons par contre que le compilo ait choisit des int de 64 bits.
[...] une des options raisonnables pour une implémentation (propager le
bit de signe) ne donne pas le résultat attendu
Bah, c'est comme d'habitude en fait. Tu rajoutes du code pour traiter un
(supposé) problème, et au passage tu rajoutes de bogues.
Là où c'est plus inquiétant, c'est qu'un texte de prescription sur la
sûreté (ou la sécurité) ne soit pas un tant soit peu sérieux sur ce
risque, alors que par exemple cela fait maintenant 18 ans que les RFC de
l'IETF doivent nécessairement inclure un alinéa sur l'impact prçu en
terme de sécurité des prescriptions du texte...
Bien sûr la seule solution sûre, c'est d'écrire les parties critiques
en assembleur directement,
Même pas. Cf. Ken Thomson, "Reflection on trusting trust." Si tu ne fais
pas confiance au compilateur C, pourquoi diable devrais-tu faire
confiance à l'assembleur ?
Et si tu écris le programme toi-même en langage machine, et que tu le
programmes aux clés, qu'est-ce qui te dit que le micro-programme du
silicium ne va pas lui-même faire ses propres modifications, par exemple
réorganiser tes décalages soigneusement réarrangé, repérer que tout cela
revient à juste tester si x (OK, le registre 8) vaut ou pas zéro, et
reprogrammer par exemple en un saut prédictif au niveau de l'appel de
cette fonction ?
:-)
Samuel DEVULDER a écrit :
Le 13/03/2015 01:33, Manuel Pégourié-Gonnard a écrit :
> Pour commencer, j'ai l'impression qu'il y a des soucis potentiels/
> théoriques de portabilité, par exemple :
>
> /* Return 1 if condition is true, 0 otherwise */
> int ct_isnonzero_u32(uint32_t x)
> {
> return (x|-x)>>31;
> }
>
> On va dire qu'on se limite aux plateformes où uint32_t existe, de toutes
> façons si c'est pas le cas ça se verra vite à la compilation :)
En fait le problème du code ci-dessus est qu'il ne marche que si x est
encodé en binaire *complément à deux*. Sur les machines binaires
*complément à un*, ca ne marche pas car ca retournera toujours 1 (-x et
~x sont identique dans cette représentation)
Samuel DEVULDER a écrit :
Le 13/03/2015 01:33, Manuel Pégourié-Gonnard a écrit :
> Pour commencer, j'ai l'impression qu'il y a des soucis potentiels/
> théoriques de portabilité, par exemple :
>
> /* Return 1 if condition is true, 0 otherwise */
> int ct_isnonzero_u32(uint32_t x)
> {
> return (x|-x)>>31;
> }
>
> On va dire qu'on se limite aux plateformes où uint32_t existe, de toutes
> façons si c'est pas le cas ça se verra vite à la compilation :)
En fait le problème du code ci-dessus est qu'il ne marche que si x est
encodé en binaire *complément à deux*. Sur les machines binaires
*complément à un*, ca ne marche pas car ca retournera toujours 1 (-x et
~x sont identique dans cette représentation)
Samuel DEVULDER a écrit :
Le 13/03/2015 01:33, Manuel Pégourié-Gonnard a écrit :
> Pour commencer, j'ai l'impression qu'il y a des soucis potentiels/
> théoriques de portabilité, par exemple :
>
> /* Return 1 if condition is true, 0 otherwise */
> int ct_isnonzero_u32(uint32_t x)
> {
> return (x|-x)>>31;
> }
>
> On va dire qu'on se limite aux plateformes où uint32_t existe, de toutes
> façons si c'est pas le cas ça se verra vite à la compilation :)
En fait le problème du code ci-dessus est qu'il ne marche que si x est
encodé en binaire *complément à deux*. Sur les machines binaires
*complément à un*, ca ne marche pas car ca retournera toujours 1 (-x et
~x sont identique dans cette représentation)
> /* Return 1 if condition is true, 0 otherwise */
> int ct_isnonzero_u32(uint32_t x)
> {
> return (x|-x)>>31;
> }
>
En fait le problème du code ci-dessus est qu'il ne marche que si x est
encodé en binaire *complément à deux*. Sur les machines binaires
*complément à un*, ca ne marche pas car ca retournera toujours 1 (-x et
~x sont identique dans cette représentation)
Ah oui, bien vu, j'avais totalement manqué ce problème des zéros
négatifs (qui se pose aussi en représentation signe-magnitude).
return ((uint32_t) x | (uint32_t) -x) >> 31;
> /* Return 1 if condition is true, 0 otherwise */
> int ct_isnonzero_u32(uint32_t x)
> {
> return (x|-x)>>31;
> }
>
En fait le problème du code ci-dessus est qu'il ne marche que si x est
encodé en binaire *complément à deux*. Sur les machines binaires
*complément à un*, ca ne marche pas car ca retournera toujours 1 (-x et
~x sont identique dans cette représentation)
Ah oui, bien vu, j'avais totalement manqué ce problème des zéros
négatifs (qui se pose aussi en représentation signe-magnitude).
return ((uint32_t) x | (uint32_t) -x) >> 31;
> /* Return 1 if condition is true, 0 otherwise */
> int ct_isnonzero_u32(uint32_t x)
> {
> return (x|-x)>>31;
> }
>
En fait le problème du code ci-dessus est qu'il ne marche que si x est
encodé en binaire *complément à deux*. Sur les machines binaires
*complément à un*, ca ne marche pas car ca retournera toujours 1 (-x et
~x sont identique dans cette représentation)
Ah oui, bien vu, j'avais totalement manqué ce problème des zéros
négatifs (qui se pose aussi en représentation signe-magnitude).
return ((uint32_t) x | (uint32_t) -x) >> 31;
[désolé pour la fausse réponse qui casse le fil, mais pour une raison qui
m'échappe le message de Samuel n'apparait pas sur le serveur que j'utilise, je
fais donc un copier-coller depuis google groups...]
[désolé pour la fausse réponse qui casse le fil, mais pour une raison qui
m'échappe le message de Samuel n'apparait pas sur le serveur que j'utilise, je
fais donc un copier-coller depuis google groups...]
[désolé pour la fausse réponse qui casse le fil, mais pour une raison qui
m'échappe le message de Samuel n'apparait pas sur le serveur que j'utilise, je
fais donc un copier-coller depuis google groups...]
Le 13/03/2015 21:12, Manuel Pégourié-Gonnard a écrit :[désolé pour la fausse réponse qui casse le fil, mais pour une raison qui
m'échappe le message de Samuel n'apparait pas sur le serveur que j'utilise, je
fais donc un copier-coller depuis google groups...]
C'est parce que j'avais écrit une bêtise et que j'ai supprimé mon
message sitôt la bêtise identifiée, mais google-group semble ignorer les
cancels.
Quelle bêtise ? J'ai lu int32_t et pas uint32_t. Du coup mon argument
tombe à l'eau.
Cependant la question peut se poser de savoir quelle est la sémantique
formelle de -x quand x est unsigned. Pour moi ca fait un overflow.
Un point à noter: si on travaille en complément à deux on peut aussi se
passer du décalage à droite en écrivant: -(x|-x)
Le 13/03/2015 21:12, Manuel Pégourié-Gonnard a écrit :
[désolé pour la fausse réponse qui casse le fil, mais pour une raison qui
m'échappe le message de Samuel n'apparait pas sur le serveur que j'utilise, je
fais donc un copier-coller depuis google groups...]
C'est parce que j'avais écrit une bêtise et que j'ai supprimé mon
message sitôt la bêtise identifiée, mais google-group semble ignorer les
cancels.
Quelle bêtise ? J'ai lu int32_t et pas uint32_t. Du coup mon argument
tombe à l'eau.
Cependant la question peut se poser de savoir quelle est la sémantique
formelle de -x quand x est unsigned. Pour moi ca fait un overflow.
Un point à noter: si on travaille en complément à deux on peut aussi se
passer du décalage à droite en écrivant: -(x|-x)
Le 13/03/2015 21:12, Manuel Pégourié-Gonnard a écrit :[désolé pour la fausse réponse qui casse le fil, mais pour une raison qui
m'échappe le message de Samuel n'apparait pas sur le serveur que j'utilise, je
fais donc un copier-coller depuis google groups...]
C'est parce que j'avais écrit une bêtise et que j'ai supprimé mon
message sitôt la bêtise identifiée, mais google-group semble ignorer les
cancels.
Quelle bêtise ? J'ai lu int32_t et pas uint32_t. Du coup mon argument
tombe à l'eau.
Cependant la question peut se poser de savoir quelle est la sémantique
formelle de -x quand x est unsigned. Pour moi ca fait un overflow.
Un point à noter: si on travaille en complément à deux on peut aussi se
passer du décalage à droite en écrivant: -(x|-x)
En fait, j'ai du mal à me faire une opinion sur les points 1 et 2, de
mon point de vue tant qu'aucune des personnes à qui j'en parle n'est
capable de me citer un cas concret de compilo qui génère une branche
avec == et pas avec une manip comme ci-dessus, on est plus dans le FUD
que dans une approche rationnelle.
En fait, j'ai du mal à me faire une opinion sur les points 1 et 2, de
mon point de vue tant qu'aucune des personnes à qui j'en parle n'est
capable de me citer un cas concret de compilo qui génère une branche
avec == et pas avec une manip comme ci-dessus, on est plus dans le FUD
que dans une approche rationnelle.
En fait, j'ai du mal à me faire une opinion sur les points 1 et 2, de
mon point de vue tant qu'aucune des personnes à qui j'en parle n'est
capable de me citer un cas concret de compilo qui génère une branche
avec == et pas avec une manip comme ci-dessus, on est plus dans le FUD
que dans une approche rationnelle.
Grosso-modo, la plupart de ces trucs reviennent a remplacer des trucs
clairs par des equivalents obfuscated qui font la meme chose.
En tant qu'auteur de compilo, je verrais ca comme un challenge:
qu'est-ce qu'il faut que je rajoute dans mon compilateur pour
optimiser ces trucs quand meme ? :p
Apres, de toutes facons, un fabricant de processeur est deja en train
de faire des trucs qui vont limiter ce genre de choses.
En fait, ce
dont tu aurais besoin pour reparer VRAIMENT ca, ca serait d'une sorte
de micro-timer, ou tu pourrais dire "demerde-toi pour que ca prenne
autant de temps que ca, exactement, quelles que soient les
instructions executees".
Sinon, cette histoire de timing constant, c'est perdu d'avance. Tu
peux au plus y arriver avec une implementation donnee sur une
generation de processeur donnee...
Grosso-modo, la plupart de ces trucs reviennent a remplacer des trucs
clairs par des equivalents obfuscated qui font la meme chose.
En tant qu'auteur de compilo, je verrais ca comme un challenge:
qu'est-ce qu'il faut que je rajoute dans mon compilateur pour
optimiser ces trucs quand meme ? :p
Apres, de toutes facons, un fabricant de processeur est deja en train
de faire des trucs qui vont limiter ce genre de choses.
En fait, ce
dont tu aurais besoin pour reparer VRAIMENT ca, ca serait d'une sorte
de micro-timer, ou tu pourrais dire "demerde-toi pour que ca prenne
autant de temps que ca, exactement, quelles que soient les
instructions executees".
Sinon, cette histoire de timing constant, c'est perdu d'avance. Tu
peux au plus y arriver avec une implementation donnee sur une
generation de processeur donnee...
Grosso-modo, la plupart de ces trucs reviennent a remplacer des trucs
clairs par des equivalents obfuscated qui font la meme chose.
En tant qu'auteur de compilo, je verrais ca comme un challenge:
qu'est-ce qu'il faut que je rajoute dans mon compilateur pour
optimiser ces trucs quand meme ? :p
Apres, de toutes facons, un fabricant de processeur est deja en train
de faire des trucs qui vont limiter ce genre de choses.
En fait, ce
dont tu aurais besoin pour reparer VRAIMENT ca, ca serait d'une sorte
de micro-timer, ou tu pourrais dire "demerde-toi pour que ca prenne
autant de temps que ca, exactement, quelles que soient les
instructions executees".
Sinon, cette histoire de timing constant, c'est perdu d'avance. Tu
peux au plus y arriver avec une implementation donnee sur une
generation de processeur donnee...