@@ -951,7 +951,12 @@ export class FileTypeParser {
951951 } ;
952952 }
953953
954- if ( this . check ( [ 0xCF , 0xFA , 0xED , 0xFE ] ) ) {
954+ if (
955+ this . check ( [ 0xFE , 0xED , 0xFA , 0xCE ] ) // 32-bit, big-endian
956+ || this . check ( [ 0xFE , 0xED , 0xFA , 0xCF ] ) // 64-bit, big-endian
957+ || this . check ( [ 0xCE , 0xFA , 0xED , 0xFE ] ) // 32-bit, little-endian
958+ || this . check ( [ 0xCF , 0xFA , 0xED , 0xFE ] ) // 64-bit, little-endian
959+ ) {
955960 return {
956961 ext : 'macho' ,
957962 mime : 'application/x-mach-binary' ,
@@ -1064,10 +1069,25 @@ export class FileTypeParser {
10641069 }
10651070
10661071 if ( this . check ( [ 0xCA , 0xFE , 0xBA , 0xBE ] ) ) {
1067- return {
1068- ext : 'class' ,
1069- mime : 'application/java-vm' ,
1070- } ;
1072+ // Java bytecode and Mach-O universal binaries have the same magic number.
1073+ // We disambiguate based on the next 4 bytes, as done by `file`.
1074+ // See https://github.com/file/file/blob/master/magic/Magdir/cafebabe
1075+ const machOArchitectureCount = Token . UINT32_BE . get ( this . buffer , 4 ) ;
1076+ const javaClassFileMajorVersion = Token . UINT16_BE . get ( this . buffer , 6 ) ;
1077+
1078+ if ( machOArchitectureCount > 0 && machOArchitectureCount <= 30 ) {
1079+ return {
1080+ ext : 'macho' ,
1081+ mime : 'application/x-mach-binary' ,
1082+ } ;
1083+ }
1084+
1085+ if ( javaClassFileMajorVersion > 30 ) {
1086+ return {
1087+ ext : 'class' ,
1088+ mime : 'application/java-vm' ,
1089+ } ;
1090+ }
10711091 }
10721092
10731093 if ( this . checkString ( '.RMF' ) ) {
0 commit comments