From: Stephan Bosch Date: Sun, 15 Oct 2017 20:53:09 +0000 (+0200) Subject: lib: istream: i_stream_unref(): Put stream value in local variable, rather than relyi... X-Git-Tag: 2.4.0~2401 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=559437a6ff172ff290bbc5771f431e5c96a2579b;p=thirdparty%2Fdovecot%2Fcore.git lib: istream: i_stream_unref(): Put stream value in local variable, rather than relying on the pointer Problem is that a destroy callback can mess with the pointer, leading to all kinds of trouble. --- diff --git a/src/lib/istream.c b/src/lib/istream.c index 168456f01f..e76ba49904 100644 --- a/src/lib/istream.c +++ b/src/lib/istream.c @@ -49,30 +49,31 @@ void i_stream_ref(struct istream *stream) io_stream_ref(&stream->real_stream->iostream); } -void i_stream_unref(struct istream **stream) +void i_stream_unref(struct istream **_stream) { - struct istream_private *_stream; + struct istream *stream = *_stream; + struct istream_private *rstream; - if (*stream == NULL) + if (stream == NULL) return; - _stream = (*stream)->real_stream; + *_stream = NULL; + rstream = stream->real_stream; - if (_stream->iostream.refcount > 1) { - if (!io_stream_unref(&_stream->iostream)) + if (rstream->iostream.refcount > 1) { + if (!io_stream_unref(&rstream->iostream)) i_unreached(); } else { /* The snapshot may contain pointers to the parent istreams. Free it before io_stream_unref() frees the parents. */ - i_stream_snapshot_free(&_stream->prev_snapshot); + i_stream_snapshot_free(&rstream->prev_snapshot); - if (io_stream_unref(&_stream->iostream)) + if (io_stream_unref(&rstream->iostream)) i_unreached(); - str_free(&_stream->line_str); - i_stream_unref(&_stream->parent); - io_stream_free(&_stream->iostream); + str_free(&rstream->line_str); + i_stream_unref(&rstream->parent); + io_stream_free(&rstream->iostream); } - *stream = NULL; } #undef i_stream_add_destroy_callback