Adding: it seems that while passing &inReq.imageInfo.transformation.0 to an UnsafePointer<Float> parameter worked before (passed a pointer to a contiguous block of 16 floats), now it's making a copy of just the first tuple element, and passing a smaller memory block. I think I'm interpreting these results correctly like that.
> On Sep 20, 2017, at 17:03 , Rick Mann via swift-users <swift-users@swift.org> > wrote: > > I've got Swift code wrapping a C API. One of the C structs the API uses looks > like this: > > typedef struct { > size_t size; > float transformation[16]; > float projection[16]; > uint32_t width; > uint32_t height; > } image_info_t; > > In Swift, the two array members are 16-tuples of floats. Eventually, the > Swift code calls an Objective-C delegate, passing a tuple to an array: > > self.delegate? > .imageReceived(self, > index: inReq.imageIndex, > data: data, > width: width, > height: height, > transform: &inReq.imageInfo.transformation.0, > projection: &inReq.imageInfo.projection.0) > > This seems to have been working fine for a long time, but we're running into > a crash in some cases, and so I've been digging into it. I turned on the > address sanitizer, and I consistently get it to trip in some C++ code that > eventually gets called with a float* to that transform tuple. > > Now, in Swift, the values of the tuple look great: > > ▿ 16 elements > - .0 : 0.548282921 > - .1 : 0.821425974 > - .2 : -0.156990349 > - .3 : 0.0 > - .4 : -0.277842015 > - .5 : 0.00185899995 > - .6 : -0.960625231 > - .7 : 0.0 > - .8 : -0.788789928 > - .9 : 0.570312977 > - .10 : 0.229245573 > - .11 : 0.0 > - .12 : 0.0475889929 > - .13 : -0.0323969983 > - .14 : -0.0113521963 > - .15 : 1.0 > > I can see this by clicking up the stack a couple frames to the Swift code. > But the Objective-C(++) delegate code, that gets passed a float*, sees this > (BTW, I can't figure out how to get the debugger, Xcode or command line, to > display inTransform as an array of 16 floats). It's clearly not the same > array. > > > (lldb) po inTransform[0] > 0.548282921 > > (lldb) po inTransform[1] > 0.0343905278 > > (lldb) po inTransform[2] > -0 > > (lldb) po inTransform[3] > 0 > > (lldb) po inTransform[4] > 0 > > (lldb) po inTransform[5] > 0 > > (lldb) po inTransform[6] > 95488384 > > (lldb) po inTransform[14] > 0.00000000000000000000000000000000000000000000560519386 > > (lldb) po inTransform[15] > 0 > > The address sanitizer spits out this: > > ================================================================= > ==1358==ERROR: AddressSanitizer: stack-buffer-overflow on address > 0x00014d3ea224 at pc 0x000100eb9a84 bp 0x00016fd84bd0 sp 0x00016fd84bc8 > READ of size 4 at 0x00014d3ea224 thread T0 > #0 0x100eb9a83 in <redacted>::addImage(void const*, int, int, int, float > const*, float const*) (<redacted>:arm64+0x100e41a83) > #1 0x10040b72b in -[<redacted> > imageReceived:index:data:width:height:transform:projection:] > (<redacted>:arm64+0x10039372b) > #2 0x10045d037 in function signature specialization <Arg[0] = Owned To > Guaranteed, Arg[1] = Owned To Guaranteed, Arg[2] = Owned To Guaranteed and > Exploded> of closure #1 () -> () in > <redacted>.imageDownloaded(<redacted>.DownloadImageRequest, index: Swift.Int) > -> () (<redacted>:arm64+0x1003e5037) > #3 0x100442bbb in closure #1 () -> () in > <redacted>.imageDownloaded(<redacted>.DownloadImageRequest, index: Swift.Int) > -> () (<redacted>:arm64+0x1003cabbb) > #4 0x10043e7fb in reabstraction thunk helper from @callee_owned () -> () > to @callee_unowned @convention(block) () -> () (<redacted>:arm64+0x1003c67fb) > #5 0x103ba9d5b in __wrap_dispatch_async_block_invoke > (/var/containers/Bundle/Application/B3E557CA-5ED9-4673-8B07-37A0F2DA472B/<redacted>.app/Frameworks/libclang_rt.asan_ios_dynamic.dylib:arm64+0x4dd5b) > #6 0x105f1549b in _dispatch_call_block_and_release > (/usr/lib/system/introspection/libdispatch.dylib:arm64+0x149b) > #7 0x105f1545b in _dispatch_client_callout > (/usr/lib/system/introspection/libdispatch.dylib:arm64+0x145b) > #8 0x105f1a04f in _dispatch_main_queue_callback_4CF > (/usr/lib/system/introspection/libdispatch.dylib:arm64+0x604f) > #9 0x181d43f1f in <redacted> > (/System/Library/Frameworks/CoreFoundation.framework/CoreFoundation:arm64+0xe9f1f) > #10 0x181d41afb in <redacted> > (/System/Library/Frameworks/CoreFoundation.framework/CoreFoundation:arm64+0xe7afb) > #11 0x181c622d7 in CFRunLoopRunSpecific > (/System/Library/Frameworks/CoreFoundation.framework/CoreFoundation:arm64+0x82d7) > #12 0x183af3f83 in GSEventRunModal > (/System/Library/PrivateFrameworks/GraphicsServices.framework/GraphicsServices:arm64+0xaf83) > #13 0x18b20e87f in UIApplicationMain > (/System/Library/Frameworks/UIKit.framework/UIKit:arm64+0x7387f) > #14 0x100122dc3 in main (<redacted>:arm64+0x1000aadc3) > #15 0x18178656b in <redacted> (/usr/lib/system/libdyld.dylib:arm64+0x156b) > > Address 0x00014d3ea224 is located in stack of thread T0 at offset 36 in frame > #0 0x10045cd57 in function signature specialization <Arg[0] = Owned To > Guaranteed, Arg[1] = Owned To Guaranteed, Arg[2] = Owned To Guaranteed and > Exploded> of closure #1 () -> () in > <redacted>.imageDownloaded(<redacted>.DownloadImageRequest, index: Swift.Int) > -> () (<redacted>:arm64+0x1003e4d57) > > This frame has 4 object(s): > [32, 36) '' <== Memory access at offset 36 overflows this variable > [48, 208) '' > [272, 276) '' > [288, 448) '' > HINT: this may be a false positive if your program uses some custom stack > unwind mechanism or swapcontext > (longjmp and C++ exceptions *are* supported) > SUMMARY: AddressSanitizer: stack-buffer-overflow > (<redacted>:arm64+0x100e41a83) in <redacted>::addImage(void const*, int, int, > int, float const*, float const*) > Shadow bytes around the buggy address: > 0x0001302dd3f0: f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 > 0x0001302dd400: f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 > 0x0001302dd410: f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 > 0x0001302dd420: f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 > 0x0001302dd430: f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 > =>0x0001302dd440: f1 f1 f1 f1[04]f2 00 00 00 00 00 00 00 00 00 00 > 0x0001302dd450: 00 00 00 00 00 00 00 00 00 00 f2 f2 f2 f2 f2 f2 > 0x0001302dd460: f2 f2 04 f2 00 00 00 00 00 00 00 00 00 00 00 00 > 0x0001302dd470: 00 00 00 00 00 00 00 00 f3 f3 f3 f3 f3 f3 f3 f3 > 0x0001302dd480: f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 > 0x0001302dd490: f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 > Shadow byte legend (one shadow byte represents 8 application bytes): > Addressable: 00 > Partially addressable: 01 02 03 04 05 06 07 > Heap left redzone: fa > Freed heap region: fd > Stack left redzone: f1 > Stack mid redzone: f2 > Stack right redzone: f3 > Stack after return: f5 > Stack use after scope: f8 > Global redzone: f9 > Global init order: f6 > Poisoned by user: f7 > Container overflow: fc > Array cookie: ac > Intra object redzone: bb > ASan internal: fe > Left alloca redzone: ca > Right alloca redzone: cb > > > > So, how do I properly go back and forth between C and Swift code with > pointers to arrays of floats? > > Thanks, > > -- > Rick Mann > rm...@latencyzero.com > > > _______________________________________________ > swift-users mailing list > swift-users@swift.org > https://lists.swift.org/mailman/listinfo/swift-users -- Rick Mann rm...@latencyzero.com _______________________________________________ swift-users mailing list swift-users@swift.org https://lists.swift.org/mailman/listinfo/swift-users