Skip to content
This repository has been archived by the owner on Feb 2, 2021. It is now read-only.

otest-shim: Deadlock due to StripAnsi nil argument exception in single byte input #555

Closed
joamaki opened this issue Aug 13, 2015 · 2 comments
Labels

Comments

@joamaki
Copy link

joamaki commented Aug 13, 2015

In some cases the test output is written one character at a time and when printing the
default NSError localized description "The operation couldn’t be completed", StripAnsi crashes
when the input is the accent in "couldn't", which has the octal code \342. This in turn causes a recursive call into the intercepted write due to logging attempt by the handleException and a deadlock in the xctool.events queue.

Program to crash StripAnsi:

int main() {
  NSString *output = [[NSString alloc] initWithBytes:"\342" length:1 encoding:NSUTF8StringEncoding];
  NSLog(@"res: %@", StripAnsi(output));
}

The exception thrown:

2015-08-13 12:06:33.068 test[14839:4584644] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '*** -[NSRegularExpression enumerateMatchesInString:options:range:usingBlock:]: nil argument'
*** First throw call stack:
(
    0   CoreFoundation                      0x00007fff93dcf03c __exceptionPreprocess + 172
    1   libobjc.A.dylib                     0x00007fff94dcb76e objc_exception_throw + 43
    2   CoreFoundation                      0x00007fff93dceeed +[NSException raise:format:] + 205
    3   Foundation                          0x00007fff9694e499 -[NSRegularExpression(NSMatching) enumerateMatchesInString:options:range:usingBlock:] + 232
    4   Foundation                          0x00007fff9694e398 -[NSRegularExpression(NSMatching) matchesInString:options:range:] + 162
    5   Foundation                          0x00007fff96a0547f -[NSRegularExpression(NSReplacement) stringByReplacingMatchesInString:options:range:withTemplate:] + 300
    6   test                                0x000000010e011bee StripAnsi + 302
    7   test                                0x000000010e011d92 main + 162
    8   libdyld.dylib                       0x00007fff963be5c9 start + 1
    9   ???                                 0x0000000000000001 0x0 + 1
)

Backtrace from the xctool.events thread showing the deadlock:

  thread #9: tid = 0x45fdfd, 0x00007fff8ba4b51a libsystem_kernel.dylib`semaphore_wait_trap + 10, queue = 'xctool.events'
    frame #0: 0x00007fff8ba4b51a libsystem_kernel.dylib`semaphore_wait_trap + 10
    frame #1: 0x00007fff94423c5b libsystem_platform.dylib`_os_semaphore_wait + 16
    frame #2: 0x00007fff93c4b557 libdispatch.dylib`_dispatch_barrier_sync_f_slow + 597
    frame #3: 0x00000001029cf3ca otest-shim-osx.dylib`__writev(fildes=<unavailable>, iov=0x00000001075ec6c0, iovcnt=2) + 116 at otest-shim.m:574
    frame #4: 0x00007fff93d0ea83 CoreFoundation`__CFLogCString + 1011
    frame #5: 0x00007fff93db280f CoreFoundation`_CFLogvEx2 + 271
    frame #6: 0x00007fff93d68285 CoreFoundation`CFLog + 165
    frame #7: 0x00007fff93dcf598 CoreFoundation`__handleUncaughtException + 888
    frame #8: 0x00007fff94dcf7cd libobjc.A.dylib`_objc_terminate() + 94
    frame #9: 0x00007fff8d50a0a1 libc++abi.dylib`std::__terminate(void (*)()) + 8
    frame #10: 0x00007fff8d50a113 libc++abi.dylib`std::terminate() + 51
    frame #11: 0x00007fff94dcf5ff libobjc.A.dylib`objc_terminate + 9
    frame #12: 0x00007fff93c41c27 libdispatch.dylib`_dispatch_client_callout + 28
    frame #13: 0x00007fff93c42e5e libdispatch.dylib`_dispatch_barrier_sync_f_invoke + 57
    frame #14: 0x00000001029cf1d1 otest-shim-osx.dylib`___write_nocancel(fildes=<unavailable>, buf=0x00007fff788f23cf, nbyte=1) + 118 at otest-shim.m:450
    frame #15: 0x00007fff8d49a9ed libsystem_c.dylib`_swrite + 87
    frame #16: 0x00007fff8d4934a7 libsystem_c.dylib`__sflush + 101
    frame #17: 0x00007fff8d4aafb1 libsystem_c.dylib`__swbuf + 177
    frame #18: 0x00007fff8d499bae libsystem_c.dylib`putchar + 91
    frame #19: 0x0000000106b174b0 libswiftCore.dylib`function signature specialization <Arg[0] = Owned To Guaranteed and Exploded, Arg[1] = Dead> of Swift._Stdout.write (inout Swift._Stdout)(Swift.String) -> () + 192
    frame #20: 0x0000000106ad877e libswiftCore.dylib`protocol witness for Swift.OutputStreamType.write <A : Swift.OutputStreamType>(inout Swift.OutputStreamType.Self)(Swift.String) -> () in conformance Swift._Stdout : Swift.OutputStreamType in Swift + 14
    frame #21: 0x0000000106a5fd0c libswiftCore.dylib`Swift.print <A, B : Swift.OutputStreamType>(A, inout B) -> () + 492
    frame #22: 0x000000010675cf8d XCGLogger`function signature specialization <Arg[0] = Dead, Arg[1] = Value Promoted from InOut> of XCGLogger.XCGConsoleLogDestination.(fullLogMessage=Swift.String at 0x00000001075ecd88) -> (XCGLogger.XCGLogDetails) -> ()).(closure #1) + 93 at XCGLogger.swift:87
    frame #23: 0x000000010675cfc7 XCGLogger`reabstraction thunk helper from @callee_owned () -> (@unowned ()) to @callee_unowned @objc_block () -> (@unowned ()) + 39 at XCGLogger.swift:0

Not sure what would be a sensible workaround as the problem seems to be in Foundation rather
then in otest-shim. Perhaps filtering non-ascii characters from the input stream or buffering?

@ExtremeMan
Copy link
Contributor

Thanks for a great bug report. I was able to reproduce deadlock with this test:

- (void)testHandlingOfUnicodeStrings
{
  fprintf(stdout, "---");
  sleep(2);
  fprintf(stdout, "\342");
  sleep(2);
}

We've already solved similar problems in other parts of xctool: 9a8a4a0, 7662c44.
I will try to repeat fixes here as well.

@ExtremeMan ExtremeMan added the bug label Aug 14, 2015
@ExtremeMan
Copy link
Contributor

Fixed in 872f33b.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Projects
None yet
Development

No branches or pull requests

2 participants