ckruse/CFPropertyList

Format error! (CFFormatError) on nil key when using REXML parser

Closed this issue · 4 comments

When CFPropertyList falls back to using REXML for parsing and it encounters a nil key, it raises. This is east to reproduce using the file referenced below.

#!/usr/bin/ruby

require 'rubygems'
require 'cfpropertylist'

file = '/System/Library/Security/authorization.plist'

plist = CFPropertyList::List.new(:file => file)
# CFPropertyList.native_types(plist.value)

Results:

/Library/Ruby/Gems/2.0.0/gems/CFPropertyList-2.2.5/lib/rbREXMLParser.rb:101:in `block in import_xml': Format error! (CFFormatError)
    from /System/Library/Frameworks/Ruby.framework/Versions/2.0/usr/lib/ruby/2.0.0/rexml/element.rb:905:in `block in each'
    from /System/Library/Frameworks/Ruby.framework/Versions/2.0/usr/lib/ruby/2.0.0/rexml/xpath.rb:67:in `each'
    from /System/Library/Frameworks/Ruby.framework/Versions/2.0/usr/lib/ruby/2.0.0/rexml/xpath.rb:67:in `each'
    from /System/Library/Frameworks/Ruby.framework/Versions/2.0/usr/lib/ruby/2.0.0/rexml/element.rb:905:in `each'
    from /Library/Ruby/Gems/2.0.0/gems/CFPropertyList-2.2.5/lib/rbREXMLParser.rb:93:in `import_xml'
    from /Library/Ruby/Gems/2.0.0/gems/CFPropertyList-2.2.5/lib/rbREXMLParser.rb:102:in `block in import_xml'
    from /System/Library/Frameworks/Ruby.framework/Versions/2.0/usr/lib/ruby/2.0.0/rexml/element.rb:905:in `block in each'
    from /System/Library/Frameworks/Ruby.framework/Versions/2.0/usr/lib/ruby/2.0.0/rexml/xpath.rb:67:in `each'
    from /System/Library/Frameworks/Ruby.framework/Versions/2.0/usr/lib/ruby/2.0.0/rexml/xpath.rb:67:in `each'
    from /System/Library/Frameworks/Ruby.framework/Versions/2.0/usr/lib/ruby/2.0.0/rexml/element.rb:905:in `each'
    from /Library/Ruby/Gems/2.0.0/gems/CFPropertyList-2.2.5/lib/rbREXMLParser.rb:93:in `import_xml'
    from /Library/Ruby/Gems/2.0.0/gems/CFPropertyList-2.2.5/lib/rbREXMLParser.rb:23:in `load'
    from /Library/Ruby/Gems/2.0.0/gems/CFPropertyList-2.2.5/lib/rbCFPropertyList.rb:347:in `load'
    from /Library/Ruby/Gems/2.0.0/gems/CFPropertyList-2.2.5/lib/rbCFPropertyList.rb:247:in `initialize'
    from /Users/bcw/Desktop/foo.rb:8:in `new'
    from /Users/bcw/Desktop/foo.rb:8:in `<main>'

As per the Twitters, this...

require "rexml/document"
file = '/System/Library/Security/authorization.plist'
File.open(file) { |fd| doc = REXML::Document.new(fd) }

Parses correctly.

The file referenced exists on all Macs. If you need me to send it you, I'll need your email address.

Ok, found the problem. It was caused by a nil return of REXML for an empty tag (like <key></key>) instead of an empty string. Per se this is correct behavior, but XML plists interpret this as an empty string.

Confirmed. Thanks for the fix, Christian!