Journal Banni de chez Microsoft.

Posté par  .
Étiquettes : aucune
17
15
mai
2009
Non, ce n'est pas un employé de chez Microsoft qui aurait envoyé un mail à son député pour se plaindre des brevets logiciels mais de la vénérable et infâme fonction C memcpy (ainsi que quelques unes de ses consœurs) qui se retrouve avec d'autres vénérables fonctions (strcat, strcpy, scanf,...) [1] bannies de chez Microsoft.

Pourquoi ? parce que ce sont des passoires et qu'elles sont responsables d'une bonne partie des dépassements de tampons, mets délicats utilisés pour injecter données et code afin d'altérer le fonctionnement d'un programme dans des buts souvent fort peu avantageux pour l'utilisateur. Responsables des failles de sécurité quoi.

On est vendredi et je vous jure que je n'ai pas fait exprès de tomber dessus aujourd'hui même mais le billet du blog SDL [2] (Security Development Lifecycle, pas l'autre) se termine sur une petite pique qui cache le troll : I wonder when Larry, Steve and Linus will start banning strcpy() in their products?. Ça a au moins le mérite de ratisser large même si cela reste approximatif. Une pointe d'humour qui se cache dans une question fort intéressante.

Alors pour ou contre HADŒPI les fonctions explicitement bannies ? Combien de fois Ulrich Drepper utilisera fuck, crap ou you don't pay me, do not fill bug reports dans ses réponses du bug tracker ? Autant de questions en suspend qui me font espérer d'avoir encore une connexion internet demain.

[1] : http://msdn.microsoft.com/en-us/library/bb288454.aspx
[2] : http://blogs.msdn.com/sdl/archive/2009/05/14/please-join-me-(...)
  • # bannir "connect"

    Posté par  . Évalué à 1.

    c'est vrai, la plupart des problèmes viennent de là. Ainsi que du clavier, que l'on devrait remplacer par le crayon, beaucoup plus fiable.

    On devrait aussi rétablir la ceinture de chasteté, combien de temps avant que l'on se rende compte de son absolue nécessité dans la jungle où nous vivons?

    Franchement HS, je sais mais bon.
    • [^] # Re: bannir "connect"

      Posté par  (site web personnel) . Évalué à 4.

      Je suis d'accord : remplacer memcpy par memcpy_s ne sert à rien. L'une est toute aussi vulnérable que l'autre à une erreur...

      Je ne comprend pas leur motif: si les bugs viennent de là, il faut les corriger, pas bannir la fonction sous prétexte que son mauvais usage a conduit à ce bug!
      On ne bannit pas les voiture sous prétexte que, mal utilisée, on peut se flinguer avec!
      • [^] # Re: bannir "connect"

        Posté par  (site web personnel) . Évalué à 10.

        Je ne comprend pas leur motif

        Il est quand même assez évident :
        avant, il fallait faire en gros :
        char destination[1000];
        if (strlen(source)<1000)
        strcpy(destination, source); //C'est safe
        else
        setrncpy(destination, source, 1000); //safe tout le temp mais lent, car rempli toujours les 1000 chars avec du padding si necessaire

        alors qu'avec, ça donne vite fait :
        char destination[1000];
        strcpy(destination, source, 1000); //C'est safe et rapide

        Bon, maintenant, je dis ça, mais je suis programmeur C++, donc vive std::string!
        • [^] # Re: bannir "connect"

          Posté par  . Évalué à 7.

          setrncpy(destination, source, 1000); //safe tout le temp

          Pas vraiment safe, en fait, parce que si tu as plus de 1000 caractères, la destination n'aura pas son '\0' final...
        • [^] # Re: bannir "connect"

          Posté par  . Évalué à 2.

          bof un bon asprintf des famille et pis ça roule ;)

          char *plop;
          asprintf(&plop, "%s", chaineACopier); // /!\ GNU_C et BSD
          ...
          free(plop)



          >Bon, maintenant, je dis ça, mais je suis programmeur C++, donc vive std::string!

          Heureusement qu'il y a boost alors, car sinon il manquerait le stricmp, et pleins d'autre fonction utile pour les strings

          Il ne faut pas décorner les boeufs avant d'avoir semé le vent

          • [^] # Re: bannir "connect"

            Posté par  . Évalué à 4.

            Oups, et le :
            int ret_libC = 0;

            ret_lobC = asprintf(&plop,...);
            if (ret_lobC == -1)
            {
            /* Gerer l'erreur */
            }

            Pour faire du code propre, il faudrait commencer à récupérer tous les codes de retour. Ca enlèverai déjà beaucoup de faille.

            Mes 30 cents.
            • [^] # Re: bannir "connect"

              Posté par  . Évalué à 2.

              tout à fait exact, j'ajouterai même qu'initialiser ses variables fait partie des choses fréquemment oubliée;
              j'aurais du écrire

              char *plop=NULL;
              if ( asprintf(&plop, ... ) == -1 ) {
              ...
              }else{
              ...
              free(plop);
              }

              Heureusement une compilation avec -Wall permet de corriger pas mal d'oubli d'initialisation ;)

              Il ne faut pas décorner les boeufs avant d'avoir semé le vent

              • [^] # Re: bannir "connect"

                Posté par  . Évalué à 1.

                C'est super, mais c'est juste totalement inefficace car il fait une allocation a chaque fois, tu ne peux pas controler la longueur max et il faut se taper le free du buffer a la fin...
                • [^] # Re: bannir "connect"

                  Posté par  . Évalué à 2.

                  Tout dépend du contexte, si en effet tu as besoin d'une taille particulière, tu as snprintf qui permet de préciser la taille du char[] que tu veux.

                  Il ne faut pas décorner les boeufs avant d'avoir semé le vent

                  • [^] # Re: bannir "connect"

                    Posté par  . Évalué à 4.

                    La difference est que wsprintf ne te garantit pas que ton buffer aura un NULL a la fin dans le cas ou le texte remplit exactement, ou est plus grand que le buffer.

                    strncpy_s lui te garantit que tu n'auras _jamais_ un cas ou le buffer n'a pas de NULL dans sa taille allouee, si tu passes un count qui est plus grand que la taille de buffer specifiee, il met un NULL au debut du buffer et retourne une erreur.

                    --> Tu es sur de ne pas te choper un buffer overflow si tu t'amuses a faire un strlen() apres par exemple.

                    La est toute la difference, et c'est la qu'on voit qu'un gars comme Ulrich Drepper qui considere ces fonctions comme inutiles est un idiot incapable de se remettre en question.
                    • [^] # Re: bannir "connect"

                      Posté par  . Évalué à 2.

                      Je comprends ce point de vue, cependant, quand j'utilise snprintf

                      j'ai en général du code autour
                      if ( (n = snprinft(...) ) >= taille) )
                      {
                      gérer le cas (en général, un realloc)
                      }
                      Utiliser des chaines tronqués dans mes codes n'est pas un truc que je puisse me permettre, ou alors j'ai après le snprintf (tout comme avec le strcpy)
                      chaine[n-1]=0; mais ces cas sont exceptionnels

                      Il ne faut pas décorner les boeufs avant d'avoir semé le vent

                      • [^] # Re: bannir "connect"

                        Posté par  . Évalué à 2.

                        Je comprends ce point de vue, cependant, quand j'utilise snprintf

                        j'ai en général du code autour


                        C'est justement tout l'interet de ces nouvelles fonctions, avec elles, que tu aies ce code ou pas, tu es protege.

                        Avec ton code, si par malheur une fois tu oublies, bonjour les degats.

                        Utiliser des chaines tronqués dans mes codes n'est pas un truc que je puisse me permettre, ou alors j'ai après le snprintf (tout comme avec le strcpy)
                        chaine[n-1]=0; mais ces cas sont exceptionnels


                        strlncpy ne tronque pas mais te donne une erreur si l'espace n'est pas suffisant, et si tu ne peux pas te permettre de tronquer, alors ton chaine[n-1]=0 n'est pas une solution, parce que ca revient a tronquer le dernier caractere, sauf si tu passes n-1 comme taille de buffer, mais la ca devient vraiment un bordel le code pour au final faire la meme chose que strnlcpy fait proprement.
                • [^] # Re: bannir "connect"

                  Posté par  . Évalué à 4.

                  Il y a un ramasse miette pour le C de microsoft ? Tout se perd…

                  Envoyé depuis mon lapin.

      • [^] # Re: bannir "connect"

        Posté par  . Évalué à 3.

        On ne bannit pas les voiture sous prétexte que, mal utilisée, on peut se flinguer avec!
        Belle analogie.

        On n'a jamais vu de constructueurs de voitures rappeler des séries à cause de vices.
      • [^] # Re: bannir "connect"

        Posté par  . Évalué à 2.

        Ouais enfin, ca n'a pas empêché de bannir gets() quand même. Et heureusement !
        • [^] # Re: bannir "connect"

          Posté par  . Évalué à 1.

          La différence c'est que gets est impossible à utiliser de façon sûre, ce qui n'est pas le cas de strcpy(). Il faut simplement avoir fait la vérification de taille avant l'appel de strcpy().


          Étienne
          • [^] # Re: bannir "connect"

            Posté par  . Évalué à 1.

            A lire tous ces commentaires, ce que je me dit, c'est pas qu'il manque des fonctions, mais un type String.

            Nan, parce que n'importe quel langage decent permet de faire un :

            String brezilien = "toto";
            String foo = brezilien;
            if(foo.length < 3)
            {
            print("samba reggae!!!");
            }
            else
            {
            print("Samba do bahia do braziu");
            }

            sans avoir a utiliser de fonctions obscures.

            Autant je peux comprendre pour le C, bas niveau tout ca, autant pour le C++, ca me depasse...
            • [^] # Re: bannir "connect"

              Posté par  . Évalué à 6.


              string brezilien = "toto";
              string foo = brezilien;

              if(foo.length() < 3)
              {
              cout << "samba reggae!!!";
              }
              else
              {
              cout << "Samba do bahia do braziu";
              }


              Voilà, t'as ton truc en C++.

              Envoyé depuis mon lapin.

              • [^] # Re: bannir "connect"

                Posté par  . Évalué à 1.

                Ben pourtant, si j'en crois http://www.joelonsoftware.com/articles/LeakyAbstractions.htm(...) ca va te peter a la gueule un jour (chercher C++ string classes are supposed to let )
                • [^] # Re: bannir "connect"

                  Posté par  . Évalué à 6.

                  Et pourquoi ?

                  Que C++ utilises des char * comme en C, et que java utilises directement la mémoire, cela change quoi ?

                  Tu penses que toute classe (ou structure pour le C) va te péter à la gueule car cela utilise des types de base ?

                  Rassures-toi, lorsque la fonction est bien codée, ce qui est la cas pour la plupart des std::string, cela ne va pas plus te péter à la gueule que n'importe quel string faussement type de base d'un langage de plus haut niveau.

                  Envoyé depuis mon lapin.

                  • [^] # Re: bannir "connect"

                    Posté par  . Évalué à 2.

                    ben si j'en crois ce que dit le monsieur, et il a pas l'air mauvais, donc je vais le croire:

                    - en c++ variable string + "literal" marche uniquement parce que l'operateur + a ete surdefini (itou pour le constructeur de copie avec l'assignement).
                    Ca marche parce qu'un des membres de l'operation est un String et que donc c'est l'operateur redefinit qui est applique.
                    Par contre, si tu fais "toto"+"tata", ca va peter, parce que ni toto ni tata ne sont des string, mais bel et bien des char*.
                    Bref, on a un truc qui ressemble a s'y meprendre a une String, mais qui n'en est clairement pas une du tout.

                    - Le truc avec java (ou n'importe quel autre langage decent qui traite les chaines comme des chaines, et pas comme des tableau d'un autre type...), c'est pas qu'il utilise directement la memoire.
                    'fin si, il le fait, mais on s'en cogne, c'est pas la question ici.
                    Ce qui est interessant c'est que le literal "toto" est un objet de la classe String.
                    Et que donc le comportement est strictement le meme que variable + variable1.
                    tu peux meme faire "toto".equals(variable);
                    C'est meme d'ailleurs ce qui est recommande de faire (ca t'evite un check de pointeur nul si tu renverses l'expression).
                    Ton literal EST un objet, pas un char*. "toto".getClass te retourne String, "toto" instanceof String te retourne true etc.
                    Bon courage pour faire ca en c++.

                    Bref, le probleme de fond, c'est que le langage n'as PAS de classe String (String est visiblement dans une lib, qui meme si elle plus ou moins standard et utilisee par tout le monde, n'est pas dans le langage, donc "toto" reste un char* et ne sera jamais une instance de string).
                    Et pour un langage objet, qui se veut moderne, c'est pour le moins deroutant.
                    Je me doute que c'est pour des raisons de compat avec le C, mais ca change rien au pb...
                    • [^] # Re: bannir "connect"

                      Posté par  . Évalué à 2.

                      Je serais tenté de te dire que pour ces arguments, «It's not a bug, it's a feature».

                      Avoir séparé tout les conteneurs et bien d'autres choses dans une bibliothèque (et non librairie) faisant partie du langage, mais pas inclue par défaut est un choix.

                      Puis finalement, c'est sur que additionner deux char * entre eux ne va pas compiler. Mais cela n'a rien à voir avec les problèmes des fonctions dont font l'objet le journal.

                      Si tu tiens à faire "foo" + "tata", et que ça compile, c'est string("foo") + "tata". Un "toto" == variable en string("toto")==variale. Un "" et un string sont deux choses différentes en C++. Un développeur C++ doit être conscient de ça, et cela n'est vraiment pas un problème.

                      C'est vrai que c'est plus long à écrire, que dans les cas présents il faut créer des objets, mais même sans avoir besoin d'être compatible avec le C, je pense que ce serais comme ça.

                      Envoyé depuis mon lapin.

                      • [^] # Re: bannir "connect"

                        Posté par  . Évalué à 1.

                        c'est une feature, pas un bug?
                        Tu te fout de moi?

                        Ca ressemble a une string, ca s'ecrit comme on ecrit naturellement une string, ca s'assigne a une string, ca s'additione a une string.
                        Mais c'est pas une string.
                        C'est un tableau (meme pas en fait, un pointeur).

                        Pour moi, un tableau c'est ca : ['t', 'o', 't', 'o', '\0'];
                        Certainement pas "toto".

                        Un "" et un string sont deux choses différentes en C++. Un développeur C++ doit être conscient de ça, et cela n'est vraiment pas un problème.
                        Ben a partir du moment ou il faut en etre conscient et que une string n'estp as une string, si c'est pb, on s'embrouille pour rien.

                        Et ca a voir avec les fonctions dont parle le journal, tout du moins pour le c++, c'est que pour le c, ca va pas trop le toucher.

                        Si la classe String etait un vrai type de base, on aurait surement moins de pb avec les strcpy et autre en c++... et on sera pas tente de reimplementer soit meme la roue ou de se fader des char*
                        • [^] # Re: bannir "connect"

                          Posté par  . Évalué à 3.

                          ben non string n'est pas un type de base, ne serai-ce que parce que sa représentation dépend du charset et de pleins d'autre détail qui peuvent varier

                          string n'est qu'un raccourcis pour basic_string et en redéfinissant ce truc là, tu peux avoir des string ne s'occupant pas de la différence majuscule/minuscule, et d'autre détails encore.
                          C'est un type complexe gérant plein de petit truc, comme le find, rfind, erase, find_first_of, find_first_not_of, find_last_of...

                          Je regrette, un type de base n'as pas toutes ces fonctions, c'est un objet.

                          ensuite j'ai vu plus haut des
                          string plop="chaine";

                          Bordel! on est pas en C!
                          string plop("chaine");

                          Il ne faut pas décorner les boeufs avant d'avoir semé le vent

                          • [^] # Re: bannir "connect"

                            Posté par  . Évalué à 2.

                            Je sais, mais c'était pour traduire son exemple le plus fidèlement possible. Désolé :D

                            Envoyé depuis mon lapin.

                          • [^] # Re: bannir "connect"

                            Posté par  . Évalué à 2.

                            ben non string n'est pas un type de base, ne serai-ce que parce que sa représentation dépend du charset et de pleins d'autre détail qui peuvent varier
                            String n'est pas un type de base?
                            Pourquoi donc TOUS les autres langages (C mis a part) l'implementent comme un type de base?
                            Surement parce que j'ai encore jamais vu un seul programme qui n'utilise pas des strings...
                            C'est un type de base au meme titre que int, float, char, boolean et tous leurs potes.
                            Sinon tu pourrais aussi dire que c'est pareil pour les int: signe, ou pas? 32 bits? pourquoi pas moins ou plus? Allez, paf, transformons implicitement 2 dans "variable + 2" en void* et faison planter le programme qui fait ca. Le dev a qu'a faire variable + int(2), apres tout, on est pas en C, non mais.

                            Ou les char? ASCII 7 ou 8 bits? UTF-8? ISO 8559-1?

                            C'est sur qu'il va falloir en faire un objet pour integrer toutes les methodes, mais ca n'empeche pas d'avoir une string literal qui soit reellement une string, plutot que de la transformer implicitement dans un type qui n'a strictement rien a voir avec sa representation dans le code.

                            C'est un type complexe gérant plein de petit truc, comme le find, rfind, erase, find_first_of, find_first_not_of, find_last_of...
                            Je vais me faire allumer, mais non, std::String ne gere pas plein de petits truc, elle gere a peine la base de la manipulation de string.
                            Ce que tu viens de citer, c'est 95% de l'api string et c'est a peine suffisant pour manipuler decemment une quelconque chaine dans les cas les plus simple.

                            Compares a n'importe quelle autre API string, ca fait un choc de voir ce que std::String gere en comparaison.
                            Pas de split. pas de trim, pas de regexp, aucune gestion du upper/lower case, pas de starts/ends with, un replace en mousse, pas moyen d'obternir la version string des autres types de base...

                            Resultat, oblige de reimplementer soi meme une bonne partie de la roue, et du coup on se tape des pinpins qui utilisent gets() ou strcpy().

                            Il est la le lien avec le probleme, pour repondre a n-2.
                            • [^] # Re: bannir "connect"

                              Posté par  (site web personnel) . Évalué à 3.

                              String n'a certainement pas a etre un type de base.

                              C'est une structure complexe que tu ne peux pas representer statiquement en memoire, elle depend tres fortement des besoins en ressources du programme.

                              Donc oui, "tous" les autre langages que le C et ses dignes heritiers ont un type string qui fait partie du langage, mais ironie du sort, ils utilisent tous tout un tas de commidites pas forcement jolies pour que le developpeur n'ait plus a se soucier de la gestion des ressources qu'il a pourtant demandees.

                              Et puis imagine deux secondes que ta classe string ne te plaise pas, tu la retouches comment, tu t'amuses a reimplementer ton compilo ?

                              Faut etre serieux deux secondes, je veux bien que le java fasse le cafe, mais ca reste sale.
                              • [^] # Re: bannir "connect"

                                Posté par  . Évalué à 5.

                                C'est une structure complexe que tu ne peux pas representer statiquement en memoire, elle depend tres fortement des besoins en ressources du programme.

                                gne?
                                http://www.docjar.com/html/api/java/lang/String.java.html
                                char[] value : les caracteres eux memes
                                int offset: offset de debut de stockage dans value
                                int count: taille de la chaine

                                'tin c'est super complexe ca!!!

                                Regardes le code des constructeurs, ca va pas pisser bien loin non plus. La partie la plus relou, c'est les pb d'encodages, qu'il faut adresser de toutes facons.
                                Une fonction native, intern() qui va bien evidemment dependre de l'endianness du processeur, donc c'est le seul truc que tu peux pas faire en java. Trop dur.

                                ils utilisent tous tout un tas de commidites pas forcement jolies pour que le developpeur n'ait plus a se soucier de la gestion des ressources qu'il a pourtant demandees.
                                Comme?
                                Java a une String immutable ce qui peut etre genant en effet (d'ou le string buffer), l'approche parait bonne, un objet immutable simple et peu gourmand tant que tu le tripatouilles et un truc dedie a la manipulation.

                                Et puis imagine deux secondes que ta classe string ne te plaise pas, tu la retouches comment, tu t'amuses a reimplementer ton compilo ?
                                Tu fournis ta propre classe String?
                                C'est tres tres vilain, c'est sur, mais ca va etre pareil en c++ si tu t'amuses a faire la meme connerie...
                                Le truc c'est que je n'ai encore jamais vu une seule reimplementation de la class String en Java.
                                En c++ par contre, hem hem...
                                Alors c'est possible parce que les chaines de base sont des char*, ce qui rend les choses possibles (en Java, faudrait passer son temps a convertir de user String a system String, ce qui tue un peu l'interet), mais ca aboutit a du code pourri et plombe qui utilise des fonctions des bois et paf le buffer overflow.

                                Et si ton type int te plait pas, tu fais quoi? Tu patches le compilo?

                                Faut etre serieux deux secondes, je veux bien que le java fasse le cafe, mais ca reste sale.
                                Sale?!?!
                                Au lieu de repeter des trucs que t'as lu dans des trolls a droite a gauche, explique moi ce qui est "sale" dans les string Java.
                                T'as le source juste au dessus, donc t'as juste a me pointer les endroits crades.
                                • [^] # Re: bannir "connect"

                                  Posté par  . Évalué à 5.

                                  Java, Perl, Python, Ruby, etc. n’ont jamais eu pour contrainte de rester au maximum compatible avec le C. C++ si.
                            • [^] # Re: bannir "connect"

                              Posté par  . Évalué à 2.

                              Encore une fois, si tu n'as pas toute une planquée de trucs avec ton string par défaut, c'est encore un choix du langage.

                              Dans combien de fichiers te sert-tu des très petites fonctions ? Inutile d'en mettre partout. Si t'en a besoin, tu importes ton truc. Le seul truc qui manque de base dans la std, ce sont les regexp, mais cela arrivera bien un jour.

                              Envoyé depuis mon lapin.

                              • [^] # Re: bannir "connect"

                                Posté par  . Évalué à 2.

                                Dans combien de fichiers te sert-tu des très petites fonctions ? Inutile d'en mettre partout
                                Tu preferes eclater tes fonctions de manipulations de string sur n paquets, les avoirs dans differentes classes plutot que d'avoir une API propre et utilisable?

                                Sinon, le trim et le split, je m'en sert couramment. Tres couramment.

                                Si t'en a besoin, tu importes ton truc
                                Ben ouais, tu importes ton trucs, tu crees une passoire qui ne verifient pas tout et tu te tapes tes failles de secu, en plus d'avoir perdu 2 jours a mal reecrire un truc que tout le monde utilise et qui devrait etre foutu dans une bonne vieille lib systeme...
                                • [^] # Re: bannir "connect"

                                  Posté par  . Évalué à 6.

                                  Sinon, tu utilises Qt.

                                  Envoyé depuis mon lapin.

                                • [^] # Re: bannir "connect"

                                  Posté par  . Évalué à 3.

                                  tu as boost pour les trim et autre joyeuseté, ça vient même avec les regexp ;)

                                  Il ne faut pas décorner les boeufs avant d'avoir semé le vent

                    • [^] # Re: bannir "connect"

                      Posté par  (site web personnel) . Évalué à 1.

                      Par contre, si tu fais "toto"+"tata", ca va peter, parce que ni toto ni tata ne sont des string, mais bel et bien des char*.

                      Petite précision sur cet exemple qui donne une erreur de compilation parce qu'on ne peut pas additionner deux pointeurs. Par contre, ça peut devenir sournois si on fait des choses du style "chaine"+entier, ce qui est valide.
                      • [^] # Re: bannir "connect"

                        Posté par  . Évalué à 2.

                        Oui, ça coupe le début du string, et si on dépasse le \0 on casse tout.
                        C'est le problème de pouvoir tout faire en C.

                        Envoyé depuis mon lapin.

                        • [^] # Re: bannir "connect"

                          Posté par  . Évalué à 4.

                          C'est le problème de pouvoir tout faire en C.
                          C'est surtout le problème de ne pas utiliser le langage adapté au besoin.

                          Il ne faut pas oublier que le C a été fait à la base pour pouvoir faire facilement des choses de "bas niveau" .... Le fait q'il permette de tout faire est un atout certain ... mais si on l'utilise pour faire des choses qu'un langage moins permissif ferait tout aussi bien (voir même mieux), ce n'est pas la faute du langage ....

                          Pour le C++, c'est un peu la même chose : un "C" évolué qui permet de faire des choses bas niveau ...
  • # Le libre et les standards...

    Posté par  (site web personnel) . Évalué à 5.

    Pour alimenter le troll, il est à noter un certain refus du libre (j'ai en exemple GLibc : http://sources.redhat.com/ml/libc-alpha/2007-09/msg00069.htm(...) ) d'implémenter des standards (car oui, les fonctions "bannies" ont des remplaçants "safe", normés qui plus est : http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1225.pdf ), donc bon sur ce sujet je dirais 1 point négatif partout : MS pour passer un peu en force, et GLibc pour refuser un standard (car l'idée vient du méchant qui a fait l'effort de passer par l'ISO/IEC?)

    A noter que le compilateur MS met un warning sur ces fonctions, désactivable, et pas une erreur, donc "banni" est un bien grand mot.
    • [^] # Re: Le libre et les standards...

      Posté par  . Évalué à 0.

      les fonctions bannies ont des remplaçants safe

      J'espère que tu ne codes pas en C toi, car si tu fais aveuglément confiance en ces fonctions autant ne pas les utiliser. Safe est un grand mot, à part envoyer une erreur à un développeur perdant de vu ce qu'il développe sans vérifier la cohérence des données qu'il manipule ça ne sert à rien. Qu'un strncpy te donne une erreur, c'est un moindre mal, mais retrouver son origine est très loin d'être toujours simple si on ne se base que sur les erreurs de ces fonctions.
      D'ailleurs ces strn* sont loin d'être exemptes de problèmes et nécessitent de toute manière certaines vérifications avant d'être utilisées.
      Si on ne gère pas proprement la cohérence des données qu'on utilise on peut vite arriver à des situations de ce genre:

      char plop[24];
      char plop2[42];
      strncpy(plop, plop2, 42);
  • # En même temps...

    Posté par  . Évalué à 6.

    D'après Ulrich Drepper (dev de la glibc) sur la question:
    This is horribly inefficient BSD crap. Using these function only
    leads to other errors. Correct string handling means that you always
    know how long your strings are and therefore you can you memcpy
    (instead of strcpy).


    tout le thread pour donner un peu de grain à moudre
    http://sources.redhat.com/ml/libc-alpha/2000-08/msg00053.htm(...)
    http://sources.redhat.com/ml/libc-alpha/2000-08/msg00060.htm(...)
    http://sources.redhat.com/ml/libc-alpha/2000-08/msg00061.htm(...)

    À vos trolls prêt partez!!!!
    • [^] # Re: En même temps...

      Posté par  . Évalué à 1.

      C'est pas de la micro-optimisation ces bidouilles ?

      Genre je sais que c'est la libc, que c'est une brique de base importante, que c'est beaucoup utilisé par pleins de programmes et tout, mais si c'est pour économiser quelques cycles CPU pour calculer des tailles, ça va à priori pas changer monstrueusement le système en un gros veau.

      Sauf cas très particuliers peut être.
      • [^] # strlcpy plus rapide que strncpy

        Posté par  (site web personnel) . Évalué à 3.

        Il me semble que strlcpy() est plus rapide que strncpy() car strlcpy() écrit un seul octet nul, alors que strncpy() remplit de zéro jusqu'à la fin.

        « man strncpy : (...) Dans le cas où la longueur de src est inférieure à n, la fin de dest sera remplie avec des caractères nuls. »
    • [^] # Re: En même temps...

      Posté par  (site web personnel) . Évalué à 5.

      Je trouve ça nul de refuser strlcpy()/strlcat() mais conserver gets() qui est connu pour être complètement troué de par sa conception !
    • [^] # Re: En même temps...

      Posté par  . Évalué à 4.

      >> Ulrich Drepper

      C'est pas le monsieur qui a motiver l'addoption de eglibc par Debian ? A tien si.

      Vous en tirez les conclusions que vous voulez.
      • [^] # Re: En même temps...

        Posté par  (site web personnel) . Évalué à 8.

        Je pense qu'il ne faut pas tout mélanger ni l'accuser de tous les maux.

        Ulrich peut être insultant et grossier, communique mal, se fout des architectures pseudo-exotiques, et gère mal le coté communautaire de "sa" libc, soit.

        Est-ce que c'est une raison pour rejeter en vrac tous ses avis techniques ? Je ne pense pas. Son explication donnée dans le thread indiqué plus haut par suJeSelS me semble tout à fait pertinente. Il en va de même pour d'autres sujets qu'on a pu découvrir lors du buzz debian/eglibc. Il est peut-être sociopathe, mais certainement pas incompétent. Je continuerai à écouter ses avis techniques.

        Debian n'a pas adopté eglibc parce que la glibc était mauvaise en elle-même, mais parce que le processus de développement, plus totalitaire que communautaire, et le comportement d'Ulrich Drepper leur demandait une importante surcharge de travail.
        • [^] # Re: En même temps...

          Posté par  . Évalué à 3.

          Il y a Ulrich Drepper d'un cote, et tout un tas d'experts en developpement de l'autre cote.

          Perso, je choisis pas le cote d'Ulrich Drepper, notamment parce que les failles je les vois quasiment toutes de part mon boulot et je ne comptes plus le nombre que j'ai vu a cause de strcpy et autres, et j'ai du mal a compter celles avec les fonctions sures parce que je ne me souviens pas en avoir vu alors qu'elles sont utilisees a peu pres partout dans Vista.

          Et ca c'est la pratique, pas la theorie...
        • [^] # Re: En même temps...

          Posté par  . Évalué à 6.

          Quel avis technique? Il se contente de dire que ca pue et que de toute facon on n'en a pas besoin. A part un tombereau d'insultes et des arguments d'autorite, on a pas grand chose a se mettre sous la dent.

          En gros il faut croire sur parole un mec qui te dis que t'est qu'un connard qui n'a aucune idee de ce que tu racontes. Je suis pas sur que ca soit la meilleure methode pour convaincre les gens...
        • [^] # Re: En même temps...

          Posté par  . Évalué à 3.

          Debian n'a pas adopté eglibc parce que la glibc était mauvaise en elle-même, mais parce que le processus de développement, plus totalitaire que communautaire, et le comportement d'Ulrich Drepper leur demandait une importante surcharge de travail.

          Et il est très probable que ce comportement rende la glibc plus mauvaise (ou moins bonne) qu'elle ne pourrait l'être. Je ne crois pas qu'il y a beaucoup d'humains normalement constitués (y compris d'excellents développeurs) qui aient envie de contribuer dans une ambiance pareille.
  • # Pisk'on trolle

    Posté par  . Évalué à 8.

    Un certain Theo avait essayé de faire intégrer des fonctions plus safe dans la libc, il me semble. Il a dû se faire traiter de masturbating monkey ou un truc du style avant de retourner faire un OS qui est secure (tout en se masturbant donc).

    En fait, ce qu'il faut interdire, c'est de coder à deux mains, ça fait du code pas secure, alors qu'en se tappant une queue (de singe) en même temps, tout rulez.

    Comme je parle d'OpenBSD, on finit par une chanson :
    "ça va troller comme sur une plage en été, ça va troller"
  • # Et pourquoi pas bannir le C entièrement ?

    Posté par  . Évalué à 1.

    Remplacé par le C#, parce que c'est plus safe. Bien évidemment, il est capital de bannir l'assembleur, parce que c'est quand même le langage qui permet de faire le plus de choses (donc de conneries). Sans oublier le binaire.
    • [^] # Re: Il faut bannir la programmation

      Posté par  . Évalué à 9.

      En utilisant un bon générateur systématique, on aurait [[La_bibliothèque_de_Babel]] des programmes. Parmi l'inifnité de programmes générés il y a un programme qui fait exactement ce qu'on veut et qui est sûr. Il n'ya a qu'à les tester tous et le trouver (et fini les bugs (et fini les problèmes de programmation)!
      • [^] # Re: Il faut bannir la programmation

        Posté par  . Évalué à 10.

        "(et fini les bugs (et fini les problèmes de programmation)!"
        Dit-il en oubliant une parenthèse fermante !
        Encore un codeur Lisp du dimanche, pfff...
      • [^] # Re: Il faut bannir la programmation

        Posté par  (site web personnel) . Évalué à 3.

        Parmi l'infinité de programmes générés il y a un programme qui fait exactement ce qu'on veut et qui est sûr.

        C'est génial comme idée, il me manquait justement un programme qui résolvait le problème de l'arrêt !
      • [^] # Re: Il faut bannir la programmation

        Posté par  . Évalué à 3.

        Pour le test, je propose de piocher dans la bibliothèque des tests : parmi tous les tests disponibles, il y a forcément un test correct qui permet de savoir exactement si le programme qu'on veut tester fait exactement ce qu'on veut.
        • [^] # Re: Il faut bannir la programmation

          Posté par  . Évalué à 1.

          Deux solutions :
          - Faire un programme qui cherche le programme qui cherche ce qu'on veut (ou le piocher dans la liste).
          - Faire une double boucle pour tester chacun des programmes avec l'un des autres.
  • # Il y en a qui le font !

    Posté par  (Mastodon) . Évalué à 6.

    Je suis justement en train de relire les "C coding standards" de notre fournisseur (équipementier aéronautique), et voici ce qu'on peut y trouver (entre autre) dans le chapitre "Security Related" :

    The following library functions shall not be used: strcpy(), strcat(), sprintf (), and gets().

    En théorie, la théorie et la pratique c'est pareil. En pratique c'est pas vrai.

  • # pas frais

    Posté par  (site web personnel) . Évalué à 2.

    Oué enfin il est pas très frais ton poisson, depuis Visual Studio 2005, l'utilisation de ces fonctions génère un warning "Deprecated".
    • [^] # Re: pas frais

      Posté par  . Évalué à 10.

      Oué enfin il est pas très frais ton poisson

      Monsieur,
      En tant qu'avocat des éditions Albert René, je constate que vous avez utilisé une expression nous appartenant dans un de vos commentaires, sans autorisation, ni compensation financière suite au préjudice apporté à mon client.

      Je vous propose donc un règlement à l'amiable : je vous sauai gré de bien vouloir verser sur un compte paypal la somme de 300 000 euros, ou nous nous verrons dans l'obligation de vous poursuivre en justice pour obtenir réparation.

      Cordialement ...
      Me . Vaux Tour et associés.
      Avocats.
  • # bannir et remplacer

    Posté par  (site web personnel) . Évalué à 0.

    Ils bannissent des fonctions jugées non fiables
    très bien
    Mais ils les remplacent par quoi ?

    hummm okok je ->
  • # Et la norme ?

    Posté par  . Évalué à 3.

    Ben, c'est bien jolie tout ça, mais, si je code en décidant d'utiliser le C99, je m'attends à ce que mon compilateur implémente correctement, toutes les fonctions de la norme. Je n'attends pas forcément de microsoft une implémentation correct des fonctions POSIX, BSD, etc. Mais de la norme, si.
    Qu'on impose des restriction à ces employés, pour éviter les bugs de débutant soit. On le fait tous, car souvent, dès que tu commence à maîtriser la programmation, on veut que tu prennent des responsabilité :-( Du coup, tout est programmé par des débutant, ou presque...
    • [^] # Re: Et la norme ?

      Posté par  . Évalué à 3.

      Ces fonctions sont bannies chez Microsoft (en interne) mais sont considérées comme dépréciées par le compilateur. Tu peux donc continuer à faire ton programme en C99, ANSI ou ce que tu veux, tu vas juste te prendre les avertissements du compilateur concernant le danger des fonctions « bannies » et qu'il faudrait les remplacer par les fonctions safe équivalentes. Donc si tu connais des problèmes de compatibilité ou de compilation alors ce ne sera pas à cause de cette mise au ban ou dépréciation (en fonction d'où on se situe).

      Je trouve que Microsoft joue plutôt bien le jeu de la sécurité sur ce point.

      The capacity of the human mind for swallowing nonsense and spewing it forth in violent and repressive action has never yet been plumbed. -- Robert A. Heinlein

      • [^] # Re: Et la norme ?

        Posté par  . Évalué à 2.

        Ben justement, je trouve au contraire que ça ressemble à une politique d'incompatibilité volontaire.

        Ex:
        ATTENTION, cette fonction est dangereuse, utilisé plutôt celle-ci (made-in microsoft).
        Quelque temps plus tard, le développeur souhaite ouvrir son programme à d'autre plateforme. Réaction à chaud du dit développeur :
        "C'est nul cette plateforme, y a pas la fonction micro_supersafe_cpy", je vais rester sur visual et ne plus regarder ailleurs.

        J'ai sans doute tort, mais ça me semble un peu abusé de mettre des warning sur des fonctions faisant parti de la norme. Microsoft devrait plutôt tenter de les sortir de la norme, puis de les faire remplacer dans la norme, puis de les implémenter.
        • [^] # Re: Et la norme ?

          Posté par  . Évalué à 2.

          Je ne trouve pas qu'il y ait incompatibilité flagrante. Il me semble, souvenirs de 2004-5, que l'on peut facilement remplacer les fonctions non safe avec celles safe par de simple

          #ifdef __MSVC__
          #define func func_s
          #endif


          Ou si ce n'est pas le cas, il me semble que ça reste assez trivial à gérer. Pas envie d'installer Windows sur une machine, ni de télécharger l'environnement de compilation de Microsoft pour confirmer :p.

          C'est sûr que si des fonctions de remplacement safe faisaient partie d'une norme ce serait plus simple à gérer.

          The capacity of the human mind for swallowing nonsense and spewing it forth in violent and repressive action has never yet been plumbed. -- Robert A. Heinlein

        • [^] # Re: Et la norme ?

          Posté par  . Évalué à 4.

          Microsoft devrait plutôt tenter de les sortir de la norme, puis de les faire remplacer dans la norme, puis de les implémenter.
          C'est moi ou y a une erreur dans l'ordre des actions ?
          Il vaudrait mieux d'abord faire rentrer les nouvelles fonctions dans la norme puis les implémenter puis en faire sortir les fonctions dépréciées, non ?
          • [^] # Re: Et la norme ?

            Posté par  . Évalué à 2.

            Oui, tu as parfaitement compris le sens de ma pensée, malgré la phrase déplorable que j'ai écrite.

            \<private\>A noter : ne pas répondre à l'heure de la sieste\</private\>
        • [^] # La norme evolue et va integrer tout ca...

          Posté par  . Évalué à 4.

          En fait ce journal est un peu trompeur, on a l'impression que tout ca est recent (c'est pas la faute de l'auteur, ca fait le tour des sites de news en ce moment et pourri les resultats de recherche sur Google avec 3 tonnes de copier-coller du meme article).

          Ca fait maintenant un petit moment que ces fonctions sont marques comme deprecated dans la lib CRT de Microsoft (tu peux virer les warnings avec un define global dans ton projet, donc si tu fais du code portable, c'est pas trop genant).

          Sinon, il y a un groupe de travail au niveau ISO (TR24731) qui reflechit justement sur ces questions, donc accuser MS me parait un peu bizarre (on va mettre ca sur le compte de l'ignorance et le fait que les resultats Google sur le sujet sont a la ramasse en ce moment). C'est meme note sur la page wikipedia (meme si pas explicite).

          http://en.wikipedia.org/wiki/C99 (voir section Future work)
          http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1225.pdf
          http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1337.pdf
          http://www.open-std.org/jtc1/sc22/wg14/www/projects

          En en parlant de code non portable et de specificites des compilateurs, on pourrait parler un peu des extensions GCC, mais on est que lundi...
        • [^] # Re: Et la norme ?

          Posté par  (site web personnel) . Évalué à 2.

          Ben justement, je trouve au contraire que ça ressemble à une politique d'incompatibilité volontaire.

          Oui, mais non : l'incompatibilité volontaire, c'est la libc Linux qui la fait.
          Microsoft utilise des fonctions ISO/IEC, donc bien standardisées.
          Après, si la libc Linux refuse d'implémenter des standards, ce n'est pas la faute de MS qui a travaillé sur le processus de normalisation...
        • [^] # Re: Et la norme ?

          Posté par  . Évalué à 1.

          En même temps, tu as déjà vu le warning affiché par gcc si tu utilises gets() ?

Suivre le flux des commentaires

Note : les commentaires appartiennent à celles et ceux qui les ont postés. Nous n’en sommes pas responsables.