javaspring-bootjunithsqldb

Upgrading HSQLDB from 2.7.0 to 2.7.1 breaks tests


I'm trying to upgrade HSQLDB from 2.7.0 to 2.7.1 but it breaks the tests. The test can be whatever, the error is always the same.

Test class:

@RunWith( SpringJUnit4ClassRunner.class )
@Transactional( transactionManager = "txManager" )
@Rollback
@ContextConfiguration( "classpath:applicationContext-test.xml" )
public class JdbcOrdersDaoImplTest {

@Autowired
private OrdersAdminDao hsqlOrdersDao;

@Test
public void setUp() {
}

applicationContext-test.xml:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:jdbc="http://www.springframework.org/schema/jdbc"
       xsi:schemaLocation="http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-4.3.xsd
        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.3.xsd">

    <import resource="classpath:applicationContext-Order-SQL.xml"/>
    <import resource="classpath:applicationContext-OrderEvent-SQL.xml"/>
    <import resource="classpath:applicationContext-Message-SQL.xml"/>

    <bean id="hsqlDataSource" class="org.apache.commons.dbcp2.BasicDataSource" destroy-method="close">
        <property name="driverClassName" value="org.hsqldb.jdbcDriver"/>
        <property name="url" value="jdbc:hsqldb:mem:test;sql.syntax_pgs=true;hsqldb.sqllog=3;hsqldb.applog=3"/>
        <property name="username" value="Foo"/>
        <property name="password" value=""/>
    </bean>

    <jdbc:initialize-database data-source="hsqlDataSource">
        <jdbc:script location="file:src/main/sql/archive/5.0/init_core_structure.sql"/>
        <jdbc:script location="classpath:hsqldb-create-sequence.sql"/>
        <jdbc:script location="classpath:create-date-function.sql"/>
    </jdbc:initialize-database>

    <bean id="hsqlOrdersDao" class="com.source.fix.gateway.data.impl.JdbcOrdersDaoImpl">
        <property name="dataSource" ref="hsqlDataSource"/>
    </bean>

    <bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="hsqlDataSource"/>
    </bean>


</beans>

Stack trace:

Failed to load ApplicationContext
java.lang.IllegalStateException: Failed to load ApplicationContext
(...)
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.springframework.jdbc.datasource.init.DataSourceInitializer#0': Invocation of init method failed; nested exception is org.springframework.jdbc.datasource.init.ScriptStatementFailedException: Failed to execute SQL script statement #1 of class path resource [create-date-function.sql]: CREATE FUNCTION DATE(v TIMESTAMP) RETURNS DATE LANGUAGE JAVA DETERMINISTIC NO SQL EXTERNAL NAME 'CLASSPATH:com.source.fix.PostgresDate.date'; nested exception is java.sql.SQLSyntaxErrorException: user lacks privilege or object not found: com.source.fix.PostgresDate
(...)
Caused by: org.springframework.jdbc.datasource.init.ScriptStatementFailedException: Failed to execute SQL script statement #1 of class path resource [create-date-function.sql]: CREATE FUNCTION DATE(v TIMESTAMP) RETURNS DATE LANGUAGE JAVA DETERMINISTIC NO SQL EXTERNAL NAME 'CLASSPATH:com.source.fix.PostgresDate.date'; nested exception is java.sql.SQLSyntaxErrorException: user lacks privilege or object not found: com.source.fix.PostgresDate
(...)
Caused by: java.sql.SQLSyntaxErrorException: user lacks privilege or object not found: com.source.fix.PostgresDate
(...)
Caused by: org.hsqldb.HsqlException: user lacks privilege or object not found: com.source.fix.PostgresDate

For context here's the changelist for 2.7.1: 20 Oct 2022 - version 2.7.1 -- version 2.7.1 jar requires JRE 11 or later - tested up to Java 17 -- version 2.7.1 alternative jar requires JRE 8 or later -- CVE-2022-41853 disallow calling java methods - setting the hsqldb.method_class_names is required for accessing java methods -- enhancements to RECURSIVE CTE's

and a description of CVE-2022-41853 from NIST: Those using java.sql.Statement or java.sql.PreparedStatement in hsqldb (HyperSQL DataBase) to process untrusted input may be vulnerable to a remote code execution attack. By default it is allowed to call any static method of any Java class in the classpath resulting in code execution. The issue can be prevented by updating to 2.7.1 or by setting the system property "hsqldb.method_class_names" to classes which are allowed to be called. For example, System.setProperty("hsqldb.method_class_names", "abc") or Java argument -Dhsqldb.method_class_names="abc" can be used. From version 2.7.1 all classes by default are not accessible except those in java.lang.Math and need to be manually enabled.

If I understand correctly (maybe I'm wrong), the problem lies in the fact that application context is not loaded automatically and I have to enable it manually. I'm not sure how to do that, though.


Solution

  • The Java command to run the application must include the class names for external methods. For example:

    java -Dhsqldb.method_class_names="com.source.fix.PostgresDate.date" ...
    

    You should be able to set this system property by adding it to the Spring framework configuring.