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

含数组命令的NGINX模块执行nginx -t时触发段错误

NGINX自定义模块配置段错误排查

问题场景

开发了一个简单的NGINX HTTP模块,代码如下:

typedef struct {
    ngx_array_t *claims;
} my_conf_t

static ngx_command_t my_commands[] = {
    { ngx_string("my_claims"),
        NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_1MORE,
        ngx_conf_set_str_array_slot,
        NGX_HTTP_LOC_CONF_OFFSET,
        offsetof(my_conf_t, claims),
        NULL },

    ngx_null_command
};

static ngx_http_module_t my_module_ctx = {
    NULL,
    my_module_init,
    NULL,
    NULL,
    NULL,
    NULL,
    my_module_create_loc_conf,
    my_module_merge_loc_conf
};


ngx_module_t my_module = {
    NGX_MODULE_V1,
    &my_module_ctx,
    my_commands,
    NGX_HTTP_MODULE,
    NULL,
    NULL,
    NULL,
    NULL,
    NULL,
    NULL,
    NULL,
    NGX_MODULE_V1_PADDING
};

当配置中使用新增的my_claims选项时,执行nginx -t触发段错误,配置示例:

location / {
    my_claims test;
    return 200 OK;
}

注释或移除该location配置后,nginx -t可正常执行。已参考NGINX Mail SSL模块示例,但未发现问题。

核心原因

段错误由以下几个关键问题导致:

  1. 结构体语法错误:my_conf_t结构体定义末尾缺少分号,编译阶段会产生隐式语法问题,破坏内存布局;
  2. 配置结构体未初始化:my_module_create_loc_conf函数未实现或未将claims字段初始化为NULL,ngx_conf_set_str_array_slot处理数组时会访问未初始化的野指针,触发非法内存访问;
  3. 合并逻辑缺失(可选):若my_module_merge_loc_conf未正确处理配置继承,也可能导致内存异常,但最直接的触发点是初始化缺失。

修复方案

1. 修正结构体语法错误

给my_conf_t结构体末尾添加分号:

typedef struct {
    ngx_array_t *claims;
} my_conf_t; // 补充分号

2. 实现正确的配置创建函数

确保my_module_create_loc_conf正确初始化配置结构体,将数组指针置为NULL:

static void *
my_module_create_loc_conf(ngx_conf_t *cf)
{
    my_conf_t *conf = ngx_pcalloc(cf->pool, sizeof(my_conf_t));
    if (conf == NULL) {
        return NULL;
    }

    // 显式初始化数组指针,避免野指针
    conf->claims = NULL;

    return conf;
}

3. 完善配置合并函数(推荐)

如果需要支持配置继承,实现my_module_merge_loc_conf处理数组的合并逻辑:

static char *
my_module_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
{
    my_conf_t *prev = parent;
    my_conf_t *conf = child;

    ngx_conf_merge_ptr_value(conf->claims, prev->claims, NULL);

    // 可选:若子配置无值,复制父配置的数组(按需实现)
    if (conf->claims == NULL && prev->claims != NULL) {
        conf->claims = ngx_array_copy(cf->pool, prev->claims);
        if (conf->claims == NULL) {
            return NGX_CONF_ERROR;
        }
    }

    return NGX_CONF_OK;
}

4. 检查初始化函数(若已实现)

如果my_module_init中有操作claims的逻辑,必须先判断指针是否为NULL,避免空指针访问。

验证

修复后重新编译模块,加载配置并执行nginx -t,即可正常通过配置检查,不会触发段错误。


内容的提问来源于stack exchange,提问作者Josh M.

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.27 17:47:47