Hacktoberfest 2026:メンテナが10月に向けて印を付けた、オープンで初心者向けの issue。 Hacktoberfest の issue を見る

Java Extractor fails to resolve method calls when a package name is shadowed by a class name (Obfuscation scenario)(My Prediction)

オープン
#21,178 コメント 4 件 リアクション 0 件 担当者 0 名 GitHub で見る

まだ誰も着手していません。

評価

難易度
4/5
見積もり時間
3〜5日
初心者へのやさしさ
42/100
issue の種類
バグ
明瞭さ
おおむね明確
活発さ
停滞
技術スタック
java
領域
devtools

調査の方向性

合成ファイル src/com/demo/util/a.java と src/com/demo/util/a/a.java、および示されているデータベース作成コマンドを使ってケースを再現し、その後 CodeQL: View AST で com.demo.util.a.a.g(...) の呼び出しを調査します。解決結果を JDBCConnectionMethod クエリと比較します。完了条件は、呼び出しが未知のメソッドとしてマークされなくなり、そのメソッドターゲットとデータフローパスが正しく解決されることです。

索引モデルが issue の本文から書いたものです。

説明

Java question

Hello CodeQL team,

I encountered an issue where CodeQL fails to resolve a method call correctly when analyzing decompiled/obfuscated Java code. The issue arises when a package name conflicts with a class name in the parent package.

In this scenario, CodeQL seems to prioritize resolving the name as a class, causing the subsequent path to be invalid, resulting in an in the AST and a broken data flow.

Reproduction Code (Synthetic Example):

Since I cannot share the proprietary code, I have constructed a minimal reproduction case that mimics the structure:

Context: A class named a exists in package com.demo.util.

Context: A package named a also exists under com.demo.util.

Target: We are trying to call a static method g() in class com.demo.util.a.a.

src/
├── com/demo/util/a.java       <-- The class "a"
└── com/demo/util/a/a.java     <-- The package "a" containing class "a"

JavaCode:

// File: src/com/demo/util/a.java
package com.demo.util;
public class a {
    // This class is empty or does NOT have method g()
}

// File: src/com/demo/util/a/a.java
package com.demo.util.a;
public class a {
    public static String g(String input) {
        return input;
    }
}

My Vul Code is :

@org.springframework.web.bind.annotation.PostMapping({"/testConnection"})
    @org.jeecg.authz.annotation.RequiresPermissions({"drag:datasource:testConnection"})
    public org.jeecg.modules.drag.config.common.Result a(@org.springframework.web.bind.annotation.RequestBody org.jeecg.modules.drag.vo.DynamicDataSourceVo dynamicDataSourceVo) throws java.sql.SQLException {
        java.sql.Connection connection = null;
        java.lang.String string = dynamicDataSourceVo.toString();
        java.lang.Object objA = this.localCache.a(string);
        if (org.jeecg.modules.drag.util.h.d(objA)) {
            int iIntValue = org.jeecg.modules.drag.util.h.e(objA).intValue();
            if (iIntValue >= 3) {
                return org.jeecg.modules.drag.config.common.Result.error("数据源已连接错误3次以上,请检查配置信息!");
            }
            if (iIntValue == 0) {
                return org.jeecg.modules.drag.config.common.Result.OK("数据库连接成功", true);
            }
        } else {
            this.localCache.a(string, 0, org.jeecg.modules.jmreport.common.util.DateUtils.k);
        }
        try {
            try {
                try {
                    java.lang.Class.forName(dynamicDataSourceVo.getDbDriver());
                    java.sql.DriverManager.setLoginTimeout(60);
                    java.sql.Connection connection2 = java.sql.DriverManager.getConnection(org.jeecg.modules.drag.util.a.a.g(dynamicDataSourceVo.getDbUrl()), dynamicDataSourceVo.getDbUsername(), dynamicDataSourceVo.getDbPassword());
                    if (connection2 != null) {
                        org.jeecg.modules.drag.config.common.Result resultOK = org.jeecg.modules.drag.config.common.Result.OK("数据库连接成功", true);
                        if (connection2 != null) {
                            try {
                                if (!connection2.isClosed()) {
                                    connection2.close();
                                }
                            } catch (java.sql.SQLException e) {
                                a.error(e.toString(), e);
                            }
                        }
                        return resultOK;
                    }
                    this.localCache.a(string, 1);
                    org.jeecg.modules.drag.config.common.Result resultOK2 = org.jeecg.modules.drag.config.common.Result.OK("failed:unknown", true);
                    if (connection2 != null) {
                        try {
                            if (!connection2.isClosed()) {
                                connection2.close();
                            }
                        } catch (java.sql.SQLException e2) {
                            a.error(e2.toString(), e2);
                        }
                    }
                    return resultOK2;
                } catch (java.lang.Exception e3) {
                    a.error(e3.toString(), e3);
                    this.localCache.a(string, 1);
                    org.jeecg.modules.drag.config.common.Result resultError = org.jeecg.modules.drag.config.common.Result.error("failed:" + e3.getMessage());
                    if (0 != 0) {
                        try {
                            if (!connection.isClosed()) {
                                connection.close();
                            }
                        } catch (java.sql.SQLException e4) {
                            a.error(e4.toString(), e4);
                            return resultError;
                        }
                    }
                    return resultError;
                }
            } catch (java.lang.ClassNotFoundException e5) {
                a.error(e5.toString(), e5);
                this.localCache.a(string, 1);
                org.jeecg.modules.drag.config.common.Result resultError2 = org.jeecg.modules.drag.config.common.Result.error("failed:not exist");
                if (0 != 0) {
                    try {
                        if (!connection.isClosed()) {
                            connection.close();
                        }
                    } catch (java.sql.SQLException e6) {
                        a.error(e6.toString(), e6);
                        return resultError2;
                    }
                }
                return resultError2;
            }
        } catch (java.lang.Throwable th) {
            if (0 != 0) {
                try {
                    if (!connection.isClosed()) {
                        connection.close();
                    }
                } catch (java.sql.SQLException e7) {
                    a.error(e7.toString(), e7);
                    throw th;
                }
            }
            throw th;
        }
    }

