From 4034a219d0af6bac2aec7ae192420faec90a3f51 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Tue, 13 Jul 2010 18:40:29 -0600 Subject: [PATCH] do nothing in System.arraycopy if length <= 0 Previously, we risked segfaults by passing negative numbers to memcpy. This commit also makes arraycopy throw an IndexOutOfBounds exception instead of an ArrayStoreException if the specified offsets and lengths would take us outside the bounds of one or both of the arrays, per the Sun documentation. --- src/builtin.cpp | 41 ++++++++++++++++++++++++----------------- src/machine.h | 6 ++++++ vm.pro | 1 + 3 files changed, 31 insertions(+), 17 deletions(-) diff --git a/src/builtin.cpp b/src/builtin.cpp index 03a4fb01f6..d8ee84cc2c 100644 --- a/src/builtin.cpp +++ b/src/builtin.cpp @@ -594,25 +594,32 @@ Avian_java_lang_System_arraycopy if (LIKELY(elementSize)) { intptr_t sl = cast(src, BytesPerWord); intptr_t dl = cast(dst, BytesPerWord); - if (LIKELY(srcOffset >= 0 and srcOffset + length <= sl and - dstOffset >= 0 and dstOffset + length <= dl)) - { - uint8_t* sbody = &cast(src, ArrayBody); - uint8_t* dbody = &cast(dst, ArrayBody); - if (src == dst) { - memmove(dbody + (dstOffset * elementSize), - sbody + (srcOffset * elementSize), - length * elementSize); + if (LIKELY(length > 0)) { + if (LIKELY(srcOffset >= 0 and srcOffset + length <= sl and + dstOffset >= 0 and dstOffset + length <= dl)) + { + uint8_t* sbody = &cast(src, ArrayBody); + uint8_t* dbody = &cast(dst, ArrayBody); + if (src == dst) { + memmove(dbody + (dstOffset * elementSize), + sbody + (srcOffset * elementSize), + length * elementSize); + } else { + memcpy(dbody + (dstOffset * elementSize), + sbody + (srcOffset * elementSize), + length * elementSize); + } + + if (classObjectMask(t, objectClass(t, dst))) { + mark(t, dst, ArrayBody + (dstOffset * BytesPerWord), length); + } + + return; } else { - memcpy(dbody + (dstOffset * elementSize), - sbody + (srcOffset * elementSize), - length * elementSize); + t->exception = makeIndexOutOfBoundsException(t); + return; } - - if (classObjectMask(t, objectClass(t, dst))) { - mark(t, dst, ArrayBody + (dstOffset * BytesPerWord), length); - } - + } else { return; } } diff --git a/src/machine.h b/src/machine.h index 0773c1acf2..4bdfccfc24 100644 --- a/src/machine.h +++ b/src/machine.h @@ -1759,6 +1759,12 @@ makeIllegalMonitorStateException(Thread* t) return makeIllegalMonitorStateException(t, 0, makeTrace(t), 0); } +inline object +makeIndexOutOfBoundsException(Thread* t) +{ + return makeIndexOutOfBoundsException(t, 0, makeTrace(t), 0); +} + inline object makeArrayIndexOutOfBoundsException(Thread* t, object message) { diff --git a/vm.pro b/vm.pro index 98d92c15b2..a6a2a54413 100644 --- a/vm.pro +++ b/vm.pro @@ -38,6 +38,7 @@ -keep public class java.lang.IllegalArgumentException -keep public class java.lang.IllegalMonitorStateException -keep public class java.lang.IllegalThreadStateException +-keep public class java.lang.IndexOutOfBoundsException -keep public class java.lang.ArrayIndexOutOfBoundsException -keep public class java.lang.ArrayStoreException -keep public class java.lang.NegativeArraySizeException