使用sscanf提取CGI脚本QUERY_STRING中变量值的问题
解决CGI脚本中用sscanf提取QUERY_STRING变量的问题
你的问题核心在于sscanf里的%s格式符——它会匹配所有非空白字符,所以会把&login_password=my_pass也一股脑读进login_email_arr里,直到遇到空格(而你的QUERY_STRING里根本没有空格),自然就没给第二个变量留下内容了。
正确的解决方案
我们可以用**扫描集(scanset)**精准控制读取的终止位置,同时加上长度限制防止缓冲区溢出:
- 用
%59[^&]读取login_email的值:[^&]表示匹配所有不是&的字符,59是限制最多读59个字符(因为你的数组是60位,留1位给字符串终止符\0)。 - 格式串里直接写
&login_password=(注意:实际环境变量QUERY_STRING里的分隔符是&,你看到的&是浏览器显示时的HTML转义,实际传递给CGI的原始值是&)。 - 对
login_password同样加上长度限制%59s,避免溢出。
修改后的完整代码
#include <stdio.h> #include <stdlib.h> #include <string.h> int main(void){ char env_arr[1000]; char* env_ptr = getenv("QUERY_STRING"); printf("content-type:text/html; charset=utf-8\n\n"); // 先检查是否成功获取到环境变量 if (env_ptr == NULL) { printf("QUERY_STRING is empty<br>"); return 1; } // 复制到可写数组(只读内存也能被sscanf读取,但这样更安全) strncpy(env_arr, env_ptr, sizeof(env_arr)-1); env_arr[sizeof(env_arr)-1] = '\0'; // 确保字符串终止 printf("%s: %s<br>", "Value of the \"QUERY_STRING\"", env_arr); printf("%s: %p<br>", "Address of the \"QUERY_STRING\"", env_ptr); char login_email_arr[60] = ""; char login_password_arr[60] = ""; // 使用扫描集和长度限制提取变量 int ret = sscanf(env_arr, "login_email=%59[^&]&login_password=%59s", login_email_arr, login_password_arr); // 检查sscanf是否成功读取两个变量 if (ret == 2) { printf("login_email: %s<br>", login_email_arr); printf("login_password : %s<br>", login_password_arr); } else { printf("Failed to parse QUERY_STRING<br>"); if (ret == 1) { printf("Only login_email was parsed: %s<br>", login_email_arr); } } return 0; }
额外注意事项
- URL解码:你现在得到的
example%40my.com是URL编码后的字符串,需要额外编写URL解码函数把%40转换成@,sscanf不会帮你完成这一步。 - 缓冲区安全:永远不要省略长度限制,否则恶意用户可以构造超长的QUERY_STRING触发缓冲区溢出,引发安全漏洞。
- 错误处理:检查
getenv的返回值(避免空指针)和sscanf的返回值(确认是否成功解析所有变量),能让你的脚本更健壮。
内容的提问来源于stack exchange,提问作者71GA
相关产品推荐
相关产品推荐

