1 /*
2  * Copyright (C) 2008 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include "java_lang_reflect_Field.h"
18 
19 #include "class_linker.h"
20 #include "class_linker-inl.h"
21 #include "common_throws.h"
22 #include "dex_file-inl.h"
23 #include "jni_internal.h"
24 #include "mirror/class-inl.h"
25 #include "mirror/field.h"
26 #include "reflection-inl.h"
27 #include "scoped_fast_native_object_access.h"
28 #include "utils.h"
29 
30 namespace art {
31 
32 template<bool kIsSet>
VerifyFieldAccess(Thread * self,mirror::Field * field,mirror::Object * obj)33 ALWAYS_INLINE inline static bool VerifyFieldAccess(Thread* self, mirror::Field* field,
34                                                    mirror::Object* obj)
35     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
36   if (kIsSet && field->IsFinal()) {
37     ThrowIllegalAccessException(
38             StringPrintf("Cannot set %s field %s of class %s",
39                 PrettyJavaAccessFlags(field->GetAccessFlags()).c_str(),
40                 PrettyField(field->GetArtField()).c_str(),
41                 field->GetDeclaringClass() == nullptr ? "null" :
42                     PrettyClass(field->GetDeclaringClass()).c_str()).c_str());
43     return false;
44   }
45   mirror::Class* calling_class = nullptr;
46   if (!VerifyAccess(self, obj, field->GetDeclaringClass(), field->GetAccessFlags(),
47                     &calling_class, 1)) {
48     ThrowIllegalAccessException(
49             StringPrintf("Class %s cannot access %s field %s of class %s",
50                 calling_class == nullptr ? "null" : PrettyClass(calling_class).c_str(),
51                 PrettyJavaAccessFlags(field->GetAccessFlags()).c_str(),
52                 PrettyField(field->GetArtField()).c_str(),
53                 field->GetDeclaringClass() == nullptr ? "null" :
54                     PrettyClass(field->GetDeclaringClass()).c_str()).c_str());
55     return false;
56   }
57   return true;
58 }
59 
60 template<bool kAllowReferences>
GetFieldValue(mirror::Object * o,mirror::Field * f,Primitive::Type field_type,JValue * value)61 ALWAYS_INLINE inline static bool GetFieldValue(mirror::Object* o, mirror::Field* f,
62                                                Primitive::Type field_type, JValue* value)
63     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
64   DCHECK_EQ(value->GetJ(), INT64_C(0));
65   MemberOffset offset(f->GetOffset());
66   const bool is_volatile = f->IsVolatile();
67   switch (field_type) {
68     case Primitive::kPrimBoolean:
69       value->SetZ(is_volatile ? o->GetFieldBooleanVolatile(offset) : o->GetFieldBoolean(offset));
70       return true;
71     case Primitive::kPrimByte:
72       value->SetB(is_volatile ? o->GetFieldByteVolatile(offset) : o->GetFieldByte(offset));
73       return true;
74     case Primitive::kPrimChar:
75       value->SetC(is_volatile ? o->GetFieldCharVolatile(offset) : o->GetFieldChar(offset));
76       return true;
77     case Primitive::kPrimInt:
78     case Primitive::kPrimFloat:
79       value->SetI(is_volatile ? o->GetField32Volatile(offset) : o->GetField32(offset));
80       return true;
81     case Primitive::kPrimLong:
82     case Primitive::kPrimDouble:
83       value->SetJ(is_volatile ? o->GetField64Volatile(offset) : o->GetField64(offset));
84       return true;
85     case Primitive::kPrimShort:
86       value->SetS(is_volatile ? o->GetFieldShortVolatile(offset) : o->GetFieldShort(offset));
87       return true;
88     case Primitive::kPrimNot:
89       if (kAllowReferences) {
90         value->SetL(is_volatile ? o->GetFieldObjectVolatile<mirror::Object>(offset) :
91             o->GetFieldObject<mirror::Object>(offset));
92         return true;
93       }
94       // Else break to report an error.
95       break;
96     case Primitive::kPrimVoid:
97       // Never okay.
98       break;
99   }
100   ThrowIllegalArgumentException(
101       StringPrintf("Not a primitive field: %s", PrettyField(f->GetArtField()).c_str()).c_str());
102   return false;
103 }
104 
CheckReceiver(const ScopedFastNativeObjectAccess & soa,jobject j_rcvr,mirror::Field ** f,mirror::Object ** class_or_rcvr)105 ALWAYS_INLINE inline static bool CheckReceiver(const ScopedFastNativeObjectAccess& soa,
106                                                jobject j_rcvr, mirror::Field** f,
107                                                mirror::Object** class_or_rcvr)
108     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
109   soa.Self()->AssertThreadSuspensionIsAllowable();
110   mirror::Class* declaringClass = (*f)->GetDeclaringClass();
111   if ((*f)->IsStatic()) {
112     if (UNLIKELY(!declaringClass->IsInitialized())) {
113       StackHandleScope<2> hs(soa.Self());
114       HandleWrapper<mirror::Field> h_f(hs.NewHandleWrapper(f));
115       HandleWrapper<mirror::Class> h_klass(hs.NewHandleWrapper(&declaringClass));
116       ClassLinker* const class_linker = Runtime::Current()->GetClassLinker();
117       if (UNLIKELY(!class_linker->EnsureInitialized(soa.Self(), h_klass, true, true))) {
118         DCHECK(soa.Self()->IsExceptionPending());
119         return false;
120       }
121     }
122     *class_or_rcvr = declaringClass;
123     return true;
124   }
125   *class_or_rcvr = soa.Decode<mirror::Object*>(j_rcvr);
126   if (!VerifyObjectIsClass(*class_or_rcvr, declaringClass)) {
127     DCHECK(soa.Self()->IsExceptionPending());
128     return false;
129   }
130   return true;
131 }
132 
Field_get(JNIEnv * env,jobject javaField,jobject javaObj)133 static jobject Field_get(JNIEnv* env, jobject javaField, jobject javaObj) {
134   ScopedFastNativeObjectAccess soa(env);
135   mirror::Field* f = soa.Decode<mirror::Field*>(javaField);
136   mirror::Object* o = nullptr;
137   if (!CheckReceiver(soa, javaObj, &f, &o)) {
138     DCHECK(soa.Self()->IsExceptionPending());
139     return nullptr;
140   }
141   // If field is not set to be accessible, verify it can be accessed by the caller.
142   if (!f->IsAccessible() && !VerifyFieldAccess<false>(soa.Self(), f, o)) {
143     DCHECK(soa.Self()->IsExceptionPending());
144     return nullptr;
145   }
146   // We now don't expect suspension unless an exception is thrown.
147   // Get the field's value, boxing if necessary.
148   Primitive::Type field_type = f->GetTypeAsPrimitiveType();
149   JValue value;
150   if (!GetFieldValue<true>(o, f, field_type, &value)) {
151     DCHECK(soa.Self()->IsExceptionPending());
152     return nullptr;
153   }
154   return soa.AddLocalReference<jobject>(BoxPrimitive(field_type, value));
155 }
156 
157 template<Primitive::Type kPrimitiveType>
GetPrimitiveField(JNIEnv * env,jobject javaField,jobject javaObj)158 ALWAYS_INLINE inline static JValue GetPrimitiveField(JNIEnv* env, jobject javaField,
159                                                      jobject javaObj) {
160   ScopedFastNativeObjectAccess soa(env);
161   mirror::Field* f = soa.Decode<mirror::Field*>(javaField);
162   mirror::Object* o = nullptr;
163   if (!CheckReceiver(soa, javaObj, &f, &o)) {
164     DCHECK(soa.Self()->IsExceptionPending());
165     return JValue();
166   }
167 
168   // If field is not set to be accessible, verify it can be accessed by the caller.
169   if (!f->IsAccessible() && !VerifyFieldAccess<false>(soa.Self(), f, o)) {
170     DCHECK(soa.Self()->IsExceptionPending());
171     return JValue();
172   }
173 
174   // We now don't expect suspension unless an exception is thrown.
175   // Read the value.
176   Primitive::Type field_type = f->GetTypeAsPrimitiveType();
177   JValue field_value;
178   if (field_type == kPrimitiveType) {
179     // This if statement should get optimized out since we only pass in valid primitive types.
180     if (UNLIKELY(!GetFieldValue<false>(o, f, kPrimitiveType, &field_value))) {
181       DCHECK(soa.Self()->IsExceptionPending());
182       return JValue();
183     }
184     return field_value;
185   }
186   if (!GetFieldValue<false>(o, f, field_type, &field_value)) {
187     DCHECK(soa.Self()->IsExceptionPending());
188     return JValue();
189   }
190   // Widen it if necessary (and possible).
191   JValue wide_value;
192   if (!ConvertPrimitiveValue(false, field_type, kPrimitiveType, field_value,
193                              &wide_value)) {
194     DCHECK(soa.Self()->IsExceptionPending());
195     return JValue();
196   }
197   return wide_value;
198 }
199 
Field_getBoolean(JNIEnv * env,jobject javaField,jobject javaObj)200 static jboolean Field_getBoolean(JNIEnv* env, jobject javaField, jobject javaObj) {
201   return GetPrimitiveField<Primitive::kPrimBoolean>(env, javaField, javaObj).GetZ();
202 }
203 
Field_getByte(JNIEnv * env,jobject javaField,jobject javaObj)204 static jbyte Field_getByte(JNIEnv* env, jobject javaField, jobject javaObj) {
205   return GetPrimitiveField<Primitive::kPrimByte>(env, javaField, javaObj).GetB();
206 }
207 
Field_getChar(JNIEnv * env,jobject javaField,jobject javaObj)208 static jchar Field_getChar(JNIEnv* env, jobject javaField, jobject javaObj) {
209   return GetPrimitiveField<Primitive::kPrimChar>(env, javaField, javaObj).GetC();
210 }
211 
Field_getDouble(JNIEnv * env,jobject javaField,jobject javaObj)212 static jdouble Field_getDouble(JNIEnv* env, jobject javaField, jobject javaObj) {
213   return GetPrimitiveField<Primitive::kPrimDouble>(env, javaField, javaObj).GetD();
214 }
215 
Field_getFloat(JNIEnv * env,jobject javaField,jobject javaObj)216 static jfloat Field_getFloat(JNIEnv* env, jobject javaField, jobject javaObj) {
217   return GetPrimitiveField<Primitive::kPrimFloat>(env, javaField, javaObj).GetF();
218 }
219 
Field_getInt(JNIEnv * env,jobject javaField,jobject javaObj)220 static jint Field_getInt(JNIEnv* env, jobject javaField, jobject javaObj) {
221   return GetPrimitiveField<Primitive::kPrimInt>(env, javaField, javaObj).GetI();
222 }
223 
Field_getLong(JNIEnv * env,jobject javaField,jobject javaObj)224 static jlong Field_getLong(JNIEnv* env, jobject javaField, jobject javaObj) {
225   return GetPrimitiveField<Primitive::kPrimLong>(env, javaField, javaObj).GetJ();
226 }
227 
Field_getShort(JNIEnv * env,jobject javaField,jobject javaObj)228 static jshort Field_getShort(JNIEnv* env, jobject javaField, jobject javaObj) {
229   return GetPrimitiveField<Primitive::kPrimShort>(env, javaField, javaObj).GetS();
230 }
231 
SetFieldValue(mirror::Object * o,mirror::Field * f,Primitive::Type field_type,bool allow_references,const JValue & new_value)232 ALWAYS_INLINE inline static void SetFieldValue(mirror::Object* o, mirror::Field* f,
233                                                Primitive::Type field_type, bool allow_references,
234                                                const JValue& new_value)
235     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
236   DCHECK(f->GetDeclaringClass()->IsInitialized());
237   MemberOffset offset(f->GetOffset());
238   const bool is_volatile = f->IsVolatile();
239   switch (field_type) {
240   case Primitive::kPrimBoolean:
241     if (is_volatile) {
242       o->SetFieldBooleanVolatile<false>(offset, new_value.GetZ());
243     } else {
244       o->SetFieldBoolean<false>(offset, new_value.GetZ());
245     }
246     break;
247   case Primitive::kPrimByte:
248     if (is_volatile) {
249       o->SetFieldBooleanVolatile<false>(offset, new_value.GetB());
250     } else {
251       o->SetFieldBoolean<false>(offset, new_value.GetB());
252     }
253     break;
254   case Primitive::kPrimChar:
255     if (is_volatile) {
256       o->SetFieldCharVolatile<false>(offset, new_value.GetC());
257     } else {
258       o->SetFieldChar<false>(offset, new_value.GetC());
259     }
260     break;
261   case Primitive::kPrimInt:
262   case Primitive::kPrimFloat:
263     if (is_volatile) {
264       o->SetField32Volatile<false>(offset, new_value.GetI());
265     } else {
266       o->SetField32<false>(offset, new_value.GetI());
267     }
268     break;
269   case Primitive::kPrimLong:
270   case Primitive::kPrimDouble:
271     if (is_volatile) {
272       o->SetField64Volatile<false>(offset, new_value.GetJ());
273     } else {
274       o->SetField64<false>(offset, new_value.GetJ());
275     }
276     break;
277   case Primitive::kPrimShort:
278     if (is_volatile) {
279       o->SetFieldShortVolatile<false>(offset, new_value.GetS());
280     } else {
281       o->SetFieldShort<false>(offset, new_value.GetS());
282     }
283     break;
284   case Primitive::kPrimNot:
285     if (allow_references) {
286       if (is_volatile) {
287         o->SetFieldObjectVolatile<false>(offset, new_value.GetL());
288       } else {
289         o->SetFieldObject<false>(offset, new_value.GetL());
290       }
291       break;
292     }
293     // Else fall through to report an error.
294     FALLTHROUGH_INTENDED;
295   case Primitive::kPrimVoid:
296     // Never okay.
297     ThrowIllegalArgumentException(StringPrintf("Not a primitive field: %s",
298                                                PrettyField(f->GetArtField()).c_str()).c_str());
299     return;
300   }
301 }
302 
Field_set(JNIEnv * env,jobject javaField,jobject javaObj,jobject javaValue)303 static void Field_set(JNIEnv* env, jobject javaField, jobject javaObj, jobject javaValue) {
304   ScopedFastNativeObjectAccess soa(env);
305   mirror::Field* f = soa.Decode<mirror::Field*>(javaField);
306   // Check that the receiver is non-null and an instance of the field's declaring class.
307   mirror::Object* o = nullptr;
308   if (!CheckReceiver(soa, javaObj, &f, &o)) {
309     DCHECK(soa.Self()->IsExceptionPending());
310     return;
311   }
312   mirror::Class* field_type;
313   const char* field_type_desciptor = f->GetArtField()->GetTypeDescriptor();
314   Primitive::Type field_prim_type = Primitive::GetType(field_type_desciptor[0]);
315   if (field_prim_type == Primitive::kPrimNot) {
316     field_type = f->GetType();
317     DCHECK(field_type != nullptr);
318   } else {
319     field_type = Runtime::Current()->GetClassLinker()->FindPrimitiveClass(field_type_desciptor[0]);
320   }
321   // We now don't expect suspension unless an exception is thrown.
322   // Unbox the value, if necessary.
323   mirror::Object* boxed_value = soa.Decode<mirror::Object*>(javaValue);
324   JValue unboxed_value;
325   if (!UnboxPrimitiveForField(boxed_value, field_type, f->GetArtField(), &unboxed_value)) {
326     DCHECK(soa.Self()->IsExceptionPending());
327     return;
328   }
329   // If field is not set to be accessible, verify it can be accessed by the caller.
330   if (!f->IsAccessible() && !VerifyFieldAccess<true>(soa.Self(), f, o)) {
331     DCHECK(soa.Self()->IsExceptionPending());
332     return;
333   }
334   SetFieldValue(o, f, field_prim_type, true, unboxed_value);
335 }
336 
337 template<Primitive::Type kPrimitiveType>
SetPrimitiveField(JNIEnv * env,jobject javaField,jobject javaObj,const JValue & new_value)338 static void SetPrimitiveField(JNIEnv* env, jobject javaField, jobject javaObj,
339                               const JValue& new_value) {
340   ScopedFastNativeObjectAccess soa(env);
341   mirror::Field* f = soa.Decode<mirror::Field*>(javaField);
342   mirror::Object* o = nullptr;
343   if (!CheckReceiver(soa, javaObj, &f, &o)) {
344     return;
345   }
346   Primitive::Type field_type = f->GetTypeAsPrimitiveType();
347   if (UNLIKELY(field_type == Primitive::kPrimNot)) {
348     ThrowIllegalArgumentException(StringPrintf("Not a primitive field: %s",
349                                                PrettyField(f->GetArtField()).c_str()).c_str());
350     return;
351   }
352 
353   // Widen the value if necessary (and possible).
354   JValue wide_value;
355   if (!ConvertPrimitiveValue(false, kPrimitiveType, field_type, new_value, &wide_value)) {
356     DCHECK(soa.Self()->IsExceptionPending());
357     return;
358   }
359 
360   // If field is not set to be accessible, verify it can be accessed by the caller.
361   if (!f->IsAccessible() && !VerifyFieldAccess<true>(soa.Self(), f, o)) {
362     DCHECK(soa.Self()->IsExceptionPending());
363     return;
364   }
365 
366   // Write the value.
367   SetFieldValue(o, f, field_type, false, wide_value);
368 }
369 
Field_setBoolean(JNIEnv * env,jobject javaField,jobject javaObj,jboolean z)370 static void Field_setBoolean(JNIEnv* env, jobject javaField, jobject javaObj, jboolean z) {
371   JValue value;
372   value.SetZ(z);
373   SetPrimitiveField<Primitive::kPrimBoolean>(env, javaField, javaObj, value);
374 }
375 
Field_setByte(JNIEnv * env,jobject javaField,jobject javaObj,jbyte b)376 static void Field_setByte(JNIEnv* env, jobject javaField, jobject javaObj, jbyte b) {
377   JValue value;
378   value.SetB(b);
379   SetPrimitiveField<Primitive::kPrimByte>(env, javaField, javaObj, value);
380 }
381 
Field_setChar(JNIEnv * env,jobject javaField,jobject javaObj,jchar c)382 static void Field_setChar(JNIEnv* env, jobject javaField, jobject javaObj, jchar c) {
383   JValue value;
384   value.SetC(c);
385   SetPrimitiveField<Primitive::kPrimChar>(env, javaField, javaObj, value);
386 }
387 
Field_setDouble(JNIEnv * env,jobject javaField,jobject javaObj,jdouble d)388 static void Field_setDouble(JNIEnv* env, jobject javaField, jobject javaObj, jdouble d) {
389   JValue value;
390   value.SetD(d);
391   SetPrimitiveField<Primitive::kPrimDouble>(env, javaField, javaObj, value);
392 }
393 
Field_setFloat(JNIEnv * env,jobject javaField,jobject javaObj,jfloat f)394 static void Field_setFloat(JNIEnv* env, jobject javaField, jobject javaObj, jfloat f) {
395   JValue value;
396   value.SetF(f);
397   SetPrimitiveField<Primitive::kPrimFloat>(env, javaField, javaObj, value);
398 }
399 
Field_setInt(JNIEnv * env,jobject javaField,jobject javaObj,jint i)400 static void Field_setInt(JNIEnv* env, jobject javaField, jobject javaObj, jint i) {
401   JValue value;
402   value.SetI(i);
403   SetPrimitiveField<Primitive::kPrimInt>(env, javaField, javaObj, value);
404 }
405 
Field_setLong(JNIEnv * env,jobject javaField,jobject javaObj,jlong j)406 static void Field_setLong(JNIEnv* env, jobject javaField, jobject javaObj, jlong j) {
407   JValue value;
408   value.SetJ(j);
409   SetPrimitiveField<Primitive::kPrimLong>(env, javaField, javaObj, value);
410 }
411 
Field_setShort(JNIEnv * env,jobject javaField,jobject javaObj,jshort s)412 static void Field_setShort(JNIEnv* env, jobject javaField, jobject javaObj, jshort s) {
413   JValue value;
414   value.SetS(s);
415   SetPrimitiveField<Primitive::kPrimShort>(env, javaField, javaObj, value);
416 }
417 
418 static JNINativeMethod gMethods[] = {
419   NATIVE_METHOD(Field, get,        "!(Ljava/lang/Object;)Ljava/lang/Object;"),
420   NATIVE_METHOD(Field, getBoolean, "!(Ljava/lang/Object;)Z"),
421   NATIVE_METHOD(Field, getByte,    "!(Ljava/lang/Object;)B"),
422   NATIVE_METHOD(Field, getChar,    "!(Ljava/lang/Object;)C"),
423   NATIVE_METHOD(Field, getDouble,  "!(Ljava/lang/Object;)D"),
424   NATIVE_METHOD(Field, getFloat,   "!(Ljava/lang/Object;)F"),
425   NATIVE_METHOD(Field, getInt,     "!(Ljava/lang/Object;)I"),
426   NATIVE_METHOD(Field, getLong,    "!(Ljava/lang/Object;)J"),
427   NATIVE_METHOD(Field, getShort,   "!(Ljava/lang/Object;)S"),
428   NATIVE_METHOD(Field, set,        "!(Ljava/lang/Object;Ljava/lang/Object;)V"),
429   NATIVE_METHOD(Field, setBoolean, "!(Ljava/lang/Object;Z)V"),
430   NATIVE_METHOD(Field, setByte,    "!(Ljava/lang/Object;B)V"),
431   NATIVE_METHOD(Field, setChar,    "!(Ljava/lang/Object;C)V"),
432   NATIVE_METHOD(Field, setDouble,  "!(Ljava/lang/Object;D)V"),
433   NATIVE_METHOD(Field, setFloat,   "!(Ljava/lang/Object;F)V"),
434   NATIVE_METHOD(Field, setInt,     "!(Ljava/lang/Object;I)V"),
435   NATIVE_METHOD(Field, setLong,    "!(Ljava/lang/Object;J)V"),
436   NATIVE_METHOD(Field, setShort,   "!(Ljava/lang/Object;S)V"),
437 };
438 
register_java_lang_reflect_Field(JNIEnv * env)439 void register_java_lang_reflect_Field(JNIEnv* env) {
440   REGISTER_NATIVE_METHODS("java/lang/reflect/Field");
441 }
442 
443 }  // namespace art
444