alibaba / druid

阿里云计算平台DataWorks(https://help.aliyun.com/document_detail/137663.html) 团队出品,为监控而生的数据库连接池
https://github.com/alibaba/druid/wiki
Apache License 2.0
27.91k stars 8.57k forks source link

mysql bug: like 条件 写为 "%"?"%" 时报错 #4437

Open 250846434 opened 3 years ago

250846434 commented 3 years ago

1.测试版本: 1.1.21/1.2,6均出现该问题 2.出错sql :select from demo where name like "%"?"%" 出错位置: ps = conn.prepareStatement(sql); 经测试 :MysqlDataSource 的 ps = conn.prepareStatement(sql); 无该问题. 3.异常信息: ```java.sql.SQLException: sql injection violation, dbType mysql, , druid-version 1.2.5, syntax error: syntax error, error in :'name like "%"?"%", pos 54, line 1, column 54, token ? : select from demo d where d.name like "%"?"%" 4:附录,在使用wallFilter时,其解析也会出错.类似于以下报错: sql injection violation, syntax error: syntax error, error in :'code like "%"?"%" ', expect QUES, actual QUES pos 232, line 9, column 43, token QUES```

报错位置存在于以下位置: com.alibaba.druid.sql.parser.ParserException: syntax error, error in :'code like "%"?"%" ', expect QUES, actual QUES pos 232, line 9, column 43, token QUES at com.alibaba.druid.sql.parser.SQLParser.printError(SQLParser.java:344) at com.alibaba.druid.sql.parser.SQLStatementParser.parseStatementList(SQLStatementParser.java:532) at com.alibaba.druid.sql.parser.SQLStatementParser.parseStatementList(SQLStatementParser.java:182) at com.alibaba.druid.wall.WallProvider.checkInternal(WallProvider.java:624) at com.alibaba.druid.wall.WallProvider.check(WallProvider.java:578)

250846434 commented 3 years ago

附 MysqlDataSource 测试文件

import com.alibaba.druid.util.JdbcUtils;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.mysql.cj.jdbc.MysqlDataSource;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;

import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.util.List;
import java.util.Map;

/**
 * @author lichen
 * @email 250846434@qq.com
 * @date 2021/9/1 14:08
 */
@Slf4j
public class ConnTest {
    private static DataSource ds;

    public static void main(String[] args) throws SQLException {
        ds = getDataSource();
        List<Map<String, Object>> a = executeQuery("select * from demo where name like \"%\"?\"%\"", "1");

    }

    //
    private static DataSource getDataSource() {
        MysqlDataSource ds = new MysqlDataSource();
        ds.setUrl("jdbc:mysql://127.0.0.1:3306/demo?allowMultiQueries=true&useUnicode=true&useSSL=false&serverTimezone=GMT%2B8&autoReconnect=true&characterEncoding=UTF-8&rewriteBatchedStatements=true");
        ds.setUser();
        ds.setPassword();
        return ds;
    }

    @SneakyThrows
    public static List<Map<String, Object>> executeQuery(String sql, Object... params) {
        List<Map<String, Object>> result = Lists.newArrayList();
        Connection conn = ds.getConnection();
        PreparedStatement ps = conn.prepareStatement(sql);
        for (int i = 0; i < params.length; i++) {
            ps.setObject(i + 1, params[i]);
        }
        ResultSet rs = ps.executeQuery();
        ResultSetMetaData metaData = rs.getMetaData(); //获得列的结果
        while (rs.next()) {
            Map<String, Object> map = Maps.newHashMap();
            for (int i = 0; i < metaData.getColumnCount(); i++) {
                String key = metaData.getColumnName(i + 1);
                Object value = rs.getObject(i + 1);
                map.put(key, value);
            }
            result.add(map);
        }
        JdbcUtils.close(rs);
        JdbcUtils.close(ps);
        JdbcUtils.close(conn);
        return result;
    }
}