Tencent / APIJSON

🏆 实时 零代码、全功能、强安全 ORM 库 🚀 后端接口和文档零代码,前端(客户端) 定制返回 JSON 的数据和结构 🏆 Real-Time coding-free, powerful and secure ORM 🚀 providing APIs and Docs without coding by Backend, and the returned JSON of API can be customized by Frontend(Client) users
http://apijson.cn
Other
17.32k stars 2.16k forks source link

一些可能的空指针引用和正则表达式错误 #48

Open mmyjona opened 6 years ago

mmyjona commented 6 years ago

环境信息

问题描述

我们用我们的源伞Pinopint扫描器扫描出一些有趣的报告,可以参考看看是否有修复价值。

错误信息

APIJSON项目 - 2018年11月16日10-25-54批次 - 已标注缺陷html报告 - 2018年11月16日10-34-30.pdf

TommyLemon commented 6 years ago

感谢,大概看了下,部分问题已确认确实存在,后续将持续改进。

anonymoustoken commented 6 years ago

@mmyjona 您这个 是商业工具吗? 我在网上找了一下 怎么 没有找到呢?

TommyLemon commented 6 years ago

@anonymoustoken 同问,我也没找到哈哈

TommyLemon commented 6 years ago

总结这个报告: 总共 10617 行代码,16 个「可能」的 bug, 24 个改进建议, 平均每行代码 bug 率低至 0.15%,也就是 (1 - bugs/lines) 高达 99.85% 。 可见 APIJSON 代码非常严谨可靠。

anonymoustoken commented 6 years ago

下一个版本说明时候 发布 @TommyLemon

TommyLemon commented 6 years ago

@anonymoustoken APIJSON 3.1.5 已发布 https://github.com/TommyLemon/APIJSON/releases/tag/3.1.5

mmyjona commented 5 years ago

@mmyjona 您这个 是商业工具吗? 我在网上找了一下 怎么 没有找到呢?

https://www.sourcebrella.com/pinpoint/ 是商业工具哈。

TommyLemon commented 5 years ago

确实是误判为 bug 的报告用例 1

src/main/java/zuo/biao/apijson/server/AbstractSQLConfig.java: 897 (可信度: 65%) zuo.biao.apijson.server.AbstractSQLConfig.putWhere(String, Object, boolean)中 AbstractSQLConfig.combine 可能的空指针解引用

对应实际文件 https://github.com/APIJSON/APIJSON/blob/d8cfc9e6be87bd6116ecf8a125a52021f0154761/APIJSON-Java-Server/APIJSONLibrary/src/main/java/zuo/biao/apijson/server/AbstractSQLConfig.java 内方法

    @Override
    public AbstractSQLConfig putWhere(String key, Object value, boolean prior) {
        if (key != null) {
            if (where == null) {
                where = new LinkedHashMap<String, Object>();    
            }
            where.put(key, value);

            combine = getCombine();
            List<String> andList = combine == null ? null : combine.get("&");
            if (value == null) {
                andList.remove(key);
            }
            else if (andList == null || andList.contains(key) == false) {
                int i = 0;
                if (andList == null) {
                    andList = new ArrayList<>();
                }
                else if (prior && andList.isEmpty() == false) {
                    if (andList.contains(KEY_ID)) {
                        i ++;
                    }
                    if (andList.contains(KEY_ID_IN)) {
                        i ++;
                    }
                    if (andList.contains(KEY_USER_ID)) {
                        i ++;
                    }
                    if (andList.contains(KEY_USER_ID_IN)) {
                        i ++;
                    }
                }

                if (prior) {
                    andList.add(i, key); //userId的优先级不能比id高  0, key);
                } else {
                    andList.add(key); //AbstractSQLExecutor.onPutColumn里getSQL,要保证缓存的SQL和查询的SQL里 where 的 key:value 顺序一致
                }
            }
            combine.put("&", andList);
        }
        return this;
    }

实际上在前面已经用 combine = getCombine(); 做了处理,return 的值不会是 null

    @NotNull
    @Override
    public Map<String, List<String>> getCombine() {
        List<String> andList = combine == null ? null : combine.get("&");
        if (andList == null) {
            andList = where == null ? new ArrayList<String>() : new ArrayList<String>(where.keySet());
            if (combine == null) {
                combine = new HashMap<>();
            }
            combine.put("&", andList);
        }
        return combine;
    }



