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