0

Just found an issue running my app through the new Address Sanitizer feature in Xcode 7 that I can't quite make any sense of:

I'm attempting to initialize a medium-sized (588x375) texture from an NSImage like this

NSImage *texture = [[NSBundle bundleForClass:self.class] imageForResource:@"ground_texture"];

NSBitmapImageRep *bitmap = (NSBitmapImageRep *)[texture bestRepresentationForDevice:@{
                                                                                         NSDeviceColorSpaceName: NSCalibratedRGBColorSpace,
                                                                                         NSDeviceBitsPerSample: @8,
                                                                                         NSDeviceIsScreen: @"YES"
                                                                                         }];
unsigned char* imageRepBitmapData = bitmap.bitmapData;

As soon as execution hits the last line of the code sample I'm getting an AsanDie complaining about a heap-buffer-overflow with this stack trace (running 10.11.1 beta):

==5070==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x61300061f8f4 at pc 0x0001000d1c34 bp 0x7fff5fbfbcd0 sp 0x7fff5fbfb488
READ of size 384 at 0x61300061f8f4 thread T0
==5070==WARNING: Can't read from symbolizer at fd 14
    #0 0x1000d1c33 in wrap_memmove (/Applications/Xcode-beta.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/clang/7.0.0/lib/darwin/libclang_rt.asan_osx_dynamic.dylib+0x39c33)
    #1 0x7fff92e1c98c in -[_NSInlineData initWithBytes:length:] (/System/Library/Frameworks/Foundation.framework/Versions/C/Foundation+0xc98c)
    #2 0x7fff92e1c4f6 in -[_NSPlaceholderData initWithBytes:length:copy:deallocator:] (/System/Library/Frameworks/Foundation.framework/Versions/C/Foundation+0xc4f6)
    #3 0x7fff92e1c954 in -[NSData(NSData) initWithBytes:length:] (/System/Library/Frameworks/Foundation.framework/Versions/C/Foundation+0xc954)
    #4 0x7fff92e28800 in +[NSData(NSData) dataWithBytes:length:] (/System/Library/Frameworks/Foundation.framework/Versions/C/Foundation+0x18800)
    #5 0x7fff923733eb in -[NSBitmapImageRep _fromCGImage:performBlockUsingMutableData:] (/System/Library/Frameworks/AppKit.framework/Versions/C/AppKit+0x2503eb)
    #6 0x7fff925d0094 in __79-[NSBitmapImageRep _withoutChangingBackingPerformBlockUsingBackingMutableData:]_block_invoke_2 (/System/Library/Frameworks/AppKit.framework/Versions/C/AppKit+0x4ad094)
    #7 0x7fff922c2093 in __75-[NSBitmapImageRep _withoutChangingBackingPerformBlockUsingBackingCGImage:]_block_invoke (/System/Library/Frameworks/AppKit.framework/Versions/C/AppKit+0x19f093)
    #8 0x7fff922c16f8 in -[NSBitmapImageRep _withoutChangingBackingPerformBlockUsingBackingCGImage:] (/System/Library/Frameworks/AppKit.framework/Versions/C/AppKit+0x19e6f8)
    #9 0x7fff921a0e96 in __79-[NSBitmapImageRep _withoutChangingBackingPerformBlockUsingBackingMutableData:]_block_invoke (/System/Library/Frameworks/AppKit.framework/Versions/C/AppKit+0x7de96)
    #10 0x7fff921a0d9b in -[NSBitmapImageRep _withoutChangingBackingPerformBlockUsingBackingMutableData:] (/System/Library/Frameworks/AppKit.framework/Versions/C/AppKit+0x7dd9b)
    #11 0x7fff921a0d16 in __57-[NSBitmapImageRep _performBlockUsingBackingMutableData:]_block_invoke (/System/Library/Frameworks/AppKit.framework/Versions/C/AppKit+0x7dd16)
    #12 0x7fff921a0c8a in -[NSBitmapImageRep _performBlockUsingBackingMutableData:] (/System/Library/Frameworks/AppKit.framework/Versions/C/AppKit+0x7dc8a)
    #13 0x7fff921a0c17 in -[NSBitmapImageRep getBitmapDataPlanes:] (/System/Library/Frameworks/AppKit.framework/Versions/C/AppKit+0x7dc17)
    #14 0x7fff921a0b9e in -[NSBitmapImageRep bitmapData] (/System/Library/Frameworks/AppKit.framework/Versions/C/AppKit+0x7db9e)

