C语言字符串拼接时秘密值末尾4字节与时间戳丢失问题咨询
根据你描述的现象——添加时间戳后秘密值末尾4字节和时间戳丢失,移除时间戳后恢复正常,最可能的原因是字符串拼接时的缓冲区溢出,以下是具体排查点和解决方法:
检查缓冲区分配大小
先计算所有拼接字段的总长度:秘密值的长度(如果是二进制数据不能用strlen,要用实际字节数) + 时间戳字符串长度 + 会话ID长度 + 秘密会话ID长度 + 1('\0'结束符)。如果你的缓冲区大小小于这个总长度,拼接时会发生内存溢出,后续写入的内容会覆盖前面的内容。比如时间戳的写入可能覆盖了秘密值的最后4字节,而后续会话ID的写入又覆盖了时间戳,最终只留下会话ID和秘密会话ID。
解决方法:改用snprintf一次性拼接,它会自动处理缓冲区边界,返回值可判断是否截断:// 根据实际字段最大长度定义足够大的缓冲区 char md5_input[512]; int ret = snprintf(md5_input, sizeof(md5_input), "%s%s%s%s", hpci_ws_secret_val, timeStamp, sessionId, secretSessionId); if (ret >= sizeof(md5_input)) { fprintf(stderr, "缓冲区不足,无法容纳拼接后的字符串\n"); return -1; }验证时间戳的字符串有效性
单独打印时间戳的内容和长度,确认它是标准的以'\0'结尾的ASCII字符串,没有隐藏控制字符:printf("时间戳内容: '%s'\n", timeStamp); printf("时间戳长度: %zu\n", strlen(timeStamp)); // 打印每个字节的十六进制,排查隐藏字符 for (size_t i = 0; i < strlen(timeStamp) + 1; i++) { printf("%02X ", (unsigned char)timeStamp[i]); } printf("\n");如果时间戳中间包含'\0',
strcat或sprintf会提前截断拼接,不过你说会话ID和秘密会话ID正常,这个可能性较低,但仍需排查。确认秘密值的存储格式
如果hpci_ws_secret_val是二进制数据(比如直接读取的哈希值),而非以'\0'结尾的C字符串,用strlen或strcat会错误地将第一个'\0'视为字符串结束。此时需要用memcpy手动处理二进制拼接,指定实际长度:char md5_input[足够大小]; size_t offset = 0; // 复制秘密值(secret_len为秘密值实际字节数) memcpy(md5_input + offset, hpci_ws_secret_val, secret_len); offset += secret_len; // 复制时间戳 size_t ts_len = strlen(timeStamp); memcpy(md5_input + offset, timeStamp, ts_len); offset += ts_len; // 复制会话ID和秘密会话ID同理 // 最后添加结束符 md5_input[offset] = '\0';排查内存覆盖问题
在拼接前后,打印秘密值的内存内容,确认是否被后续写入覆盖:// secret_len为秘密值实际长度 printf("拼接前秘密值: "); for (int i = 0; i < secret_len; i++) { printf("%02X ", (unsigned char)hpci_ws_secret_val[i]); } printf("\n"); // 执行拼接操作 printf("拼接后秘密值: "); for (int i = 0; i < secret_len; i++) { printf("%02X ", (unsigned char)hpci_ws_secret_val[i]); } printf("\n");如果拼接后秘密值最后4字节发生变化,说明确实是缓冲区溢出导致的内存覆盖。
内容的提问来源于stack exchange,提问作者venkysmarty

