Эх сурвалжийг харах

fix: 修复设置写入 param 字段乱码 - use-after-free bug

Coze-Commit-Type: user
Coze-User-ID: 256649704250362
Coze-Conversation-ID: 11640025
steven_roc 2 сар өмнө
parent
commit
fb7dd59f10

BIN
assets/image.png


+ 30 - 0
mppt_monitor/CHANGELOG.md

@@ -4,6 +4,36 @@
 
 ---
 
+## [2.1.1] - 2026-08-06
+
+### Bug 修复:设置写入 param 字段乱码 (Use-After-Free)
+
+#### 问题
+POST `/api/settings` 写入设备参数时,响应 JSON 中 `param` 字段显示乱码(如 `"param":"b,"`),浏览器端报 "Invalid JSON body" 错误。
+
+#### 根因
+`param` 指针指向 `cJSON_Parse()` 解析后的 `req` 对象内部内存(`j_param->valuestring`)。在调用 `cJSON_Delete(req)` 释放内存后,`param` 成为悬空指针,后续 `snprintf` 使用它导致读取已释放内存,产生乱码。
+
+#### 修复
+在 `cJSON_Delete(req)` 之前,将 `param` 字符串复制到本地缓冲区 `param_copy[64]`,后续所有响应构造均使用 `param_copy`。
+
+```c
+// 修复前(错误)
+cJSON_Delete(req);          // 释放内存
+snprintf(resp, ..., param); // 使用悬空指针 → 乱码
+
+// 修复后(正确)
+char param_copy[64];
+snprintf(param_copy, sizeof(param_copy), "%s", param); // 提前复制
+cJSON_Delete(req);
+snprintf(resp, ..., param_copy); // 使用安全副本
+```
+
+#### 影响范围
+- `src/web_server.c` - `handle_api_settings()` 函数
+
+---
+
 ## [2.1.0] - 2026-08-06
 
 ### 新增:设备设置功能 (Device Settings)

BIN
mppt_monitor/build/mppt_monitor


BIN
mppt_monitor/mppt_data.db


+ 9 - 5
mppt_monitor/src/web_server.c

@@ -163,6 +163,10 @@ static void handle_api_settings(struct mg_connection *c, struct mg_http_message
     const char *param = j_param->valuestring;
     uint16_t value = (uint16_t)j_value->valueint;
 
+    /* Copy param string early - it points into req's memory which may be freed */
+    char param_copy[64];
+    snprintf(param_copy, sizeof(param_copy), "%s", param);
+
     /* Map parameter name to register address */
     uint16_t reg_addr = 0xFFFF;
     const char *param_desc = "";
@@ -201,11 +205,11 @@ static void handle_api_settings(struct mg_connection *c, struct mg_http_message
 
     /* Validate */
     if (modbus_validate_setting(reg_addr, value, current_battery_type) != 0) {
-        cJSON_Delete(req);
         char err_msg[256];
         snprintf(err_msg, sizeof(err_msg),
                  "{\"error\":\"Invalid value for %s (reg 0x%04X). Value %u out of range.\"}",
-                 param, reg_addr, value);
+                 param_copy, reg_addr, value);
+        cJSON_Delete(req);
         mg_http_reply(c, 400, "Content-Type: application/json\r\n", "%s", err_msg);
         return;
     }
@@ -228,17 +232,17 @@ static void handle_api_settings(struct mg_connection *c, struct mg_http_message
                  "{\"success\":true,\"device_addr\":%d,\"param\":\"%s\","
                  "\"param_desc\":\"%s\",\"reg_addr\":\"0x%04X\",\"value\":%d,"
                  "\"message\":\"写入成功\"}",
-                 dev_addr, param, param_desc, reg_addr, value);
+                 dev_addr, param_copy, param_desc, reg_addr, value);
         mg_http_reply(c, 200, "Content-Type: application/json\r\nAccess-Control-Allow-Origin: *\r\n",
                       "%s", resp);
         printf("[WEB] Settings write success: dev %d, %s (0x%04X) = %u\n",
-               dev_addr, param, reg_addr, value);
+               dev_addr, param_copy, reg_addr, value);
     } else {
         char resp[256];
         snprintf(resp, sizeof(resp),
                  "{\"success\":false,\"error\":\"Modbus写入失败,请检查设备连接\","
                  "\"device_addr\":%d,\"param\":\"%s\"}",
-                 dev_addr, param);
+                 dev_addr, param_copy);
         mg_http_reply(c, 500, "Content-Type: application/json\r\n", "%s", resp);
     }
 }