0x7002h: Validá los datos en la frontera del programa¶
Enunciado normativo¶
Todo dato que ingresa desde fuera del programa (teclado, archivo, argumentos de línea de comandos, red) DEBE validarse inmediatamente en la frontera, antes de usarse. NO DEBE confiarse en que la entrada es correcta “porque el usuario debería ingresar bien”.
¿Por qué existe esta regla?¶
El problema¶
El exterior del programa es hostil e impredecible. Un usuario puede escribir letras donde se espera un número, un archivo puede venir truncado y un argumento puede faltar. Si el dato se usa sin validar, el error se propaga profundamente y se manifiesta lejos de su origen, donde es caro de rastrear.
Validar en la frontera concentra todas las suposiciones en un único lugar y garantiza que el interior del programa trabaje sólo con datos confiables.
Consecuencias de violarla¶
| Tipo de consecuencia | Efecto concreto |
|---|---|
| Comportamiento indefinido | Usar un entero sin inicializar porque scanf falló. |
| Desbordamiento | Copiar entrada de longitud ilimitada en un buffer fijo. |
| Crash | Acceder a un arreglo con un índice ingresado por el usuario. |
| Bug silencioso | Un valor basura se propaga y produce resultados absurdos. |
Fundamento en la cátedra¶
Es un principio de robustez estándar: los datos no confiables se sanean en el punto de entrada. Se articula con 0x300Ch: Verificá siempre los límites de los arreglos antes de acceder a sus elementos (límites), 0x4002h: Validá los retornos de las operaciones de lectura y escritura de archivos (retornos de lectura) y 0x6004h: No reutilices una variable para propósitos distintos (contrato de funciones).
Alcance y excepciones¶
Aplica a todo canal externo: scanf, fgets, fread, argv, variables de
entorno, sockets, archivos. No se revalida dentro del programa lo ya
validado en la frontera (se documenta el contrato, eso es suficiente). Una
constante literal del propio código no es entrada externa.
Ejemplos exhaustivos¶
❌ Contraejemplo 1 — Confiar en scanf¶
int edad;
printf("Edad: ");
scanf("%d", &edad);
char categoria = (edad >= 18) ? 'A' : 'B';Por qué falla: si el usuario escribe “abc”, scanf falla, edad queda
indeterminada y la comparación usa basura. Además el ternario está prohibido
(0x1007h: No utilizar el operador condicional (ternario) ?:).
❌ Contraejemplo 2 — Copiar entrada sin límite¶
char nombre[32];
printf("Nombre: ");
scanf("%s", nombre);Por qué falla: una entrada de 100 caracteres desborda nombre y corrompe la
pila; es un buffer overflow clásico. Debe usarse un ancho máximo
(0x400Ah: Prohibición de operar sobre flujos de archivo tras haber invocado fclose() (use-after-close), 0x5006h: Preferí fgets sobre gets y scanf para leer cadenas).
✅ Ejemplo conforme 1 — Validación con retorno¶
int edad;
printf("Edad: ");
if (scanf("%d", &edad) != 1) {
fprintf(stderr, "Entrada invalida\n");
return EXIT_FAILURE;
}
if (edad < 0 || edad > EDAD_MAXIMA) {
fprintf(stderr, "Edad fuera de rango\n");
return EXIT_FAILURE;
}Se verifica el retorno de scanf y el rango antes de usar edad.
✅ Ejemplo conforme 2 — Lectura acotada con fgets¶
char nombre[32];
if (fgets(nombre, sizeof(nombre), stdin) == NULL) {
fprintf(stderr, "Error de lectura\n");
return EXIT_FAILURE;
}
nombre[strcspn(nombre, "\n")] = '\0';fgets nunca escribe más de sizeof(nombre) - 1 bytes y se verifica el
retorno.
⚠️ Casos límite¶
argv: verificar queargcalcanza antes de tocarargv[i].Archivos: un archivo “propio” puede venir editado o corrupto; validar formato y cantidades.
Valores límite: comprobar también
INT_MAX, cadenas vacías y cantidades negativas, no sólo el tipo.
Cómo detectarla¶
| Herramienta | Comando | Señal |
|---|---|---|
kaneda | auditoría de seguridad | scanf sin ancho, gets, copias sin límite. |
valgrind | valgrind ./programa | Lecturas de memoria no inicializada por entrada fallida. |
Checklist de autocontrol¶
¿Verifiqué el retorno de toda lectura?
¿Comprobé el rango del valor ingresado?
¿El buffer de destino acota la escritura?
¿
argvse valida antes de usarse?
Reglas relacionadas¶
0x300Ch: Verificá siempre los límites de los arreglos antes de acceder a sus elementos — verificación de límites de arreglos.
0x4002h: Validá los retornos de las operaciones de lectura y escritura de archivos — validación de retornos de E/S.
0x5006h: Preferí fgets sobre gets y scanf para leer cadenas — preferir
fgetsagetsyscanf.0x2016h: Escribí el contrato de la función antes de implementarla — contrato que fija las precondiciones.