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