惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

L
LangChain Blog
Scott Helme
Scott Helme
D
Darknet – Hacking Tools, Hacker News & Cyber Security
Stack Overflow Blog
Stack Overflow Blog
Forbes - Security
Forbes - Security
T
The Blog of Author Tim Ferriss
Y
Y Combinator Blog
S
Schneier on Security
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
Cisco Talos Blog
Cisco Talos Blog
N
News | PayPal Newsroom
H
Hackread – Cybersecurity News, Data Breaches, AI and More
Project Zero
Project Zero
Cyberwarzone
Cyberwarzone
Vercel News
Vercel News
M
MIT News - Artificial intelligence
云风的 BLOG
云风的 BLOG
Google Online Security Blog
Google Online Security Blog
Simon Willison's Weblog
Simon Willison's Weblog
MongoDB | Blog
MongoDB | Blog
Martin Fowler
Martin Fowler
T
Tenable Blog
I
InfoQ
W
WeLiveSecurity
Google DeepMind News
Google DeepMind News
G
Google Developers Blog
D
DataBreaches.Net
博客园 - Franky
Know Your Adversary
Know Your Adversary
Spread Privacy
Spread Privacy
S
Security @ Cisco Blogs
Hacker News: Ask HN
Hacker News: Ask HN
J
Java Code Geeks
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
F
Full Disclosure
C
Cisco Blogs
Google DeepMind News
Google DeepMind News
P
Proofpoint News Feed
C
CXSECURITY Database RSS Feed - CXSecurity.com
The Cloudflare Blog
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
I
Intezer
The GitHub Blog
The GitHub Blog
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
F
Fortinet All Blogs
Jina AI
Jina AI
V
Visual Studio Blog
L
LINUX DO - 热门话题
WordPress大学
WordPress大学
aimingoo的专栏
aimingoo的专栏

SumSec's Blog

