Skip to content

Commit

Permalink
Merge pull request #653 from dkimitsa/JEP181/nestbased_access_control
Browse files Browse the repository at this point in the history
Limited support for JEP181 Nestbased access control
  • Loading branch information
Tom-Ski authored Jan 3, 2023
2 parents a5b9351 + 3d8ba40 commit 3e16178
Show file tree
Hide file tree
Showing 4 changed files with 58 additions and 4 deletions.
53 changes: 51 additions & 2 deletions compiler/compiler/src/main/java/org/robovm/compiler/Access.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,14 @@
import org.robovm.compiler.clazz.Clazz;
import org.robovm.compiler.clazz.ClazzInfo;

import org.robovm.compiler.clazz.Clazzes;
import soot.ClassMember;
import soot.SootClass;
import soot.tagkit.NestHostTag;
import soot.tagkit.NestMembersTag;

import java.util.Arrays;
import java.util.List;

/**
* @author niklas
Expand Down Expand Up @@ -63,8 +69,8 @@ public static boolean checkClassAccessible(ClazzInfo target, ClazzInfo caller) {
return false;
}

public static boolean checkMemberAccessible(ClassMember member, Clazz caller, Clazz target,
SootClass runtimeClass) {
public static boolean checkMemberAccessible(Clazzes clazzes, ClassMember member, Clazz caller, Clazz target,
SootClass runtimeClass) {

if (caller == target || member.isPublic()) {
return true;
Expand Down Expand Up @@ -99,6 +105,11 @@ public static boolean checkMemberAccessible(ClassMember member, Clazz caller, Cl
}
}

// JEP 181: Nest-Based Access Control
if (areNestmates(clazzes, target.getSootClass(), caller.getSootClass())) {
return true;
}

// TODO: HACK! Allow lambda classes to access private methods of the class
// using them.
if ((caller.getSootClass().getModifiers() & 0x1000 /*ACC_SYNTHETIC*/) > 0
Expand All @@ -115,4 +126,42 @@ public static boolean isSubClassOrSame(SootClass superclass, SootClass clazz) {
}
return clazz == superclass;
}

/**
* JVM Access Control for Nestmates
*
* A field or method R is accessible to a class or interface D if and only if any of the following conditions are true:
* * ...
* * R is private and is declared in a different class or interface C, and C and D, are nestmates.
* For types C and D to be nestmates they must have the same nest host. A type C claims to be a member of
* the nest hosted by D, if it lists D in its NestHost attribute.
* The membership is validated if D also lists C in its NestMembers attribute.
* D is implicitly a member of the nest that it hosts.
*/
private static boolean areNestmates(Clazzes clazzes, SootClass target, SootClass caller) {
NestHostTag callerTag = (NestHostTag)caller.getTag("NestHostTag");
NestHostTag targetTag = (NestHostTag)target.getTag("NestHostTag");
// at least one to be set, otherwise these either same class or doesn't share host
if (callerTag == null && targetTag == null)
return false;
String callerHost = callerTag != null ? callerTag.getNestHostClass() : caller.getName().replace('.', '/');
String targetHost = targetTag != null ? targetTag.getNestHostClass() : target.getName().replace('.', '/');
if (!callerHost.equals(targetHost))
return false;
SootClass nestHost = clazzes.loadSootClass(callerHost);
if (nestHost == null)
return false; // should not happen

// now both mates should be in the list of NestMembers
NestMembersTag membersTag = (NestMembersTag) nestHost.getTag("NestMembersTag");
if (membersTag == null)
return false;
List<String> members = Arrays.asList(membersTag.getNestMembers());
if (callerTag != null && !members.contains(caller.getName().replace('.', '/')))
return false;
if (targetTag != null && !members.contains(target.getName().replace('.', '/')))
return false;

return true;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -448,7 +448,7 @@ private boolean checkMemberAccessible(Function f, Trampoline t, ClassMember memb
runtimeClass = c.getSootClass();
}

if (Access.checkMemberAccessible(member, caller, target, runtimeClass)) {
if (Access.checkMemberAccessible(config.getClazzes(), member, caller, target, runtimeClass)) {
return true;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,11 @@ public Clazz load(String internalName) {
return clazz;
}

public SootClass loadSootClass(String internalName) {
Clazz clazz = load(internalName);
return clazz != null ? clazz.getSootClass() : null;
}

public List<InputStream> loadResources(String resource) throws IOException {
List<InputStream> arr = new ArrayList<>();
for (Path p : getPaths()) {
Expand Down
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -285,7 +285,7 @@
<dependency>
<groupId>com.mobidevelop.robovm</groupId>
<artifactId>robovm-soot</artifactId>
<version>2.5.0-7</version>
<version>2.5.0-9</version>
</dependency>
</dependencies>
</dependencyManagement>
Expand Down

0 comments on commit 3e16178

Please sign in to comment.