C:从函数返回字符串

时间:2011-10-11 22:30:16

标签: c string

我有一个返回字符串的函数:

const *char getMyPassword()
{
    return "mysecretpassword";
}

嗯,它工作得很好,但我发现如果我在Unix系统上运行“字符串”,它会显示在列表中......不是很好。

更换它的最简单方法是什么?该函数位于库中,我希望保持灵活性。我现在开始在函数内进行mallocing,字符串中的字符串消失了。但是,我何时可以再次释放它?

char * getMyPassword()
{
unsigned char arr[] = { 'p', 'a', 's', 's', 'w', 'o', 'r' , 'd', '\0' };
char *return_arr = malloc(sizeof(arr));
strcpy(return_arr, arr);
return return_arr;

}

如果我以前使用malloc并传递指针,那么我怎么能知道之前的大小,因为密码大小只在函数中知道?

作为一个计划B我可以通过一个巨大的阵列,但这似乎不是很优雅。我该怎么做呢?

编辑:我添加了strcpy(return_arr,arr)。我实际上是在原始代码中使用它,但在这里忘记了它。

5 个答案:

答案 0 :(得分:2)

我认为这里的问题是,当你试图返回一个像这样的字符串时,你试图返回一个指向本地定义的变量的指针。我希望你的第一个函数能够工作,因为指针将地址返回给文字,这通过执行程序是静态的。同样,您可以将本地范围中的char []变量声明为静态;所以它不在本地范围内。

但老实说,我不明白为什么你想要一个函数返回一个指向字符串文字的指针;当你可以简单地定义局部范围之外的文字时,实际需要它。

答案 1 :(得分:2)

我有一些想法:

  1. 存储密码的哈希版本。在getMyPassword()中,取消变量并将其返回。

  2. 将密码存储在受保护的文件中(加密,仅对您的用户具有读取权限等)。从文件中加载密码并在函数中返回。

  3. 合并1和2 - 将散列密码存储在受保护的文件中,取消隐藏并返回。

  4. 这完全取决于你想要的安全程度。

答案 2 :(得分:2)

除了安全问题之外,您要做的是动态分配缓冲区。

你可以采取两种方法。

  1. 在您的函数中始终malloc并记录它返回malloced结果。
  2. 遵循一些标准库函数的道路,要求用户将指针传递给有效缓冲区及其大小,并返回实际复制的大小。其中一些函数允许check传递,当您传入null缓冲区时,它们不会尝试分配它,而是返回保存结构所需的大小。
  3. 在我看来,您已经实施了方法#1。

    对于方法#2,请使用此签名:

    int getMyPassword( char* buffer, size_t buff_size, size_t* p_num_copied )
    {
      unsigned char arr[] = { 'p', 'a', 's', 's', 'w', 'o', 'r' , 'd', '\0' };
    
      if ( buffer == 0 )
      {
        *p_num_copied = sizeof(arr);
        return SUCCESS;
      }
    
      if ( buff_size < sizeof(arr) )
      {
        *p_num_copied = sizeof(arr);
        return BUFFER_TOO_SMALL;
      }
    
      memcpy( buffer, arr, sizeof(arr) );
    
      *p_num_copied = sizeof( arr );
    
      return SUCCESS;
    }
    

    方法#2的优点是,在许多情况下,调用者可以在堆栈上分配缓冲区,尤其是在您通告所需的最大缓冲区大小时。另一个优点是内存管理现在完全由客户端处理。在通用库中,您不希望根据特定的库内存分配架构创建客户端。

    回复评论

    如果您总是希望在客户端代码中使用已分配的值,那么我就是这样做的:

    char* clientGetPasswordFromLibrary( )
    {
      // in our day and age it's fine to allocate this much on stack
      char buffer[256];
      size_t num_copied;
    
      int status = getMyPassword( buffer, sizeof(buffer), &num_copied );
    
      char* ret_val = NULL;
    
      if ( status == BUFFER_TOO_SMALL )
      {
        ret_val = malloc( num_copied );
    
        if ( ret_val == NULL )
        {
          return NULL;
        }
    
        getMyPassword( ret_val, num_copied, &num_copied );
      }
      else
      {
        ret_val = malloc( num_copied );
    
        if ( ret_val == NULL )
        {
          return NULL;
        }
    
        memcpy( ret_val, buffer, num_copied );
      }
    
      return ret_val;
    }
    

答案 3 :(得分:1)

这或多或少是徒劳的(你知道,任何逆转你的程序的人都可以轻松获得密码)隐写术练习。例如,您可以增强安全性,请执行以下操作:

  1. 选择与所有字符进行异或的“种子”值。
  2. 执行getMyPassword功能以接受该字符。这样,如果你不知道种子,这个功能大多没用。
  3. 因此,例如,将值55作为种子。你可以有类似的东西:

    char * getMyPassword(char seed)
    {
    const char* str = "SEX@DDVG";
    char *return_arr = malloc(9); /* 8+1 */
    for (int i=0 ; i < 9 ; ++i)
       return_arr[i] = str[i] ^ seed;
    return_arr[i] = 0;
    return return_arr;
    }
    

    您必须致电getMyPassword(55)才能获得正确的结果。我发誓,55是随机选择的,我不知道DDVG是什么:)

答案 4 :(得分:0)

关于安全问题,将密码安全地传递给进程的常用方法是使用环境。例如,如果您的程序最终从网页调用,您可以在安全apache配置文件中设置一次密码(通过SetEnv PASSWORD“secret”),它将传递给它运行的每个cgi脚本,以及它们运行的​​任何内容。然后在你的程序中你只需要嵌入getenv(“密码”)。

一个常见的错误是在程序的命令行上接受密码,这不应该这样做,因为命令行可以被/ proc中的任何进程访问。这就是'ps'如何显示正在运行的内容。

此外,您可以将程序权限设置为可执行但不可读(chmod -r + x程序)。所以它可以运行但其内容实际上无法读取。对于Web服务树中的任何内容总是一个好主意,以避免因服务器配置错误而意外泄露事物。这是否适用于shell脚本是依赖于实现的,但它适用于已编译的程序。