With this allocation strack trace:

0x6130005d59f4 is located 0 bytes to the right of 372-byte region [0x6130005d5880,0x6130005d59f4)
allocated by thread T0 here:
    #0 0x1000dabb0 in wrap_malloc (/Applications/Xcode-beta.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/clang/7.0.0/lib/darwin/libclang_rt.asan_osx_dynamic.dylib+0x42bb0)
    #1 0x7fff92372c42 in -[NSBitmapImageRep _fromCGImage:performBlockUsingMutableData:] (/System/Library/Frameworks/AppKit.framework/Versions/C/AppKit+0x24fc42)
    #2 0x7fff925d0094 in __79-[NSBitmapImageRep _withoutChangingBackingPerformBlockUsingBackingMutableData:]_block_invoke_2 (/System/Library/Frameworks/AppKit.framework/Versions/C/AppKit+0x4ad094)
    #3 0x7fff922c2093 in __75-[NSBitmapImageRep _withoutChangingBackingPerformBlockUsingBackingCGImage:]_block_invoke (/System/Library/Frameworks/AppKit.framework/Versions/C/AppKit+0x19f093)
    #4 0x7fff922c16f8 in -[NSBitmapImageRep _withoutChangingBackingPerformBlockUsingBackingCGImage:] (/System/Library/Frameworks/AppKit.framework/Versions/C/AppKit+0x19e6f8)
    #5 0x7fff921a0e96 in __79-[NSBitmapImageRep _withoutChangingBackingPerformBlockUsingBackingMutableData:]_block_invoke (/System/Library/Frameworks/AppKit.framework/Versions/C/AppKit+0x7de96)
    #6 0x7fff921a0d9b in -[NSBitmapImageRep _withoutChangingBackingPerformBlockUsingBackingMutableData:] (/System/Library/Frameworks/AppKit.framework/Versions/C/AppKit+0x7dd9b)
    #7 0x7fff921a0d16 in __57-[NSBitmapImageRep _performBlockUsingBackingMutableData:]_block_invoke (/System/Library/Frameworks/AppKit.framework/Versions/C/AppKit+0x7dd16)
    #8 0x7fff921a0c8a in -[NSBitmapImageRep _performBlockUsingBackingMutableData:] (/System/Library/Frameworks/AppKit.framework/Versions/C/AppKit+0x7dc8a)
    #9 0x7fff921a0c17 in -[NSBitmapImageRep getBitmapDataPlanes:] (/System/Library/Frameworks/AppKit.framework/Versions/C/AppKit+0x7dc17)
    #10 0x7fff921a0b9e in -[NSBitmapImageRep bitmapData] (/System/Library/Frameworks/AppKit.framework/Versions/C/AppKit+0x7db9e)
    #11 0x1026e788c in -[MyOpenGLRenderingThingie loadTexture:intoTexture:] (/Users/me/Library/Developer/Xcode/DerivedData/...)

So basically deep in the guts of AppKit.

Any ideas what the matter could be..?

ATV
  • 4,116
  • 3
  • 23
  • 42
  • 1
    What's with `texture` vs. `sourceImage`? You show the stack trace of the allocation. That's secondary info. Show the stack trace of the actual violation that address sanitizer detected. Finally, to extract bitmap data from an arbitrary image, you should not access its representations. You should draw it into a bitmap that you construct to your specifications. See "NSBitmapImageRep: CoreGraphics impedance matching and performance notes" in the [10.6 AppKit release notes](https://developer.apple.com/library/mac/releasenotes/AppKit/RN-AppKitOlderNotes/#X10_6Notes). – Ken Thomases Sep 20 '15 at 10:13
  • Source snippet fixed - still getting used to ASAN, thanks for the heads up. stack trace of the buffer overflow added – ATV Sep 20 '15 at 10:30
  • Does it make a difference to check the `valid` property on `texture` before getting a representation? What do you get if you log `texture` and `bitmap`? – Ken Thomases Sep 20 '15 at 11:09
  • Logging bitmap trigger the same crash/ASAN error, logging the texture works just fine and it looks just fine. I've followed your advice and am now setting up my own `NSBitmapImageRep` - works on 10.8 and 10.11 so I guess I'm covered for my 10.11 app update… – ATV Sep 20 '15 at 12:17

0 Answers0