Fix linting issues in Unsafe native
Bug: 203762565
Test: art/test/testrunner/testrunner.py -t 2235-JdkUnsafeTest
Change-Id: I16e0fbce6face8a7fc5e144f58e7c6b0a68d13f2
diff --git a/runtime/native/jdk_internal_misc_Unsafe.cc b/runtime/native/jdk_internal_misc_Unsafe.cc
index 61154d0..6acf4a5 100644
--- a/runtime/native/jdk_internal_misc_Unsafe.cc
+++ b/runtime/native/jdk_internal_misc_Unsafe.cc
@@ -38,6 +38,30 @@
namespace art {
+namespace {
+ // Checks a JNI argument `size` fits inside a size_t and throws a RuntimeException if not (see
+ // jdk/internal/misc/Unsafe.java comments).
+ bool ValidJniSizeArgument(jlong size) REQUIRES_SHARED(Locks::mutator_lock_) {
+ const jlong maybe_truncated_size = static_cast<jlong>(static_cast<size_t>(size));
+ if (LIKELY(size >= 0 && size == maybe_truncated_size)) {
+ return true;
+ }
+ ThrowRuntimeException("Bad size: %" PRIu64, size);
+ return false;
+ }
+
+ // Checks a JNI argument `offset` fits inside a size_t and is less than the size. This method
+ // and throws a RuntimeException if not (see jdk/internal/misc/Unsafe.java comments).
+ bool ValidJniOffsetArgument(jlong offset, jlong size) REQUIRES_SHARED(Locks::mutator_lock_) {
+ const jlong maybe_truncated_offset = static_cast<jlong>(static_cast<size_t>(offset));
+ if (LIKELY(offset >= 0 && offset < size && offset == maybe_truncated_offset)) {
+ return true;
+ }
+ ThrowRuntimeException("Bad offset %" PRIu64 " size %" PRIu64, offset, size);
+ return false;
+ }
+} // namespace
+
static jboolean Unsafe_compareAndSetInt(JNIEnv* env, jobject, jobject javaObj, jlong offset,
jint expectedValue, jint newValue) {
ScopedFastNativeObjectAccess soa(env);
@@ -253,17 +277,21 @@
static jlong Unsafe_allocateMemory(JNIEnv* env, jobject, jlong bytes) {
ScopedFastNativeObjectAccess soa(env);
- // bytes is nonnegative and fits into size_t
- if (bytes < 0 || bytes != (jlong)(size_t) bytes) {
- ThrowIllegalAccessException("wrong number of bytes");
+ if (bytes == 0) {
return 0;
}
- void* mem = malloc(bytes);
+ // bytes is nonnegative and fits into size_t
+ if (!ValidJniSizeArgument(bytes)) {
+ DCHECK(soa.Self()->IsExceptionPending());
+ return 0;
+ }
+ const size_t malloc_bytes = static_cast<size_t>(bytes);
+ void* mem = malloc(malloc_bytes);
if (mem == nullptr) {
soa.Self()->ThrowOutOfMemoryError("native alloc");
return 0;
}
- return (uintptr_t) mem;
+ return reinterpret_cast<uintptr_t>(mem);
}
static void Unsafe_freeMemory(JNIEnv* env ATTRIBUTE_UNUSED, jobject, jlong address) {
@@ -331,16 +359,17 @@
static void Unsafe_copyMemory(JNIEnv *env, jobject unsafe ATTRIBUTE_UNUSED, jlong src,
jlong dst, jlong size) {
+ ScopedFastNativeObjectAccess soa(env);
if (size == 0) {
return;
}
// size is nonnegative and fits into size_t
- if (size < 0 || size != (jlong)(size_t) size) {
- ScopedFastNativeObjectAccess soa(env);
- ThrowIllegalAccessException("wrong number of bytes");
+ if (!ValidJniSizeArgument(size)) {
+ DCHECK(soa.Self()->IsExceptionPending());
+ return;
}
- size_t sz = (size_t)size;
- memcpy(reinterpret_cast<void *>(dst), reinterpret_cast<void *>(src), sz);
+ const size_t memcpy_size = static_cast<size_t>(size);
+ memcpy(reinterpret_cast<void *>(dst), reinterpret_cast<void *>(src), memcpy_size);
}
template<typename T>
@@ -382,27 +411,32 @@
return;
}
// size is nonnegative and fits into size_t
- if (size < 0 || size != (jlong)(size_t) size) {
- ThrowIllegalAccessException("wrong number of bytes");
+ if (!ValidJniSizeArgument(size)) {
+ DCHECK(soa.Self()->IsExceptionPending());
+ return;
}
- size_t sz = (size_t)size;
- size_t dst_offset = (size_t)dstOffset;
+ if (!ValidJniOffsetArgument(dstOffset, size)) {
+ DCHECK(soa.Self()->IsExceptionPending());
+ return;
+ }
+ const size_t copy_bytes = static_cast<size_t>(size);
+ const size_t dst_offset = static_cast<size_t>(dstOffset);
ObjPtr<mirror::Object> dst = soa.Decode<mirror::Object>(dstObj);
ObjPtr<mirror::Class> component_type = dst->GetClass()->GetComponentType();
if (component_type->IsPrimitiveByte() || component_type->IsPrimitiveBoolean()) {
// Note: Treating BooleanArray as ByteArray.
- copyToArray(srcAddr, ObjPtr<mirror::ByteArray>::DownCast(dst), dst_offset, sz);
+ copyToArray(srcAddr, ObjPtr<mirror::ByteArray>::DownCast(dst), dst_offset, copy_bytes);
} else if (component_type->IsPrimitiveShort() || component_type->IsPrimitiveChar()) {
// Note: Treating CharArray as ShortArray.
- copyToArray(srcAddr, ObjPtr<mirror::ShortArray>::DownCast(dst), dst_offset, sz);
+ copyToArray(srcAddr, ObjPtr<mirror::ShortArray>::DownCast(dst), dst_offset, copy_bytes);
} else if (component_type->IsPrimitiveInt() || component_type->IsPrimitiveFloat()) {
// Note: Treating FloatArray as IntArray.
- copyToArray(srcAddr, ObjPtr<mirror::IntArray>::DownCast(dst), dst_offset, sz);
+ copyToArray(srcAddr, ObjPtr<mirror::IntArray>::DownCast(dst), dst_offset, copy_bytes);
} else if (component_type->IsPrimitiveLong() || component_type->IsPrimitiveDouble()) {
// Note: Treating DoubleArray as LongArray.
- copyToArray(srcAddr, ObjPtr<mirror::LongArray>::DownCast(dst), dst_offset, sz);
+ copyToArray(srcAddr, ObjPtr<mirror::LongArray>::DownCast(dst), dst_offset, copy_bytes);
} else {
- ThrowIllegalAccessException("not a primitive array");
+ ThrowIllegalArgumentException("not a primitive array");
}
}
@@ -417,27 +451,32 @@
return;
}
// size is nonnegative and fits into size_t
- if (size < 0 || size != (jlong)(size_t) size) {
- ThrowIllegalAccessException("wrong number of bytes");
+ if (!ValidJniSizeArgument(size)) {
+ DCHECK(soa.Self()->IsExceptionPending());
+ return;
}
- size_t sz = (size_t)size;
- size_t src_offset = (size_t)srcOffset;
+ if (!ValidJniOffsetArgument(srcOffset, size)) {
+ DCHECK(soa.Self()->IsExceptionPending());
+ return;
+ }
+ const size_t copy_bytes = static_cast<size_t>(size);
+ const size_t src_offset = static_cast<size_t>(srcOffset);
ObjPtr<mirror::Object> src = soa.Decode<mirror::Object>(srcObj);
ObjPtr<mirror::Class> component_type = src->GetClass()->GetComponentType();
if (component_type->IsPrimitiveByte() || component_type->IsPrimitiveBoolean()) {
// Note: Treating BooleanArray as ByteArray.
- copyFromArray(dstAddr, ObjPtr<mirror::ByteArray>::DownCast(src), src_offset, sz);
+ copyFromArray(dstAddr, ObjPtr<mirror::ByteArray>::DownCast(src), src_offset, copy_bytes);
} else if (component_type->IsPrimitiveShort() || component_type->IsPrimitiveChar()) {
// Note: Treating CharArray as ShortArray.
- copyFromArray(dstAddr, ObjPtr<mirror::ShortArray>::DownCast(src), src_offset, sz);
+ copyFromArray(dstAddr, ObjPtr<mirror::ShortArray>::DownCast(src), src_offset, copy_bytes);
} else if (component_type->IsPrimitiveInt() || component_type->IsPrimitiveFloat()) {
// Note: Treating FloatArray as IntArray.
- copyFromArray(dstAddr, ObjPtr<mirror::IntArray>::DownCast(src), src_offset, sz);
+ copyFromArray(dstAddr, ObjPtr<mirror::IntArray>::DownCast(src), src_offset, copy_bytes);
} else if (component_type->IsPrimitiveLong() || component_type->IsPrimitiveDouble()) {
// Note: Treating DoubleArray as LongArray.
- copyFromArray(dstAddr, ObjPtr<mirror::LongArray>::DownCast(src), src_offset, sz);
+ copyFromArray(dstAddr, ObjPtr<mirror::LongArray>::DownCast(src), src_offset, copy_bytes);
} else {
- ThrowIllegalAccessException("not a primitive array");
+ ThrowIllegalArgumentException("not a primitive array");
}
}
static jboolean Unsafe_getBoolean(JNIEnv* env, jobject, jobject javaObj, jlong offset) {
diff --git a/runtime/native/sun_misc_Unsafe.cc b/runtime/native/sun_misc_Unsafe.cc
index 5014f34..e9c5af0 100644
--- a/runtime/native/sun_misc_Unsafe.cc
+++ b/runtime/native/sun_misc_Unsafe.cc
@@ -230,7 +230,7 @@
static jlong Unsafe_allocateMemory(JNIEnv* env, jobject, jlong bytes) {
ScopedFastNativeObjectAccess soa(env);
// bytes is nonnegative and fits into size_t
- if (bytes < 0 || bytes != (jlong)(size_t) bytes) {
+ if (bytes < 0 || bytes != static_cast<jlong>(static_cast<size_t>(bytes))) {
ThrowIllegalAccessException("wrong number of bytes");
return 0;
}
@@ -311,11 +311,11 @@
return;
}
// size is nonnegative and fits into size_t
- if (size < 0 || size != (jlong)(size_t) size) {
+ if (size < 0 || size != static_cast<jlong>(static_cast<size_t>(size))) {
ScopedFastNativeObjectAccess soa(env);
ThrowIllegalAccessException("wrong number of bytes");
}
- size_t sz = (size_t)size;
+ size_t sz = static_cast<size_t>(size);
memcpy(reinterpret_cast<void *>(dst), reinterpret_cast<void *>(src), sz);
}
@@ -358,11 +358,11 @@
return;
}
// size is nonnegative and fits into size_t
- if (size < 0 || size != (jlong)(size_t) size) {
+ if (size < 0 || size != static_cast<jlong>(static_cast<size_t>(size))) {
ThrowIllegalAccessException("wrong number of bytes");
}
- size_t sz = (size_t)size;
- size_t dst_offset = (size_t)dstOffset;
+ size_t sz = static_cast<size_t>(size);
+ size_t dst_offset = static_cast<size_t>(dstOffset);
ObjPtr<mirror::Object> dst = soa.Decode<mirror::Object>(dstObj);
ObjPtr<mirror::Class> component_type = dst->GetClass()->GetComponentType();
if (component_type->IsPrimitiveByte() || component_type->IsPrimitiveBoolean()) {
@@ -393,11 +393,11 @@
return;
}
// size is nonnegative and fits into size_t
- if (size < 0 || size != (jlong)(size_t) size) {
+ if (size < 0 || size != static_cast<jlong>(static_cast<size_t>(size))) {
ThrowIllegalAccessException("wrong number of bytes");
}
- size_t sz = (size_t)size;
- size_t src_offset = (size_t)srcOffset;
+ size_t sz = static_cast<size_t>(size);
+ size_t src_offset = static_cast<size_t>(srcOffset);
ObjPtr<mirror::Object> src = soa.Decode<mirror::Object>(srcObj);
ObjPtr<mirror::Class> component_type = src->GetClass()->GetComponentType();
if (component_type->IsPrimitiveByte() || component_type->IsPrimitiveBoolean()) {