Commit 6598fd21 authored by Clément Bœsch's avatar Clément Bœsch Committed by Philipp Schafft

Fix: cleanup format residual after close

This fixes the situation where shout_open(), shout_close(), and
shout_open() again are called on the same shout_t context. If this
happens, the shout_t.send callback will remain set after close,
preventing the stream from being re-opened in try_connect().  As a
result, the next write will cause a use after free on
shout_t.format_data (free happened on the shout_close() call).

Technically, only reseting shout_t.send is enough to fix the crash, but
making sure format_data is always reset as well makes similar issues
much more deterministic and understandable when crashing. The close
callback is also reset for consistency and integrity.

This issue was observed with the libshout output of MPD.

For the record, here are the steps to reproduce the crash:

In a mpd.conf:

    audio_output {
        type        "shout"
        name        "My Shout Stream"
        host        "localhost"
        port        "8000"
        mount       "/mpd.ogg"
        password    "hackme"
        bitrate     "128"
        format      "44100:16:1"
    }

Then assuming icecast is running with the default configuration:

    mpc add /             # add all files to the playlist
    mpc play              # start writing to the shout stream
    mpc toggleoutput 1    # disable shout output (calls shout_close)
    mpc toggleoutput 1    # enable shout output (calls shout_open on the same shout_t)
    mpc play              # write again to the shout stream

Closes #2312, #2318
parent b807c1e2
......@@ -198,8 +198,12 @@ int shout_close(shout_t *self)
if (!self->connection)
return self->error = SHOUTERR_UNCONNECTED;
if (self->connection && self->connection->current_message_state == SHOUT_MSGSTATE_SENDING1 && self->close)
if (self->connection && self->connection->current_message_state == SHOUT_MSGSTATE_SENDING1 && self->close) {
self->close(self);
self->format_data = NULL;
self->send = NULL;
self->close = NULL;
}
shout_connection_unref(self->connection);
self->connection = NULL;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment