Merge pull request #54 from SDWebImage/bugfix_encoding_leak

Fix the encoding leak when input CGImage is not RGBA8888 or RGB888
This commit is contained in:
DreamPiggy 2021-02-24 20:40:31 +08:00 committed by GitHub
commit 9d3c8fdc20
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 10 additions and 9 deletions

View File

@ -762,20 +762,21 @@ static CGSize SDCalculateThumbnailSize(CGSize fullSize, BOOL preserveAspectRatio
if (!dataProvider) { if (!dataProvider) {
return nil; return nil;
} }
CFDataRef dataRef = CGDataProviderCopyData(dataProvider);
if (!dataRef) {
return nil;
}
// Check colorSpace is RGB/RGBA // Check colorSpace is RGB/RGBA
CGColorSpaceRef colorSpace = CGImageGetColorSpace(imageRef); CGColorSpaceRef colorSpace = CGImageGetColorSpace(imageRef);
BOOL isRGB = CGColorSpaceGetModel(colorSpace) == kCGColorSpaceModelRGB; BOOL isRGB = CGColorSpaceGetModel(colorSpace) == kCGColorSpaceModelRGB;
CFDataRef dataRef;
uint8_t *rgba = NULL; // RGBA Buffer managed by CFData, don't call `free` on it, instead call `CFRelease` on `dataRef` uint8_t *rgba = NULL; // RGBA Buffer managed by CFData, don't call `free` on it, instead call `CFRelease` on `dataRef`
// We could not assume that input CGImage's color mode is always RGB888/RGBA8888. Convert all other cases to target color mode using vImage // We could not assume that input CGImage's color mode is always RGB888/RGBA8888. Convert all other cases to target color mode using vImage
BOOL isRGB888 = isRGB && byteOrderNormal && alphaInfo == kCGImageAlphaNone && components == 3; BOOL isRGB888 = isRGB && byteOrderNormal && alphaInfo == kCGImageAlphaNone && components == 3;
BOOL isRGBA8888 = isRGB && byteOrderNormal && alphaInfo == kCGImageAlphaLast && components == 4; BOOL isRGBA8888 = isRGB && byteOrderNormal && alphaInfo == kCGImageAlphaLast && components == 4;
if (isRGB888 || isRGBA8888) { if (isRGB888 || isRGBA8888) {
// If the input CGImage is already RGB888/RGBA8888 // If the input CGImage is already RGB888/RGBA8888
dataRef = CGDataProviderCopyData(dataProvider);
if (!dataRef) {
return nil;
}
rgba = (uint8_t *)CFDataGetBytePtr(dataRef); rgba = (uint8_t *)CFDataGetBytePtr(dataRef);
} else { } else {
// Convert all other cases to target color mode using vImage // Convert all other cases to target color mode using vImage
@ -798,7 +799,6 @@ static CGSize SDCalculateThumbnailSize(CGSize fullSize, BOOL preserveAspectRatio
convertor = vImageConverter_CreateWithCGImageFormat(&srcFormat, &destFormat, NULL, kvImageNoFlags, &error); convertor = vImageConverter_CreateWithCGImageFormat(&srcFormat, &destFormat, NULL, kvImageNoFlags, &error);
if (error != kvImageNoError) { if (error != kvImageNoError) {
CFRelease(dataRef);
return nil; return nil;
} }
@ -806,7 +806,6 @@ static CGSize SDCalculateThumbnailSize(CGSize fullSize, BOOL preserveAspectRatio
error = vImageBuffer_InitWithCGImage(&src, &srcFormat, nil, imageRef, kvImageNoFlags); error = vImageBuffer_InitWithCGImage(&src, &srcFormat, nil, imageRef, kvImageNoFlags);
if (error != kvImageNoError) { if (error != kvImageNoError) {
vImageConverter_Release(convertor); vImageConverter_Release(convertor);
CFRelease(dataRef);
return nil; return nil;
} }
@ -814,21 +813,23 @@ static CGSize SDCalculateThumbnailSize(CGSize fullSize, BOOL preserveAspectRatio
error = vImageBuffer_Init(&dest, height, width, destFormat.bitsPerPixel, kvImageNoFlags); error = vImageBuffer_Init(&dest, height, width, destFormat.bitsPerPixel, kvImageNoFlags);
if (error != kvImageNoError) { if (error != kvImageNoError) {
vImageConverter_Release(convertor); vImageConverter_Release(convertor);
CFRelease(dataRef); free(src.data);
return nil; return nil;
} }
// Convert input color mode to RGB888/RGBA8888 // Convert input color mode to RGB888/RGBA8888
error = vImageConvert_AnyToAny(convertor, &src, &dest, NULL, kvImageNoFlags); error = vImageConvert_AnyToAny(convertor, &src, &dest, NULL, kvImageNoFlags);
// Free the buffer
free(src.data);
vImageConverter_Release(convertor); vImageConverter_Release(convertor);
if (error != kvImageNoError) { if (error != kvImageNoError) {
CFRelease(dataRef); free(dest.data);
return nil; return nil;
} }
rgba = dest.data; // Converted buffer rgba = dest.data; // Converted buffer
bytesPerRow = dest.rowBytes; // Converted bytePerRow bytesPerRow = dest.rowBytes; // Converted bytePerRow
CFRelease(dataRef); // Use CFData to manage bytes for free, the same code path for error handling
dataRef = CFDataCreateWithBytesNoCopy(kCFAllocatorDefault, rgba, bytesPerRow * height, kCFAllocatorDefault); dataRef = CFDataCreateWithBytesNoCopy(kCFAllocatorDefault, rgba, bytesPerRow * height, kCFAllocatorDefault);
} }