Caractères nulles dans un NSPipe ?

tabliertablier Membre
décembre 2009 modifié dans API AppKit #1
J'utilise NSTask et NSPipe pour lancer un "AppleEvent Logging" et récupérer le texte de retour.
Jusque là  rien d'exceptionnel! pour faire cela, j'ai utilisé "TaskWrapper" qui est dans l'exemple "Moriarity" de Apple.

Mais  "AppleEvent Logging" à  quelques bugs!!  Utilisé directement dans la console j'obtiens (extrait du texte):
      key 'fltp' -
        { 1 } 'enum':  4 bytes {
          '?
        }
      key '----' -
        { 1 } 'obj ':  - 4 items {
          key 'form' -
            { 1 } 'enum':  4 bytes {
              'indx'

Le code '?  devrait être '?'.  Mais comme ces codes ont tous 4 caractères, je soupçonne que celui-ci devrait s'écrire 
'?\000\000\000', soit ? suivi de 3 nulls (c'est parfaitement autorisé dans les codes AppleEvent).

Mon problème:
en utilisant "AppleEvent Logging" lancé par un NSTask et en récupérant les données par un NSPipe, le bloc de donnée qui contient les nuls est carrément sauté!
Je n'arrive pas à  savoir si c'est le pipe qui me fait une m.... ou si c'est le traitement postérieur dans "TaskWrapper" qui est inadéquat.
Qui aurait des lumières sur un truc aussi tordu? est-ce que le Pipe transmet tout les caractères y compris les nuls?

(Je joins le texte complet pris dans la console dans un .rtf zippé. Le bloc sauté est en rouge!)

Réponses

  • wiskywisky Membre
    13:27 modifié #2
    Les null ne sont pas prévu pour fermer une chaine ? Ce qui fait que là  les Null ne sont pas traiter/affiché correctement ! Il manque le guillemet de fin à  cause de ça, la fonction d'affichage stoppe au premier null !
  • AliGatorAliGator Membre, Modérateur
    décembre 2009 modifié #3
    Essaye avec '?  ' (des espaces à  la place des \000) ou '  ?'... ou même pourquoi pas... '?' tout court !

    En effet, tu dois déjà  savoir que mettre entre appostrophes un caractère, comme [tt]'A'[/tt], est la façon de représenter le caractère "A" en C, et est strictement équivalente à  écrire son code ascii. Ainsi, les notation 'A', 0x41 et 65 sont toutes les trois équivalentes, elles représentent un char (valeur sur un octet) de valeur 65.

    Eh bien avec deux caractères entre les apostrophes, c'est pareil sauf que ça représente un "short". Et avec quatre caractères, un long. Ainsi, 'AB' sera équivalent à  0x4142 (ou 0x4241 je sais plus trop ça dépend de l'endianness attention à  ce point tout de même), et 'ABCD' à  0x41424344 (ou 0x44434241 ?).

    Du coup un code AppleEvent, généralement représentés par 4 lettres entre apostrophes, est en fait un long... et '?', qui correspond à  la valeur 63, peut tout à  fait tenir dans un long ;)
  • tabliertablier Membre
    13:27 modifié #4
      :( Hélas, ce n'est pas moi qui fait l'erreur!!  C'est le "AppleEvent logging" du système qui, dans le terminal, ne représente pas correctement les codes. Pour ma part, je ne fais que récupérer et interpréter le résultat.
    J'ai posté chez apple pour leur signaler l'erreur "unmatched apostrophe". Mais d'ici qu'ils acceptent de corriger l'erreur !!!!!
    Ce qui m'intéresse c'est:  est ce qu'il y a moyen de s'en sortir en récupérant réellement tout les caractères, y compris les nulls?

    Pour info voici le texte de base envoyé à  Apple:
    Error description:  In AppleEvent code,  there is a syntax error in the logging output.

    This error is produced on both PPC and Intel platforms.
    In order to produce the error do the following:

    1) Save the following AppleScript as an application:

    tell application "Microsoft Excel"
    set xb to name of workbook 1
    set xc to name of sheet 1 of workbook xb
    save (sheet 1 of workbook xb) in file ((path to desktop) & xc) as CSV file format
    end tell


    2) In Excel, open a workbook containing some data.

    3) In Terminal, start AppleEvent logging and the AppleScript application created above, using the following command line:

    prompt$  export AEDebugSends=1; export AEDebugReceives=1 ; 'path_to AppleScript_application' <return>

    All AppleEvents are printed in Terminal. The line indicated below contains a syntax error - unmatched apostrophe

    AE2000 (563): Sending an event:


    oo start of event oo


    { 1 } 'aevt':  core/save (ppc ){
              return id: 36896773 (0x2330005)
        transaction id: 0 (0x0)
      interaction level: 96 (0x60)
        reply required: 1 (0x1)
                remote: 0 (0x0)
          for recording: 0 (0x0)
            reply port: 0 (0x0)
      target:
        { 2 } 'psn ':  8 bytes {
          { 0x0, 0x76076 } (Microsoft Excel)
        }
      fEventSourcePSN: { 0x0,0x7e07e } (testx2.app)
      optional attributes:
        { 1 } 'reco':  - 1 items {
          key 'csig' -
            { 1 } 'magn':  4 bytes {
              65536l (0x10000)
            }
        }

      event data:
        { 1 } 'aevt':  - 3 items {
          key 'kfil' -
            { 1 } 'furl':  40 bytes {
                    000: 6669 6c65  3a2f 2f6c  6f63 616c  686f 7374    file://localhost
                    001: 2f7e 2f64  6573 6b74  6f70 2f54  7275 6325    /~/desktop/Truc%
                    002: 3230 6d61  6368 696e                          20machin       
            }
          key 'fltp' -
            { 1 } 'enum':  4 bytes {
              '?                                                              <<<<<<<<<<<<<< 
      syntax error

            }
          key '----' -
            { 1 } 'obj ':  - 4 items {
              key 'form' -
                { 1 } 'enum':  4 bytes {
                  'indx'
                }
              key 'want' -
                { 1 } 'type':  4 bytes {
                  'X128'
                }
              key 'seld' -
                { 1 } 'long':  4 bytes {
                  1 (0x1)
                }
              key 'from' -
                { 1 } 'obj ':  - 4 items {
                  key 'form' -
                    { 1 } 'enum':  4 bytes {
                      'name'
                    }
                  key 'want' -
                    { 1 } 'type':  4 bytes {
                      'X141'
                    }
                  key 'seld' -
                    { 1 } 'utxt':  22 bytes {
                      "Truc machin"
                    }
                  key 'from' -
                    { -1 } 'null':  null descriptor
                }
            }
        }
    }


    oo  end of event  oo

  • AliGatorAliGator Membre, Modérateur
    13:27 modifié #5
    En même temps c'est un bug d'un outil de debug (dont la sortie n'est pas sensée être interprétée, puisque c'est fait pour du debug à  lire par le développeur, pas par un programme), donc je doute qu'ils le corrigent de sitôt...
  • tabliertablier Membre
    13:27 modifié #6
      >:( Exact et c'est le deuxième bug que je trouve dans cet outil!
    Débugguer avec des outils buggués ! ou va-t-on! Dans ce cas précis, les AppleEvents sont corrects car le script marche bien!  je pense donc que c'est seulement l'affichage qui est faux (printf?). Mon idée serait d'avoir un "Pipe binaire" qui permettrait de récupèrer tout les caractères! mais je ne sais pas comment faire!

    Bien sur, dans "AEv-Utility" je tiens compte de ces erreurs! Mais à  chaque découverte d'erreur je dois corriger le programme!!
  • AliGatorAliGator Membre, Modérateur
    décembre 2009 modifié #7
    Moi je trouve ça un peu gênant mais ça me choque pas non plus plus que ça :
    1) D'une c'est pas une application de debug, mais un flag pour activer ou non des traces. Et ça ça change tout. Tu peux pas dire que des traces sont buguées, c'est juste des traces.
    C'est comme si tu disais que les messages de la console sont bugués parce qu'ils affichent "Laoding" au lieu de "Loading" pour un message de debug écrit par une appli juste parce que le dev qui a mis ces messages de debug a fait une faute de frappe...

    2) C'est aussi pour ça que je te rappelle que c'est pas non plus fait pour être parsé ce genre de sortie. Rien n'interdit à  Apple d'ailleurs un jour de faire sortir comme traces autre chose que cela, par exemple mettre un ">>" au début de chaque ligne qu'il écrit... C'est comme la console, c'est fait pour être lu par un utilisateur pour l'aider à  déboguer, mais pas à  être parsé par un outil.

    Après si tu fais un outil qui arrive à  parser ça, tu as le droit, mais comme la sortie des traces de debug n'est pas non plus faite pour ça, donc tu ne pourras pas non plus te plaindre si Apple change ses traces.
    D'ailleurs, dans les documents officiels documentant ces méthodes de debug et traces, c'est même dit très clairement...
    WARNING: The debugging facilities described in this technote are unsupported. We reserve the right to change or eliminate each facility as dictated by the evolution of Mac OS X; this has happened in the past, and we fully expect it to happen again in the future. These facilities are for debugging only: you must not ship a product that relies on the existence or functionality of the facilities described in this technote.


    Donc certes je comprend que ça soit vraiment gênant pour toi et que ça t'énerve. Mais en même temps c'est pas un bug d'un logiciel dont on cause, là . C'est une trace qui n'est pas formatée comme tu espérais parce qu'ils ont oublié un cas particulier en utilisant un fprintf pour écrire une trace dans la console... on peut pas vrament parler de bug.
  • tabliertablier Membre
    décembre 2009 modifié #8
    (nota: je suis sous 10.5.8, je pense que ce ne doit pas être très différents sous 10.6 ?)
    La manière d'utiliser le "Apple Event logging" est expliquée dans "Apple Events Programming Guide", dans la section "Examining Apple Events". Donc de ce coté tu as tout a fait raison, cela peut être considéré comme du "trace".
    Par contre Apple dit clairement que cela permet d'examiner le contenu des Apple Events. Il définit les syntaxes de représentation, mais ne s'y tient pas! dans ce sens la on peut aussi dire qu'il y a un bug dans le programme de 'trace' et que les résultats sont à  considérer avec suspicion! Ainsi, si tu veux reproduire l'Apple Event en question, tu ne peux savoir comment est fait le code '?    Le 0x00 est un caractère signifiant dans les codes puisque en fait un code est un long, donc '? (si le fprintf s'est arrêté au caractère nul) correspond au moins à  256*256 possibilités: de '?\000\000\000'  à   '?\000\777\777'

      ;) Nous ne nous fâcherons pas pour cela et je vais faire un appel au peuple car je suis incapable de faire seul un très grand nombre d'essais avec AEv-Utility. je demanderai juste qu'on me renvoie les scripts qui posent problème (pas de résultat ou résultats tronqués). Je vais voir comment présenter cela dans les projets d'applications je pense.
  • wiskywisky Membre
    13:27 modifié #9
    Au risque de me répéter le caratère null \000 ou 0x00 est celui utilisé pour déterminé la fin d'une chaine. fprintf est une fonction C qui détecte ce caractère pour mettre fin à  son travail. Une chaine n'ayant pas de caractère null provoquera un buffer overflow.
    Ex de buffer overflow :
    <br />char txt[2];<br />txt[0]=&#39;T&#39;;<br />txt[1]=&#39;e&#39;;<br />txt[2]=&#39;s&#39;;<br />printf(&quot;%s&quot;, txt); // &lt;&lt; affichera le contenu de la mémoire sous forme de string jusqu&#39;à  trouver 0x00 !<br />
    

    Ex correct :
    <br />char txt[2];<br />txt[0]=&#39;T&#39;;<br />txt[1]=&#39;e&#39;;<br />txt[2]=0x00;<br />printf(&quot;%s&quot;, txt); // &lt;&lt; affichera &#39;Te&#39; mais pas le caractère de fin : 0x00 !<br />
    


    Donc si tu lui demande d'afficher une chaine '?\000\000\000' sous la forme :
    <br />char * txt = &quot;&#39;?&#092;0&#092;0&#092;0&#39;&#092;0&quot;;<br />prinf(&quot;%s&quot;,txt); <br />
    

    printf stoppera sont exécution au premier 0x00 et la dernière apostrophe ne sera jamais affiché car le caratère de fin de chaine est avant la fin réel de la chaine.
    Il faut donc utiliser un autre caractère !
  • tabliertablier Membre
    13:27 modifié #10
    à  Wisky

    Je connais ça depuis les années 90/92. Si tu as suivi la discussion, tu as du voir que ce n'est pas moi qui utilise Printf, mais le système sous le terminal (bash probablement). Donc je ne peux rien y changer! J'ai donc signalé à  Apple le fait que le code était tracé incomplètement (unmatched apostrophe), ce qui ne m'empèche pas de ne pas en être content!!!!
  • AliGatorAliGator Membre, Modérateur
    décembre 2009 modifié #11
    Oui, il faudrait que Apple modifie son code qui fait le trace pour ne plus avoir le bug.
    Bug certainement généré par un printf qui ne prend pas en compte que le code à  4 caractères peut contenir des caractères NULL, enfin on suppose que ça vient de là  même si rien nous le prouve... Mais c'est justement parce qu'on sait comment fonctionne printf qu'on a supposé que la raison venait de là  !!

    Ceci dit quand j'y pense, vu que le FourCC* est en fait un long, je trouverai bizarre qu'ils utilisent un [tt]printf("%s",...)[/tt], mais y'a tellement de manières pour afficher ce genre de choses... Par exemple définir
    typedef union {<br />&nbsp; char[4] byte;<br />&nbsp; long code;<br />} fourcc;
    
    Et utiliser byte[0] à  byte[3] pour afficher les caractères avec un printf("%c%c%c%c",...)

    Ou encore utiliser directement
    long fourcc = &#39;abcd&#39;;<br />printf(&quot;&#39;%.4s&#39; , (char*)&amp;fourcc);
    
    quoique là  ça affiche le code dans le sens inverse (du moins sous Intel), donc faut passer fourcc à  la moulinette du swap des octets selon l'endianness...

    Ou encore ils ont peut-être une méthode interne qui prend un FourCC (sous forme de long) et génère un char[5] à  partir de là , donc le 5e char est \0 bien sûr...

    Dans tous les cas, tout cela n'est que supposition de comment Apple a généré ces traces... Mais vu ce qu'on voit, à  mon avis dès que ton FourCC contient un caractère non-imprimable (enfin soit un long dont un des octet de sa représentation informatique ait une valeur inférieure à  20, quoi), c'est pas gagné qu'ils aient prévu le coup pour l'afficher proprement !


    *FourCC est le terme générique pour désigner ce genre de code à  4 caractères, qu'Apple a souvent utilisé, y compris pour les codes types et créateur. C'est l'acronyme de "Four Characters Code".
  • wiskywisky Membre
    13:27 modifié #12
    dans 1261470582:

    à  Wisky

    Je connais ça depuis les années 90/92. Si tu as suivi la discussion, tu as du voir que ce n'est pas moi qui utilise Printf, mais le système sous le terminal (bash probablement). Donc je ne peux rien y changer! J'ai donc signalé à  Apple le fait que le code était tracé incomplètement (unmatched apostrophe), ce qui ne m'empèche pas de ne pas en être content!!!!

    Ce que je voulais dire c'est que si il utilise printf tu risque pas de pouvoir afficher des caractères non imprimables. Sauf en hexa !
Connectez-vous ou Inscrivez-vous pour répondre.