确实是误判为 bug 的报告用例 2

src/main/java/zuo/biao/apijson/JSONObject.java: 411 (可信度: 95%) 1 这里比较了 clazz 和 null,说明 clazz 可能为空指针 2 调用 clazz 的 java.lang.Class.getName 方法(使用可疑的空指针)

对应实际文件 https://github.com/APIJSON/APIJSON/blob/d8cfc9e6be87bd6116ecf8a125a52021f0154761/APIJSON-Java-Server/APIJSONLibrary/src/main/java/zuo/biao/apijson/JSONObject.java 内方法

    /**put and return value
     * @param key  StringUtil.isEmpty(key, true) ? key = value.getClass().getSimpleName();
     * @param value
     * @return value
     */
    @Override
    public Object put(String key, Object value) {
        if (value == null) {
            Log.e(TAG, "put  value == null >> return null;");
            return null;
        }
        if (StringUtil.isEmpty(key, true)) {
            Class<?> clazz = value.getClass();
            if (clazz == null || clazz.getAnnotation(MethodAccess.class) == null) {
                throw new IllegalArgumentException("puts  StringUtil.isNotEmpty(key, true) == false" +
                        " && clazz == null || clazz.getAnnotation(MethodAccess.class) == null" +
                        " \n key为空时仅支持 类型被@MethodAccess注解 的value !!!" +
                        " \n 如果一定要这么用,请对 " + clazz.getName() + " 注解!" +
                        " \n 如果是类似 key[]:{} 结构的请求,建议用 putsAll(...) !");
            }
            key = value.getClass().getSimpleName();
        }
        return super.put(key, value);
    }

