From a840c51c5dbe4e9408a9471a56d11f9d5dd34499 Mon Sep 17 00:00:00 2001 From: Boris-Barboris Date: Fri, 30 Mar 2018 09:11:30 +0000 Subject: [PATCH 1/4] fix integer overflow protection absence for LocalManualEvent --- source/vibe/core/sync.d | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/source/vibe/core/sync.d b/source/vibe/core/sync.d index edee964..0c2caa4 100644 --- a/source/vibe/core/sync.d +++ b/source/vibe/core/sync.d @@ -778,7 +778,7 @@ struct LocalManualEvent { target_timeout = now + timeout; } - while (m_waiter.m_emitCount <= emit_count) { + while (m_waiter.m_emitCount - emit_count > 0) { m_waiter.wait!interruptible(timeout != Duration.max ? target_timeout - now : Duration.max); try now = Clock.currTime(UTC()); catch (Exception e) { assert(false, e.msg); } @@ -805,6 +805,22 @@ unittest { runEventLoop(); } +unittest { + import vibe.core.core : exitEventLoop, runEventLoop, runTask, sleep; + auto e = createManualEvent(); + // integer overflow test + e.m_waiter.m_emitCount = int.max; + auto w1 = runTask({ e.wait(50.msecs, e.emitCount); }); + runTask({ + sleep(5.msecs); + e.emit(); + sleep(50.msecs); + assert(!w1.running); + exitEventLoop(); + }); + runEventLoop(); +} + unittest { // ensure that cancelled waiters are properly handled and that a FIFO order is implemented import vibe.core.core : exitEventLoop, runEventLoop, runTask, sleep; From 489b35539b8b8d2c83d799d441f2c1a096ac5345 Mon Sep 17 00:00:00 2001 From: Boris-Barboris Date: Fri, 30 Mar 2018 09:28:45 +0000 Subject: [PATCH 2/4] fix comparison in doWait --- source/vibe/core/sync.d | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/vibe/core/sync.d b/source/vibe/core/sync.d index 0c2caa4..041f57d 100644 --- a/source/vibe/core/sync.d +++ b/source/vibe/core/sync.d @@ -778,7 +778,7 @@ struct LocalManualEvent { target_timeout = now + timeout; } - while (m_waiter.m_emitCount - emit_count > 0) { + while (m_waiter.m_emitCount - emit_count >= 0) { m_waiter.wait!interruptible(timeout != Duration.max ? target_timeout - now : Duration.max); try now = Clock.currTime(UTC()); catch (Exception e) { assert(false, e.msg); } From bf9d736c4f40017cf9b90d81f27f5a32552475cd Mon Sep 17 00:00:00 2001 From: Boris-Barboris Date: Fri, 30 Mar 2018 09:42:22 +0000 Subject: [PATCH 3/4] another way around. Fix typo in comment. --- source/vibe/core/sync.d | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/source/vibe/core/sync.d b/source/vibe/core/sync.d index 041f57d..8d9868d 100644 --- a/source/vibe/core/sync.d +++ b/source/vibe/core/sync.d @@ -743,8 +743,8 @@ struct LocalManualEvent { */ int wait() { return wait(this.emitCount); } - /** Acquires ownership and waits until the emit count differs from the - given one or until a timeout is reached. + /** Acquires ownership and waits until the signal is emitted and the emit + count is larger than a given one. Throws: May throw an $(D InterruptException) if the task gets interrupted @@ -778,7 +778,7 @@ struct LocalManualEvent { target_timeout = now + timeout; } - while (m_waiter.m_emitCount - emit_count >= 0) { + while (m_waiter.m_emitCount - emit_count <= 0) { m_waiter.wait!interruptible(timeout != Duration.max ? target_timeout - now : Duration.max); try now = Clock.currTime(UTC()); catch (Exception e) { assert(false, e.msg); } From 788973f628617098c27f0e8babd4b3cf6cebd0c4 Mon Sep 17 00:00:00 2001 From: Boris-Barboris Date: Fri, 30 Mar 2018 12:59:24 +0000 Subject: [PATCH 4/4] same measures for ManualEvent --- source/vibe/core/sync.d | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/vibe/core/sync.d b/source/vibe/core/sync.d index 8d9868d..f84a455 100644 --- a/source/vibe/core/sync.d +++ b/source/vibe/core/sync.d @@ -1027,8 +1027,8 @@ struct ManualEvent { int ec = this.emitCount; acquireThreadWaiter((scope ThreadWaiter w) { - while (ec <= emit_count) { - w.wait!interruptible(timeout != Duration.max ? target_timeout - now : Duration.max, ms_threadEvent, () => this.emitCount > emit_count); + while (ec - emit_count <= 0) { + w.wait!interruptible(timeout != Duration.max ? target_timeout - now : Duration.max, ms_threadEvent, () => (this.emitCount - emit_count) > 0); ec = this.emitCount; if (timeout != Duration.max) {