Projects
openEuler:24.03:SP1:Everything
xnio
_service:tar_scm:backport-CVE-2023-5685.patch
Sign Up
Log In
Username
Password
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File _service:tar_scm:backport-CVE-2023-5685.patch of Package xnio
From a2fce38d48cca947ea42ee3bead08dd138b42c01 Mon Sep 17 00:00:00 2001 From: Flavia Rainone <frainone@redhat.com> Date: Fri, 14 Oct 2022 17:00:46 -0300 Subject: [PATCH] [XNIO-423] CVE-2023-5685 Move the recursion in NotifierState to a iteration, preventing a stack overflow exception when the chain of notifier states becomes problematically big Signed-off-by: Flavia Rainone <frainone@redhat.com> Origin: https://github.com/xnio/xnio/commit/a2fce38d48cca947ea42ee3bead08dd138b42c01 --- .../main/java/org/xnio/AbstractIoFuture.java | 238 ++++++++++++++---- 1 file changed, 187 insertions(+), 51 deletions(-) diff --git a/api/src/main/java/org/xnio/AbstractIoFuture.java b/api/src/main/java/org/xnio/AbstractIoFuture.java index 6118a0c7e3..030336b918 100644 --- a/api/src/main/java/org/xnio/AbstractIoFuture.java +++ b/api/src/main/java/org/xnio/AbstractIoFuture.java @@ -74,6 +74,141 @@ IOException getException() { } } + private static abstract class NestedState<T> extends State<T> { + private final State<T> next; + + public NestedState(final State next) { + this.next = next; + } + + /** + * Perform any actions that need to be executed when future is done, delegation of done notification to next is + * taken care of by invoker. + * + * @param future the future + * @param result the result + */ + protected abstract void doNotifyDone(AbstractIoFuture<T> future, T result); + + @Override + public void notifyDone(AbstractIoFuture<T> future, T result) { + doNotifyDone(future, result); + if (next instanceof NestedState) { + NestedState<T> current = this; + do { + current = (NestedState<T>) current.next; + current.doNotifyDone(future, result); + } while (current.next instanceof NestedState); + current.next.notifyDone(future, result); + } else { + next.notifyDone(future, result); + } + + } + + /** + * Perform any actions that need to be done at this state for handling failure, delegation of failure + * notification to next is taken care of by invoker + * + * @param future the future + * @param exception the failure + */ + protected abstract void doNotifyFailed(AbstractIoFuture<T> future, IOException exception); + + @Override + public void notifyFailed(AbstractIoFuture<T> future, IOException exception) { + doNotifyFailed(future, exception); + if (next instanceof NestedState) { + NestedState<T> current = this; + do { + current = (NestedState<T>) current.next; + current.doNotifyFailed(future, exception); + } while (current.next instanceof NestedState); + current.next.notifyFailed(future, exception); + } else { + next.notifyFailed(future, exception); + } + } + + /** + * Perform any actions that need to be done at this state for handling cancellation, delegation of cancellation + * notification to next is taken care of by invoker + * + * @param future the future + */ + protected abstract void doNotifyCancelled(AbstractIoFuture<T> future); + + + + @Override + public void notifyCancelled(AbstractIoFuture<T> future) { + doNotifyCancelled(future); + if (next instanceof NestedState) { + NestedState<T> current = this; + do { + current = (NestedState<T>) current.next; + current.doNotifyCancelled(future); + } while (current.next instanceof NestedState); + current.next.notifyCancelled(future); + } else { + next.notifyCancelled(future); + } + } + + /** + * Perform any actions that need to be done at this state for cancellation. Delegation of cancellation to next + * is taken care of by invoker. + */ + protected abstract void doCancel(); + + /** + * Just delegate cancel() to first next state in the nested chain that is not a NestedState. + */ + @Override + public void cancel() { + doCancel(); + if (next instanceof NestedState) { + NestedState<T> current = this; + do { + current = (NestedState<T>) current.next; + current.doCancel(); + } while (current.next instanceof NestedState); + current.next.cancel(); + } else { + next.cancel(); + } + } + + /** + * Return {@code true} to indicate that, at this state, cancel is requested. If returns false, invoker + * will check for inner next states in the chain until it finds a positive result or the final state in the + * chain. + * + * @return {@code true} to indicate that cancel is requested; {@code false} to delegate response to nested + * state. + */ + protected abstract boolean isCancelRequested(); + + @Override + public boolean cancelRequested() { + if (isCancelRequested()) { + return true; + } + if (next instanceof NestedState) { + NestedState<T> current = this; + do { + current = (NestedState<T>) current.next; + if (current.isCancelRequested()) { + return true; + } + } while (current.next instanceof NestedState); + return current.next.cancelRequested(); + } else { + return next.cancelRequested(); + } + } + } + static final class InitialState<T> extends State<T> { Status getStatus() { @@ -229,13 +364,12 @@ boolean cancelRequested() { } } - static final class NotifierState<T, A> extends State<T> { - final State<T> next; + static final class NotifierState<T, A> extends NestedState<T> { final Notifier<? super T, A> notifier; final A attachment; NotifierState(final State<T> next, final Notifier<? super T, A> notifier, final A attachment) { - this.next = next; + super(next); this.notifier = notifier; this.attachment = attachment; } @@ -244,40 +378,41 @@ Status getStatus() { return Status.WAITING; } - void notifyDone(final AbstractIoFuture<T> future, final T result) { + @Override + protected void doNotifyDone(final AbstractIoFuture<T> future, final T result) { doNotify(future); - next.notifyDone(future, result); } - void notifyFailed(final AbstractIoFuture<T> future, final IOException exception) { + @Override + protected void doNotifyFailed(final AbstractIoFuture<T> future, final IOException exception) { doNotify(future); - next.notifyFailed(future, exception); } - void notifyCancelled(final AbstractIoFuture<T> future) { + @Override + protected void doNotifyCancelled(final AbstractIoFuture<T> future) { doNotify(future); - next.notifyCancelled(future); } - void cancel() { - next.cancel(); + + @Override + protected void doCancel() { } private void doNotify(final AbstractIoFuture<T> future) { future.runNotifier(new NotifierRunnable<T, A>(notifier, future, attachment)); } - boolean cancelRequested() { - return next.cancelRequested(); + @Override + protected boolean isCancelRequested() { + return false; } } - static final class WaiterState<T> extends State<T> { - final State<T> next; + static final class WaiterState<T> extends NestedState<T> { final Thread waiter; WaiterState(final State<T> next, final Thread waiter) { - this.next = next; + super(next); this.waiter = waiter; } @@ -285,36 +420,35 @@ Status getStatus() { return Status.WAITING; } - void notifyDone(final AbstractIoFuture<T> future, final T result) { + @Override + protected void doNotifyDone(final AbstractIoFuture<T> future, final T result) { LockSupport.unpark(waiter); - next.notifyDone(future, result); } - void notifyFailed(final AbstractIoFuture<T> future, final IOException exception) { + @Override + protected void doNotifyFailed(final AbstractIoFuture<T> future, final IOException exception) { LockSupport.unpark(waiter); - next.notifyFailed(future, exception); } - void notifyCancelled(final AbstractIoFuture<T> future) { + @Override + protected void doNotifyCancelled(final AbstractIoFuture<T> future) { LockSupport.unpark(waiter); - next.notifyCancelled(future); } - void cancel() { - next.cancel(); - } + @Override + protected void doCancel() {} - boolean cancelRequested() { - return next.cancelRequested(); + @Override + protected boolean isCancelRequested() { + return false; } } - static final class CancellableState<T> extends State<T> { - final State<T> next; + static final class CancellableState<T> extends NestedState<T> { final Cancellable cancellable; CancellableState(final State<T> next, final Cancellable cancellable) { - this.next = next; + super(next); this.cancellable = cancellable; } @@ -322,58 +456,60 @@ Status getStatus() { return Status.WAITING; } - void notifyDone(final AbstractIoFuture<T> future, final T result) { - next.notifyDone(future, result); + @Override + protected void doNotifyDone(final AbstractIoFuture<T> future, final T result) { } - void notifyFailed(final AbstractIoFuture<T> future, final IOException exception) { - next.notifyFailed(future, exception); + @Override + protected void doNotifyFailed(final AbstractIoFuture<T> future, final IOException exception) { } - void notifyCancelled(final AbstractIoFuture<T> future) { - next.notifyCancelled(future); + @Override + protected void doNotifyCancelled(final AbstractIoFuture<T> future) { } - void cancel() { + @Override + protected void doCancel() { try { cancellable.cancel(); } catch (Throwable ignored) {} - next.cancel(); } - boolean cancelRequested() { - return next.cancelRequested(); + @Override + protected boolean isCancelRequested() { + return false; } } - static final class CancelRequestedState<T> extends State<T> { - final State<T> next; + static final class CancelRequestedState<T> extends NestedState<T> { CancelRequestedState(final State<T> next) { - this.next = next; + super(next); } Status getStatus() { return Status.WAITING; } - void notifyDone(final AbstractIoFuture<T> future, final T result) { - next.notifyDone(future, result); + @Override + protected void doNotifyDone(final AbstractIoFuture<T> future, final T result) { } - void notifyFailed(final AbstractIoFuture<T> future, final IOException exception) { - next.notifyFailed(future, exception); + @Override + protected void doNotifyFailed(final AbstractIoFuture<T> future, final IOException exception) { } - void notifyCancelled(final AbstractIoFuture<T> future) { - next.notifyCancelled(future); + @Override + protected void doNotifyCancelled(final AbstractIoFuture<T> future) { } - void cancel() { + @Override + protected void doCancel() { // terminate } - boolean cancelRequested() { + @Override + protected boolean isCancelRequested() { return true; } }
Locations
Projects
Search
Status Monitor
Help
Open Build Service
OBS Manuals
API Documentation
OBS Portal
Reporting a Bug
Contact
Mailing List
Forums
Chat (IRC)
Twitter
Open Build Service (OBS)
is an
openSUSE project
.
浙ICP备2022010568号-2