From 40dfa53051f00f4292d50160b6aed7e57d380daa Mon Sep 17 00:00:00 2001 From: "Steinar H. Gunderson" Date: Wed, 29 Apr 2026 22:24:34 +0200 Subject: [PATCH] Do not blindly trust UNIX file attributes from MS-DOS. Several archives made with old MS-DOS archivers will contain garbage in the UNIX permissions field. unar does not trust such file permissions in general for regular files, but it does if they are directories or special files (like symlinks). This can cause issues, e.g.: http://checkpoint.untergrund.net/files/ReBoy_v1.1a.zip unpacks successfully, but directories do not have the appropriate permissions and the result is basically unreadable without further chmod-ing. https://ftp.untergrund.net/users/irokos/magz/canadian_born_coders/aft-11.zip fails unpacking; it believes two of the files are symlinks, and one of them has a file name that is so long that symlink() fails. Both unpack successfully using unzip, which verifies UNIX permissions against MS-DOS permissions; all files must be user-readable, directories must always be user-executable, and the read-only bit must be the opposite of the user-writable permission. If they do not match, the UNIX permissions are ignored. Implement the same logic, so that the two files above extract successfully. --- XADZipParser.m | 27 ++++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/XADZipParser.m b/XADZipParser.m index aec19c25..a7bc54a9 100644 --- a/XADZipParser.m +++ b/XADZipParser.m @@ -841,6 +841,20 @@ -(NSDictionary *)parseZipExtraWithLength:(int)length nameData:(NSData *)namedata +static uint16_t EquivalentUNIXPermissions(uint32_t extfileattrib) +{ + uint16_t perms = 0400; + + // Convert from read-only bit to write permissions. + if(!(extfileattrib&1)) perms |= 0200; + + // For subdirectories, set the executable bit. + if(extfileattrib&0x10) perms |= 0100; + + return perms; +} + + -(void)addZipEntryWithSystem:(int)system extractVersion:(int)extractversion @@ -996,10 +1010,21 @@ -(void)addZipEntryWithSystem:(int)system // While the original system was MSDos, most novel archivers on those systems can still set valid permissions // For example, Archive created on windows, can still have valid symlinks in it int perm = extfileattrib >> 16; + + bool use_posix_permissions = true; + // Ignore permissions set to 0, as these are most likely writte by buggy archivers. + if(perm == 0) use_posix_permissions = false; // Ignore file permissions, because these can lead to the incorrect handling of the files on MacOS - if (perm >= S_IFIFO) { + else if(perm < S_IFIFO) use_posix_permissions = false; + + // If the UNIX permissions and MS-DOS permissions are inconsistent, ignore the UNIX permissions. + // This is the same logic as used in Info-ZIP (unzip). + else if((perm&0700) != EquivalentUNIXPermissions(extfileattrib)) use_posix_permissions = false; + + if(use_posix_permissions) + { [dict setObject:[NSNumber numberWithInt:perm] forKey:XADPosixPermissionsKey]; }