2009-03-10 11 views
8

Cuando un usuario carga un archivo, al azar lo reemplaza la carga de otro usuario, finalmente he rastreado el problema hasta PHP y el nombre del archivo tmp se reutiliza. ¿Hay alguna manera de arreglar esto? ¿Hay alguna manera de hacer mejores nombres al azar? Parece degradarse con el tiempo, ya que en el nombre de archivo aleatorio, la semilla se debilita. Esto es en PHP 5.2.8 y FreeBSD 7.0Nombres temporales de archivo PHP para cargas colisionando

Aquí es un registro que muestra cómo el mismo nombre de archivo tmp se acostumbra y se sobrescribe con otra carga: http://pastebin.com/m65790440

Cualquier ayuda es muy apreciada. He estado tratando de arreglar esto por más de 4 meses y ha empeorado con el tiempo. Gracias.

EDITAR: Tenga en cuenta que esto no es un problema de código PHP, esto sucede antes de llegar a ningún código PHP, el archivo recibido a través de $ _FILES ['nombre'] ['tmp_name'] es incorrecto cuando se recibe y se remonta a que se sobrescribe con la carga de otra persona antes de que llegue al script de procesamiento de carga

+0

¿Es su dir de tmp ese el problema o el directorio en el que copia/mueve el archivo? – Greg

+0

Experimento el mismo problema con Freebsd 8 y PHP 5.3. Para reproducir tengo un script de carga muy simple. Para 5 pruebas, es bastante probable que se produzca una colisión. Esto es realmente malo Realmente no tengo ninguna idea por dónde empezar. Este problema también es difícil para Google, como se mencionó anteriormente. –

Respuesta

-1

Recomendaría usar un generador de GUID para el nombre de archivo, ya que está obteniendo tantos.

+0

¿Hay alguna manera de anular la entrada de archivos de nombres PHP? a partir de ahora php usa un esquema 'phpxxxxx' – mrmanman

2

¿Funciona PHP bajo apache, como mod_php?

Usted puede tratar de create a per-process temporary upload directory cuyo nombre contiene el php getmypid(), a continuación, ini_set su proceso de PHP upload_tmp_dir a ese directorio. Esto no funcionará si se genera un nuevo proceso php para cada solicitud.

+0

¿Hay alguna manera de anular la entrada de archivos de nombres PHP? – mrmanman

+0

no, pero es posible que pueda anular (en tiempo de ejecución) el directorio temporal donde se descargan los archivos temporales – vladr

0

Mueva sus archivos a un directorio de usuario después de que se hayan cargado. Esos archivos temporales deben eliminarse.

+0

Esta es la solución correcta. Los archivos de carga temporal de PHP solo están destinados a permanecer donde están por la cantidad de tiempo que le lleva a su secuencia de comandos de procesamiento moverlos a donde realmente pertenecen. – chaos

+0

En algún momento, la política de PHP consistió en eliminar los archivos temporales al final de la solicitud si no los movió/renombró, por lo que su mecanismo actual completo también se romperá si actualiza esa versión. – chaos

+0

Se están moviendo. El archivo que el script de procesamiento de carga de PHP recibe de $ _FILES ['name'] ['tmp_name'] es incorrecto para comenzar con – mrmanman

4

Parece que algo está muy mal con la instalación de PHP o con cualquier llamada al sistema que PHP utiliza internamente para generar los nombres de archivo aleatorios (lo más probable es tempnam).

Para todos los demás: PHP maneja los archivos cargados internamente antes de que se procese el código de usuario. Estos nombres se almacenan en $_FILES['file']['tmp_name'] (donde 'archivo' es el nombre (entre comillas) del elemento de entrada de archivo en el formulario).

+0

Sí, creo que es correcto, ahora necesito resolver cómo solucionarlo = B – mrmanman

+0

I ' He estado viendo si podía encontrar algo en Google, pero no lo hice. ¿El problema todavía ocurre si configura upload_tmp_dir en un directorio diferente? – Powerlord

+0

Sí, solo lo probé y el problema todavía ocurre cuando el upload_tmp_dir se establece en algo diferente, ¿se afectaría "noatime" en la partición/var (donde se cargan los archivos)? – mrmanman

3

Después de perseguir el código correspondiente a _gettemp en la implementación de libc de FreeBSD 7, estoy claro con respecto a cómo el contenido del archivo tmp_name podría ser válido. (Para rastrearlo, puede descargar una copia de PHP 5.2.8 y leer en main/rfc1867.c - llamadas a la línea 1018 en main/php_open_temporary_file.c, la función comienza en la línea 227, que hace su trabajo principal en la función que comienza en la línea 97, que, sin embargo, es esencialmente solo un contenedor para mkstemp en su sistema, que se encuentra en el FreeBSD libc implementation en la línea 66 (vinculado), que usa _gettemp (igual que el anterior) para generar el nombre de archivo aleatorio. Sin embargo, the manpage for mkstemp menciona en la sección BUGS que arc4random() function no reentrante. Es podría ser una posibilidad de que 2 solicitudes simultáneas estén ingresando a la sección del código crítico y devolver el mismo tmp_name - Sé muy poco acerca de cómo funciona Apache con mod_php o php-cgi para comentar allí (aunque usando FastCGI/php -cgi podría funcionar - No puedo comentar con éxito sobre esto en este momento).

Sin embargo, apuntando a la solución más simple, si no está experimentando el archivo tmp_name que no es válido, pero colisionando con otros archivos cargados (por ejemplo, si usa la parte de nombre de archivo de tmp_name como su única fuente de exclusividad en el nombre de archivo almacenado), podría enfrentar colisiones debido al birthday paradox. En another question mencionas tener unos 5,000,000 de archivos para mover, y en still another question mencionas recibir 30-40k cargas por día. Esto me parece una situación primordial para una colisión de paradojas de cumpleaños. El mktemp man page menciona que (si usa seis 'X' como lo hace PHP) hay 56,800,235,584 nombres de archivo posibles (62 ** 6, o 62 ** n donde n = número de 'X', etc.). Sin embargo, dado que tiene más de 5 millones de archivos, la probabilidad de una colisión es approximately 100% (otra heurística sugiere que ya habrá experimentado un pedido de 220 colisiones, si ((archivos * (archivos-1))/2)/(62 ** 6) significa cualquier cosa, donde archivos = 5,000,000). Si este es el problema al que se enfrenta (probable, si no agrega más entropía al nombre de archivo cargado generado), puede intentar algo como move_uploaded_file($file['tmp_name'], UPLOADS.sha1(mt_rand().$file['tmp_name']).strrchr($file['name'], '.')), con la idea de agregar más aleatoriedad al nombre de archivo aleatorio, evitando colisiones. Una alternativa podría ser agregar dos más 'X' a la línea 134 de main/php_open_temporary_file.c y volver a compilar.

Cuestiones relacionadas