event/SocketMonitor: don't cancel if OnSocketReady() returns false

Expect OnSocketReady() to cancel events.  If it returns false, the
SocketMonitor may be destructed already.  This fixes a use-after-free
bug in the "httpd" output plugin.
This commit is contained in:
Max Kellermann 2019-04-03 23:23:56 +02:00
parent d2eb4df8fc
commit f6941f9a44
4 changed files with 8 additions and 11 deletions

1
NEWS
View File

@ -1,6 +1,7 @@
ver 0.21.8 (not yet released)
* output
- httpd: add missing mutex lock
- httpd: fix use-after-free bug
* fix Bonjour bug
* fix build failure with GCC 9

View File

@ -568,7 +568,8 @@ ProxyDatabase::OnSocketReady(gcc_unused unsigned flags) noexcept
if (!is_idle) {
// TODO: can this happen?
IdleMonitor::Schedule();
return false;
SocketMonitor::Cancel();
return true;
}
unsigned idle = (unsigned)mpd_recv_idle(connection, false);
@ -586,7 +587,8 @@ ProxyDatabase::OnSocketReady(gcc_unused unsigned flags) noexcept
idle_received |= idle;
is_idle = false;
IdleMonitor::Schedule();
return false;
SocketMonitor::Cancel();
return true;
}
void

View File

@ -110,15 +110,9 @@ BufferedSocket::OnSocketReady(unsigned flags) noexcept
if (flags & READ) {
assert(!input.IsFull());
if (!ReadToBuffer())
if (!ReadToBuffer() || !ResumeInput())
return false;
if (!ResumeInput())
/* we must return "true" here or
SocketMonitor::Dispatch() will call
Cancel() on a freed object */
return true;
if (!input.IsFull())
ScheduleRead();
}

View File

@ -33,8 +33,8 @@ SocketMonitor::Dispatch(unsigned flags) noexcept
{
flags &= GetScheduledFlags();
if (flags != 0 && !OnSocketReady(flags) && IsDefined())
Cancel();
if (flags != 0)
OnSocketReady(flags);
}
SocketMonitor::~SocketMonitor() noexcept