From 0f01ffe3a09cfef68e7b752a8c56b1d5820c8a75 Mon Sep 17 00:00:00 2001 From: Patrik Nordwall Date: Wed, 20 Feb 2013 11:42:29 +0100 Subject: [PATCH] Add fail fast checks to prevent null message, see #2800 (cherry picked from commit 5526f9d2a8b01f944ff078ce57f2a03c21649d05) * Added null check in Envelope.apply --- .../src/main/scala/akka/actor/ActorRef.scala | 2 ++ .../main/scala/akka/actor/ActorRefProvider.scala | 1 + .../main/scala/akka/actor/dungeon/Dispatch.scala | 1 - .../scala/akka/dispatch/AbstractDispatcher.scala | 4 +++- akka-actor/src/main/scala/akka/event/Logging.scala | 5 ++++- .../src/main/scala/akka/pattern/AskSupport.scala | 14 ++++++++------ .../scala/akka/remote/RemoteActorRefProvider.scala | 4 +++- 7 files changed, 21 insertions(+), 10 deletions(-) diff --git a/akka-actor/src/main/scala/akka/actor/ActorRef.scala b/akka-actor/src/main/scala/akka/actor/ActorRef.scala index 82bf2c34ff..2802d2c8ec 100644 --- a/akka-actor/src/main/scala/akka/actor/ActorRef.scala +++ b/akka-actor/src/main/scala/akka/actor/ActorRef.scala @@ -452,6 +452,7 @@ private[akka] class EmptyLocalActorRef(override val provider: ActorRefProvider, } override def !(message: Any)(implicit sender: ActorRef = Actor.noSender): Unit = message match { + case null ⇒ throw new InvalidMessageException("Message is null") case d: DeadLetter ⇒ specialHandle(d.message) // do NOT form endless loops, since deadLetters will resend! case _ if !specialHandle(message) ⇒ @@ -480,6 +481,7 @@ private[akka] class DeadLetterActorRef(_provider: ActorRefProvider, _eventStream: EventStream) extends EmptyLocalActorRef(_provider, _path, _eventStream) { override def !(message: Any)(implicit sender: ActorRef = this): Unit = message match { + case null ⇒ throw new InvalidMessageException("Message is null") case d: DeadLetter ⇒ if (!specialHandle(d.message)) eventStream.publish(d) case _ ⇒ if (!specialHandle(message)) eventStream.publish(DeadLetter(message, if (sender eq Actor.noSender) provider.deadLetters else sender, this)) diff --git a/akka-actor/src/main/scala/akka/actor/ActorRefProvider.scala b/akka-actor/src/main/scala/akka/actor/ActorRefProvider.scala index 7853832b87..2d1c15d12d 100644 --- a/akka-actor/src/main/scala/akka/actor/ActorRefProvider.scala +++ b/akka-actor/src/main/scala/akka/actor/ActorRefProvider.scala @@ -386,6 +386,7 @@ class LocalActorRefProvider private[akka] ( override def isTerminated: Boolean = stopped.isOn override def !(message: Any)(implicit sender: ActorRef = Actor.noSender): Unit = stopped.ifOff(message match { + case null ⇒ throw new InvalidMessageException("Message is null") case Failed(ex, _) if sender ne null ⇒ { causeOfTermination = Some(ex); sender.asInstanceOf[InternalActorRef].stop() } case NullMessage ⇒ // do nothing case _ ⇒ log.error(this + " received unexpected message [" + message + "]") diff --git a/akka-actor/src/main/scala/akka/actor/dungeon/Dispatch.scala b/akka-actor/src/main/scala/akka/actor/dungeon/Dispatch.scala index 8d4a62d073..a931164d43 100644 --- a/akka-actor/src/main/scala/akka/actor/dungeon/Dispatch.scala +++ b/akka-actor/src/main/scala/akka/actor/dungeon/Dispatch.scala @@ -91,7 +91,6 @@ private[akka] trait Dispatch { this: ActorCell ⇒ def sendMessage(msg: Envelope): Unit = try { val m = msg.message.asInstanceOf[AnyRef] - if (m eq null) throw new InvalidMessageException("Message is null") if (system.settings.SerializeAllMessages && !m.isInstanceOf[NoSerializationVerificationNeeded]) { val s = SerializationExtension(system) s.deserialize(s.serialize(m).get, m.getClass).get diff --git a/akka-actor/src/main/scala/akka/dispatch/AbstractDispatcher.scala b/akka-actor/src/main/scala/akka/dispatch/AbstractDispatcher.scala index fff250c547..3ec4e24e90 100644 --- a/akka-actor/src/main/scala/akka/dispatch/AbstractDispatcher.scala +++ b/akka-actor/src/main/scala/akka/dispatch/AbstractDispatcher.scala @@ -20,8 +20,10 @@ import scala.util.control.NonFatal final case class Envelope private (val message: Any, val sender: ActorRef) object Envelope { - def apply(message: Any, sender: ActorRef, system: ActorSystem): Envelope = + def apply(message: Any, sender: ActorRef, system: ActorSystem): Envelope = { + if (message == null) throw new InvalidMessageException("Message is null") new Envelope(message, if (sender ne Actor.noSender) sender else system.deadLetters) + } } /** diff --git a/akka-actor/src/main/scala/akka/event/Logging.scala b/akka-actor/src/main/scala/akka/event/Logging.scala index 851c6cf1f3..dab5b14504 100644 --- a/akka-actor/src/main/scala/akka/event/Logging.scala +++ b/akka-actor/src/main/scala/akka/event/Logging.scala @@ -720,7 +720,10 @@ object Logging { val path: ActorPath = new RootActorPath(Address("akka", "all-systems"), "/StandardOutLogger") def provider: ActorRefProvider = throw new UnsupportedOperationException("StandardOutLogger does not provide") override val toString = "StandardOutLogger" - override def !(message: Any)(implicit sender: ActorRef = Actor.noSender): Unit = print(message) + override def !(message: Any)(implicit sender: ActorRef = Actor.noSender): Unit = { + if (message == null) throw new InvalidMessageException("Message is null") + print(message) + } } val StandardOutLogger = new StandardOutLogger diff --git a/akka-actor/src/main/scala/akka/pattern/AskSupport.scala b/akka-actor/src/main/scala/akka/pattern/AskSupport.scala index 18f88ba30e..1937a81110 100644 --- a/akka-actor/src/main/scala/akka/pattern/AskSupport.scala +++ b/akka-actor/src/main/scala/akka/pattern/AskSupport.scala @@ -193,12 +193,14 @@ private[akka] final class PromiseActorRef private (val provider: ActorRefProvide override def !(message: Any)(implicit sender: ActorRef = Actor.noSender): Unit = state match { case Stopped | _: StoppedWithPath ⇒ provider.deadLetters ! message - case _ ⇒ if (!(result.tryComplete( - message match { - case Status.Success(r) ⇒ Success(r) - case Status.Failure(f) ⇒ Failure(f) - case other ⇒ Success(other) - }))) provider.deadLetters ! message + case _ ⇒ + if (message == null) throw new InvalidMessageException("Message is null") + if (!(result.tryComplete( + message match { + case Status.Success(r) ⇒ Success(r) + case Status.Failure(f) ⇒ Failure(f) + case other ⇒ Success(other) + }))) provider.deadLetters ! message } override def sendSystemMessage(message: SystemMessage): Unit = message match { diff --git a/akka-remote/src/main/scala/akka/remote/RemoteActorRefProvider.scala b/akka-remote/src/main/scala/akka/remote/RemoteActorRefProvider.scala index c138b9f2d0..a9856c238a 100644 --- a/akka-remote/src/main/scala/akka/remote/RemoteActorRefProvider.scala +++ b/akka-remote/src/main/scala/akka/remote/RemoteActorRefProvider.scala @@ -355,8 +355,10 @@ private[akka] class RemoteActorRef private[akka] ( def sendSystemMessage(message: SystemMessage): Unit = try remote.send(message, None, this) catch handleException - override def !(message: Any)(implicit sender: ActorRef = Actor.noSender): Unit = + override def !(message: Any)(implicit sender: ActorRef = Actor.noSender): Unit = { + if (message == null) throw new InvalidMessageException("Message is null") try remote.send(message, Option(sender), this) catch handleException + } def start(): Unit = if (props.isDefined && deploy.isDefined) provider.useActorOnNode(path, props.get, deploy.get, getParent)