* This is a rather huge commit, which changes the build order of
[cacao.git] / src / vm / access.c
1 /* src/vmcore/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 7246 2007-01-29 18:49:05Z twisti $
26
27 */
28
29
30 #include "config.h"
31
32 #include <assert.h>
33
34 #include "vm/types.h"
35
36 #include "vm/access.h"
37 #include "vm/builtin.h"
38 #include "vm/exceptions.h"
39
40 #include "vm/jit/stacktrace.h"
41
42 #include "vmcore/class.h"
43
44
45 /****************************************************************************/
46 /* ACCESS CHECKS                                                            */
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         if (cls->flags & ACC_PUBLIC)
75                 return true;
76
77         /* a class in the same package is always accessible */
78         if (SAME_PACKAGE(referer, cls))
79                 return true;
80
81         /* a non-public class in another package is not accessible */
82         return false;
83 }
84
85
86
87
88 /* access_is_accessible_member *************************************************
89  
90    Check if a field or method is accessible from a given class
91   
92    IN:
93        referer..........the class containing the reference
94        declarer.........the class declaring the member
95        memberflags......the access flags of the member
96   
97    RETURN VALUE:
98        true.............access permitted
99        false............access denied
100
101    NOTE:
102        This function only performs the checks listed in section 5.4.4.
103            "Access Control" of "The Java(TM) Virtual Machine Specification,
104            Second Edition".
105
106            In particular a special condition for protected access with is
107            part of the verification process according to the spec is not
108            checked in this function.
109    
110 *******************************************************************************/
111
112 bool access_is_accessible_member(classinfo *referer, classinfo *declarer,
113                                                                  s4 memberflags)
114 {
115         assert(referer);
116         assert(declarer);
117         
118         /* public members are accessible */
119         if (memberflags & ACC_PUBLIC)
120                 return true;
121
122         /* {declarer is not an interface} */
123
124         /* private members are only accessible by the class itself */
125         if (memberflags & ACC_PRIVATE)
126                 return (referer == declarer);
127
128         /* {the member is protected or package private} */
129
130         /* protected and package private members are accessible in the same package */
131         if (SAME_PACKAGE(referer,declarer))
132                 return true;
133
134         /* package private members are not accessible outside the package */
135         if (!(memberflags & ACC_PROTECTED))
136                 return false;
137
138         /* {the member is protected and declarer is in another package} */
139
140         /* a necessary condition for access is that referer is a subclass of declarer */
141         assert((referer->state & CLASS_LINKED) && (declarer->state & CLASS_LINKED));
142         if (builtin_isanysubclass(referer,declarer))
143                 return true;
144
145         return false;
146 }
147
148
149 /* access_check_caller *********************************************************
150  
151    Check if the (indirect) caller has access rights to a member.
152   
153    IN:
154        declarer.........the class declaring the member
155        memberflags......the access flags of the member
156            calldepth........number of callers to ignore
157                             For example if the stacktrace looks like this:
158
159                                            java.lang.reflect.Method.invokeNative (Native Method)
160                                    [0] java.lang.reflect.Method.invoke (Method.java:329)
161                                    [1] <caller>
162
163                                         you must specify 1 so the access rights of <caller> 
164                                                 are checked.
165   
166    RETURN VALUE:
167        true.............access permitted
168        false............access denied, an exception has been thrown
169    
170 *******************************************************************************/
171
172 bool access_check_caller(classinfo *declarer, s4 memberflags, s4 calldepth)
173 {
174         java_objectarray *oa;
175         classinfo        *callerclass;
176
177         /* if everything is public, there is nothing to check */
178
179         if ((declarer->flags & ACC_PUBLIC) && (memberflags & ACC_PUBLIC))
180                 return true;
181
182         /* get the caller's class */
183
184         oa = stacktrace_getClassContext();
185
186         if (oa == NULL)
187                 return false;
188
189         assert(calldepth >= 0 && calldepth < oa->header.size);
190
191         callerclass = (classinfo *) oa->data[calldepth];
192
193         /* check access rights */
194
195         if (!access_is_accessible_class(callerclass, declarer)
196                 || !access_is_accessible_member(callerclass, declarer, memberflags))
197         {
198                 exceptions_throw_illegalaccessexception(callerclass);
199                 return false;
200         }
201
202         /* access granted */
203
204         return true;
205 }
206
207
208 /*
209  * These are local overrides for various environment variables in Emacs.
210  * Please do not remove this and leave it at the end of the file, where
211  * Emacs will automagically detect them.
212  * ---------------------------------------------------------------------
213  * Local variables:
214  * mode: c
215  * indent-tabs-mode: t
216  * c-basic-offset: 4
217  * tab-width: 4
218  * End:
219  * vim:noexpandtab:sw=4:ts=4:
220  */
221