Skip to content

Commit 9d3c8fd

Browse files
authored
Merge pull request #54 from SDWebImage/bugfix_encoding_leak
Fix the encoding leak when input CGImage is not RGBA8888 or RGB888
2 parents 7d68ede + 44b1aae commit 9d3c8fd

File tree

1 file changed

+10
-9
lines changed

1 file changed

+10
-9
lines changed

SDWebImageWebPCoder/Classes/SDImageWebPCoder.m

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -762,20 +762,21 @@ - (nullable NSData *)sd_encodedWebpDataWithImage:(nullable CGImageRef)imageRef
762762
if (!dataProvider) {
763763
return nil;
764764
}
765-
CFDataRef dataRef = CGDataProviderCopyData(dataProvider);
766-
if (!dataRef) {
767-
return nil;
768-
}
769765
// Check colorSpace is RGB/RGBA
770766
CGColorSpaceRef colorSpace = CGImageGetColorSpace(imageRef);
771767
BOOL isRGB = CGColorSpaceGetModel(colorSpace) == kCGColorSpaceModelRGB;
772768

769+
CFDataRef dataRef;
773770
uint8_t *rgba = NULL; // RGBA Buffer managed by CFData, don't call `free` on it, instead call `CFRelease` on `dataRef`
774771
// We could not assume that input CGImage's color mode is always RGB888/RGBA8888. Convert all other cases to target color mode using vImage
775772
BOOL isRGB888 = isRGB && byteOrderNormal && alphaInfo == kCGImageAlphaNone && components == 3;
776773
BOOL isRGBA8888 = isRGB && byteOrderNormal && alphaInfo == kCGImageAlphaLast && components == 4;
777774
if (isRGB888 || isRGBA8888) {
778775
// If the input CGImage is already RGB888/RGBA8888
776+
dataRef = CGDataProviderCopyData(dataProvider);
777+
if (!dataRef) {
778+
return nil;
779+
}
779780
rgba = (uint8_t *)CFDataGetBytePtr(dataRef);
780781
} else {
781782
// Convert all other cases to target color mode using vImage
@@ -798,37 +799,37 @@ - (nullable NSData *)sd_encodedWebpDataWithImage:(nullable CGImageRef)imageRef
798799

799800
convertor = vImageConverter_CreateWithCGImageFormat(&srcFormat, &destFormat, NULL, kvImageNoFlags, &error);
800801
if (error != kvImageNoError) {
801-
CFRelease(dataRef);
802802
return nil;
803803
}
804804

805805
vImage_Buffer src;
806806
error = vImageBuffer_InitWithCGImage(&src, &srcFormat, nil, imageRef, kvImageNoFlags);
807807
if (error != kvImageNoError) {
808808
vImageConverter_Release(convertor);
809-
CFRelease(dataRef);
810809
return nil;
811810
}
812811

813812
vImage_Buffer dest;
814813
error = vImageBuffer_Init(&dest, height, width, destFormat.bitsPerPixel, kvImageNoFlags);
815814
if (error != kvImageNoError) {
816815
vImageConverter_Release(convertor);
817-
CFRelease(dataRef);
816+
free(src.data);
818817
return nil;
819818
}
820819

821820
// Convert input color mode to RGB888/RGBA8888
822821
error = vImageConvert_AnyToAny(convertor, &src, &dest, NULL, kvImageNoFlags);
822+
823+
// Free the buffer
824+
free(src.data);
823825
vImageConverter_Release(convertor);
824826
if (error != kvImageNoError) {
825-
CFRelease(dataRef);
827+
free(dest.data);
826828
return nil;
827829
}
828830

829831
rgba = dest.data; // Converted buffer
830832
bytesPerRow = dest.rowBytes; // Converted bytePerRow
831-
CFRelease(dataRef); // Use CFData to manage bytes for free, the same code path for error handling
832833
dataRef = CFDataCreateWithBytesNoCopy(kCFAllocatorDefault, rgba, bytesPerRow * height, kCFAllocatorDefault);
833834
}
834835

0 commit comments

Comments
 (0)