Ubuntu 下 nginx-1.24.0 源码分析 - ngx_atoi 函数

发布于:2025-02-23 ⋅ 阅读:(10) ⋅ 点赞:(0)

ngx_atoi

声明在 src/core/ngx_string.h

ngx_int_t ngx_atoi(u_char *line, size_t n);

 定义在 src/core/ngx_string.c

ngx_int_t
ngx_atoi(u_char *line, size_t n)
{
    ngx_int_t  value, cutoff, cutlim;

    if (n == 0) {
        return NGX_ERROR;
    }

    cutoff = NGX_MAX_INT_T_VALUE / 10;
    cutlim = NGX_MAX_INT_T_VALUE % 10;

    for (value = 0; n--; line++) {
        if (*line < '0' || *line > '9') {
            return NGX_ERROR;
        }

        if (value >= cutoff && (value > cutoff || *line - '0' > cutlim)) {
            return NGX_ERROR;
        }

        value = value * 10 + (*line - '0');
    }

    return value;
}

函数签名 

ngx_int_t
ngx_atoi(u_char *line, size_t n)
  • u_char *line:待转换的字符串指针
  • size_t n:字符串有效长度(避免依赖'\0'终止符)
  • 返回值

    • 如果成功,返回转换后的整数值。
    • 如果失败(例如字符串包含非数字字符或超出整数范围),返回 NGX_ERROR

功能

该函数的作用是将一个长度为 n 的字符串转换为一个整数,并确保转换过程中不会发生溢出。

1. 参数检查 
if (n == 0) {
    return NGX_ERROR;
}

检查输入字符串的长度是否为 0。

如果长度为 0,则无法进行任何转换,直接返回错误。

这是最基本的边界条件检查,防止后续逻辑因无效输入而崩溃。

2. 定义变量并计算溢出阈值 
ngx_int_t value, cutoff, cutlim;
cutoff = NGX_MAX_INT_T_VALUE / 10;
cutlim = NGX_MAX_INT_T_VALUE % 10;

变量说明

value:用于存储当前累积的整数值。

cutoff:整数最大值除以 10 的结果。

cutlim:整数最大值对 10 取余的结果。


NGX_MAX_INT_T_VALUE:当前平台的整型最大值

定义在 src/core/ngx_config.h

#define NGX_MAX_INT_T_VALUE  9223372036854775807

在每次累加之前,通过比较当前值与 cutoffcutlim 来判断是否会溢出。

这种方法避免了直接进行溢出操作导致未定义行为。

遍历字符串并逐字符处理 
for (value = 0; n--; line++) {
    if (*line < '0' || *line > '9') {
        return NGX_ERROR;
    }

 

作用 :逐字符遍历输入字符串,并检查每个字符是否为合法的数字字符。

逻辑

*line < '0' || *line > '9':判断当前字符是否不在 '0''9' 范围内。

如果发现非法字符,立即返回错误。

意图

确保输入字符串只包含数字字符。

提前终止无效输入的处理,提高效率。

检测整数溢出

    if (value >= cutoff && (value > cutoff || *line - '0' > cutlim)) {
        return NGX_ERROR;
    }

作用 :在累加之前,检测当前值是否会超出整数范围。

逻辑

value >= cutoff:当前值已经接近整数最大值。

(value > cutoff || *line - '0' > cutlim)

如果当前值大于 cutoff,则一定会溢出。

如果当前值等于 cutoff,但当前字符对应的数字大于 cutlim,也会溢出。

意图

通过提前检测溢出,避免在累加时触发未定义行为。

这是 Nginx 设计中非常重要的健壮性保障。

累加当前字符的数值 
    value = value * 10 + (*line - '0');
  • 作用 :将当前字符的数值累加到 value 中。
  • 逻辑
    • *line - '0':将字符 '0''9' 转换为对应的整数值 0 到 9。
    • value * 10:将当前值左移一位(相当于乘以 10)。
    • 最终结果是将当前字符的数值追加到已有整数的末尾。
  • 意图
    • 实现字符串到整数的逐步转换。
返回最终结果 
return value;

当所有字符都成功处理后,返回最终的整数值