Skip to content

ArrayIndexOutOfBoundsException in Http2Connection.writeSynReset #8658

Open
@metalichesky

Description

@metalichesky

For a long time we have been experiencing a rare but fatal crash in our app (size, offset and byteCount may vary, but other parts stays the same):

Fatal Exception: java.lang.ArrayIndexOutOfBoundsException: size=1 offset=0 byteCount=4087
       at okio.-SegmentedByteString.checkOffsetAndCount(Util.kt:26)
       at okio.AsyncTimeout$sink$1.write(AsyncTimeout.kt:109)
       at okio.RealBufferedSink.emitCompleteSegments(RealBufferedSink.kt:256)
       at okio.RealBufferedSink.writeByte(RealBufferedSink.kt:211)
       at okhttp3.internal.Util.writeMedium(Util.java:317)
       at okhttp3.internal.http2.Http2Writer.frameHeader(Http2Writer.kt:261)
       at okhttp3.internal.http2.Http2Writer.rstStream(Http2Writer.kt:128)
       at okhttp3.internal.http2.Http2Connection.writeSynReset$okhttp(Http2Connection.java:354)
       at okhttp3.internal.http2.Http2Connection$writeSynResetLater$$inlined$execute$default$1.runOnce(TaskQueue.kt:220)
       at okhttp3.internal.concurrent.TaskRunner.runTask(TaskRunner.kt:116)
       at okhttp3.internal.concurrent.TaskRunner.access$runTask(TaskRunner.kt:42)
       at okhttp3.internal.concurrent.TaskRunner$runnable$1.run(TaskRunner.kt:65)
       at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
       at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
       at java.lang.Thread.run(Thread.java:919)

For which we do not have a clear reproducible example. It is not entirely clear what exactly happens from the stack trace and analytics logs. However, judging by other logs from our analytics system, users experience this crash when switching content in the Exoplayer audio player when playing various audio streams over the Internet. It is possible that the same address is used for both audio tracks and the http2 connection is reused.

Currently we use our own DataSource implementation based on OkHttp 4.12.0 and okio 3.9.0, but face it with previous versions too.
There is no correlation with Android OS versions and device vendors found.

This exception is not handled in any way and is not passed to the application for handling, which violates the principle of defensive programming and does not allow steps to be taken to restore the application's functionality.

Why writeSynResetLater called for a network connection?
If such an exception occurs when calling writeSynReset, then maybe it is possible to catch such exceptions at the library level and stop the connection by calling Http2Connection.failConnection and then removing this connection from the connection pool?
So after requesting stream again OkHttp will create new connection instead of the broken one.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions