Bugs y Exploits‎ > ‎Introducción‎ > ‎

Errores de programación comunes



División por cero

Una división por cero es, en informática, un clásico error lógico.

Puesto que muchos algoritmos informáticos clásicos de división usan el método de restas sucesivas, al ser el divisor cero, la resta como tal se ejecuta por siempre, ya que el dividendo nunca cambia. La aplicación en cuestión entra entonces en un bucle infinito.

Para prevenir esto, actualmente los procesadores matemáticos entregan un error al sistema si durante una división el divisor es cero. Este error suele ser de una categoría tal que la aplicación en cuestión será terminada sin remedio.

Por su parte, los compiladores más modernos incorporan mensajes de error cuando una división por cero ocurre explícitamente; algunos compiladores también pueden tratar de detectar divisiones por cero no explícitas. Aquellos lenguajes que incorporan manejo de excepciones pueden capturar este evento para que sea tratado apropiadamente, ejecutando un código especialmente dedicado a este caso.



Bucle infinito

Bucle infinito en programación es aquel ciclo que se repite de forma indefinida ya que su condición para finalizar nunca se cumple.

Por definición un bucle debe contener condiciones que establezcan cuándo empieza y cuándo acaba, de manera que, mientras las condiciones se cumplan, ejecute una secuencia de código de manera repetitiva. En el caso de ciclo infinito, si la condición de finalización no se alcanza, el bucle seguirá ejecutando el segmento de código indefinidamente.



Ejemplo de Ciclo Infinito en C (WHILE)


 #include<stdio.h>

int main(void)
{
int x = 0;
while(x < 10)
{
if(x == 9)
x = 0;
x++;
printf("No acabare nunca!\n");
}
return 0;
}

Se observa que la sentencia printf("No acabare nunca\n"); siempre se ejecuta porque la condición del bucle while() siempre es cierta, no existe una condición de salida que obligue al bucle a finalizar. Exactamente, no se alcanza la condición de salida.



Ejemplo de Ciclo Infinito en C (FOR)


 #include<stdio.h>

int main(void)
{
for(int cont=0;cont<5;cont++)
{
if (cont==4)
cont=0;
printf("%d\n",cont);
}
return 0;
}

En la sentencia "printf" se muestra en pantalla 0,1,2,3,0,1,2,3,0,.... infinitamente y mientras no llegue a 5 no se cerrará el programa.



Problemas aritméticos

Un problema aritmético (dentro de la computación), se denomina al desbordamiento de datos debido a la sobre ocupación (overflow) de la memoria disponible como tipos de datos.


Overflow (Desbordamiento)

Cuando el resultado de sumar dos o más números (hablando en sistema numeral decimal) es igual o mayor que 10 (diez), se coloca la primera cifra bajo la columna que se está sumando y la segunda cifra marca el desbordamiento y se añade a la siguiente columna a la izquierda. En otros países también es conocido como reserva. Ejemplo: en la suma 6 + 8 = 14, la cifra 1, marca el acarreo y debe sumarse a la siguiente columna de acuerdo al valor relativo de la misma; en este caso es cero, por tanto, puede expresarse como 0 + 1 = 1.

En informática es motivo de fuertes precauciones para evitar su aparecimiento o tratarlo si aparece. Al realizar una operación aritmética en binario, si el bit más alto resulta conllevar un acarreo, no hay forma de representar una cifra más para ese acarreo.

Por ejemplo, si sumamos dos números de 32 bits y solo podemos representar su resultado en 32 bits pero el resultado conlleva un acarreo, necesitaríamos 33 bits para poder representarlo, pero como esto no es posible, ese valor se pierde dando lugar a un error de cálculo.


Underflow (Subdesbordamiento)

En informática un subdesbordamiento de búfer (Buffer underflow/underrun) es un problema aritmético, esto sucede cuando un búfer carga su información (flujo de datos) a una velocidad más baja que el procesamiento de la misma, esto hace que el programa o dispositivo que procesa dicha información se detenga momentánea y seguidamente por el hecho de que si continua, estaría haciendo una solicitud a un espacio de memoria nula, un subdesbordamiento de búfer puede efectuarse en cualquier software o dispositivo que dependa del flujo de datos o carga de un búfer: Grabadores, exploradores de internet, etc.

Ejemplo de Subdesbordamiento:

búfer.cargar.velocidad 2
programa.procesar.info.velocidad 3

