From d2b068755876fd990b289c810bc1cd71e7c6cefc Mon Sep 17 00:00:00 2001 From: Jenn Magder Date: Wed, 28 Apr 2021 11:05:09 -0700 Subject: [PATCH] Remove Finder extended attributes before code signing iOS frameworks (#81342) --- .../lib/src/build_system/targets/ios.dart | 19 ++++- .../build_system/targets/ios_test.dart | 81 ++++++++++++++++++- 2 files changed, 93 insertions(+), 7 deletions(-) diff --git a/packages/flutter_tools/lib/src/build_system/targets/ios.dart b/packages/flutter_tools/lib/src/build_system/targets/ios.dart index dbef1fa0c0..eb9a7775b8 100644 --- a/packages/flutter_tools/lib/src/build_system/targets/ios.dart +++ b/packages/flutter_tools/lib/src/build_system/targets/ios.dart @@ -626,7 +626,20 @@ void _signFramework(Environment environment, String binaryPath, BuildMode buildM if (codesignIdentity == null || codesignIdentity.isEmpty) { return; } - final ProcessResult result = environment.processManager.runSync([ + + // Extended attributes applied by Finder can cause code signing errors. Remove them. + // https://developer.apple.com/library/archive/qa/qa1940/_index.html + final ProcessResult xattrResult = environment.processManager.runSync([ + 'xattr', + '-r', + '-d', + 'com.apple.FinderInfo', + binaryPath, + ]); + if (xattrResult.exitCode != 0) { + environment.logger.printTrace('Failed to remove FinderInfo extended attributes from $binaryPath.\n${xattrResult.stderr}'); + } + final ProcessResult codesignResult = environment.processManager.runSync([ 'codesign', '--force', '--sign', @@ -637,7 +650,7 @@ void _signFramework(Environment environment, String binaryPath, BuildMode buildM ], binaryPath, ]); - if (result.exitCode != 0) { - throw Exception('Failed to codesign $binaryPath with identity $codesignIdentity.\n${result.stderr}'); + if (codesignResult.exitCode != 0) { + throw Exception('Failed to codesign $binaryPath with identity $codesignIdentity.\n${codesignResult.stderr}'); } } diff --git a/packages/flutter_tools/test/general.shard/build_system/targets/ios_test.dart b/packages/flutter_tools/test/general.shard/build_system/targets/ios_test.dart index 4fb1bab25d..6dfccab044 100644 --- a/packages/flutter_tools/test/general.shard/build_system/targets/ios_test.dart +++ b/packages/flutter_tools/test/general.shard/build_system/targets/ios_test.dart @@ -138,7 +138,14 @@ void main() { final Directory frameworkDirectory = environment.outputDir.childDirectory('App.framework'); final File frameworkDirectoryBinary = frameworkDirectory.childFile('App'); - processManager.addCommand( + processManager.addCommands([ + FakeCommand(command: [ + 'xattr', + '-r', + '-d', + 'com.apple.FinderInfo', + frameworkDirectoryBinary.path, + ]), FakeCommand(command: [ 'codesign', '--force', @@ -147,7 +154,7 @@ void main() { '--timestamp=none', frameworkDirectoryBinary.path, ]), - ); + ]); await const DebugIosApplicationBundle().build(environment); expect(processManager.hasRemainingExpectations, isFalse); @@ -184,7 +191,14 @@ void main() { final Directory frameworkDirectory = environment.outputDir.childDirectory('App.framework'); final File frameworkDirectoryBinary = frameworkDirectory.childFile('App'); - processManager.addCommand( + processManager.addCommands([ + FakeCommand(command: [ + 'xattr', + '-r', + '-d', + 'com.apple.FinderInfo', + frameworkDirectoryBinary.path, + ]), FakeCommand(command: [ 'codesign', '--force', @@ -192,7 +206,7 @@ void main() { 'ABC123', frameworkDirectoryBinary.path, ]), - ); + ]); await const ReleaseIosApplicationBundle().build(environment); expect(processManager.hasRemainingExpectations, isFalse); @@ -277,6 +291,7 @@ void main() { FakeCommand lipoCommandNonFatResult; FakeCommand lipoVerifyArm64Command; FakeCommand bitcodeStripCommand; + FakeCommand xattrRemoveCommand; setUp(() { final FileSystem fileSystem = MemoryFileSystem.test(); @@ -313,6 +328,14 @@ void main() { '-o', binary.path, ]); + + xattrRemoveCommand = FakeCommand(command: [ + 'xattr', + '-r', + '-d', + 'com.apple.FinderInfo', + binary.path, + ]); }); testWithoutContext('iphonesimulator', () async { @@ -621,6 +644,54 @@ void main() { expect(processManager.hasRemainingExpectations, isFalse); }); + testWithoutContext('logs when extended attribute fails', () async { + binary.createSync(recursive: true); + + final Environment environment = Environment.test( + fileSystem.currentDirectory, + processManager: processManager, + artifacts: artifacts, + logger: logger, + fileSystem: fileSystem, + outputDir: outputDir, + defines: { + kIosArchs: 'arm64', + kSdkRoot: 'path/to/iPhoneOS.sdk', + kBitcodeFlag: '', + kCodesignIdentity: 'ABC123', + }, + ); + + processManager.addCommands([ + copyPhysicalFrameworkCommand, + lipoCommandNonFatResult, + lipoVerifyArm64Command, + bitcodeStripCommand, + FakeCommand( + command: [ + 'xattr', + '-r', + '-d', + 'com.apple.FinderInfo', + binary.path, + ], + exitCode: 1, + stderr: 'Failed to remove extended attributes', + ), + FakeCommand(command: [ + 'codesign', + '--force', + '--sign', + 'ABC123', + '--timestamp=none', + binary.path, + ]), + ]); + + await const DebugUnpackIOS().build(environment); + expect(logger.traceText, contains('Failed to remove extended attributes')); + }); + testWithoutContext('fails when codesign fails', () async { binary.createSync(recursive: true); @@ -644,6 +715,7 @@ void main() { lipoCommandNonFatResult, lipoVerifyArm64Command, bitcodeStripCommand, + xattrRemoveCommand, FakeCommand(command: [ 'codesign', '--force', @@ -688,6 +760,7 @@ void main() { lipoCommandNonFatResult, lipoVerifyArm64Command, bitcodeStripCommand, + xattrRemoveCommand, FakeCommand(command: [ 'codesign', '--force',