URL: https://linuxfr.org/users/tarnyko/journaux/c23-un-memset_explicit-qui-carbure Title: C23: un memset_explicit() qui carbure Authors: Tarnyko Date: 2025年01月21日T05:58:56+01:00 License: CC By-SA Tags: compilateur, langage_c et c23 Score: 22 Hello nal, Parmi les propositions mal-aimées de la [norme C23](https://linuxfr.org/users/tarnyko/journaux/c23-listes-variantes-et-le-turfu), j'invoque **[memset_explicit()](https://www.open-std.org/jtc1/sc22/wg14/www/docs/n2897.htm)**. Bon d'accord, c'est pas si nouveau : pour C11 on avait déjà [memset_s()](https://www.open-std.org/jtc1/sc22/wg14/www/docs/n1381.pdf), dont ce n'est que l'évolution à un paramètre près. Dans les deux cas, le support s'en est trouvé relégué à l'[annexe K](https://port70.net/~nsz/c/c11/n1570.html#K), c'est-à-dire le morceau de la norme qu'on est "_invité à, mais pas obligé_" d'implémenter. Concrètement et ironiquement, seuls deux célèbres compilateurs propriétaires l'implémentent [ici](https://fr.wikipedia.org/wiki/Visual_C%2B%2B) et [là](https://fr.wikipedia.org/wiki/Xcode) ; on y revient... La raison fondamentale est qu'on touche ici à une zone grise : le rôle d'un développeur est d'exprimer une intention, le compilateur d'interpréter et éventuellement optimiser. Mais que se passe-t-il quand les deux se mêlent, voire se brouillent ? Prenons ce code par exemple: #define PW_LEN 16 char password[PW_LEN+1]; scanf("%PW_LENs", password); [...] memset(password, 0, PW_LEN); return; On saisit un mot de passe qu'on chiffre éventuellement, puis on l'utilise (non montré), enfin on le nettoie avec _memset()_ pour qu'il n'en reste pas trace dans la mémoire de la machine hôte. Et après on n'y accède plus jamais. Logique. Que se dit le compilateur, avec un niveau d'optimisation de type "_release_" (= dés ["_-O1_" pour GCC](https://gcc.gnu.org/onlinedocs/gcc/Optimize-Options.html#index-O)) ? "_Pas la peine de garder la dernière instruction, elle ne sert à rien et on y gagne !_" Et c'est comme ça qu'on passe par exemple de cet assembleur x86 : pxor %xmm0, %xmm0 movups %xmm0, (%rsp) ou alors : rep stos %al, (%edi) à... rien du tout. Si si, tu peux essayer avec [cet exemple](https://github.com/Tarnyko/suave_code_samples/blob/master/C/C23/memset_explicit/README#L22) ; pas une trace. Autrement dit, paie ta mesure de sécurité ! Le problème est ici que l'intention du développeur est déjouée par le compilateur faute de contexte. Et comme le contexte en C c'est inexistant, on espère qu'il soit véhiculé par une fonction... explicite, dont l'implémentation concrète sera malheureusement très variable car hyper-dépendante de la plate-forme matérielle ET logicielle. Bon après, concrètement en son absence ? Alors presque chacun a sa solution maison qui marche bien tant qu'on reste... à la maison justement. Entre autres : - **Linux/GlibC** a [explicit_bzero()](https://www.gnu.org/software/gnulib/manual/html_node/explicit_005fbzero.html), comme **FreeBSD** d'ailleurs -sauf que ce dernier ne le [déclare pas dans le même header](https://man.freebsd.org/cgi/man.cgi?query=explicit_bzero), sacré lui ! - **macOS** est semi-pro, il implémente la [version de C11](https://developer.apple.com/documentation/kernel/2876438-memset_s) mais pas (encore ?) celle de C23 ; - un certain **OS répandu** en a [une qui marche bien](https://learn.microsoft.com/en-us/windows-hardware/drivers/ddi/wdm/nf-wdm-rtlsecurezeromemory) tant qu'on utilise son compilateur maison. A sa décharge, c'est plutôt l'implémentation OSS de l'équipe d'en face qui laisse à désirer ; - **Android** n'a... juste rien ? Face à ce chaos ambiant, je te présente : Mon [implémentation multi-plateforme de memset_explicit()](https://github.com/Tarnyko/suave_code_samples/blob/master/C/C23/memset_explicit) -------------------------------------------------------- _(qui s'appuie en partie sur le [bon travail préalable d'un monsieur](https://github.com/gsbabil/memset_explicit/))_ Elle n'est forcément pas parfaite, mais je te garantis que je l'ai essayée partout où j'ai raisonnablement pu. Elle fait appel à l'annexe K dans les rares cas où c'est dispo, à défaut tente la solution maison, se replie sur un code assembleur x86/ARM si ça convient, et en dernier recours tente de forcer la main du compilateur. Tu peux essayer les étapes du [README](https://github.com/Tarnyko/suave_code_samples/blob/master/C/C23/memset_explicit/README), et me dire si tout fonctionne dans ton cas particulier. Je t'en serai très reconnaissant :-) !

AltStyle によって変換されたページ (->オリジナル) /