在将相关代码追踪到 FreeBSD 7 的 libc 实现中的_gettemp之后,我不清楚文件的内容是如何tmp_name
无效的。(要跟踪它,您可以下载 PHP 5.2.8 的副本并读取main/rfc1867.c
1018 行调用 in main/php_open_temporary_file.c
,该函数从第 227 行开始,它在从第 97 行开始的函数中执行它的主要工作,然而,它本质上是只是系统上 mkstemp 的一个包装器,它位于第 66 行(链接)的FreeBSD libc 实现中,它使用_gettemp(与上面相同)实际生成随机文件名。但是mkstemp 的手册页在 BUGS 部分中提到该arc4random()
函数是不可重入的。它可能有 2 个同时请求进入关键代码部分并返回相同的可能性tmp_name
- 我对 Apache 如何与 mod_php 或 php-cgi 一起工作知之甚少,无法在此处发表评论(尽管使用 FastCGI/php-cgi 可能有效 - 我可以'此时不能成功评论)。
但是,针对最简单的解决方案,如果您没有完全体验到文件tmp_name
本身无效,而是与其他上传的文件发生冲突(例如,如果使用 tmp_name 的文件名部分作为存储文件名中唯一性的唯一来源),由于生日悖论,您可能会面临碰撞。在另一个问题中,您提到要移动大约 5,000,000 个文件,在另一个问题中,您提到每天要接收 30-40k 上传。这让我觉得这是生日悖论碰撞的主要情况。mktemp手册页提到(如果像 PHP 那样使用六个“X”)有 56,800,235,584 个可能的文件名(62 ** 6 或 62 ** n,其中 n =“X”的数量等)。但是,鉴于您有超过 500 万个文件,发生冲突的概率大约为 100%(另一个启发式方法表明,如果 ((files*(files-1)) /2)/(62**6) 表示任何东西,其中文件 = 5,000,000)。如果这是您面临的问题(很可能,如果不向生成的上传文件名添加进一步的熵),您可以尝试类似move_uploaded_file($file['tmp_name'], UPLOADS.sha1(mt_rand().$file['tmp_name']).strrchr($file['name'], '.'))
的方法 - 为随机文件名添加更多随机性,防止冲突。另一种方法是在第 134 行添加两个“X”main/php_open_temporary_file.c
并重新编译。