Skip to content

ArgumentError - invalid byte sequence in UTF-8 | Parsing binary plist #12469

@dalemyers

Description

@dalemyers

Report

What did you do?

Ran pod install

What did you expect to happen?

Install all pod dependencies correctly.

What happened instead?

Got an error:

ArgumentError - invalid byte sequence in UTF-8
/opt/homebrew/Cellar/cocoapods/1.15.2/libexec/gems/xcodeproj-1.24.0/lib/xcodeproj/plist.rb:92:in `match'
/opt/homebrew/Cellar/cocoapods/1.15.2/libexec/gems/xcodeproj-1.24.0/lib/xcodeproj/plist.rb:92:in `match'
/opt/homebrew/Cellar/cocoapods/1.15.2/libexec/gems/xcodeproj-1.24.0/lib/xcodeproj/plist.rb:92:in `file_in_conflict?'
/opt/homebrew/Cellar/cocoapods/1.15.2/libexec/gems/xcodeproj-1.24.0/lib/xcodeproj/plist.rb:21:in `read_from_path'
/opt/homebrew/lib/ruby/gems/3.3.0/gems/cocoapods-1.15.2/lib/cocoapods/xcode/xcframework.rb:41:in `initialize'
/opt/homebrew/lib/ruby/gems/3.3.0/gems/cocoapods-1.15.2/lib/cocoapods/target/pod_target.rb:446:in `new'
/opt/homebrew/lib/ruby/gems/3.3.0/gems/cocoapods-1.15.2/lib/cocoapods/target/pod_target.rb:446:in `block (2 levels) in xcframeworks'
/opt/homebrew/lib/ruby/gems/3.3.0/gems/cocoapods-1.15.2/lib/cocoapods/target/pod_target.rb:445:in `map'
/opt/homebrew/lib/ruby/gems/3.3.0/gems/cocoapods-1.15.2/lib/cocoapods/target/pod_target.rb:445:in `block in xcframeworks'
/opt/homebrew/lib/ruby/gems/3.3.0/gems/cocoapods-1.15.2/lib/cocoapods/target/pod_target.rb:444:in `each'
/opt/homebrew/lib/ruby/gems/3.3.0/gems/cocoapods-1.15.2/lib/cocoapods/target/pod_target.rb:444:in `each_with_object'
/opt/homebrew/lib/ruby/gems/3.3.0/gems/cocoapods-1.15.2/lib/cocoapods/target/pod_target.rb:444:in `xcframeworks'
/opt/homebrew/lib/ruby/gems/3.3.0/gems/cocoapods-1.15.2/lib/cocoapods/installer/xcode/pods_project_generator/pod_target_installer.rb:69:in `block in install!'
/opt/homebrew/lib/ruby/gems/3.3.0/gems/cocoapods-1.15.2/lib/cocoapods/user_interface.rb:149:in `message'
/opt/homebrew/lib/ruby/gems/3.3.0/gems/cocoapods-1.15.2/lib/cocoapods/installer/xcode/pods_project_generator/pod_target_installer.rb:40:in `install!'
/opt/homebrew/lib/ruby/gems/3.3.0/gems/cocoapods-1.15.2/lib/cocoapods/installer/xcode/pods_project_generator.rb:115:in `block in install_pod_targets'
/opt/homebrew/lib/ruby/gems/3.3.0/gems/cocoapods-1.15.2/lib/cocoapods/installer/xcode/pods_project_generator.rb:112:in `map'
/opt/homebrew/lib/ruby/gems/3.3.0/gems/cocoapods-1.15.2/lib/cocoapods/installer/xcode/pods_project_generator.rb:112:in `install_pod_targets'
/opt/homebrew/lib/ruby/gems/3.3.0/gems/cocoapods-1.15.2/lib/cocoapods/installer/xcode/single_pods_project_generator.rb:32:in `block in install_all_pod_targets'
/opt/homebrew/lib/ruby/gems/3.3.0/gems/cocoapods-1.15.2/lib/cocoapods/user_interface.rb:149:in `message'
/opt/homebrew/lib/ruby/gems/3.3.0/gems/cocoapods-1.15.2/lib/cocoapods/installer/xcode/single_pods_project_generator.rb:31:in `install_all_pod_targets'
/opt/homebrew/lib/ruby/gems/3.3.0/gems/cocoapods-1.15.2/lib/cocoapods/installer/xcode/single_pods_project_generator.rb:19:in `generate!'
/opt/homebrew/lib/ruby/gems/3.3.0/gems/cocoapods-1.15.2/lib/cocoapods/installer.rb:320:in `block in create_and_save_projects'
/opt/homebrew/lib/ruby/gems/3.3.0/gems/cocoapods-1.15.2/lib/cocoapods/user_interface.rb:64:in `section'
/opt/homebrew/lib/ruby/gems/3.3.0/gems/cocoapods-1.15.2/lib/cocoapods/installer.rb:315:in `create_and_save_projects'
/opt/homebrew/lib/ruby/gems/3.3.0/gems/cocoapods-1.15.2/lib/cocoapods/installer.rb:307:in `generate_pods_project'
/opt/homebrew/lib/ruby/gems/3.3.0/gems/cocoapods-1.15.2/lib/cocoapods/installer.rb:183:in `integrate'
/opt/homebrew/lib/ruby/gems/3.3.0/gems/cocoapods-1.15.2/lib/cocoapods/installer.rb:170:in `install!'
/opt/homebrew/lib/ruby/gems/3.3.0/gems/cocoapods-1.15.2/lib/cocoapods/command/install.rb:52:in `run'
/opt/homebrew/lib/ruby/gems/3.3.0/gems/claide-1.1.0/lib/claide/command.rb:334:in `run'
/opt/homebrew/lib/ruby/gems/3.3.0/gems/cocoapods-1.15.2/lib/cocoapods/command.rb:52:in `run'
/opt/homebrew/lib/ruby/gems/3.3.0/gems/cocoapods-1.15.2/bin/pod:55:in `<top (required)>'
/opt/homebrew/Cellar/cocoapods/1.15.2/libexec/bin/pod:25:in `load'
/opt/homebrew/Cellar/cocoapods/1.15.2/libexec/bin/pod:25:in `<main>'

