Java: add a test exercising Spring component liveness detection

The existing Spring stubs are expanded sufficiently to support the needed annotations and a few referenced classes and exceptions.
This commit is contained in:
Chris Smowton
2024-08-16 16:36:08 +01:00
parent e3b9b0a9bd
commit 9c0bdbb20a
42 changed files with 1557 additions and 1 deletions

View File

@@ -0,0 +1,6 @@
| com.semmle.a |
| com.semmle.b |
| com.semmle.c |
| com.semmle.d |
| com.semmle.e |
| com.semmle.h |

View File

@@ -0,0 +1,6 @@
import java
import semmle.code.java.frameworks.spring.Spring
import SpringProfiles
from SpringBasePackage basePackage
select basePackage

View File

@@ -0,0 +1,7 @@
| com/semmle/e/DeadProfileComponent.java:8:14:8:33 | DeadProfileComponent | dead |
| com/semmle/e/LiveConfiguration.java:16:14:16:30 | LiveConfiguration | live |
| com/semmle/e/LiveProfileComponent.java:8:14:8:33 | LiveProfileComponent | live |
| com/semmle/e/LiveRestController.java:12:14:12:31 | LiveRestController | live |
| com/semmle/f/DeadConfiguration.java:9:14:9:30 | DeadConfiguration | dead |
| com/semmle/g/ProfileComponent.java:6:14:6:29 | ProfileComponent | dead |
| com/semmle/h/WebXMLLiveConfiguration.java:11:14:11:36 | WebXMLLiveConfiguration | live |

View File

@@ -0,0 +1,7 @@
import java
import semmle.code.java.frameworks.spring.Spring
import SpringProfiles
from SpringComponent springComponent, string isLive
where if springComponent.isLive() then isLive = "live" else isLive = "dead"
select springComponent, isLive

View File

@@ -0,0 +1,4 @@
| !annotationProfile | annotationProfile | inactive |
| annotationProfile | annotationProfile | active |
| sometimesEnabledProfile | sometimesEnabledProfile | active |
| xmlConfigurationProfile | xmlConfigurationProfile | inactive |

View File

@@ -0,0 +1,7 @@
import java
import semmle.code.java.frameworks.spring.Spring
import SpringProfiles
from SpringProfileExpr springProfileExpr, string active
where if springProfileExpr.isActive() then active = "active" else active = "inactive"
select springProfileExpr, springProfileExpr.getProfile(), active

View File

@@ -0,0 +1,20 @@
import java
import semmle.code.java.frameworks.spring.Spring
/**
* Mark the XML configuration profile as never enabled. This should allow us to deduce that the
* com.semmle.g.ProfileComponent is dead, because com.semmle.g is only a base package in the
* profile-config.xml file, which is only enabled if xmlConfigurationProfile is enabled.
*/
class XMLConfigurationProfile extends NeverEnabledSpringProfile {
XMLConfigurationProfile() { this = "xmlConfigurationProfile" }
}
/**
* Mark the annotation profile as always enabled. This should allow us to deduce that the
* com.semmle.e.DeadProfileComponent is dead, because the profile is "!annotationProfile", and that
* com.semmle.e.LiveProfileComponent is live, because the profile is "annotationProfile".
*/
class AnnotationProfile extends AlwaysEnabledSpringProfile {
AnnotationProfile() { this = "annotationProfile" }
}

View File

@@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
<!-- Java-based annotation-driven Spring container definition -->
<context-param>
<param-name>contextClass</param-name>
<param-value>org.springframework.web.context.support.AnnotationConfigWebApplicationContext</param-value>
</context-param>
<!-- Location of Java @Configuration classes that configure the components that makeup this application -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>com.semmle.h</param-value>
</context-param>
</web-app>

View File

@@ -0,0 +1,3 @@
package com.semmle.d;
public interface DMarkerClass {}

View File

@@ -0,0 +1,8 @@
package com.semmle.e;
import org.springframework.context.annotation.Profile;
import org.springframework.stereotype.Component;
@Component
@Profile({"!annotationProfile"})
public class DeadProfileComponent {}

View File

@@ -0,0 +1,16 @@
package com.semmle.e;
import com.semmle.d.DMarkerClass;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
/**
* This configuration is live because the config.xml file contains a component-scan element that
* includes com.semmle.e as a base package.
*/
@Configuration
@ComponentScan(
value = "com.semmle.a",
basePackages = {"com.semmle.b", "com.semmle.c"},
basePackageClasses = {DMarkerClass.class})
public class LiveConfiguration {}

View File

@@ -0,0 +1,8 @@
package com.semmle.e;
import org.springframework.context.annotation.Profile;
import org.springframework.stereotype.Component;
@Component
@Profile({"annotationProfile"})
public class LiveProfileComponent {}

View File

@@ -0,0 +1,18 @@
package com.semmle.e;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* Live because it is in a live package, and has a {@code RestController} annotation which is
* annotated with {@code @Controller} which is annotated with {@code @Component}, making it a
* component.
*/
@RestController
public class LiveRestController {
@RequestMapping(value = {"/"})
public String testMethod() {
return "result";
}
}

View File

@@ -0,0 +1,9 @@
package com.semmle.f;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
/** This is a dead configuration class, because this class is not in a registered base package. */
@Configuration
@ComponentScan("com.semmle.f")
public class DeadConfiguration {}

View File

@@ -0,0 +1,6 @@
package com.semmle.g;
import org.springframework.stereotype.Component;
@Component
public class ProfileComponent {}

View File

@@ -0,0 +1,11 @@
package com.semmle.h;
import org.springframework.context.annotation.Configuration;
/**
* This configuration is live because the web.xml file specifies
* AnnotationConfigWebApplicationContext as the {@code contextClass}, and has a
* contextConfigLocation value that includes this package (com.semmle.h).
*/
@Configuration
public class WebXMLLiveConfiguration {}

View File

@@ -0,0 +1,12 @@
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.2.xsd"
profile="sometimesEnabledProfile">
<context:component-scan base-package="com.semmle.e" />
</beans>

View File

@@ -0,0 +1,2 @@
//semmle-extractor-options: --javac-args -cp
//semmle-extractor-options: ${testdir}/../../../../stubs/springframework-5.3.8/

View File

@@ -0,0 +1,12 @@
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.2.xsd"
profile="xmlConfigurationProfile">
<context:component-scan base-package="com.semmle.g" />
</beans>