AI Agent 工程的必然演进:CLI、Skills、Harne… 从安全角度谈Java反射机制--前章 · SUMSEC 从安全角度谈Java反射机制--终章 · SUMSEC 逆向学习fastjson反序列化始 · SUMSEC 2020年研究回顾总结 · SUMSEC Abstract syntax tree classes for … Analyzing data flow in Java · SUM… Annotations in Java · SUMSEC Basic query for Java code · SUMSEC BypassSuper使用介绍说明 · SUMSEC CodeQL Create OpenJdk/Jdk8 Databa… CodeQL library for Java · SUMSEC Navigating the call graph · SUMSEC Types in Java · SUMSEC Working with source locations · S… Aliases · SUMSEC Expression · SUMSEC Formulas · SUMSEC Javadoc · SUMSEC Modules · SUMSEC Predicates · SUMSEC Queries · SUMSEC Type · SUMSEC Variables · SUMSEC 一道shiro反序列化题目引发的思考 · SUMSEC 修改ysoserial使其支持任意代码执行 · SUMSEC 自定义 ClassLoader 隔离运行不同版本jar包的方式 ·… 2020网鼎杯---Java文件上传wp · SUMSEC CNVD-2020-10487(CVE-2020-1938)tom… JDSRC安全课笔记 · SUMSEC Java反序列化链回显解决方案 · SUMSEC Skipped breakpoint because it hap… Windows Terminal 配置文件 · SUMSEC bypass 学习笔记之绕安全狗bypass safedog · … 一次意外的代码审计----JfinalCMS审计 · SUMSEC 一篇文章读懂Java代码审计之XXE · SUMSEC 从安全角度谈Java反射机制--序章 · SUMSEC 小楼昨夜又春风,你知ysoserial-Gadget-URLDNS… 春眠不觉晓,RCE知多少? · SUMSEC 漫谈Commons-Collections反序列化 · SUMSEC 漫谈Java反序列化 · SUMSEC 白头搔更短,SSTI惹人心! · SUMSEC 记一次面试题 · SUMSEC About Me 关于我 · SUMSEC Apache Flink任意Jar包上传导致远程代码执行 · SU… CVE-2019-1388 UAC提权复现 · SUMSEC CVE-2019-16097 || Harbor任意管理员注册漏洞… Python加密shellcode免杀 · SUMSEC Telegram机器人作为渗透测试框架 · SUMSEC VM虚拟机无法安装vmtools解决|本程序需要您将此虚拟机上安装… 谁能想到,电视遥控器竟成了 Vibe Coding 神器 · SU… 从手改 Skill 到自动进化:评测结果和执行轨迹如何让 Agen… 模型人人都能用,什么才是你能带走的?我的答案是一个可进化的SKIL… 模型人人都能用,什么才是你能带走的?我的答案是一个可进化的Skil… AI 时代 ShiroAttack2 5.x:修改了什么 · SU… 在 AGI 降临前,先给 AI 开一条”脑内弹幕”通道 · SUM… 一篇博文,三种时间:网页幻灯与 Remotion 动效的交付逻辑 … 🔍 别让大模型”想太多”:SKILL开发中的语义陷阱与抗幻觉设计 … 2022 年年度总结 · SUMSEC Java Swing To RCE 漏洞分析 · SUMSEC SpringBoot GatewayEL表达式漏洞分析 · SUM… Sensitive keys in codebases · SUM… 论如何优雅注入 Java 内存马 · SUMSEC SUMSEC 知识点 · SUMSEC VMWare Workspace ONE Access Auth … Spring Framework RCE CVE-2022-229… 相似度算法调研 · SUMSEC CVE-2022-33891 Apache Spark shell… 正则匹配配置不当 · SUMSEC Spring Data MongoDB SpEL CVE-2022… CodeQl Usage Tricks · SUMSEC Spring Boot RCE到内存马探索 · SUMSEC Shiro后渗透拓展面 · SUMSEC shiro反序列化漏洞攻击拓展面–修改key · SUMSEC GitHub Java CodeQL CTF · SUMSEC Hack-Tools 转化成Web · SUMSEC CodeQL与Shiro550碰撞 · SUMSEC CodeQL初见Shiro550 · SUMSEC CodeQL与AST之间联系 · SUMSEC Java加载动态链接库 · SUMSEC Log4j2 漏洞分析 · SUMSEC Interprocedural-Analysis 过程间分析 · … Data Analysis Foundation 数据分析基础 ·… Data Flow Analysis · SUMSEC Intermediate Representation 中间代表(… PII泄露–用CodeQL识别日志中的PII数据 · SUMSEC CodeQL workshop for Java: Unsafe … 前言 · SUMSEC 漏洞环境的搭建 · SUMSEC Fastjson回显 · SUMSEC Tomcat通用回显学习笔记 · SUMSEC 从Java反序列化漏洞题看CodeQL数据流 · SUMSEC 概述 · SUMSEC 记一次Log4j失败的Gadget挖掘记录 · SUMSEC Ysoserial改造记录 · SUMSEC JNDI注入 · SUMSEC shiro JRMP gadget · SUMSEC Fastjson MySQL gadget复现 · SUMSEC 2021年度总结 · SUMSEC
Overflow-prone comparisons in Jav…
2026-07-17 · via SumSec's Blog

Overflow-prone comparisons in Java


title: Overflow-prone comparisons in Java
photos: ‘https://acg.toubiec.cn/random?ssl=true&id=zOcwUy5cQWGbSmnx'
date: 2021-03-24 19:01:42
tags:
categories: codeql
password:
permalink:


Overflow-prone comparisons in Java

You can use CodeQL to check for comparisons in Java code where one side of the comparison is prone to overflow.

你可以使用CodeQL来检查Java代码中的比较,比较的一方容易溢出。

About this article

In this tutorial article you’ll write a query for finding comparisons between integers and long integers in loops that may lead to non-termination due to overflow.

在这篇教程文章中,你将写一个查询,用于查找循环中整数和长整数之间的比较,这些比较可能会由于溢出而导致非终止。

To begin, consider this code snippet:

首先,考虑这个代码片段:

void foo(long l) {
    for(int i=0; i<l; i++) {
        // do something
    }
}

If l is bigger than 231- 1 (the largest positive value of type int), then this loop will never terminate: i will start at zero, being incremented all the way up to 231- 1, which is still smaller than l. When it is incremented once more, an arithmetic overflow occurs, and i becomes -231, which also is smaller than l! Eventually, i will reach zero again, and the cycle repeats.

如果l大于231- 1(int类型的最大正值),那么这个循环将永远不会终止:i将从零开始,一直递增到231- 1,这仍然小于l.当它再次递增时,发生算术溢出,i变成-231,这也小于l!最终,i将再次达到零,并重复循环。最终,i将再次达到零,循环往复。

More about overflow

All primitive numeric types have a maximum value, beyond which they will wrap around to their lowest possible value (called an “overflow”). For int, this maximum value is 231- 1. Type long can accommodate larger values up to a maximum of 263- 1. In this example, this means that l can take on a value that is higher than the maximum for type int; i will never be able to reach this value, instead overflowing and returning to a low value.

所有的基元数字类型都有一个最大值,超过这个最大值,它们就会被包围到可能的最低值(称为 “溢出”),对于int来说,这个最大值是231- 1,long类型可以容纳更大的值,最大为263- 1。对于int来说,这个最大值是231- 1,而long类型可以容纳更大的值,最大值是263- 1。在这个例子中,这意味着l可以接受一个比int类型的最大值更高的值;i将永远无法达到这个值,而是溢出并返回一个低值。

We’re going to develop a query that finds code that looks like it might exhibit this kind of behavior. We’ll be using several of the standard library classes for representing statements and functions. For a full list, see “Abstract syntax tree classes for working with Java programs.”

我们将开发一个查询,找到看起来可能表现出这种行为的代码。我们将使用几个标准库类来表示语句和函数。有关完整的列表,请参见 “用于处理Java程序的抽象语法树类”。

Initial query

We’ll start by writing a query that finds less-than expressions (CodeQL class LTExpr) where the left operand is of type int and the right operand is of type long:

我们先写一个查找小于表达式的查询(CodeQL类LTExpr),其中左操作数的类型是int,右操作数的类型是long:

import java

from LTExpr expr
where expr.getLeftOperand().getType().hasName("int") and
    expr.getRightOperand().getType().hasName("long")
select expr

See this in the query console on LGTM.com. This query usually finds results on most projects.

➤ 在LGTM.com的查询控制台中可以看到。这个查询通常能在大多数项目上找到结果。

image-20210324163948437

image-20210324163958286

image-20210324164025185

Notice that we use the predicate getType (available on all subclasses of Expr) to determine the type of the operands. Types, in turn, define the hasName predicate, which allows us to identify the primitive types int and long. As it stands, this query finds all less-than expressions comparing int and long, but in fact we are only interested in comparisons that are part of a loop condition. Also, we want to filter out comparisons where either operand is constant, since these are less likely to be real bugs. The revised query looks like this:

请注意,我们使用谓词 getType(可用于 Expr 的所有子类)来确定操作数的类型。Types则定义了hasName谓词,它允许我们识别基元类型int和long。目前来看,这个查询可以找到所有比较int和long的小于表达式,但实际上我们只对作为循环条件一部分的比较感兴趣。另外,我们希望过滤掉操作数为常数的比较,因为这些比较不太可能是真正的错误。修改后的查询是这样的:

import java

from LTExpr expr
where expr.getLeftOperand().getType().hasName("int") and
    expr.getRightOperand().getType().hasName("long") and
    exists(LoopStmt l | l.getCondition().getAChildExpr*() = expr) and
    not expr.getAnOperand().isCompileTimeConstant()
select expr

See this in the query console on LGTM.com. Notice that fewer results are found.

➤ 在LGTM.com的查询控制台中看到。注意,发现的结果较少。

image-20210324164138891

image-20210324164211737

The class LoopStmt is a common superclass of all loops, including, in particular, for loops as in our example above. While different kinds of loops have different syntax, they all have a loop condition, which can be accessed through predicate getCondition. We use the reflexive transitive closure operator * applied to the getAChildExpr predicate to express the requirement that expr should be nested inside the loop condition. In particular, it can be the loop condition itself.

LoopStmt 类是所有循环的共同超类,特别是包括我们上面例子中的 for 循环。虽然不同种类的循环有不同的语法,但它们都有一个循环条件,可以通过谓词getCondition访问。我们使用应用于getAChildExpr谓词的反身转义闭合操作符*来表达expr应该嵌套在循环条件里面的要求。特别是,它可以是循环条件本身。

The final conjunct in the where clause takes advantage of the fact that predicates can return more than one value (they are really relations). In particular, getAnOperand may return either operand of expr, so expr.getAnOperand().isCompileTimeConstant() holds if at least one of the operands is constant. Negating this condition means that the query will only find expressions where neither of the operands is constant.

where子句中的最后一个连词利用了谓词可以返回多个值的事实(它们实际上是关系)。特别是,getAnOperand可以返回expr的任何一个操作数,所以expr.getAnOperand().isCompileTimeConstant()在操作数中至少有一个是常数时成立。否定这个条件意味着查询将只找到操作数都不是常数的表达式。

Generalizing the query

Of course, comparisons between int and long are not the only problematic case: any less-than comparison between a narrower and a wider type is potentially suspect, and less-than-or-equals, greater-than, and greater-than-or-equals comparisons are just as problematic as less-than comparisons.

当然,int和long之间的比较并不是唯一有问题的情况:窄类型和宽类型之间的任何小于等于的比较都有可能是可疑的,小于或等于、大于等于和大于等于的比较和小于等于的比较一样有问题。

In order to compare the ranges of types, we define a predicate that returns the width (in bits) of a given integral type:

为了比较类型的范围,我们定义了一个谓词来返回给定积分类型的宽度(以位为单位):

int width(PrimitiveType pt) {
    (pt.hasName("byte") and result=8) or
    (pt.hasName("short") and result=16) or
    (pt.hasName("char") and result=16) or
    (pt.hasName("int") and result=32) or
    (pt.hasName("long") and result=64)
}

We now want to generalize our query to apply to any comparison where the width of the type on the smaller end of the comparison is less than the width of the type on the greater end. Let’s call such a comparison overflow prone, and introduce an abstract class to model it:

我们现在想把我们的查询泛化为适用于任何比较,在比较中较小端类型的宽度小于较大端类型的宽度。让我们把这样的比较称为溢出式比较,并引入一个抽象类来模拟它。

abstract class OverflowProneComparison extends ComparisonExpr {
    Expr getLesserOperand() { none() }
    Expr getGreaterOperand() { none() }
}

There are two concrete child classes of this class: one for <= or < comparisons, and one for >= or > comparisons. In both cases, we implement the constructor in such a way that it only matches the expressions we want:

这个类有两个具体的子类:一个用于<=或<比较,另一个用于>=或>比较。在这两种情况下,我们以这样的方式实现构造函数,使它只匹配我们想要的表达式。

class LTOverflowProneComparison extends OverflowProneComparison {
    LTOverflowProneComparison() {
        (this instanceof LEExpr or this instanceof LTExpr) and
        width(this.getLeftOperand().getType()) < width(this.getRightOperand().getType())
    }
}

class GTOverflowProneComparison extends OverflowProneComparison {
    GTOverflowProneComparison() {
        (this instanceof GEExpr or this instanceof GTExpr) and
        width(this.getRightOperand().getType()) < width(this.getLeftOperand().getType())
    }
}

Now we rewrite our query to make use of these new classes:

现在我们重写我们的查询来使用这些新类:

import java

// Return the width (in bits) of a given integral type 
int width(PrimitiveType pt) {
  (pt.hasName("byte") and result=8) or
  (pt.hasName("short") and result=16) or
  (pt.hasName("char") and result=16) or
  (pt.hasName("int") and result=32) or
  (pt.hasName("long") and result=64)
}

// Find any comparison where the width of the type on the smaller end of 
// the comparison is less than the width of the type on the greater end
abstract class OverflowProneComparison extends ComparisonExpr {
  Expr getLesserOperand() { none() }
  Expr getGreaterOperand() { none() }
}

// Return `<=` and `<` comparisons
class LTOverflowProneComparison extends OverflowProneComparison {
  LTOverflowProneComparison() {
    (this instanceof LEExpr or this instanceof LTExpr) and
    width(this.getLeftOperand().getType()) < width(this.getRightOperand().getType())
  }
}

// Return `>=` and `>` comparisons
class GTOverflowProneComparison extends OverflowProneComparison {
  GTOverflowProneComparison() {
    (this instanceof GEExpr or this instanceof GTExpr) and
    width(this.getRightOperand().getType()) < width(this.getLeftOperand().getType())
  }
}

from OverflowProneComparison expr
where exists(LoopStmt l | l.getCondition().getAChildExpr*() = expr) and
      not expr.getAnOperand().isCompileTimeConstant()
select expr

See the full query in the query console on LGTM.com.

➤ 在LGTM.com的查询控制台中查看完整的查询。

image-20210324164413796