406 行 Class<?> clazz = value.getClass(); Class 是对象声明后就有的,到执行这行前 value 已经判断过,又不会为 null, 所以实际上 clazz 不会为 null,407 行 if (clazz == null || clazz.getAnnotation(MethodAccess.class) == null) { 中 clazz == null 是一个冗余的判断,后面删掉了,实际上 411 行 clazz.getName() 永远不会因为 clazz == null 而导致 throw NullPointerException, 所以这也是一个误判为 bug 的用例。



确实是误判为 bug 的报告用例 3

严重 空指针解引用 src/main/java/zuo/biao/apijson/server/AbstractSQLConfig.java:844 (可信度 50%)

对应实际文件 https://github.com/Tencent/APIJSON/blob/d8cfc9e6be87bd6116ecf8a125a52021f0154761/APIJSON-Java-Server/APIJSONLibrary/src/main/java/zuo/biao/apijson/server/AbstractSQLConfig.java 内方法

    /**
     * @param key
     * @param exactMatch
     * @return
     */
    @JSONField(serialize = false)
    @Override
    public Object getWhere(String key, boolean exactMatch) {
        if (exactMatch) {
            return where == null ? null : where.get(key);
        }

        Set<String> set = key == null || where == null ? null : where.keySet();
        if (set != null) {
            synchronized (where) {
                if (where != null) {
                    int index;
                    for (String k : set) {
                        index = k.indexOf(key);
                        if (index >= 0 && StringUtil.isName(k.substring(index)) == false) {
                            return where.get(k);
                        }
                    }
                }
            }
        }
        return null;
    }

843 行已经用 set != null 来判断,而根据 842 行代码,where 为 null 时 set 必定为 null, 永远不会因为 where == null 而导致 throw NullPointerException, 所以这也是一个误判为 bug 的用例。

TommyLemon commented 5 years ago

确实是验证为 bug 的报告用例 1

缺陷位置: src/main/java/zuo/biao/apijson/server/AbstractParser.java: 1077 标注: 确认 时间: 2018-11-16 10:25:54 可信度: 98% 缺陷ID: 551386e3a9a5cb4d8d4f43e32105174e

确实是验证为 bug 的报告用例 2

image 已在新版通过 Log.DEBUG 判断,false 时不返回数据库对应的 SQLException 真实信息来解决 https://github.com/Tencent/APIJSON/blob/bbcf05e01c724894a5ba0dcddd49a14bbfeb5346/APIJSONORM/src/main/java/apijson/orm/AbstractParser.java image

TommyLemon commented 3 years ago

确实是验证为 bug 的报告用例 1 缺陷位置: src/main/java/zuo/biao/apijson/server/AbstractParser.java: 1077 标注: 确认 时间: 2018-11-16 10:25:54 可信度: 98% 缺陷ID: 551386e3a9a5cb4d8d4f43e32105174e

已解决 https://github.com/Tencent/APIJSON/commit/bbcf05e01c724894a5ba0dcddd49a14bbfeb5346

TommyLemon commented 3 years ago

这两个摘要有点奇怪 image

对应的代码行只是简单的一个 setter 方法给成员变量赋值,并没有加锁,这里也不需要加锁 https://github.com/Tencent/APIJSON/blob/d8cfc9e6be87bd6116ecf8a125a52021f0154761/APIJSON-Java-Server/APIJSONLibrary/src/main/java/zuo/biao/apijson/server/AbstractParser.java image

TommyLemon commented 3 years ago

这个看起来没必要改 image 因为写 default 也只是不做任何处理就直接 break https://github.com/Tencent/APIJSON/blob/d8cfc9e6be87bd6116ecf8a125a52021f0154761/APIJSON-Java-Server/APIJSONLibrary/src/main/java/zuo/biao/apijson/server/AbstractSQLConfig.java image

TommyLemon commented 3 years ago

image https://github.com/Tencent/APIJSON/blob/d8cfc9e6be87bd6116ecf8a125a52021f0154761/APIJSON-Java-Server/APIJSONLibrary/src/main/java/zuo/biao/apijson/JSONObject.java image

已去除多余的判空 https://github.com/Tencent/APIJSON/blob/bbcf05e01c724894a5ba0dcddd49a14bbfeb5346/APIJSONORM/src/main/java/apijson/JSONObject.java image

TommyLemon commented 3 years ago

image 这个没必要改,还是保留判空为好 https://github.com/Tencent/APIJSON/blob/d8cfc9e6be87bd6116ecf8a125a52021f0154761/APIJSON-Java-Server/APIJSONLibrary/src/main/java/zuo/biao/apijson/SQL.java image

TommyLemon commented 3 years ago

image https://github.com/Tencent/APIJSON/blob/d8cfc9e6be87bd6116ecf8a125a52021f0154761/APIJSON-Java-Server/APIJSONLibrary/src/main/java/zuo/biao/apijson/server/AbstractSQLConfig.java image 已优化 https://github.com/Tencent/APIJSON/blob/bbcf05e01c724894a5ba0dcddd49a14bbfeb5346/APIJSONORM/src/main/java/apijson/orm/AbstractSQLConfig.java image

TommyLemon commented 3 years ago

image https://github.com/Tencent/APIJSON/blob/d8cfc9e6be87bd6116ecf8a125a52021f0154761/APIJSON-Java-Server/APIJSONLibrary/src/main/java/zuo/biao/apijson/server/AbstractObjectParser.java image 已优化 https://github.com/Tencent/APIJSON/blob/master/APIJSONORM/src/main/java/apijson/orm/AbstractObjectParser.java image

TommyLemon commented 3 years ago

TODO 待优化

image https://github.com/Tencent/APIJSON/blob/d8cfc9e6be87bd6116ecf8a125a52021f0154761/APIJSON-Java-Server/APIJSONLibrary/src/main/java/zuo/biao/apijson/server/AbstractParser.java image https://github.com/Tencent/APIJSON/blob/master/APIJSONORM/src/main/java/apijson/orm/AbstractParser.java image



TODO 待优化

image https://github.com/Tencent/APIJSON/blob/d8cfc9e6be87bd6116ecf8a125a52021f0154761/APIJSON-Java-Server/APIJSONLibrary/src/main/java/zuo/biao/apijson/server/AbstractSQLConfig.java image https://github.com/Tencent/APIJSON/blob/master/APIJSONORM/src/main/java/apijson/orm/AbstractSQLConfig.java image

Rkyzzy commented 3 years ago

你好!请问这两个剩余的TODO修复了吗?我能尝试修复吗,谢谢!

TommyLemon commented 3 years ago

你好!请问这两个剩余的TODO修复了吗?我能尝试修复吗,谢谢!

还没有哦,可以的,非常感谢👍