You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

ASP.NET Core应用整数溢出问询:分页乘法是否存在溢出风险

ASP.NET Core分页代码中的整数溢出风险分析

核心结论

会引发整数溢出漏洞,你代码里intSkip * intTake的乘法操作确实存在安全风险,以下是具体分析和修复方案:

风险原因

.NET中的int是32位有符号整数,取值范围为-2147483648到2147483647。当查询字符串传入的pageNo和itemsPerPage都是较大的正整数时,两者的乘积很容易超出int的最大值,触发整数溢出:

  • 比如pageNo=50000、itemsPerPage=50000,乘积为2500000000,已经超过int的最大值;
  • .NET默认不会对有符号整数溢出抛出异常,溢出后的结果会变成错误的负数或小正数;
  • 错误的skip值传给EF Core的Skip方法后,要么抛出参数非法异常,要么导致分页逻辑完全失效(比如返回空数据、跳过条目数远低于预期)。

修复方案

1. 强制溢出检查

用checked块包裹乘法操作,溢出时直接抛出异常,提前拦截非法输入:

[HttpGet]
public async Task<IActionResult> GetAllBooksAsync([FromQuery] string pageNo, string itemsPerPage)
{
    int intSkip = int.TryParse(pageNo, out int _skip) ? _skip : 0;
    int intTake = int.TryParse(itemsPerPage, out int _take) ? _take : 0;

    int skip;
    try
    {
        checked
        {
            skip = intSkip * intTake;
        }
    }
    catch (OverflowException)
    {
        return BadRequest("分页参数过大,请传入合理的页码和每页条目数");
    }

    var result = await _repo.GetAllBooksAsync(skip, intTake);
    return Ok(result);
}

2. 限制参数范围

直接对pageNo和itemsPerPage的取值做上限限制,从源头避免乘积溢出:

[HttpGet]
public async Task<IActionResult> GetAllBooksAsync([FromQuery] string pageNo, string itemsPerPage)
{
    // 根据业务需求调整上限,比如页码最大10000,每页条目数最大1000
    int intSkip = int.TryParse(pageNo, out int _skip) ? Math.Clamp(_skip, 0, 10000) : 0;
    int intTake = int.TryParse(itemsPerPage, out int _take) ? Math.Clamp(_take, 0, 1000) : 0;

    var result = await _repo.GetAllBooksAsync(intSkip * intTake, intTake);
    return Ok(result);
}

3. 使用更大的数据类型

将分页计算变量改为long(64位整数),扩大取值范围避免溢出:

  • 控制器方法修改:
[HttpGet]
public async Task<IActionResult> GetAllBooksAsync([FromQuery] string pageNo, string itemsPerPage)
{
    long longSkip = long.TryParse(pageNo, out long _skip) ? _skip : 0;
    int intTake = int.TryParse(itemsPerPage, out int _take) ? _take : 0;

    long skip = longSkip * intTake;
    var result = await _repo.GetAllBooksAsync(skip, intTake);
    return Ok(result);
}
  • 仓储方法修改:
public async Task<IEnumerable<Book>> GetAllBooksAsync(long skip = 0, int take = 0)
{
    var query = _ctx.Books.Skip((int)skip);
    // 若skip可能超过int范围,可直接用Skip(skip),EF Core支持long类型的Skip参数
    if(take < 1)
    {
        return await query.ToListAsync();
    }

    return await query.Take(take).ToListAsync();
}

额外优化:修正分页逻辑

通常分页页码从1开始,当前代码中pageNo=1时会跳过第一页所有数据,建议调整为:

skip = (intSkip - 1) * intTake;

同时注意处理intSkip为0的情况,避免出现负数skip值。


内容的提问来源于stack exchange,提问作者Zombies are Real

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.14 11:13:12