239 fieldDescriptor fd;
240
241 /* make sure it is a static field */
242 if (!jfieldIDWorkaround::is_static_jfieldID(fid))
243 ReportJNIFatalError(thr, fatal_should_be_static);
244
245 /* validate the class being passed */
246 ASSERT_OOPS_ALLOWED;
247 Klass* k_oop = jniCheck::validate_class(thr, cls, false);
248
249 /* check for proper subclass hierarchy */
250 JNIid* id = jfieldIDWorkaround::from_static_jfieldID(fid);
251 Klass* f_oop = id->holder();
252 if (!k_oop->is_subtype_of(f_oop))
253 ReportJNIFatalError(thr, fatal_wrong_static_field);
254
255 /* check for proper field type */
256 if (!id->find_local_field(&fd))
257 ReportJNIFatalError(thr, fatal_static_field_not_found);
258 if ((fd.field_type() != ftype) &&
259 !(fd.field_type() == T_ARRAY && ftype == T_OBJECT)) {
260 ReportJNIFatalError(thr, fatal_static_field_mismatch);
261 }
262 }
263
264 static inline void
265 checkInstanceFieldID(JavaThread* thr, jfieldID fid, jobject obj, int ftype)
266 {
267 fieldDescriptor fd;
268
269 /* make sure it is an instance field */
270 if (jfieldIDWorkaround::is_static_jfieldID(fid))
271 ReportJNIFatalError(thr, fatal_should_be_nonstatic);
272
273 /* validate the object being passed and then get its class */
274 ASSERT_OOPS_ALLOWED;
275 oop oopObj = jniCheck::validate_object(thr, obj);
276 if (oopObj == nullptr) {
277 ReportJNIFatalError(thr, fatal_null_object);
278 }
279 Klass* k_oop = oopObj->klass();
280
281 if (!jfieldIDWorkaround::is_valid_jfieldID(k_oop, fid)) {
282 ReportJNIFatalError(thr, fatal_wrong_field);
283 }
284
285 /* make sure the field exists */
286 int offset = jfieldIDWorkaround::from_instance_jfieldID(k_oop, fid);
287 if (!InstanceKlass::cast(k_oop)->contains_field_offset(offset))
288 ReportJNIFatalError(thr, fatal_wrong_field);
289
290 /* check for proper field type */
291 if (!InstanceKlass::cast(k_oop)->find_field_from_offset(offset,
292 false, &fd))
293 ReportJNIFatalError(thr, fatal_instance_field_not_found);
294
295 if ((fd.field_type() != ftype) &&
296 !(fd.field_type() == T_ARRAY && ftype == T_OBJECT)) {
297 ReportJNIFatalError(thr, fatal_instance_field_mismatch);
298 }
299 }
300
301 static inline void
302 checkString(JavaThread* thr, jstring js)
303 {
304 ASSERT_OOPS_ALLOWED;
305 oop s = jniCheck::validate_object(thr, js);
306 if ((s == nullptr) || !java_lang_String::is_instance(s))
307 ReportJNIFatalError(thr, fatal_non_string);
308 }
309
310 static inline arrayOop
311 check_is_array(JavaThread* thr, jarray jArray)
312 {
313 ASSERT_OOPS_ALLOWED;
314 arrayOop aOop;
315
316 aOop = (arrayOop)jniCheck::validate_object(thr, jArray);
327 if (!aOop->is_typeArray()) {
328 ReportJNIFatalError(thr, fatal_prim_type_array_expected);
329 }
330 return aOop;
331 }
332
333 static inline void
334 check_primitive_array_type(JavaThread* thr, jarray jArray, BasicType elementType)
335 {
336 BasicType array_type;
337 arrayOop aOop;
338
339 aOop = check_is_primitive_array(thr, jArray);
340 array_type = TypeArrayKlass::cast(aOop->klass())->element_type();
341 if (array_type != elementType) {
342 ReportJNIFatalError(thr, fatal_element_type_mismatch);
343 }
344 }
345
346 static inline void
347 check_is_obj_array(JavaThread* thr, jarray jArray) {
348 arrayOop aOop = check_is_array(thr, jArray);
349 if (!aOop->is_objArray()) {
350 ReportJNIFatalError(thr, fatal_object_array_expected);
351 }
352 }
353
354 /*
355 * Copy and wrap array elements for bounds checking.
356 * Remember the original elements (GuardedMemory::get_tag())
357 */
358 static void* check_jni_wrap_copy_array(JavaThread* thr, jarray array,
359 void* orig_elements) {
360 void* result;
361 IN_VM(
362 oop a = JNIHandles::resolve_non_null(array);
363 size_t len = arrayOop(a)->length() <<
364 TypeArrayKlass::cast(a->klass())->log2_element_size();
365 result = GuardedMemory::wrap_copy(orig_elements, len, orig_elements);
366 )
367 return result;
368 }
369
449
450 oop jniCheck::validate_object(JavaThread* thr, jobject obj) {
451 if (obj == nullptr) return nullptr;
452 ASSERT_OOPS_ALLOWED;
453 oop oopObj = jniCheck::validate_handle(thr, obj);
454 if (oopObj == nullptr) {
455 ReportJNIFatalError(thr, fatal_bad_ref_to_jni);
456 }
457 return oopObj;
458 }
459
460 // Warn if a class descriptor is in decorated form; class descriptors
461 // passed to JNI findClass should not be decorated unless they are
462 // array descriptors.
463 void jniCheck::validate_class_descriptor(JavaThread* thr, const char* name) {
464 if (name == nullptr) return; // implementation accepts null so just return
465
466 size_t len = strlen(name);
467
468 if (len >= 2 &&
469 name[0] == JVM_SIGNATURE_CLASS && // 'L'
470 name[len-1] == JVM_SIGNATURE_ENDCLASS ) { // ';'
471 char msg[JVM_MAXPATHLEN];
472 jio_snprintf(msg, JVM_MAXPATHLEN, "%s%s%s",
473 warn_bad_class_descriptor1, name, warn_bad_class_descriptor2);
474 ReportJNIWarning(thr, msg);
475 }
476
477 // Verify that the class name given is a valid utf8 string
478 if (!UTF8::is_legal_utf8((const unsigned char*)name, (int)strlen(name), false)) {
479 char msg[JVM_MAXPATHLEN];
480 jio_snprintf(msg, JVM_MAXPATHLEN, "%s%s%s", fatal_non_utf8_class_name1, name, fatal_non_utf8_class_name2);
481 ReportJNIFatalError(thr, msg);
482 }
483 }
484
485 Klass* jniCheck::validate_class(JavaThread* thr, jclass clazz, bool allow_primitive) {
486 ASSERT_OOPS_ALLOWED;
487 oop mirror = jniCheck::validate_handle(thr, clazz);
488 if (mirror == nullptr) {
489 ReportJNIFatalError(thr, fatal_received_null_class);
1589 return result;
1590 JNI_END
1591
1592 JNI_ENTRY_CHECKED(jobjectArray,
1593 checked_jni_NewObjectArray(JNIEnv *env,
1594 jsize len,
1595 jclass clazz,
1596 jobject init))
1597 functionEnter(thr);
1598 jobjectArray result = UNCHECKED()->NewObjectArray(env,len,clazz,init);
1599 functionExit(thr);
1600 return result;
1601 JNI_END
1602
1603 JNI_ENTRY_CHECKED(jobject,
1604 checked_jni_GetObjectArrayElement(JNIEnv *env,
1605 jobjectArray array,
1606 jsize index))
1607 functionEnter(thr);
1608 IN_VM(
1609 check_is_obj_array(thr, array);
1610 )
1611 jobject result = UNCHECKED()->GetObjectArrayElement(env,array,index);
1612 functionExit(thr);
1613 return result;
1614 JNI_END
1615
1616 JNI_ENTRY_CHECKED(void,
1617 checked_jni_SetObjectArrayElement(JNIEnv *env,
1618 jobjectArray array,
1619 jsize index,
1620 jobject val))
1621 functionEnter(thr);
1622 IN_VM(
1623 check_is_obj_array(thr, array);
1624 )
1625 UNCHECKED()->SetObjectArrayElement(env,array,index,val);
1626 functionExit(thr);
1627 JNI_END
1628
1629 #define WRAPPER_NewScalarArray(Return, Result) \
1630 JNI_ENTRY_CHECKED(Return, \
1631 checked_jni_New##Result##Array(JNIEnv *env, \
1632 jsize len)) \
1633 functionEnter(thr); \
1634 Return result = UNCHECKED()->New##Result##Array(env,len); \
1635 functionExit(thr); \
1636 return (Return) result; \
1637 JNI_END
1638
1639 WRAPPER_NewScalarArray(jbooleanArray, Boolean)
1640 WRAPPER_NewScalarArray(jbyteArray, Byte)
1641 WRAPPER_NewScalarArray(jshortArray, Short)
1642 WRAPPER_NewScalarArray(jcharArray, Char)
1643 WRAPPER_NewScalarArray(jintArray, Int)
|
239 fieldDescriptor fd;
240
241 /* make sure it is a static field */
242 if (!jfieldIDWorkaround::is_static_jfieldID(fid))
243 ReportJNIFatalError(thr, fatal_should_be_static);
244
245 /* validate the class being passed */
246 ASSERT_OOPS_ALLOWED;
247 Klass* k_oop = jniCheck::validate_class(thr, cls, false);
248
249 /* check for proper subclass hierarchy */
250 JNIid* id = jfieldIDWorkaround::from_static_jfieldID(fid);
251 Klass* f_oop = id->holder();
252 if (!k_oop->is_subtype_of(f_oop))
253 ReportJNIFatalError(thr, fatal_wrong_static_field);
254
255 /* check for proper field type */
256 if (!id->find_local_field(&fd))
257 ReportJNIFatalError(thr, fatal_static_field_not_found);
258 if ((fd.field_type() != ftype) &&
259 !(fd.field_type() == T_ARRAY && ftype == T_OBJECT) &&
260 !(fd.field_type() == T_PRIMITIVE_OBJECT && ftype == T_OBJECT)) {
261 ReportJNIFatalError(thr, fatal_static_field_mismatch);
262 }
263 }
264
265 static inline void
266 checkInstanceFieldID(JavaThread* thr, jfieldID fid, jobject obj, int ftype)
267 {
268 fieldDescriptor fd;
269
270 /* make sure it is an instance field */
271 if (jfieldIDWorkaround::is_static_jfieldID(fid))
272 ReportJNIFatalError(thr, fatal_should_be_nonstatic);
273
274 /* validate the object being passed and then get its class */
275 ASSERT_OOPS_ALLOWED;
276 oop oopObj = jniCheck::validate_object(thr, obj);
277 if (oopObj == nullptr) {
278 ReportJNIFatalError(thr, fatal_null_object);
279 }
280 Klass* k_oop = oopObj->klass();
281
282 if (!jfieldIDWorkaround::is_valid_jfieldID(k_oop, fid)) {
283 ReportJNIFatalError(thr, fatal_wrong_field);
284 }
285
286 /* make sure the field exists */
287 int offset = jfieldIDWorkaround::from_instance_jfieldID(k_oop, fid);
288 if (!InstanceKlass::cast(k_oop)->contains_field_offset(offset))
289 ReportJNIFatalError(thr, fatal_wrong_field);
290
291 /* check for proper field type */
292 if (!InstanceKlass::cast(k_oop)->find_field_from_offset(offset,
293 false, &fd))
294 ReportJNIFatalError(thr, fatal_instance_field_not_found);
295
296 if ((fd.field_type() != ftype) &&
297 !(fd.field_type() == T_ARRAY && ftype == T_OBJECT) &&
298 !(fd.field_type() == T_PRIMITIVE_OBJECT && ftype == T_OBJECT)) {
299 ReportJNIFatalError(thr, fatal_instance_field_mismatch);
300 }
301 }
302
303 static inline void
304 checkString(JavaThread* thr, jstring js)
305 {
306 ASSERT_OOPS_ALLOWED;
307 oop s = jniCheck::validate_object(thr, js);
308 if ((s == nullptr) || !java_lang_String::is_instance(s))
309 ReportJNIFatalError(thr, fatal_non_string);
310 }
311
312 static inline arrayOop
313 check_is_array(JavaThread* thr, jarray jArray)
314 {
315 ASSERT_OOPS_ALLOWED;
316 arrayOop aOop;
317
318 aOop = (arrayOop)jniCheck::validate_object(thr, jArray);
329 if (!aOop->is_typeArray()) {
330 ReportJNIFatalError(thr, fatal_prim_type_array_expected);
331 }
332 return aOop;
333 }
334
335 static inline void
336 check_primitive_array_type(JavaThread* thr, jarray jArray, BasicType elementType)
337 {
338 BasicType array_type;
339 arrayOop aOop;
340
341 aOop = check_is_primitive_array(thr, jArray);
342 array_type = TypeArrayKlass::cast(aOop->klass())->element_type();
343 if (array_type != elementType) {
344 ReportJNIFatalError(thr, fatal_element_type_mismatch);
345 }
346 }
347
348 static inline void
349 check_is_obj_or_inline_array(JavaThread* thr, jarray jArray) {
350 arrayOop aOop = check_is_array(thr, jArray);
351 if (!aOop->is_objArray() && !aOop->is_flatArray()) {
352 ReportJNIFatalError(thr, fatal_object_array_expected);
353 }
354 }
355
356 /*
357 * Copy and wrap array elements for bounds checking.
358 * Remember the original elements (GuardedMemory::get_tag())
359 */
360 static void* check_jni_wrap_copy_array(JavaThread* thr, jarray array,
361 void* orig_elements) {
362 void* result;
363 IN_VM(
364 oop a = JNIHandles::resolve_non_null(array);
365 size_t len = arrayOop(a)->length() <<
366 TypeArrayKlass::cast(a->klass())->log2_element_size();
367 result = GuardedMemory::wrap_copy(orig_elements, len, orig_elements);
368 )
369 return result;
370 }
371
451
452 oop jniCheck::validate_object(JavaThread* thr, jobject obj) {
453 if (obj == nullptr) return nullptr;
454 ASSERT_OOPS_ALLOWED;
455 oop oopObj = jniCheck::validate_handle(thr, obj);
456 if (oopObj == nullptr) {
457 ReportJNIFatalError(thr, fatal_bad_ref_to_jni);
458 }
459 return oopObj;
460 }
461
462 // Warn if a class descriptor is in decorated form; class descriptors
463 // passed to JNI findClass should not be decorated unless they are
464 // array descriptors.
465 void jniCheck::validate_class_descriptor(JavaThread* thr, const char* name) {
466 if (name == nullptr) return; // implementation accepts null so just return
467
468 size_t len = strlen(name);
469
470 if (len >= 2 &&
471 (name[0] == JVM_SIGNATURE_CLASS || name[0] == JVM_SIGNATURE_PRIMITIVE_OBJECT) && // 'L' or 'Q'
472 name[len-1] == JVM_SIGNATURE_ENDCLASS ) { // ';'
473 char msg[JVM_MAXPATHLEN];
474 jio_snprintf(msg, JVM_MAXPATHLEN, "%s%s%s",
475 warn_bad_class_descriptor1, name, warn_bad_class_descriptor2);
476 ReportJNIWarning(thr, msg);
477 }
478
479 // Verify that the class name given is a valid utf8 string
480 if (!UTF8::is_legal_utf8((const unsigned char*)name, (int)strlen(name), false)) {
481 char msg[JVM_MAXPATHLEN];
482 jio_snprintf(msg, JVM_MAXPATHLEN, "%s%s%s", fatal_non_utf8_class_name1, name, fatal_non_utf8_class_name2);
483 ReportJNIFatalError(thr, msg);
484 }
485 }
486
487 Klass* jniCheck::validate_class(JavaThread* thr, jclass clazz, bool allow_primitive) {
488 ASSERT_OOPS_ALLOWED;
489 oop mirror = jniCheck::validate_handle(thr, clazz);
490 if (mirror == nullptr) {
491 ReportJNIFatalError(thr, fatal_received_null_class);
1591 return result;
1592 JNI_END
1593
1594 JNI_ENTRY_CHECKED(jobjectArray,
1595 checked_jni_NewObjectArray(JNIEnv *env,
1596 jsize len,
1597 jclass clazz,
1598 jobject init))
1599 functionEnter(thr);
1600 jobjectArray result = UNCHECKED()->NewObjectArray(env,len,clazz,init);
1601 functionExit(thr);
1602 return result;
1603 JNI_END
1604
1605 JNI_ENTRY_CHECKED(jobject,
1606 checked_jni_GetObjectArrayElement(JNIEnv *env,
1607 jobjectArray array,
1608 jsize index))
1609 functionEnter(thr);
1610 IN_VM(
1611 check_is_obj_or_inline_array(thr, array);
1612 )
1613 jobject result = UNCHECKED()->GetObjectArrayElement(env,array,index);
1614 functionExit(thr);
1615 return result;
1616 JNI_END
1617
1618 JNI_ENTRY_CHECKED(void,
1619 checked_jni_SetObjectArrayElement(JNIEnv *env,
1620 jobjectArray array,
1621 jsize index,
1622 jobject val))
1623 functionEnter(thr);
1624 IN_VM(
1625 check_is_obj_or_inline_array(thr, array);
1626 )
1627 UNCHECKED()->SetObjectArrayElement(env,array,index,val);
1628 functionExit(thr);
1629 JNI_END
1630
1631 #define WRAPPER_NewScalarArray(Return, Result) \
1632 JNI_ENTRY_CHECKED(Return, \
1633 checked_jni_New##Result##Array(JNIEnv *env, \
1634 jsize len)) \
1635 functionEnter(thr); \
1636 Return result = UNCHECKED()->New##Result##Array(env,len); \
1637 functionExit(thr); \
1638 return (Return) result; \
1639 JNI_END
1640
1641 WRAPPER_NewScalarArray(jbooleanArray, Boolean)
1642 WRAPPER_NewScalarArray(jbyteArray, Byte)
1643 WRAPPER_NewScalarArray(jshortArray, Short)
1644 WRAPPER_NewScalarArray(jcharArray, Char)
1645 WRAPPER_NewScalarArray(jintArray, Int)
|