and my QL code is:

/**
 * @name Find JDBC Connection Calls
 * @description Find all usages of DriverManager.getConnection
 * @kind problem
 * @problem.severity warning
 * @id java/find-jdbc-connection
 */

import java

// 1. 定义这个目标方法 (和你写的一样,稍微优化了精准度)
class JDBCConnectionMethod extends Method {
  JDBCConnectionMethod() {
    // DriverManager 是类名,不需要 getAnAncestor,直接用 hasQualifiedName 更快更准
    this.getDeclaringType().hasQualifiedName("java.sql", "DriverManager") and
    this.hasName("getConnection")
  }
}

// 2. 核心查询逻辑
from MethodCall call
where 
  // 限制这个调用必须是调用了我们上面定义的那个方法
  call.getMethod() instanceof JDBCConnectionMethod
select call, "发现 DriverManager.getConnection 的调用,第0个参数是: " + call.getArgument(0)

// /**
//  * @name Check for Ghost Class
//  * @kind problem
//  * @id java/check-ghost-class
//  */
// import java

// from Class c
// where c.hasQualifiedName("org.jeecg.modules.drag.util.a", "a")
// select c, "文件路径: " + c.getFile().getAbsolutePath(), "代码行数: " + c.getNumberOfLinesOfCode()

Observed Behavior (AST View):

When using "CodeQL: View AST" in VS Code on the line com.demo.util.a.a.g(...):

The method call is marked as .

The qualifier com.demo.util.a resolves to the Class com.demo.util.a instead of the Package.

Since Class com.demo.util.a does not contain method a or g, the resolution fails.

Expected Behavior:

CodeQL should correctly identify that com.demo.util.a.a refers to the class a inside package com.demo.util.a, even if a class named com.demo.util.a exists.

Build Environment:

Build Mode: codeql database create --command="autobuild -none" ... (Analyzing source code directly)

CodeQL CLI Version: [这里填你的版本,例如 2.23.8]

OS: [/ macOS Sonoma]

Impact: This causes severe data flow breakage in TaintTracking for obfuscated applications, as the source-to-sink path is interrupted at the method call.

thank you sir :) I await your reply

主要言語
CodeQL
スター
10.1k
フォーク
2.1k
平均マージ
2日 16時間
マージ済み PR(30日)
143

コントリビューションガイド

コントリビューションガイドを開く

はじめの一歩

  1. issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
  2. 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
  3. リポジトリをフォークし、ブランチを切って変更します。
  4. issue 番号を参照したプルリクエストを送ります。

github/codeql のほかの issue

github/codeql の issue をすべて見る

似ている issue

DevTools の issue をもっと見る

新しい issue をメールで受け取る

初心者向けの GitHub issue を短くまとめたダイジェスト。