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