gmain: clamp over-large timeouts

g_main_context_prepare() needs to calculate the timeout to pass to
poll(), expressed in milliseconds as a gint.  But since the ready time
for a GSource is represented by gint64 microseconds, it's possible that
it could be more than G_MAXINT * 1000 microseconds in the future, and so
can't be represented as a gint. This conversion to a narrower signed
type is implementation-defined, but there are two possible outcomes:

* the result is >= 0, in which case poll() will time out earlier than we
  might hope (with no adverse consequences besides an unwanted wakeup)
* the result is < 0, in which case, if there are no other sources,
  poll() will block forever

This is extremely unlikely to happen in practice, but can be avoided by
clamping the gint64 value, which we know to be positive, to G_MAXINT.

Thanks to Tomasz Miąsko for pointing this out on !496.
This commit is contained in:
Will Thompson 2018-11-26 20:38:55 +00:00
parent 6490fe7fe8
commit cdc2dd8eb1
No known key found for this signature in database
GPG Key ID: 3422DC0D7AD482A7

View File

@ -3525,13 +3525,13 @@ g_main_context_prepare (GMainContext *context,
}
else
{
gint timeout;
gint64 timeout;
/* rounding down will lead to spinning, so always round up */
timeout = (source->priv->ready_time - context->time + 999) / 1000;
if (source_timeout < 0 || timeout < source_timeout)
source_timeout = timeout;
source_timeout = MIN (timeout, G_MAXINT);
}
}