{ "topic": "secure-coding", "type": "code_reading", "schema_version": "1.0.0", "generated": "2026-09-17T00:00:00+08:00", "questions": [ { "id": "cr-001", "type": "code_reading", "difficulty": 2, "tags": [ "安全编程", "整数溢出", "内存安全" ], "question": "阅读以下C代码,回答问题。", "code": "#include \n#include \n#include \n\nvoid process_input(const char *user_input) {\n unsigned int len = strlen(user_input);\n // 检查长度是否合理\n if (len > 1024) {\n printf(\"Input too long!\\n\");\n return;\n }\n // 分配缓冲区:len + 1 用于存放结尾的 '\\0'\n char *buffer = (char *)malloc(len + 1);\n if (buffer == NULL) {\n printf(\"Memory allocation failed!\\n\");\n return;\n }\n strcpy(buffer, user_input);\n printf(\"Processed: %s\\n\", buffer);\n free(buffer);\n}\n\nint main(int argc, char *argv[]) {\n if (argc < 2) {\n printf(\"Usage: %s \\n\", argv[0]);\n return 1;\n }\n process_input(argv[1]);\n return 0;\n}", "language": "c", "sub_questions": [ { "index": 1, "type": "single_choice", "question": "当 user_input 的 strlen 返回值恰好为 SIZE_MAX(即 (size_t)-1)时,len + 1 的结果是什么?", "options": { "A": "0,因为无符号整数溢出后回绕到 0", "B": "SIZE_MAX + 1 = 一个更大的数", "C": "程序会崩溃", "D": "编译器会报错" }, "answer": "A", "explanation": "unsigned int 在 C 语言中发生溢出时会进行模 2^N 回绕(wrap around)。当 len 为 SIZE_MAX 时,len + 1 回绕为 0。此时 malloc(0) 的行为是实现定义的——可能返回 NULL 或一个可 free 的指针,但分配的大小为 0 字节。后续 strcpy 会写入远超分配空间的数据,导致堆缓冲区溢出。" }, { "index": 2, "type": "single_choice", "question": "这段代码在上述溢出场景下,strcpy(buffer, user_input) 会导致什么后果?", "options": { "A": "正常复制,程序正常运行", "B": "堆缓冲区溢出(heap buffer overflow),可能执行任意代码", "C": "栈溢出", "D": "只会影响 buffer 变量,不会影响其他数据" }, "answer": "B", "explanation": "当 len + 1 回绕为 0 时,malloc(0) 可能分配一个极小的内存块(或返回一个有效指针但大小为 0),而 user_input 的实际长度远超分配空间。strcpy 会将整个 user_input 复制到这个过小的缓冲区中,造成堆缓冲区溢出,可能覆盖堆上的其他数据结构,攻击者可利用此漏洞执行任意代码。" }, { "index": 3, "type": "short_answer", "question": "请修改 process_input 函数,修复其中存在的所有安全问题(至少指出并修复 2 个问题)。", "answer": "修复方案应包括:\n1. 将 strlen 返回值类型改为 size_t(而非 unsigned int),避免类型截截断;\n2. 在 len + 1 运算前检查 len 是否等于 SIZE_MAX(或使用安全的加法函数如 __builtin_add_overflow / SafeInt),防止整数溢出回绕;\n3. 使用 strncpy 或 memcpy 替代 strcpy,限制拷贝长度;\n4. 检查 malloc 返回值后,对 buffer 大小为 0 的情况进行防御;\n5. 考虑使用 calloc 或更安全的内存分配函数。\n\n示例修复代码:\nvoid process_input(const char *user_input) {\n size_t len = strlen(user_input);\n if (len > 1024) { printf(\"Input too long!\\n\"); return; }\n if (len == SIZE_MAX) { printf(\"Invalid input length!\\n\"); return; }\n char *buffer = (char *)malloc(len + 1);\n if (buffer == NULL || len + 1 == 0) { printf(\"Allocation failed!\\n\"); return; }\n memcpy(buffer, user_input, len);\n buffer[len] = '\\0';\n printf(\"Processed: %s\\n\", buffer);\n free(buffer);\n}", "explanation": "修复涉及多个层面:类型安全(size_t)、整数溢出检查(SIZE_MAX 边界)、安全的内存复制(memcpy 替代 strcpy)。这些都是安全编码的基本实践。" } ], "explanation": "此代码阅读题考察学生对整数溢出导致缓冲区溢出的安全漏洞理解,以及修复安全漏洞的能力。", "source": null, "related": [] } ] }