Regla 0x4007h: Prohibición de rutas absolutas hardcodeadas en llamadas de archivo
Archivos y E/S (0x40XX)
0x4007h: Prohibición de rutas absolutas hardcodeadas en llamadas de archivo¶
Enunciado normativo¶
NO DEBE incluirse una ruta absoluta literal (por ejemplo
/home/...,/tmp/...oC:\\...) en una llamada afopen. La ruta DEBE ser relativa al directorio de ejecución o provenir de un argumento de la línea de comandos o de una variable de entorno.
La regla tampoco permite “arreglar” la ruta para tu máquina: exige que el programa no dependa de una ubicación física concreta.
¿Por qué existe esta regla?¶
El problema¶
En C, el nombre de un archivo es una cadena cuyo significado depende del sistema operativo: ISO/IEC 9899:2011 §7.21.3 lo trata como una cadena multibyte y deja la interpretación de la ruta a la implementación. Una ruta absoluta codificada en el fuente funciona solo en la máquina y la cuenta donde se escribió.
El problema es doble. Por portabilidad, el programa deja de funcionar en otra computadora, en otro sistema operativo o incluso en el mismo equipo si cambia el usuario. Por seguridad y reproducibilidad, una ruta absoluta revela la estructura del entorno y, si el archivo se abre con permisos amplios, puede sobrescribir datos ajenos al proyecto. Además, en trabajos grupales cada integrante tiene su propio directorio de inicio, de modo que el código se rompe en cuanto se comparte.
La solución idiomática es recibir la ruta como parámetro. main puede declarar
int main(int argc, char *argv[]) (§5.1.2.2.1) y tomar argv[1]; las
bibliotecas y funciones reciben la ruta por parámetro, como ya hacen fopen y
las funciones de esta categoría.
Consecuencias de violarla¶
| Tipo de consecuencia | Efecto concreto |
|---|---|
| No portabilidad | El programa falla en cualquier máquina distinta a la de origen. |
| No reproducibilidad | Las pruebas dependen del estado del sistema de archivos local. |
| Seguridad | Una ruta fija con permisos de escritura puede dañar archivos ajenos. |
| Trabajo en equipo | La entrega no compila ni corre en el entorno del corrector. |
Fundamento en el estándar y en la cátedra¶
ISO/IEC 9899:2011 §7.21.3 define que los nombres de archivo son cadenas
multibyte cuya validez y formato son dependientes de la implementación;
§5.1.2.2.1 define los parámetros de main como el mecanismo portátil para
recibir datos del entorno de ejecución. La cátedra prohíbe las rutas absolutas
porque las entregas se corrigen en un entorno distinto del de desarrollo.
Alcance y excepciones¶
Aplica a cualquier cadena que se pase a fopen, freopen, remove o
rename. No alcanza a rutas construidas dinámicamente a partir de argumentos,
variables de entorno o del directorio actual, aunque en esos casos hay que
validar el resultado.
Excepción razonable: un recurso de prueba dentro del repositorio puede referirse con una ruta relativa al directorio de compilación, siempre que no dependa del usuario ni del equipo.
Ejemplos exhaustivos¶
❌ Contraejemplo 1 — Ruta absoluta de la máquina del autor¶
FILE *f = fopen("/home/usuario/tp/datos.csv", "r");Por qué falla: la ruta solo existe en la cuenta usuario de esa computadora.
En el equipo del corrector no existe y fopen retorna NULL; el programa no
tiene forma de abrir los datos.
❌ Contraejemplo 2 — Ruta absoluta de Windows y separador específico¶
FILE *f = fopen("C:\\Users\\Ana\\datos.csv", "r");Por qué falla: además de ser absoluta, usa la convención de rutas de Windows.
En Linux, C:\Users\Ana\datos.csv es un nombre de archivo relativo extraño, no
una ruta válida.
✅ Ejemplo conforme 1 — Ruta relativa al directorio de trabajo¶
FILE *f = fopen("datos.csv", "r");
if (f == NULL) {
perror("datos.csv");
return -1;
}El programa asume que el archivo está en el directorio desde el que se ejecuta, una convención independiente de la máquina. El fallo se diagnostica con la ruta efectivamente intentada.
✅ Ejemplo conforme 2 — Ruta recibida por la línea de comandos¶
int main(int argc, char *argv[])
{
if (argc != 2) {
fprintf(stderr, "uso: %s ARCHIVO\n", argv[0]);
return 1;
}
FILE *f = fopen(argv[1], "r");
if (f == NULL) {
perror(argv[1]);
return 1;
}
/* ... */
fclose(f);
return 0;
}La ruta la decide quien ejecuta el programa, no el código fuente; el programa se adapta a cualquier entorno y el mensaje de error nombra el archivo real.
⚠️ Casos límite¶
Directorio actual: una ruta relativa depende del current working directory; si el programa cambia de directorio, la misma cadena apunta a otro lugar.
Recursos empaquetados: los archivos de prueba pueden ir junto al fuente, pero la ruta debe ser relativa y documentada.
Variables de entorno:
getenves aceptable si se verifica que no retorneNULLantes de usarla.Construcción con
snprintf: si se arma la ruta concatenando partes, hay que respetar el tamaño del búfer (ver 0x5004h: Todas las operaciones con cadenas deben ser seguras).
Cómo detectarla¶
| Herramienta | Comando | Señal |
|---|---|---|
gaff | gaff check archivo.c | Regla 0x4007h: literal de ruta absoluta en fopen/freopen. |
grep | grep -n '"/' archivo.c | Cadenas que comienzan con / dentro de la llamada. |
| Revisión manual | — | Todo fopen con cadena literal debe evaluarse como ruta relativa. |
Checklist de autocontrol¶
¿La ruta proviene de un argumento, una variable o es relativa?
¿Validé que la ruta de entrada no sea
NULLantes de usarla?¿Evité rutas y separadores específicos de una plataforma?
¿El mensaje de error nombra la ruta realmente intentada?
Reglas relacionadas¶
0x4001h: Manejá correctamente la apertura y cierre de archivos — verificar el retorno de la apertura con la ruta elegida.
0x4003h: Utilizá errno, perror y strerror para reportar fallos del sistema operativo de manera precisa — reportar el fallo con
perrorsobre la ruta recibida.0x4009h: Prohibición de anidar llamadas a fopen() directamente dentro de funciones de E/S — no anidar la apertura en otra llamada de E/S.
0x5004h: Todas las operaciones con cadenas deben ser seguras — operaciones de cadenas seguras al componer rutas.