#33 ✓resolved
Martin S.

libplist has issues when sub nodes of type dict are used

Reported by Martin S. | April 15th, 2009 @ 02:46 PM

I noticed libplist 0.10 fails miserably if one uses subnodes in the plist files.

To test simply change the node to in the 1.plist data example and run plist_test. You'll see it even changes some sub nodes of type string into key for no reason in the .out plist file.

I'll look into the issue myself if I got the time.

Comments and changes to this ticket

  • Jonathan Beck

    Jonathan Beck April 15th, 2009 @ 04:45 PM

    Do you mean only changing the array node into dict in 1.plist ?, ie :

    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
    <plist version="1.0">
    <dict>
        <key>Some ASCII string</key>
        <string></string>
        <key>Some UTF8 strings</key>
        <dict>
            <string></string>
            <string></string>
            <string></string>
            <string></string>
            <string></string>
            <string></string>
            <string></string>
            <string></string>
            <string></string>
        </dict>
        <key>Boolean</key>
        <false/>
        <key>Another Boolean</key>
        <true/>
        <key>Some Int</key>
        <integer></integer>
        <key>Some Real</key>
        <real></real>
        <key>Some Date</key>
        <date></date>
        <key>Some Data</key>
        <data>
        </data>
    </dict>
    </plist>
    
    

    In this case the plist wouldn't be valid. dict must follow a certain pattern : they must contain an even number of child and all even child index must be of type KEY (and also non empty). That is why if you change array to dict in 1.plist output will generate keys.

    However it is true that current libplist expect all input to be correct plists and will probably fail if they aren't.

    There is definitely room for improvement in error checking here.

  • Martin S.

    Martin S. April 15th, 2009 @ 05:10 PM

    You are right, didn't notice that it had to be valid like that which of course means the test is correct.

    However, there was another issue I had came up with once I tried to send this to lockdownd:

    
    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
    <plist version="1.0">
    <dict>
    	<key>ClientOptions</key>
    	<dict>
    		<key>ApplicationType</key>
    		<string>User</string>
    	</dict>
    	<key>Command</key>
    	<string>Browse</string>
    </dict>
    </plist>
    

    The code to construct it somehow fails to create the 2nd dict node.

    
    ...
    plist_t node = plist_new_dict();
    plist_add_sub_key_el(node, "ClientOptions");
    plist_add_sub_string_el(node, "GetValue");
    plist_t subnode = plist_new_dict();
    plist_add_sub_key_el(subnode, "ApplicationType");
    plist_add_sub_string_el(subnode, "User");
    plist_add_sub_node(node, subnode);
    plist_add_sub_key_el(node,"Command");
    plist_add_sub_string_el(node, "Browse");
    ...
    

    This ends up with an empty dict subnode for some reason.

    Also regarding Python, calling "add_sub_node", "PListNode(somexmlstring)", "get_first_child" and related seems to cause a segfault here.

  • Nikias Bassen

    Nikias Bassen April 15th, 2009 @ 06:34 PM

    Hi, the line

    plist_add_sub_string_el(node, "GetValue");

    is not required to make the xml plist show above, in fact it even creates an invalid plist. But even with this line it works here. Using plist_to_xml I get exactly what you wrote (in xml) above...

  • Jonathan Beck

    Jonathan Beck April 15th, 2009 @ 06:38 PM

    • Tag changed from libplist to libplist, python
    • State changed from “new” to “open”

    Regarding the empty dict, I can't reproduce the problem. I used this :

    #include <stdio.h>
    #include <stdlib.h>
    #include <plist/plist.h>
    
    int main(int argc, char *argv[])
    {
      plist_t node = plist_new_dict();
      plist_add_sub_key_el(node, "ClientOptions");
      plist_add_sub_string_el(node, "GetValue");
      plist_t subnode = plist_new_dict();
      plist_add_sub_key_el(subnode, "ApplicationType");
      plist_add_sub_string_el(subnode, "User");
      plist_add_sub_node(node, subnode);
      plist_add_sub_key_el(node,"Command");
      plist_add_sub_string_el(node, "Browse");
    
      char* xml = 0;
      int l = 0;
      plist_to_xml(node, &xml, &l);
    
      printf("%s\n", xml);
    
      return 0;
    }
    
    

    which I compiled with :

    gcc -g -O0 test.c -o test -lplist
    
    

    it gives me the following output :

    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
    <plist version="1.0">
    <dict>
        <key>ClientOptions</key>
        <string>GetValue</string>
        <dict>
            <key>ApplicationType</key>
            <string>User</string>
        </dict>
        <key>Command</key>
        <string>Browse</string>
    </dict>
    </plist>
    
    

    What is your environment ? i386 or x86_64 ? what version of the dependencies do you use (libglib2 and libxml2).

    Regarding the python segfault, I am able to reproduce with the following script:

    #! /usr/bin/env python
    # -*- coding: utf-8 -*-
    from libplist.PList import *
    
    dict = PListNode(PLIST_DICT)
    dict.add_sub_key("ClientOptions")
    dict.add_sub_string("GetValue")
    
    subdict = PListNode(PLIST_DICT)
    subdict.add_sub_key("ApplicationType")
    subdict.add_sub_string("User")
    dict.add_sub_node(subdict)
    
    dict.add_sub_key("Command")
    dict.add_sub_string("Browse")
    
    print dict.to_xml()
    
    dict2 = PListNode( dict.to_xml() )
    
    print dict2.to_xml()
    
    

    I will analyze this part.

  • Jonathan Beck

    Jonathan Beck April 15th, 2009 @ 06:44 PM

    Ah, you're right Nikias, the GetValue line must be removed to make a valid plist.

    Still have the segfault in python though...

  • Jonathan Beck

    Jonathan Beck April 15th, 2009 @ 08:40 PM

    So I've reworked the SWIG binding since there were multiple errors. Now I don't have any segfault anymore.

    Let me know if last HEAD, so I can close this ticket and tag a new version.

  • Martin S.

    Martin S. April 15th, 2009 @ 09:28 PM

    Thanks for looking into it.

    Despite the usecase you posted working now, the code below fails (not sure if that is expected): @@@dict = PListNode(PLIST_DICT) dict.add_sub_key("ClientOptions") subdict = PListNode(PLIST_DICT) subdict.add_sub_key("ApplicationType") subsubdict = PListNode(PLIST_DICT) subsubdict.add_sub_key("TestKey") subsubdict.add_sub_string("TestString") subdict.add_sub_node(subsubdict) dict.add_sub_node(subdict) dict.add_sub_key("Command") dict.add_sub_string("Browse")@@@

    Also using dict.get_first_child() still segfaults.

  • Jonathan Beck

    Jonathan Beck April 18th, 2009 @ 09:18 AM

    Ok so there was still lifecycle issue in subnodes (deleting twice subnodes data) It should be fixed.

    get_first_child is also fixed.

    Hope it is fully functional now :)

  • Martin S.

    Martin S. April 18th, 2009 @ 01:15 PM

    Nice and thanks a lot, couldn't disturb it by anything thrown at it now. Feel free to close ticket and push a tag. :)

  • Jonathan Beck

    Jonathan Beck April 19th, 2009 @ 03:45 PM

    • State changed from “open” to “resolved”

Please Sign in or create a free account to add a new ticket.

With your very own profile, you can contribute to projects, track your activity, watch tickets, receive and update tickets through your email and much more.

New-ticket Create new ticket

Create your profile

Help contribute to this project by taking a few moments to create your personal profile. Create your profile ยป

A project around supporting the iPhone in Linux.

See http://libimobiledevice.org

People watching this ticket

Pages