Skip to content

Java字符串拼接时Next字段为nil导致的panic #3150

@LordofAvernus

Description

@LordofAvernus

版本信息(Version)

java-sql-extractor v1.0.0 commit 2b8c3c0894a191034cd98aa3f9d8d98412b23d5c
SQLE: 4.2507.x main

问题描述(Describe)

在解析包含字符串拼接表达式的Java代码时,当遇到 + null 或不完整的表达式(如 + 后面没有操作数)时,会导致 runtime error: invalid memory address or nil pointer dereference panic。

具体场景包括:

  1. Java代码中包含 String sql = "SELECT * FROM users" + null; 这样的表达式
  2. 不完整的字符串拼接表达式,如 String sql = "SELECT * FROM users" + ;
  3. 多行字符串拼接时,ANTLR解析器在某些边界条件下可能无法正确初始化 Next 字段

截图或日志(Log)

panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x1 addr=0x0 pc=0x...]

goroutine 1 [running]:
github.com/actiontech/java-sql-extractor/parser.getStrValueFromExpression(0x...)
    /path/to/parser/util.go:22

如何复现(To Reproduce)

  1. 创建包含以下Java代码的文件:
public class TestClass {
    public void testMethod() {
        String sql = "SELECT * FROM users" + null;
        executeQuery(sql);
    }
    
    private void executeQuery(String sql) {
        // JDBC调用
    }
}
  1. 调用 GetSqlFromJavaFile() 函数解析该文件
  2. 程序会panic并退出

问题原因

getStrValueFromExpressionGetSqlsFromVisitor 函数中,当处理带有 PLUS 符号的表达式时,代码没有检查 expr.Nextarg.Next 是否为 nil,就直接进行递归调用,导致空指针解引用。

根本原因是ANTLR解析器在处理某些语法结构时,Next 字段可能为 nil,特别是在以下情况:

  • 语法错误导致的不完整表达式
  • 复杂的动态SQL构建场景
  • 解析器边界条件处理

解决方案

在所有使用 expr.Nextarg.Next 进行递归调用的地方,添加空指针检查:

修复前:

if expr.Symbol == PLUS {
    nextStrs := getStrValueFromExpression(expr.Next)

修复后:

if expr.Symbol == PLUS && expr.Next != nil {
    nextStrs := getStrValueFromExpression(expr.Next)

修复位置:

  1. util.go:20 - getStrValueFromExpression 函数中的 identifier 处理
  2. util.go:38 - getStrValueFromExpression 函数中的 literal 处理
  3. util.go:83 - getValueFromCallExpr 函数中的 literal 处理
  4. util.go:151 - GetSqlsFromVisitor 函数中的 identifier 处理
  5. util.go:171 - GetSqlsFromVisitor 函数中的 literal 处理

变更影响面

受影响的模块或功能

  • 正面影响:提高了代码的健壮性,防止空指针解引用导致的panic
  • 用户使用流程:用户现在可以安全地解析包含不完整字符串拼接表达式的Java文件,不会导致程序崩溃
  • 后台工作流:SQLE等依赖此库的系统在处理复杂Java代码时更加稳定

外部引用的潜在问题或风险

  • 无风险:此修复是防御性编程,不会影响现有正常功能的运行
  • 向后兼容:修复保持了原有逻辑不变,当 Nextnil 时,跳过处理,不影响正常字符串拼接功能
  • 性能影响:添加的 nil 检查开销极小,对性能无显著影响

版本兼容性

  • 无破坏性变更:此修复是纯防御性修改,不会破坏现有API或功能
  • 向后兼容:所有现有的正常使用场景都会继续正常工作
  • 升级建议:建议所有使用此库的项目升级到修复版本

测试建议

  1. 单元测试:运行 go test -v 验证所有测试用例通过
  2. 边界测试:测试各种不完整的字符串拼接表达式
  3. 回归测试:确保正常的字符串拼接功能仍然工作正常
  4. 集成测试:在SQLE等依赖项目中测试Java文件解析功能
  5. 压力测试:使用 go test -bench=. 验证性能没有显著下降

测试命令:

cd parser
go test -v                    # 运行所有测试
go test -bench=BenchmarkPanicFix  # 性能测试

Metadata

Metadata

Assignees

Labels

bugSomething isn't working

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions