含数组命令的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模块示例,但未发现问题。
核心原因
段错误由以下几个关键问题导致:
- 结构体语法错误:
my_conf_t结构体定义末尾缺少分号,编译阶段会产生隐式语法问题,破坏内存布局; - 配置结构体未初始化:
my_module_create_loc_conf函数未实现或未将claims字段初始化为NULL,ngx_conf_set_str_array_slot处理数组时会访问未初始化的野指针,触发非法内存访问; - 合并逻辑缺失(可选):若
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.
相关产品推荐
相关产品推荐

