@@ -129,6 +129,12 @@ public enum ActionKind {
129
129
Throw
130
130
}
131
131
132
+ public enum CollectMode {
133
+ Single ,
134
+ SinglePrivilegedMethodUsage ,
135
+ All
136
+ }
137
+
132
138
public static class Options {
133
139
@ Option (help = "Path to file where to store report of Truffle language privilege access." )//
134
140
public static final HostedOptionKey <String > TruffleTCKPermissionsReportFile = new HostedOptionKey <>(null );
@@ -151,6 +157,15 @@ public static class Options {
151
157
"Warn": Log a warning message to stderr.
152
158
"Throw" (default): Throw an exception and abort the native-image build process.""" , type = OptionType .Expert )//
153
159
public static final HostedOptionKey <ActionKind > TruffleTCKUnusedAllowListEntriesAction = new HostedOptionKey <>(ActionKind .Throw );
160
+
161
+ @ Option (help = """
162
+ Specifies how privileged method violations are reported.
163
+ Available options:
164
+ - Single: Reports only one violation in total.
165
+ - SinglePrivilegedMethodUsage: Reports one call path per privileged method used.
166
+ - All: Reports all call paths for all violations.
167
+ """ , type = OptionType .Expert )//
168
+ public static final HostedOptionKey <CollectMode > TruffleTCKCollectMode = new HostedOptionKey <>(CollectMode .SinglePrivilegedMethodUsage );
154
169
}
155
170
156
171
/**
@@ -346,6 +361,7 @@ public void afterAnalysis(AfterAnalysisAccess access) {
346
361
}
347
362
FeatureImpl .AfterAnalysisAccessImpl accessImpl = (FeatureImpl .AfterAnalysisAccessImpl ) access ;
348
363
DebugContext debugContext = accessImpl .getDebugContext ();
364
+ CollectMode collectMode = Options .TruffleTCKCollectMode .getValue ();
349
365
try (DebugContext .Scope s = debugContext .scope (ClassUtil .getUnqualifiedName (getClass ()))) {
350
366
BigBang bb = accessImpl .getBigBang ();
351
367
Map <BaseMethodNode , Set <BaseMethodNode >> cg = callGraph (bb , deniedMethods , debugContext , (SVMHost ) bb .getHostVM ());
@@ -356,8 +372,11 @@ public void afterAnalysis(AfterAnalysisAccess access) {
356
372
if (cg .containsKey (deniedMethod )) {
357
373
collectViolations (report , deniedMethod ,
358
374
maxStackDepth , Options .TruffleTCKPermissionsMaxErrors .getValue (),
359
- cg , contextFilters ,
375
+ cg , contextFilters , collectMode ,
360
376
new LinkedList <>(), new HashSet <>(), 1 , 0 );
377
+ if (!report .isEmpty () && collectMode == CollectMode .Single ) {
378
+ break ;
379
+ }
361
380
}
362
381
}
363
382
if (!report .isEmpty ()) {
@@ -569,6 +588,7 @@ private static boolean isBackTraceOverLanguageMethod(AnalysisMethodNode method,
569
588
* @param callGraph call graph obtained from
570
589
* {@link PermissionsFeature#callGraph(BigBang, Set, DebugContext, SVMHost)}
571
590
* @param contextFiltersParam filters removing known valid calls
591
+ * @param collectMode violation collect mode, see {@link Options#TruffleTCKCollectMode}
572
592
* @param currentPath current path from a privileged method in a call graph
573
593
* @param visited set of already visited methods, these methods are already part of an existing
574
594
* report or do not lead to language class
@@ -581,6 +601,7 @@ private int collectViolations(
581
601
int maxReports ,
582
602
Map <BaseMethodNode , Set <BaseMethodNode >> callGraph ,
583
603
Set <CallGraphFilter > contextFiltersParam ,
604
+ CollectMode collectMode ,
584
605
List <BaseMethodNode > currentPath ,
585
606
Set <BaseMethodNode > visited ,
586
607
int depth ,
@@ -599,7 +620,8 @@ private int collectViolations(
599
620
Set <BaseMethodNode > callers = callGraph .get (mNode );
600
621
if (depth > maxDepth ) {
601
622
if (!callers .isEmpty ()) {
602
- numReports = collectViolations (report , callers .iterator ().next (), maxDepth , maxReports , callGraph , contextFiltersParam , currentPath , visited , depth + 1 , numReports );
623
+ numReports = collectViolations (report , callers .iterator ().next (), maxDepth , maxReports , callGraph , contextFiltersParam , collectMode , currentPath , visited , depth + 1 ,
624
+ numReports );
603
625
}
604
626
} else if (!isSystemOrSafeClass (mNode )) {
605
627
List <BaseMethodNode > callPath = new ArrayList <>(currentPath );
@@ -608,7 +630,10 @@ private int collectViolations(
608
630
} else {
609
631
for (BaseMethodNode caller : callers ) {
610
632
if (contextFiltersParam .stream ().noneMatch ((f ) -> f .test (mNode , caller , currentPath ))) {
611
- numReports = collectViolations (report , caller , maxDepth , maxReports , callGraph , contextFiltersParam , currentPath , visited , depth + 1 , numReports );
633
+ numReports = collectViolations (report , caller , maxDepth , maxReports , callGraph , contextFiltersParam , collectMode , currentPath , visited , depth + 1 , numReports );
634
+ if (numReports > initialNumReports && collectMode != CollectMode .All ) {
635
+ break ;
636
+ }
612
637
}
613
638
}
614
639
}
0 commit comments