使用带有__FILE__的`basename`是否安全?

时间:2016-07-26 14:43:07

标签: c++ c posix

标题非常明确:将basenameman 3 basename)与__FILE__一起使用是否安全?

它编译并且似乎工作正常, basename的参数是char*(不是const char*)和man - 页面说:

  

dirname()和basename()都可以修改path的内容,因此在调用其中一个函数时可能需要传递一个副本。

所以,这让我很担心。

也许问题应该更像:__FILE__的类型是什么?它不是字符串文字/ const char*吗?但如果是,为什么没有编译时错误(const char*char*)?

2 个答案:

答案 0 :(得分:8)

仔细阅读 basename(3)并注意:

  

警告:两个不同的功能basename() - 见下文。

并照顾 NOTES

  

有两个不同版本的basename() - POSIX版本   如上所述,和GNU版本,后面的

      #define _GNU_SOURCE         /* See feature_test_macros(7) */
      #include <string.h>
     

GNU版从不修改其参数,并返回空   path具有尾部斜杠时的字符串

(重点是我的)

因为据说GNU版本没有修改它的参数,所以__FILE__使用它是安全的

顺便说一下,你可以考虑自定义你的GCC(例如用MELT)来定义一些__builtin_basename,如果给出一个像__FILE__这样的字符串文字,或者在调用时会在编译时计算基本名称<{1}}在运行时。

请注意basenamelibgen.h

答案 1 :(得分:4)

  

__FILE__的类型是什么?它不是字符串文字/ const char *?

是。这是一个字符串文字。

  

但如果是,为什么没有编译时错误(const char * to char *)?

可能是因为你使用的实现(glibc)可能会在你传递的字符串文字中返回一个指针(即它不会修改它的输入)。 在任何情况下,您都不能依赖它,如上所述。

C标准(c11,§6.10.8.1)说__FILE__是一个字符串文字:

  

__FILE__当前源文件的假定名称(字符串siteral)。

POSIX说:

  

basename()函数可以修改路径指向的字符串,   并且可以返回指向内部存储的指针。返回的指针   可能无效或存储可能被a覆盖   后续调用basename()。

(强调我的)。

所以,不,用basename()来呼叫__FILE__是不安全的。您只需复制__FILE__并在其上执行basename()

char *filename = strdup(__FILE__);
if (filename) {
    /* error */
}
char *file_basename = basename(filename);
free(filename);

由于__FILE__是字符串文字,因此使用数组是另一种选择:

char filename[] = __FILE__;
char *file_basename = basename(filename);