99#import < React/RCTUIManagerUtils.h>
1010#endif
1111#import < React/RCTBridge.h>
12+ #include < fcntl.h>
13+ #include < sys/stat.h>
14+ #include < unistd.h>
1215
1316#ifdef RCT_NEW_ARCH_ENABLED
1417#import < rnviewshot/rnviewshot.h>
@@ -35,13 +38,22 @@ - (dispatch_queue_t)methodQueue
3538RCT_EXPORT_METHOD (releaseCapture:(nonnull NSString *)uri)
3639{
3740 NSString *directory = [NSTemporaryDirectory () stringByAppendingPathComponent: @" ReactNative" ];
38- // Ensure it's a valid file in the tmp directory
39- if ([uri hasPrefix: directory] && ![uri isEqualToString: directory]) {
40- NSFileManager *fileManager = [NSFileManager new ];
41- if ([fileManager fileExistsAtPath: uri]) {
42- [fileManager removeItemAtPath: uri error: NULL ];
43- }
41+ NSString *prefix = [directory stringByAppendingString: @" /" ];
42+ if (![uri hasPrefix: prefix]) return ;
43+ NSString *name = [uri substringFromIndex: prefix.length];
44+ if (name.length == 0 || [name isEqualToString: @" ." ] || [name isEqualToString: @" .." ] ||
45+ [name containsString: @" /" ] || [name containsString: @" \0 " ]) return ;
46+
47+ // Captures are direct temporary-file children. Use file-only, descriptor-relative
48+ // deletion so a changed leaf cannot redirect cleanup or become a recursive delete.
49+ int directoryFD = open (directory.fileSystemRepresentation , O_RDONLY | O_DIRECTORY | O_NOFOLLOW | O_CLOEXEC );
50+ if (directoryFD < 0 ) return ;
51+ struct stat info;
52+ const char *fileName = name.fileSystemRepresentation ;
53+ if (fileName && fstatat (directoryFD, fileName, &info, AT_SYMLINK_NOFOLLOW ) == 0 && S_ISREG (info.st_mode )) {
54+ unlinkat (directoryFD, fileName, 0 );
4455 }
56+ close (directoryFD);
4557}
4658
4759RCT_EXPORT_METHOD (captureRef:(nonnull NSNumber *)target
0 commit comments