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