CocoaPods Environment

Stack

   CocoaPods : 1.15.2
        Ruby : ruby 3.3.0 (2023-12-25 revision 5124f9ac75) [arm64-darwin23]
    RubyGems : 3.5.4
        Host : macOS 14.5 (23F79)
       Xcode : 15.2 (15C500b)
         Git : git version 2.44.0
Ruby lib dir : /opt/homebrew/Cellar/ruby/3.3.0/lib
Repositories : cocoapods - git - https://github.com/CocoaPods/Specs.git @ a61962c72e79c37e4b703204d6682d0147ab6f82

               trunk - CDN - https://cdn.cocoapods.org/

Installation Source

Executable Path: /opt/homebrew/Cellar/cocoapods/1.15.2/libexec/bin/pod

Plugins

cocoapods-deintegrate : 1.0.5
cocoapods-plugins     : 1.0.0
cocoapods-search      : 1.0.1
cocoapods-trunk       : 1.6.0
cocoapods-try         : 1.2.0

Notes

I'm not a Ruby developer, so I can't be 100% here, but the logic in plist.rb seems incorrect. Here's the method:

def self.read_from_path(path)
  path = path.to_s
  unless File.exist?(path)
    raise Informative, "The plist file at path `#{path}` doesn't exist."
  end
  contents = File.read(path)
  if file_in_conflict?(contents)
    raise Informative, "The file `#{path}` is in a merge conflict."
  end
  case Nanaimo::Reader.plist_type(contents)
  when :xml, :binary
    CFPropertyList.native_types(CFPropertyList::List.new(:data => contents).value)
  else
    Nanaimo::Reader.new(contents).parse!.as_ruby
  end
end

We read the file contents, then check if it's in conflict using this method:

def self.file_in_conflict?(contents)
  conflict_regex = /
    ^<{7}(?!<) # Exactly 7 left arrows at the beginning of the line
    [\w\W]* # Anything
    ^={7}(?!=) # Exactly 7 equality symbols at the beginning of the line
    [\w\W]* # Anything
    ^>{7}(?!>) # Exactly 7 right arrows at the beginning of the line
  /xm
  contents.match(conflict_regex)
end

It seems that contents.match(conflict_regex) expects a UTF-8 string, but if a plist is a binary plist, then it will run into issues. A bytewise check, rather than a string check should be used here if I understand what's happening correctly.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions