Twitter iPhone pliant OnePlus 11 PS5 Disney+ Orange Livebox Windows 11

Un compilateur totalement sûr les allocations mémoire ?

10 réponses
Avatar
Stéphane Zuckerman
Bonjour,

En effectuant quelques recherches sur le net, je suis tomb=E9 sur cet
article :

=AB=A0Implementation of the memory-safe full ANSI-C compiler =BB (PLDI
2009).
(URL : http://www.informatik.uni-trier.de/~ley/db/conf/pldi/pldi2009.html)

Je suis en train de m'atteler =E0 sa lecture, mais je me demandais si
quelqu'un avait eu vent de cette impl=E9mentation et si il/elle avait
des commentaires (=AB=A0marchera jamais en vrai =BB/=AB trop cool gigalol
=BB)... Si on a la certitude d'avoir une m=E9moire correctement g=E9r=E9 d=
=E8s
la compilation sans trop de perte de performances, je trouve =E7a plut=F4t
int=E9ressant...

St=E9phane

10 réponses

Avatar
-ed-
On 15 juil, 18:50, Stéphane Zuckerman
wrote:
Bonjour,

En effectuant quelques recherches sur le net, je suis tombé sur cet
article :

« Implementation of the memory-safe full ANSI-C compiler » (PLDI
2009).
(URL :http://www.informatik.uni-trier.de/~ley/db/conf/pldi/pldi2009.html)



Il semble que l'accès au document ne soit pas libre...

De plus, je ne vois pas ce qui empêche en C standard, d'utiliser la
mémoire correctement et sans erreurs...
Avatar
Richard Delorme
Le 16/07/2009 02:52, -ed- a écrit :
On 15 juil, 18:50, Stéphane Zuckerman
wrote:
Bonjour,

En effectuant quelques recherches sur le net, je suis tombé sur cet
article :

« Implementation of the memory-safe full ANSI-C compiler » (PLDI
2009).
(URL :http://www.informatik.uni-trier.de/~ley/db/conf/pldi/pldi2009.html)



Il semble que l'accès au document ne soit pas libre...




On peut trouver la thèse de l'auteur (traduite en anglais) ici :

http://www.taplas.org/~oiwa/thesis.pdf

J'ai parcouru très vite. Le principe consiste à utiliser un pointeur
"intelligent" qui détecte les principales erreurs (pointeur non
initialisé, accès hors tableau, etc.) pour, en général, terminer le
programme proprement. Ça évite certaines attaques, mais ça ne résoud pas
tous les problèmes.


De plus, je ne vois pas ce qui empêche en C standard, d'utiliser la
mémoire correctement et sans erreurs...



La bêtise humaine, malheureusement très répandu (je suis moi-même
contaminé). A noter que le programme de M. Iowa est un compilateur de C
standard, qui ne change rien au langage.

--
Richard
Avatar
-ed-
On 16 juil, 07:37, Richard Delorme wrote:
> De plus, je ne vois pas ce qui empêche en C standard, d'utiliser la
> mémoire correctement et sans erreurs...

La bêtise humaine, malheureusement très répandu (je suis moi-même
contaminé). A noter que le programme de M. Iowa est un compilateur de C
standard, qui ne change rien au langage.



Quelques méthodes de travail simpples permettent de vérifier ce qu'on
fait...

J'utilise la vérification de la présence du dernier 0 d'une chaine
pour savoir si il y a eu débordement ou non. (OK, si il y a eu
débordement grave, le comportement étant indéfini, la méthode ne
fonctionne pas toujours).

http://www.bien-programmer.fr/clib.htm
Extrait de sys.h :

/* controles */
#define LIM_STR(s) (s)[sizeof (s) - 1]=0
#define CHK_STR(s) ASSERT((s)[sizeof (s) - 1]==0)

#ifndef NDEBUG
#define LIM_PTR(p,l) (p)[(l) -1]=0
#else
#define LIM_PTR(p,l)
#endif
#define CHK_PTR(p,l) ASSERT((p)[(l) -1]==0)

Sinon, pour les tableau, un assert() bien placé, avec une condition
correctement établie, qui vérifie les index avant usage suffit à
détecter les erreurs.
Avatar
Richard Delorme
Le 16/07/2009 08:23, -ed- a écrit :
#ifndef NDEBUG
#define LIM_PTR(p,l) (p)[(l) -1]=0
#else
#define LIM_PTR(p,l)
#endif



A mon avis, c'est ce genre de code qui est particulièrement dangereux ;
car, en fonction de la définition ou non de NDEBUG, on obtient deux
programmes aux comportements différents : par exemple, un programme qui
plante quand NDEBUG n'est pas défini, mais qui marche quand NDEBUG est
défini. Ça peut être difficile à déboguer.

--
Richard
Avatar
zwim
Le Thu, 16 Jul 2009 07:37:28 +0200
Richard Delorme a écrit
Le 16/07/2009 02:52, -ed- a écrit :
On 15 juil, 18:50, Stéphane Zuckerman
wrote:
Bonjour,

En effectuant quelques recherches sur le net, je suis tombé sur cet
article :

« Implementation of the memory-safe full ANSI-C compiler » (PLDI
2009).
(URL :http://www.informatik.uni-trier.de/~ley/db/conf/pldi/pldi2009.html)



Il semble que l'accès au document ne soit pas libre...




On peut trouver la thèse de l'auteur (traduite en anglais) ici :

http://www.taplas.org/~oiwa/thesis.pdf

J'ai parcouru très vite. Le principe consiste à utiliser un pointeur
"intelligent" qui détecte les principales erreurs (pointeur non
initialisé, accès hors tableau, etc.) pour, en général, terminer le
programme proprement. Ça évite certaines attaques, mais ça ne résoud pas
tous les problèmes.


De plus, je ne vois pas ce qui empêche en C standard, d'utiliser la
mémoire correctement et sans erreurs...



La bêtise humaine, malheureusement très répandu (je suis moi-même
contaminé). A noter que le programme de M. Iowa est un compilateur de C
standard, qui ne change rien au langage.



J'ai lu rapidement aussi, et même si les idées sont intéressantes
l'overhead est quand même très important de ce que j'ai pu voir.

Un facteur 2.5 à 3 au moins, dans la plupart des cas non triviaux ce
n'est pas rien.

Alors certes le C n'est pas très sûr (si on fait n'importe quoi avec)
mais il a au moins le mérite d'être rapide sans pour autant être aussi
impénétrable qu'un code en assembleur. Donc si ce compilateur lui
enlève cette qualité principale c'est quand même dommage.

L'auteur préconise pour palier à cela de réécrire entièrement le
compilateur en assembleur (ou un langage intermédiaire entre l'asm et
le C) en tenant compte des idées théoriques énoncées dans la thèse,
alors que jusqu'à présent il a écrit un préprocesseur qui sort du C et
qui est compilé par le compilo natif de la plateforme.

Je pense que si les idées sont bonnes, on trouvera des gens pour faire
cela (le premier compilo C++ était aussi un preprocesseur C, ce n'est
plus tout à fait le cas aujourd'hui).


--
zwim.
Rien n'est impossible que la mesure de la volonté humaine...
Avatar
-ed-
On 16 juil, 17:22, Richard Delorme wrote:
Le 16/07/2009 08:23, -ed- a écrit :

> #ifndef NDEBUG
> #define LIM_PTR(p,l) (p)[(l) -1]=0
> #else
> #define LIM_PTR(p,l)
> #endif

A mon avis, c'est ce genre de code qui est particulièrement dangereux ;
car, en fonction de la définition ou non de NDEBUG, on obtient deux
programmes aux comportements différents : par exemple, un programme qui
plante quand NDEBUG n'est pas défini, mais qui marche quand NDEBUG est
défini. Ça peut être difficile à déboguer.



Hum. Le but est de passer le jeu de tests en mode debug. Ensuite, en
production, plus rien de fâcheux de doit arriver si la couverture des
TU est correcte ...
Avatar
Richard Delorme
Le 17/07/2009 01:53, -ed- a écrit :
On 16 juil, 17:22, Richard Delorme wrote:
Le 16/07/2009 08:23, -ed- a écrit :

#ifndef NDEBUG
#define LIM_PTR(p,l) (p)[(l) -1]=0
#else
#define LIM_PTR(p,l)
#endif


A mon avis, c'est ce genre de code qui est particulièrement dangereux ;
car, en fonction de la définition ou non de NDEBUG, on obtient deux
programmes aux comportements différents : par exemple, un programme qui
plante quand NDEBUG n'est pas défini, mais qui marche quand NDEBUG est
défini. Ça peut être difficile à déboguer.



Hum. Le but est de passer le jeu de tests en mode debug.



Oui mais ton LIM_PTR ne teste rien, il fait une assignation. Donc en
mode débogage, les chaines sont toutes correctement terminée par ""
mais éventuellement tronquée, et pas en mode production.

--
Richard
Avatar
-ed-
On 17 juil, 11:55, Richard Delorme wrote:
Le 17/07/2009 01:53, -ed- a écrit :

> On 16 juil, 17:22, Richard Delorme  wrote:
>> Le 16/07/2009 08:23, -ed- a écrit :

>>> #ifndef NDEBUG
>>> #define LIM_PTR(p,l) (p)[(l) -1]=0
>>> #else
>>> #define LIM_PTR(p,l)
>>> #endif
>> A mon avis, c'est ce genre de code qui est particulièrement dangereu x ;
>> car, en fonction de la définition ou non de NDEBUG, on obtient deux
>> programmes aux comportements différents : par exemple, un programme qui
>> plante quand NDEBUG n'est pas défini, mais qui marche quand NDEBUG e st
>> défini. Ça peut être difficile à déboguer.

> Hum. Le but est de passer le jeu de tests en mode debug.

Oui mais ton LIM_PTR ne teste rien, il fait une assignation. Donc en



Bien sûr. C'est CHK_PTR() qui est 'actif'...

LIM_xxx() pose la limite et CHK_xxx() la teste. C'est difficile à
comprendre ? Il faut 3 pages de doc ?

mode débogage, les chaines sont toutes correctement terminée par ""
mais éventuellement tronquée, et pas en mode production.



Et ? Le but est de passer les tests (en mode debug) qui sont censés
couvrir les cas d'exploitation. Quel est le problème ?
Avatar
Richard Delorme
Le 26/07/2009 17:00, -ed- a écrit :
On 17 juil, 11:55, Richard Delorme wrote:
Le 17/07/2009 01:53, -ed- a écrit :

On 16 juil, 17:22, Richard Delorme wrote:
Le 16/07/2009 08:23, -ed- a écrit :
#ifndef NDEBUG
#define LIM_PTR(p,l) (p)[(l) -1]=0
#else
#define LIM_PTR(p,l)
#endif


A mon avis, c'est ce genre de code qui est particulièrement dangereux ;
car, en fonction de la définition ou non de NDEBUG, on obtient deux
programmes aux comportements différents : par exemple, un programme qui
plante quand NDEBUG n'est pas défini, mais qui marche quand NDEBUG est
défini. Ça peut être difficile à déboguer.


Hum. Le but est de passer le jeu de tests en mode debug.


Oui mais ton LIM_PTR ne teste rien, il fait une assignation. Donc en



Bien sûr. C'est CHK_PTR() qui est 'actif'...

LIM_xxx() pose la limite et CHK_xxx() la teste. C'est difficile à
comprendre ? Il faut 3 pages de doc ?



Sans doute, comme présenté ici je ne vois pas comment utiliser ton
LIM_xxx() ou ton CHK_xxx(), ou alors je vois des techniques plus
efficaces et lisibles.


mode débogage, les chaines sont toutes correctement terminée par ""
mais éventuellement tronquée, et pas en mode production.



Et ? Le but est de passer les tests (en mode debug) qui sont censés
couvrir les cas d'exploitation. Quel est le problème ?



Dans ce cas tu as un problème de terminologie. Le mode debug ne sert pas
à faire paser des tests, il sert, comme son nom l'indique, à déboguer.
Pour tes tests tu devrais utiliser un système de macros propres. Du genre :

#ifdef UNIT_TESTING
#define LIM_PTR(p,l) (p)[(l) -1]=0
#else
#define LIM_PTR(p,l)
#endif

--
Richard
Avatar
-ed-
On 26 juil, 19:49, Richard Delorme wrote:

Dans ce cas tu as un problème de terminologie. Le mode debug ne sert pa s
à faire paser des tests, il sert, comme son nom l'indique, à débogu er.
Pour tes tests tu devrais utiliser un système de macros propres. Du gen re :

#ifdef UNIT_TESTING
#define LIM_PTR(p,l) (p)[(l) -1]=0
#else
#define LIM_PTR(p,l)
#endif

--
Richard



Oui, pourquoi pas. J'ai été au plus simple. Chacun définit ses
stratégies de développement. Du moment que le résultat est fiable...

Pour ce qui est de l'utilisation, avec un pointeur sur un tableau, par
exemple ;

char *s = malloc(size);
LIM_PTR(s, size);

strcpy (s, "Hello world");
CHK_PTR(s, size);

Et voila ça a craqué...