conj 代碼審查:緩衝區溢出隱患與正確寫法char *conj(char *s, char *t)
{
char *p = s;
while (*s) ________;
while (*t) {
*s = ________;
s++;
t++;
}
*s = '\0';
________;
}
標準答案:s++, *t, return p。
s 且無容量檢查 → 緩衝區溢出風險極高。呼叫端若傳入字串常量(conj("hello", "world"))或容量不足的陣列,直接導致未定義行為(崩潰、資料損毀、安全漏洞)。const 正確性缺失:t 僅讀取,應宣告為 const char *t。#include <stddef.h> // size_t
/**
* 安全拼接:將 src 附加到 dst 末尾,確保以 '\0' 結尾。
* @param dst 目標緩衝區,必須可寫,大小至少 dst_size
* @param dst_size 目標緩衝區總大小(含結尾 '\0' 空間)
* @param src 來源字串
* @return 拼接後字串長度(不含 '\0'),若截斷回傳 -1
*/
int str_concat_safe(char *dst, size_t dst_size, const char *src)
{
if (!dst || !src || dst_size == 0) return -1;
size_t dst_len = 0;
while (dst_len < dst_size && dst[dst_len]) ++dst_len; // 尋找 dst 結尾
if (dst_len == dst_size) return -1; // dst 未以 '\0' 結尾或已滿
size_t copied = 0;
while (copied + 1 < dst_size - dst_len && src[copied]) {
dst[dst_len + copied] = src[copied];
++copied;
}
dst[dst_len + copied] = '\0';
return (src[copied] == '\0') ? (int)(dst_len + copied) : -1; // -1 表示截斷
}
char buf[100] = "Hello";
str_concat_safe(buf, sizeof buf, ", "); // 成功
str_concat_safe(buf, sizeof buf, "World!"); // 成功
printf("%s\n", buf); // Hello, World!
strncat(dst, src, dst_size - strlen(dst) - 1) —— 需自行計算剩餘空間,易出現 off-by-one。strlcat(dst, src, dst_size)(BSD/GNU 擴充,非標準) —— 回傳嘗試建立的總長度,截斷檢測方便。snprintf(dst + len, dst_size - len, "%s", src) —— 通用但效能稍低。「果真是不負責任的考試題。這個函數直接修改了 s 字串不說,還隨意擴充了 s 的使用記憶體,很容易導致緩衝區溢出。」