Skip to content

Commit fe7b718

Browse files
authored
Merge commit from fork
1 parent d2b796b commit fe7b718

1 file changed

Lines changed: 34 additions & 11 deletions

File tree

Autoupdate/SUBinaryDeltaApply.m

Lines changed: 34 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -177,7 +177,8 @@ BOOL applyBinaryDelta(NSString *source, NSString *finalDestination, NSString *pa
177177
[archive enumerateItems:^(SPUDeltaArchiveItem *item, BOOL *stop) {
178178
NSString *relativePath = item.relativeFilePath;
179179

180-
if ([relativePath.pathComponents containsObject:@".."]) {
180+
NSArray<NSString *> *relativePathComponents = relativePath.pathComponents;
181+
if ([relativePathComponents containsObject:@".."]) {
181182
if (error != NULL) {
182183
*error = [NSError errorWithDomain:NSCocoaErrorDomain code:NSFileWriteUnknownError userInfo:@{ NSLocalizedDescriptionKey: [NSString stringWithFormat:@"Relative path '%@' contains '..' path component", relativePath] }];
183184
}
@@ -187,18 +188,40 @@ BOOL applyBinaryDelta(NSString *source, NSString *finalDestination, NSString *pa
187188

188189
NSString *sourceFilePath = [source stringByAppendingPathComponent:relativePath];
189190
NSString *destinationFilePath = [destination stringByAppendingPathComponent:relativePath];
191+
190192
{
191-
NSString *destinationParentDirectory = destinationFilePath.stringByDeletingLastPathComponent;
192-
NSDictionary<NSFileAttributeKey, id> *destinationParentDirectoryAttributes = [fileManager attributesOfItemAtPath:destinationParentDirectory error:NULL];
193-
194-
// It is OK for the directory parent to not exist if it has already been removed
195-
if (destinationParentDirectoryAttributes != nil) {
196-
// But if it does exist, make sure the entry in the parent directory we're looking at is good
197-
// If it's inside a symlink, this is not good in any circumstance
198-
NSString *fileType = destinationParentDirectoryAttributes[NSFileType];
199-
if ([fileType isEqualToString:NSFileTypeSymbolicLink]) {
193+
// Walk each intermediate directory component of relativePath, excluding the last component, and verify none are symlinks.
194+
NSUInteger relativePathComponentCount = relativePathComponents.count;
195+
NSString *cumulativePath = destination;
196+
for (NSUInteger relativePathComponentIndex = 0; relativePathComponentIndex + 1 < relativePathComponentCount; relativePathComponentIndex++) {
197+
cumulativePath = [cumulativePath stringByAppendingPathComponent:relativePathComponents[relativePathComponentIndex]];
198+
199+
char cumulativePathBuffer[PATH_MAX + 1] = {0};
200+
if (![cumulativePath getFileSystemRepresentation:cumulativePathBuffer maxLength:PATH_MAX]) {
201+
if (error != NULL) {
202+
*error = [NSError errorWithDomain:NSCocoaErrorDomain code:NSFileWriteUnknownError userInfo:@{ NSLocalizedDescriptionKey: [NSString stringWithFormat:@"Failed to create patch because '%@' cannot be converted to file system path.", cumulativePath] }];
203+
}
204+
*stop = YES;
205+
return;
206+
}
207+
208+
struct stat cumulativePathStat = {0};
209+
if (lstat(cumulativePathBuffer, &cumulativePathStat) != 0) {
210+
if (errno == ENOENT) {
211+
// Directory doesn't exist, so it can't be a symlink - safe to continue
212+
break;
213+
}
214+
215+
if (error != NULL) {
216+
*error = [NSError errorWithDomain:NSCocoaErrorDomain code:NSFileWriteUnknownError userInfo:@{ NSLocalizedDescriptionKey: [NSString stringWithFormat:@"Failed to create patch because failed to stat '%@' with error: %d", cumulativePath, errno] }];
217+
}
218+
*stop = YES;
219+
return;
220+
}
221+
222+
if (S_ISLNK(cumulativePathStat.st_mode)) {
200223
if (error != NULL) {
201-
*error = [NSError errorWithDomain:NSCocoaErrorDomain code:NSFileWriteUnknownError userInfo:@{ NSLocalizedDescriptionKey: [NSString stringWithFormat:@"Failed to create patch because '%@' cannot be a symbolic link.", destinationParentDirectory] }];
224+
*error = [NSError errorWithDomain:NSCocoaErrorDomain code:NSFileWriteUnknownError userInfo:@{ NSLocalizedDescriptionKey: [NSString stringWithFormat:@"Failed to create patch because '%@' cannot contain a symbolic link in its intermediate path.", destinationFilePath.stringByDeletingLastPathComponent] }];
202225
}
203226
*stop = YES;
204227
return;

0 commit comments

Comments
 (0)