-
Notifications
You must be signed in to change notification settings - Fork 0
/
access.cpp
93 lines (70 loc) · 2.96 KB
/
access.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
#include "std.h"
#include "rope.h"
static int isSameRuntimePackage(Class *classobj1, Class *classobj2) {
if(classobj1 != classobj2) {
ClassBlock *cb1 = CLASS_CB(classobj1);
ClassBlock *cb2 = CLASS_CB(classobj2);
/* The class loader must match */
if(cb1->class_loader != cb2->class_loader)
return FALSE;
else {
/* And the package name */
/* If either class is an array compare the element
name to get rid of leading array characters (the
class loaders are the same) */
if(IS_ARRAY(cb1))
cb1 = CLASS_CB(cb1->element_class);
if(IS_ARRAY(cb2))
cb2 = CLASS_CB(cb2->element_class);
if(cb1 != cb2) {
const char *ptr1 = cb1->name;
const char *ptr2 = cb2->name;
/* Names must match at least up to the last slash
in each. Note, we do not need to check for NULLs
because names _must_ be different (same loader,
but different class). */
while(*ptr1++ == *ptr2++);
for(ptr1--; *ptr1 && *ptr1 != '/'; ptr1++);
/* Didn't match to last slash in ptr1 */
if(*ptr1)
return FALSE;
for(ptr2--; *ptr2 && *ptr2 != '/'; ptr2++);
/* Didn't match to last slash in ptr2 */
if(*ptr2)
return FALSE;
}
}
}
return TRUE;
}
int checkClassAccess(Class *classobj1, Class *classobj2) {
ClassBlock *cb1 = CLASS_CB(classobj1);
/* We can access it if it is public */
if(cb1->access_flags & ACC_PUBLIC)
return TRUE;
/* Or if they're members of the same runtime package */
return isSameRuntimePackage(classobj1, classobj2);
}
static int checkMethodOrFieldAccess(int access_flags, Class *decl_class, Class *classobj) {
/* Public methods and fields are always accessible */
if(access_flags & ACC_PUBLIC)
return TRUE;
/* If the method or field is private, it must be declared in
the accessing class */
if(access_flags & ACC_PRIVATE)
return decl_class == classobj;
/* The method or field must be protected or package-private */
/* If it is protected it is accessible if it is declared in the
accessing class or in a super-class */
if((access_flags & ACC_PROTECTED) && isSubClassOf(decl_class, classobj))
return TRUE;
/* Lastly protected and package-private methods/fields are accessible
if they are in the same runtime package as the accessing class */
return isSameRuntimePackage(decl_class, classobj);
}
int checkMethodAccess(MethodBlock *mb, Class *classobj) {
return checkMethodOrFieldAccess(mb->access_flags, mb->classobj, classobj);
}
int checkFieldAccess(FieldBlock *fb, Class *classobj) {
return checkMethodOrFieldAccess(fb->access_flags, fb->classobj, classobj);
}