* src/vm/jit/x86_64/asmpart.S (asm_abstractmethoderror): Keep stack aligned.
[cacao.git] / src / vm / access.cpp
1 /* src/vm/access.c - checking access rights
2
3    Copyright (C) 1996-2005, 2006, 2007, 2008
4    CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
5
6    This file is part of CACAO.
7
8    This program is free software; you can redistribute it and/or
9    modify it under the terms of the GNU General Public License as
10    published by the Free Software Foundation; either version 2, or (at
11    your option) any later version.
12
13    This program is distributed in the hope that it will be useful, but
14    WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16    General Public License for more details.
17
18    You should have received a copy of the GNU General Public License
19    along with this program; if not, write to the Free Software
20    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21    02110-1301, USA.
22
23 */
24
25
26 #include "config.h"
27
28 #include <assert.h>
29 #include <string.h>
30
31 #include "vm/types.h"
32
33 #include "mm/memory.hpp"
34
35 #include "native/llni.h"
36
37 #include "vm/access.hpp"
38 #include "vm/jit/builtin.hpp"
39 #include "vm/class.hpp"
40 #include "vm/exceptions.hpp"
41 #include "vm/field.hpp"
42 #include "vm/globals.hpp"
43 #include "vm/method.hpp"
44
45 #include "vm/jit/stacktrace.hpp"
46
47 #if defined(__cplusplus)
48 extern "C" {
49 #endif
50
51 /* access_is_accessible_class **************************************************
52  
53    Check if a class is accessible from another class
54   
55    IN:
56        referer..........the class containing the reference
57        cls..............the result of resolving the reference
58   
59    RETURN VALUE:
60        true.............access permitted
61        false............access denied
62    
63    NOTE:
64        This function performs the checks listed in section 5.4.4.
65            "Access Control" of "The Java(TM) Virtual Machine Specification,
66            Second Edition".
67
68 *******************************************************************************/
69
70 bool access_is_accessible_class(classinfo *referer, classinfo *cls)
71 {
72         assert(referer);
73         assert(cls);
74
75         /* Public classes are always accessible. */
76
77         if (cls->flags & ACC_PUBLIC)
78                 return true;
79
80         /* A class in the same package is always accessible. */
81
82         if (SAME_PACKAGE(referer, cls))
83                 return true;
84
85 #if defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
86         /* Code for Sun's OpenJDK (see
87            hotspot/src/share/vm/runtime/reflection.cpp
88            (Reflection::verify_class_access)): Allow all accesses from
89            sun/reflect/MagicAccessorImpl subclasses to succeed
90            trivially. */
91
92         /* NOTE: This check must be before checks that could return
93            false. */
94
95         if (class_issubclass(referer, class_sun_reflect_MagicAccessorImpl))
96                 return true;
97 #endif
98
99         /* A non-public class in another package is not accessible. */
100
101         return false;
102 }
103
104
105 /* access_is_accessible_member *************************************************
106  
107    Check if a field or method is accessible from a given class
108   
109    IN:
110        referer..........the class containing the reference
111        declarer.........the class declaring the member
112        memberflags......the access flags of the member
113   
114    RETURN VALUE:
115        true.............access permitted
116        false............access denied
117
118    NOTE:
119        This function only performs the checks listed in section 5.4.4.
120            "Access Control" of "The Java(TM) Virtual Machine Specification,
121            Second Edition".
122
123            In particular a special condition for protected access with is
124            part of the verification process according to the spec is not
125            checked in this function.
126    
127 *******************************************************************************/
128
129 bool access_is_accessible_member(classinfo *referer, classinfo *declarer,
130                                                                  s4 memberflags)
131 {
132         assert(referer);
133         assert(declarer);
134
135         /* Public members are accessible. */
136
137         if (memberflags & ACC_PUBLIC)
138                 return true;
139
140 #if defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
141         /* Code for Sun's OpenJDK (see
142            hotspot/src/share/vm/runtime/reflection.cpp
143            (Reflection::verify_class_access)): Allow all accesses from
144            sun/reflect/MagicAccessorImpl subclasses to succeed
145            trivially. */
146
147         /* NOTE: This check must be before checks that could return
148            false. */
149
150         if (class_issubclass(referer, class_sun_reflect_MagicAccessorImpl))
151                 return true;
152 #endif
153
154         /* {declarer is not an interface} */
155
156         /* private members are only accessible by the class itself */
157
158         if (memberflags & ACC_PRIVATE)
159                 return (referer == declarer);
160
161         /* {the member is protected or package private} */
162
163         /* protected and package private members are accessible in the
164            same package */
165
166         if (SAME_PACKAGE(referer, declarer))
167                 return true;
168
169         /* package private members are not accessible outside the package */
170
171         if (!(memberflags & ACC_PROTECTED))
172                 return false;
173
174         /* {the member is protected and declarer is in another package} */
175
176         /* a necessary condition for access is that referer is a subclass
177            of declarer */
178
179         assert((referer->state & CLASS_LINKED) && (declarer->state & CLASS_LINKED));
180
181         if (class_isanysubclass(referer, declarer))
182                 return true;
183
184         return false;
185 }
186
187
188 /* access_check_field **********************************************************
189  
190    Check if the (indirect) caller has access rights to the specified
191    field.
192   
193    IN:
194        f................the field to check
195            callerdepth......number of callers to ignore
196                             For example if the stacktrace looks like this:
197
198                                    [0] java.lang.reflect.Method.invokeNative (Native Method)
199                                    [1] java.lang.reflect.Method.invoke
200                                    [2] <caller>
201
202                                         you must specify 2 so the access rights of <caller> 
203                                                 are checked.
204   
205    RETURN VALUE:
206        true.............access permitted
207        false............access denied, an exception has been thrown
208    
209 *******************************************************************************/
210
211 #if defined(ENABLE_JAVASE)
212 bool access_check_field(fieldinfo *f, int callerdepth)
213 {
214         classinfo *callerclass;
215         char      *msg;
216         int        msglen;
217         utf       *u;
218
219         /* If everything is public, there is nothing to check. */
220
221         if ((f->clazz->flags & ACC_PUBLIC) && (f->flags & ACC_PUBLIC))
222                 return true;
223
224         /* Get the caller's class. */
225
226         callerclass = stacktrace_get_caller_class(callerdepth);
227
228         if (callerclass == NULL)
229                 return false;
230
231         /* Check access rights. */
232
233         if (!access_is_accessible_member(callerclass, f->clazz, f->flags)) {
234                 msglen =
235                         utf_bytes(f->clazz->name) +
236                         strlen(".") +
237                         utf_bytes(f->name) +
238                         strlen(" not accessible from ") +
239                         utf_bytes(callerclass->name) +
240                         strlen("0");
241
242                 msg = MNEW(char, msglen);
243
244                 utf_copy_classname(msg, f->clazz->name);
245                 strcat(msg, ".");
246                 utf_cat_classname(msg, f->name);
247                 strcat(msg, " not accessible from ");
248                 utf_cat_classname(msg, callerclass->name);
249
250                 u = utf_new_char(msg);
251
252                 MFREE(msg, char, msglen);
253                 
254                 exceptions_throw_illegalaccessexception(u);
255
256                 return false;
257         }
258
259         /* access granted */
260
261         return true;
262 }
263 #endif
264
265
266 /* access_check_method *********************************************************
267  
268    Check if the (indirect) caller has access rights to the specified
269    method.
270   
271    IN:
272        m................the method to check
273            callerdepth......number of callers to ignore
274                             For example if the stacktrace looks like this:
275
276                                    [1] java.lang.reflect.Method.invokeNative (Native Method)
277                                    [1] java.lang.reflect.Method.invoke
278                                    [2] <caller>
279
280                                         you must specify 2 so the access rights of <caller> 
281                                                 are checked.
282   
283    RETURN VALUE:
284        true.............access permitted
285        false............access denied, an exception has been thrown
286    
287 *******************************************************************************/
288
289 #if defined(ENABLE_JAVASE)
290 bool access_check_method(methodinfo *m, int callerdepth)
291 {
292         classinfo *callerclass;
293         char      *msg;
294         int        msglen;
295         utf       *u;
296
297         /* If everything is public, there is nothing to check. */
298
299         if ((m->clazz->flags & ACC_PUBLIC) && (m->flags & ACC_PUBLIC))
300                 return true;
301
302         /* Get the caller's class. */
303
304         callerclass = stacktrace_get_caller_class(callerdepth);
305
306         if (callerclass == NULL)
307                 return false;
308
309         /* Check access rights. */
310
311         if (!access_is_accessible_member(callerclass, m->clazz, m->flags)) {
312                 msglen =
313                         utf_bytes(m->clazz->name) +
314                         strlen(".") +
315                         utf_bytes(m->name) +
316                         utf_bytes(m->descriptor) +
317                         strlen(" not accessible from ") +
318                         utf_bytes(callerclass->name) +
319                         strlen("0");
320
321                 msg = MNEW(char, msglen);
322
323                 utf_copy_classname(msg, m->clazz->name);
324                 strcat(msg, ".");
325                 utf_cat_classname(msg, m->name);
326                 utf_cat_classname(msg, m->descriptor);
327                 strcat(msg, " not accessible from ");
328                 utf_cat_classname(msg, callerclass->name);
329
330                 u = utf_new_char(msg);
331
332                 MFREE(msg, char, msglen);
333                 
334                 exceptions_throw_illegalaccessexception(u);
335
336                 return false;
337         }
338
339         /* access granted */
340
341         return true;
342 }
343
344 #endif
345
346 #if defined(__cplusplus)
347 }
348 #endif
349
350
351 /*
352  * These are local overrides for various environment variables in Emacs.
353  * Please do not remove this and leave it at the end of the file, where
354  * Emacs will automagically detect them.
355  * ---------------------------------------------------------------------
356  * Local variables:
357  * mode: c++
358  * indent-tabs-mode: t
359  * c-basic-offset: 4
360  * tab-width: 4
361  * End:
362  * vim:noexpandtab:sw=4:ts=4:
363  */
364