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