En este caso el búfer carga información a una velocidad de valor "2" y es procesado por el programa
o dispositivo a una velocidad de valor "3" (1 de offset).


Fuga de memoria

Error de software que ocurre cuando un bloque de memoria reservada no es liberada en un programa 
de computación. Comúnmente ocurre porque se pierden todas las referencias a esa área de memoria
antes de haberse liberado

Dependiendo de la cantidad de memoria perdida y el tiempo que el programa siga en ejecución, este problema puede llevar al agotamiento de la memoria disponible en la computadora.

Este problema se da principalmente en aquellos lenguajes de programación en los que el manejo de memoria es manual (C o C++ principalmente), y por lo tanto es el programador el que debe saber en qué momento exacto puede liberar la memoria. Otros lenguajes utilizan un recolector de basura que automáticamente efectúa esta liberación. Sin embargo todavía es posible la existencia de fugas en estos lenguajes si el programa acumula referencias a objetos, impidiendo así que el recolector llegue a considerarlos en desuso.

Existen varias formas de luchar contra este problema. Una forma es el uso de un recolector de basura incluso en el caso en el que éste no sea parte estándar del lenguaje. El más conocido recolector de basura usado de esta manera es el Boehm-Demers-Weiser conservative garbage collector. Otras técnicas utilizadas son la adopción de esquemas de conteo de referencias o el uso de pools de memoria (técnica menos popular, utilizada en el servidor Apache y en el sistema de versiones Subversion).

También hay herramientas para "auscultar" un programa y detectar las fugas. Una de las herramientas más conocidas es Valgrind.



Desbordamiento de búfer

En seguridad informática y programación, un desbordamiento de buffer (del inglés buffer overflow o buffer overrun) es un error de software que se produce cuando se copia una cantidad de datos sobre un área que no es lo suficientemente grande para contenerlos, sobrescribiendo de esta manera otras zonas de memoria. Esto se debe en general a un fallo de programación. La consecuencia de escribir en una zona de memoria imprevista puede resultar impredecible. Existen zonas de memoria protegidas por el sistema operativo. Si se produce la escritura fuera de una zona de memoria protegida se producirá una excepción del sistema de acceso a memoria seguido de la terminación del programa. Bajo ciertas condiciones, un usuario obrando con malas intenciones puede aprovecharse de este mal funcionamiento o una vulnerabilidad para acceder tener control sobre el sistema. agujero de seguridad.

En algunas ocasiones eso puede suponer la posibilidad de alterar el flujo del programa pudiendo hacer que éste realice operaciones no previstas. Esto es posible dado que en las arquitecturas comunes de computadoras, la memoria no tiene separación entre la dedicada a datos y a programa.

Si el programa que tiene el error en cuestión tiene privilegios especiales se convierte además en un fallo de seguridad. El código copiado especialmente preparado para obtener los privilegios del programa atacado se llama shellcode.


Código fuente de ejemplo

En el siguiente ejemplo se presenta un código fuente en C con un error de programación. Una vez compilado, el programa generará un desbordamiento de buffer si se lo invoca desde la línea de comandos con un argumento lo suficientemente grande, pues este argumento se usa para llenar un buffer, sin validar previamente su longitud.

/* overflow.c - demuestra un desbordamiento de buffer */

#include <stdio.h>
#include <string.h>

int main(int argc, char *argv[])
{
char buffer[10];
if (argc < 2)
{
fprintf(stderr, "MODO DE USO: %s string\n", argv[0]);
return 1;
}
strcpy(buffer, argv[1]);
return 0;
}

Strings de 9 caracteres o menos no provocarán desbordamiento de buffer. Por el contrario, strings de 10 caracteres o más sí: esto siempre es incorrecto, aunque no siempre resultará en un error del programa o segmentation fault.

Este programa puede reescribirse en forma más segura usando la función strncpy de la siguiente manera.

/* mejor.c - demuestra un método de resolver el problema */

#include <stdio.h>
#include <string.h>

int main(int argc, char *argv[])
{
char buffer[10];
if (argc < 2)
{
fprintf(stderr, "MODO DE USO: %s string\n", argv[0]);
return 1;
}
strncpy(buffer, argv[1], sizeof(buffer));
buffer[sizeof(buffer) - 1] = '\0';
return 0;
}

Nota: depuración de programas es el proceso de identificar y corregir errores.

http://es.wikipedia.org/wiki/Error_de_software
Comments