C:从函数返回字符串

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

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并传递一个指针,那么我怎么能知道之前的大小,因为密码大小只在函数中知道?

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

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

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

你可以采取两种方法。

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

在我看来,你已经实施了方法#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; } 

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

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

我有一些想法:

  1. 存储密码的散列版本。 在getMyPassword()中,取消变量并返回它。

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

  3. 合并1和2 – 将哈希密码存储在受保护的文件中,取消对象并将其返回。

这一切都取决于你想要的安全程度。

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

  1. 选择与所有字符进行异或的“种子”值。
  2. getMyPassword函数是否接受该字符。 这样,如果你不知道种子,这个function大多没用。

因此,例如,将值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是什么:)

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

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

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