@@ -129,6 +129,25 @@ public enum ActionKind {
129
129
Throw
130
130
}
131
131
132
+ /**
133
+ * Specifies how privileged method violations are reported. See
134
+ * {@link Options#TruffleTCKCollectMode}.
135
+ */
136
+ public enum CollectMode {
137
+ /**
138
+ * Reports only one violation in total.
139
+ */
140
+ Single ,
141
+ /**
142
+ * Reports one call path per privileged method used.
143
+ */
144
+ SinglePrivilegedMethodUsage ,
145
+ /**
146
+ * Reports all call paths for all violations.
147
+ */
148
+ All
149
+ }
150
+
132
151
public static class Options {
133
152
@ Option (help = "Path to file where to store report of Truffle language privilege access." )//
134
153
public static final HostedOptionKey <String > TruffleTCKPermissionsReportFile = new HostedOptionKey <>(null );
@@ -151,6 +170,15 @@ public static class Options {
151
170
"Warn": Log a warning message to stderr.
152
171
"Throw" (default): Throw an exception and abort the native-image build process.""" , type = OptionType .Expert )//
153
172
public static final HostedOptionKey <ActionKind > TruffleTCKUnusedAllowListEntriesAction = new HostedOptionKey <>(ActionKind .Throw );
173
+
174
+ @ Option (help = """
175
+ Specifies how privileged method violations are reported.
176
+ Available options:
177
+ - Single: Reports only one violation in total.
178
+ - SinglePrivilegedMethodUsage: Reports one call path per privileged method used.
179
+ - All: Reports all call paths for all violations.
180
+ """ , type = OptionType .Expert )//
181
+ public static final HostedOptionKey <CollectMode > TruffleTCKCollectMode = new HostedOptionKey <>(CollectMode .SinglePrivilegedMethodUsage );
154
182
}
155
183
156
184
/**
@@ -346,6 +374,7 @@ public void afterAnalysis(AfterAnalysisAccess access) {
346
374
}
347
375
FeatureImpl .AfterAnalysisAccessImpl accessImpl = (FeatureImpl .AfterAnalysisAccessImpl ) access ;
348
376
DebugContext debugContext = accessImpl .getDebugContext ();
377
+ CollectMode collectMode = Options .TruffleTCKCollectMode .getValue ();
349
378
try (DebugContext .Scope s = debugContext .scope (ClassUtil .getUnqualifiedName (getClass ()))) {
350
379
BigBang bb = accessImpl .getBigBang ();
351
380
Map <BaseMethodNode , Set <BaseMethodNode >> cg = callGraph (bb , deniedMethods , debugContext , (SVMHost ) bb .getHostVM ());
@@ -356,8 +385,11 @@ public void afterAnalysis(AfterAnalysisAccess access) {
356
385
if (cg .containsKey (deniedMethod )) {
357
386
collectViolations (report , deniedMethod ,
358
387
maxStackDepth , Options .TruffleTCKPermissionsMaxErrors .getValue (),
359
- cg , contextFilters ,
388
+ cg , contextFilters , collectMode ,
360
389
new LinkedList <>(), new HashSet <>(), 1 , 0 );
390
+ if (!report .isEmpty () && collectMode == CollectMode .Single ) {
391
+ break ;
392
+ }
361
393
}
362
394
}
363
395
if (!report .isEmpty ()) {
@@ -367,7 +399,14 @@ public void afterAnalysis(AfterAnalysisAccess access) {
367
399
(pw ) -> {
368
400
StringBuilder builder = new StringBuilder ();
369
401
for (List <BaseMethodNode > callPath : report ) {
402
+ boolean privilegedMethod = true ;
370
403
for (BaseMethodNode call : callPath ) {
404
+ if (privilegedMethod ) {
405
+ builder .append ("Illegal call to privileged method " );
406
+ privilegedMethod = false ;
407
+ } else {
408
+ builder .append (" at " );
409
+ }
371
410
builder .append (call .asStackTraceElement ()).append (System .lineSeparator ());
372
411
}
373
412
builder .append (System .lineSeparator ());
@@ -569,6 +608,7 @@ private static boolean isBackTraceOverLanguageMethod(AnalysisMethodNode method,
569
608
* @param callGraph call graph obtained from
570
609
* {@link PermissionsFeature#callGraph(BigBang, Set, DebugContext, SVMHost)}
571
610
* @param contextFiltersParam filters removing known valid calls
611
+ * @param collectMode violation collect mode, see {@link Options#TruffleTCKCollectMode}
572
612
* @param currentPath current path from a privileged method in a call graph
573
613
* @param visited set of already visited methods, these methods are already part of an existing
574
614
* report or do not lead to language class
@@ -581,6 +621,7 @@ private int collectViolations(
581
621
int maxReports ,
582
622
Map <BaseMethodNode , Set <BaseMethodNode >> callGraph ,
583
623
Set <CallGraphFilter > contextFiltersParam ,
624
+ CollectMode collectMode ,
584
625
List <BaseMethodNode > currentPath ,
585
626
Set <BaseMethodNode > visited ,
586
627
int depth ,
@@ -599,7 +640,8 @@ private int collectViolations(
599
640
Set <BaseMethodNode > callers = callGraph .get (mNode );
600
641
if (depth > maxDepth ) {
601
642
if (!callers .isEmpty ()) {
602
- numReports = collectViolations (report , callers .iterator ().next (), maxDepth , maxReports , callGraph , contextFiltersParam , currentPath , visited , depth + 1 , numReports );
643
+ numReports = collectViolations (report , callers .iterator ().next (), maxDepth , maxReports , callGraph , contextFiltersParam , collectMode , currentPath , visited , depth + 1 ,
644
+ numReports );
603
645
}
604
646
} else if (!isSystemOrSafeClass (mNode )) {
605
647
List <BaseMethodNode > callPath = new ArrayList <>(currentPath );
@@ -608,7 +650,10 @@ private int collectViolations(
608
650
} else {
609
651
for (BaseMethodNode caller : callers ) {
610
652
if (contextFiltersParam .stream ().noneMatch ((f ) -> f .test (mNode , caller , currentPath ))) {
611
- numReports = collectViolations (report , caller , maxDepth , maxReports , callGraph , contextFiltersParam , currentPath , visited , depth + 1 , numReports );
653
+ numReports = collectViolations (report , caller , maxDepth , maxReports , callGraph , contextFiltersParam , collectMode , currentPath , visited , depth + 1 , numReports );
654
+ if (numReports > initialNumReports && collectMode != CollectMode .All ) {
655
+ break ;
656
+ }
612
657
}
613
658
}
614
659
}
0 commit comments