diff --git a/core/jvm-native/src/main/scala/cats/effect/ArrayStack.scala b/core/jvm-native/src/main/scala/cats/effect/ArrayStack.scala index ae5d5f7e25..6375cbccb3 100644 --- a/core/jvm-native/src/main/scala/cats/effect/ArrayStack.scala +++ b/core/jvm-native/src/main/scala/cats/effect/ArrayStack.scala @@ -17,6 +17,7 @@ package cats.effect import Platform.static +import PlatformStatics.VM_MaxArraySize private final class ArrayStack[A <: AnyRef]( private[this] var buffer: Array[AnyRef], @@ -72,7 +73,17 @@ private final class ArrayStack[A <: AnyRef]( private[this] def checkAndGrow(): Unit = if (index >= buffer.length) { val len = buffer.length - val buffer2 = new Array[AnyRef](len * 2) + val targetLen = len * 2 + + val resizeLen = + if (targetLen < 0) + throw new Exception(s"Overflow while resizing array. Request length: $targetLen") + else if (len > VM_MaxArraySize / 2) + VM_MaxArraySize + else + targetLen + + val buffer2 = new Array[AnyRef](resizeLen) System.arraycopy(buffer, 0, buffer2, 0, len) buffer = buffer2 } diff --git a/core/jvm-native/src/main/scala/cats/effect/PlatformStatics.scala b/core/jvm-native/src/main/scala/cats/effect/PlatformStatics.scala new file mode 100644 index 0000000000..e7ddfc579d --- /dev/null +++ b/core/jvm-native/src/main/scala/cats/effect/PlatformStatics.scala @@ -0,0 +1,8 @@ +package cats.effect + +// copy from scala.runtime.PStatics +private[effect] object PlatformStatics { + // `Int.MaxValue - 8` traditional soft limit to maximize compatibility with diverse JVMs + // See https://stackoverflow.com/a/8381338 for example + final val VM_MaxArraySize = 2147483639 +}