2626
2727import java .io .IOException ;
2828import java .io .InputStream ;
29- import java .lang .reflect .Method ;
3029import java .net .URISyntaxException ;
3130import java .net .URL ;
3231import java .nio .file .FileSystem ;
3332import java .nio .file .FileSystems ;
3433import java .nio .file .Files ;
3534import java .nio .file .Path ;
3635import java .nio .file .Paths ;
37- import java .security .CodeSource ;
38- import java .security .ProtectionDomain ;
3936import java .util .HashSet ;
4037import java .util .Optional ;
4138import java .util .Properties ;
4239import java .util .Set ;
4340import java .util .stream .Stream ;
4441
42+ import com .oracle .graal .pointsto .meta .AnalysisMethod ;
43+ import com .oracle .graal .pointsto .meta .AnalysisType ;
4544import com .oracle .svm .core .feature .AutomaticallyRegisteredFeature ;
4645import com .oracle .svm .core .feature .InternalFeature ;
4746import com .oracle .svm .core .traits .BuiltinTraits .BuildtimeAccessOnly ;
4847import com .oracle .svm .core .traits .BuiltinTraits .NoLayeredCallbacks ;
4948import com .oracle .svm .core .traits .SingletonLayeredInstallationKind .Independent ;
5049import com .oracle .svm .core .traits .SingletonTraits ;
50+ import com .oracle .svm .hosted .FeatureImpl .AfterAnalysisAccessImpl ;
51+ import com .oracle .svm .util .JVMCIReflectionUtil ;
5152import com .oracle .svm .util .LogUtils ;
53+ import com .oracle .svm .util .ResolvedJavaPackage ;
54+
55+ import jdk .vm .ci .meta .ResolvedJavaType ;
5256
5357/**
5458 * A feature that detects whether a native image may be vulnerable to Log4Shell.
@@ -67,14 +71,8 @@ public class Log4ShellFeature implements InternalFeature {
6771 /* Different versions of log4j overload all these methods. */
6872 private static final Set <String > targetMethods = Set .of ("debug" , "error" , "fatal" , "info" , "log" , "trace" , "warn" );
6973
70- private static Optional <String > getPomVersion (Class <?> log4jClass ) {
71- ProtectionDomain pd = log4jClass .getProtectionDomain ();
72- CodeSource cs = pd .getCodeSource ();
73-
74- if (cs == null ) {
75- return Optional .empty ();
76- }
77- URL location = cs .getLocation ();
74+ private static Optional <String > getPomVersion (ResolvedJavaType log4jClass ) {
75+ URL location = JVMCIReflectionUtil .getOrigin (log4jClass );
7876 if (location == null ) {
7977 return Optional .empty ();
8078 }
@@ -148,20 +146,20 @@ private static boolean vulnerableLog4jTwo(String[] components) {
148146 return false ;
149147 }
150148
151- private AfterAnalysisAccess afterAnalysisAccess ;
149+ private AfterAnalysisAccessImpl afterAnalysisAccess ;
152150
153151 @ Override
154152 public void afterAnalysis (AfterAnalysisAccess access ) {
155- this .afterAnalysisAccess = access ;
153+ this .afterAnalysisAccess = ( AfterAnalysisAccessImpl ) access ;
156154 }
157155
158156 public String getUserWarning () {
159- Class <?> log4jClass = afterAnalysisAccess .findClassByName (log4jClassName );
157+ AnalysisType log4jClass = afterAnalysisAccess .findTypeByName (log4jClassName );
160158 if (log4jClass == null ) {
161159 return null ;
162160 }
163161
164- Package log4jPackage = log4jClass .getPackage ();
162+ ResolvedJavaPackage log4jPackage = JVMCIReflectionUtil .getPackage (log4jClass );
165163 String version = log4jPackage .getImplementationVersion ();
166164
167165 if (version == null ) {
@@ -186,21 +184,21 @@ public String getUserWarning() {
186184 Set <String > vulnerableMethods = new HashSet <>();
187185
188186 if (("1" .equals (components [0 ]) && vulnerableLog4jOne (components )) || ("2" .equals (components [0 ]) && vulnerableLog4jTwo (components ))) {
189- for (Method method : log4jClass .getMethods ( )) {
187+ for (AnalysisMethod method : log4jClass .getDeclaredMethods ( false )) {
190188 String methodName = method .getName ();
191- if (targetMethods .contains (methodName ) && (afterAnalysisAccess .isReachable (method ) || (afterAnalysisAccess .reachableMethodOverrides (method ).size () > 0 ))) {
192- vulnerableMethods .add (method .getDeclaringClass ().getName () + "." + method .getName ());
189+ if (targetMethods .contains (methodName ) && (afterAnalysisAccess .isReachable (method ) || (! afterAnalysisAccess .reachableMethodOverrides (method ).isEmpty () ))) {
190+ vulnerableMethods .add (method .getDeclaringClass ().toClassName () + "." + method .getName ());
193191 }
194192 }
195193 }
196194
197- if (vulnerableMethods .size () == 0 ) {
195+ if (vulnerableMethods .isEmpty () ) {
198196 return null ;
199197 }
200198
201199 StringBuilder renderedErrorMessage = new StringBuilder (String .format (log4jVulnerableErrorMessage ));
202200 for (String method : vulnerableMethods ) {
203- renderedErrorMessage .append (System .lineSeparator () + " - " + method );
201+ renderedErrorMessage .append (System .lineSeparator ()). append ( " - " ). append ( method );
204202 }
205203 return renderedErrorMessage .toString ();
206204 }
0 commit comments