CocoaHTTPServer
CocoaHTTPServer copied to clipboard
CRASH: index 0 beyond bounds for empty array
* Terminating app due to uncaught exception 'NSRangeException', reason: '* -[__NSArrayM objectAtIndex:]: index 0 beyond bounds for empty array'
HTTPConnection.m:1477 DDRange range = [[ranges objectAtIndex:rangeIndex] ddrangeValue];
Thread 25, Queue : RoutingHTTPServer Concurrent Queue #0 0x3c452350 in __pthread_kill () #1 0x3c3c9122 in pthread_kill () #2 0x3c405972 in abort () #3 0x3b9a3d4e in abort_message () #4 0x3b9a0ff8 in default_terminate() () #5 0x3bf54a76 in _objc_terminate() () #6 0x3b9a107a in safe_handler_caller(void (*)()) () #7 0x3b9a1114 in std::terminate() () #8 0x3b9a2512 in __cxa_throw () #9 0x3bf549be in objc_exception_throw () #10 0x34177b74 in -__NSArrayM objectAtIndex: #11 0x007171b6 in -[HTTPConnection continueSendingMultiRangeResponseBody] at ..../HTTPServer/CocoaHTTPServer/HTTPConnection.m:1477 #12 0x0071babe in __43-[HTTPConnection responseHasAvailableData:]_block_invoke at ..../HTTPServer/CocoaHTTPServer/HTTPConnection.m:2528 #13 0x3c36c11e in _dispatch_call_block_and_release () #14 0x3c3704d6 in _dispatch_async_f_redirect_invoke () #15 0x3c370960 in _dispatch_root_queue_drain () #16 0x3c370ac0 in _dispatch_worker_thread2 () #17 0x3c3a0a10 in _pthread_wqthread () #18 0x3c3a08a4 in start_wqthread ()
I've encountered this exception as well but never got around to submitting my patch for it. The problem occurs when a client makes a byte range request beyond the content length. In this case parseRangeRequest:forContentLength: returns NO, but leaves ranges set to an empty array. When responseHasAvailableData: is called ranges is non-nil and the code tries to access a non-existent range. A simple fix is to change the test in responseHasAvailableData: from if (ranges == nil) to if ([ranges count] < 1).
However, CocoaHTTPServer's behavior here is also not following the RFC. A last-byte-pos beyond the range of the content is supposed to be considered as content length - 1, but the server is considering the range header invalid. That can be fixed by changing if(r2 > contentLength) return NO; to if(r2 > contentLength) r2 = contentLength - 1;.
The part I didn't get to was handling a first-byte-pos that is beyond the range of the content. In this case the server is supposed to send a 416 response.
It works, thank you!
Some years later, I have also hit the same hurdle. Thanks for the explanation.