【问题标题】:How do I properly work with Strings in C?如何在 C 中正确使用字符串?
【发布时间】:2011-06-23 19:24:06
【问题描述】:

Java、Python 等已经毁了我。我正在尝试通过响应服务器代码来自动化 FTP 客户端:

例如:

// I know this is ugly, please bear with me

char username[25];
strcat(username, USER); //"USER "
strcat(username, usr); // "foo"
strcat(username, "\n"); // = "USER foo\n"

char password[25];
strcat(password, PASS); //"PASS "
strcat(password, pswd); //"bar"
strcat(password, "\n"); // = "PASS bar\n"


//read/write loop

while (1) { 

    char* responsePtr;
    serverCode = readSocket(sockfd, mybuffer);

    if (serverCode == 221) 
                    break;

    if (serverCode == 220)
        responsePtr = &username;

    if (serverCode == 331)
        responsePtr = &password;

    writeSocket(sockfd, responsePtr);

}

当我尝试这个时,它适用于 USER,但我得到一些错误的 PASS 文本:

C->S: USER anonymous
S->C: 331 Please specify the password.
C->S: (??_?PASS random

谁能比我更聪明、更有经验给我一些 C 字符串指针?显然这不适合我。

【问题讨论】:

    标签: c string strcat


    【解决方案1】:

    您需要在连接到它们之前初始化您的字符串。数组默认不初始化。

    char username[25] = "";
    char password[25] = "";
    

    对于它的价值,您可以使用sprintf 更轻松地创建字符串:

    sprintf(username, "USER %s\n", usr);
    sprintf(password, "PASS %s\n", pswd);
    

    希望您也意识到使用固定大小的缓冲区会导致缓冲区溢出错误。为了安全起见,您应该确保防范它们。这很烦人,但这对你来说是 C:

    if (snprintf(username, 25, "USER %s\n", usr)  >= 25 ||
        snprintf(password, 25, "PASS %s\n", pswd) >= 25)
    {
        fprintf(stderr, "buffer overflow\n");
        exit(EXIT_FAILURE);
    }
    

    【讨论】:

    • C->S: USER 匿名 S->C: 331 请指定密码。 C->S: PASS random S->C: 230 登录成功。 :)
    • 我刚刚重新加载并看到了您的 sprintf 添加。感谢您的提示,我一直在寻找一种更好的方式来连接我的字符串。
    • 我通常先strcpy,然后是strcat。我猜它的偏好。
    • 建议:将幻数25替换为sizeof username
    • @Marlon 这不仅仅是优先级; strcpy 和 strcat 会产生等待发生的缓冲区溢出安全漏洞。使用 snprintf 或者更好的动态字符串库(或现代计算机语言)。
    【解决方案2】:

    一些有用的规则。

    • 记得初始化和空终止你的字符串。
    • 使用库函数。
    • 在处理外部数据时检查字符串长度和/或使用 n(大小受限)函数。
    • 在调整缓冲区大小时不要忘记终止符。

    【讨论】:

      【解决方案3】:

      你不应该 strcat 一个未初始化的数组。 试试:

      char *password[25] = "";
      password = strcat(PASS);
      

      第一个。

      另外,您应该使用strncat() 而不是strcat() 以避免溢出。


      我认为这样做更容易:

      int len = snprintf(password, 25, "%s %s\n", PASS, pswd);
      if (len > 25) {
          // oops! password is too long dude :-(
      }
      

      See here for some examples.

      【讨论】:

      • 模组必须锁定帖子吗?
      【解决方案4】:

      尝试在用户名和密码数组中添加“\n\0”,而不仅仅是“\n”。

      【讨论】:

      • 我已经尝试过了——不过,考虑到垃圾在字符串之前而不是之后,这并不重要。此外,\n 是 FTP 的分隔符,因此 \0 并不重要。
      • 好吧。我认为垃圾可能是由于服务器端的问题而存在的。
      • 不可能。我只是解析服务器代码(在本例中为 331)并将我的指针设置为一个新字符串。该字符串与服务器的操作没有太大关系。不过还是谢谢:)
      猜你喜欢
      • 2014-03-08
      • 1970-01-01
      • 2012-04-03
      • 2016-01-18
      • 1970-01-01
      • 2016-02-16
      • 2021-09-03
      相关资源
      最近更新 更多