Pregunta de C

Alvaro Herrera alvherre en commandprompt.com
Mie Mayo 10 10:55:56 CLT 2006


rodrigo ahumada escribió:
> On Tue, 9 May 2006 20:07:10 -0400
> Alvaro Herrera <alvherre en alvh.no-ip.org> wrote:
> 
> > Se aprecia que las variables arr y nulls son creadas como arreglos del
> > tamaño especificado que no es constante en tiempo de compilacion, sino
> > que se determina en tiempo de ejecucion dependiendo del contenido del
> > struct Relation.
> > 
> > Es valido esto?  Debo mencionar que compila perfectamente sin ningun
> > warning (con varias opciones -W), y que funciona perfectamente para
> > algunos valores de foo->natts.  Sin embargo, el programa se cae en un
> > caso muy particular que es cuando foo->natts es 61, un valor superior a
> > los valores tipicos.  (natts es el numero de columnas de una tabla; por
> > lo tanto 61 es un valor perfectamente valido pero tipicamente los
> > valores andan cercanos a la veintena).
> 
> [...]
> 
> yo hice este codigo:
> 
> [...]

> y al ver el .s que sale:
>  (lo estuve siguiendo un poco, no se si lo hice bien, pero se nota que
>  en la funcion rareza, en dos partes se guardan bytes en el stack
>  segun el valor de [ebp+8] (valor))

Gracias!  Yo no se leer assembly lamentablemente :-(  Pero creo que tu
interpretacion tiene sentido, e indica que no hay un bug realmente, sino
que el codigo deberia funcionar.

> 	...
> .globl rareza
> 	.type	rareza, @function
> rareza:
> 	push	%ebp
> 	mov	%ebp, %esp
> 	push	%ebx
> 	sub	%esp, 36		  ; reserva 36 bytes en el stack 
> 	mov	DWORD PTR [%ebp-12], %esp ; guarda el tope del stack dentro de esos 36 bytes
> 	
> 	mov	%edx, DWORD PTR [%ebp+8]  ; edx = valor
> 	lea	%eax, [%edx+15]		  ; eax = valor +15
> 	add	%eax, 15		  ; eax = valor + 15 +15
> 	shr	%eax, 4			  ; eax = (valor + 15 +15) / 16
> 	sal	%eax, 4			  ; eax = ((valor + 15 +15) / 16) * 16  ¿?
> 	sub	%esp, %eax		  ; reserva EAX bytes mas en el stack 
> 	lea	%eax, [%esp+8]		  ; eax = 8 bytes antes del tope del stack
> 	add	%eax, 15		  ; 
> 	shr	%eax, 4
> 	sal	%eax, 4
> 	mov	DWORD PTR [%ebp-16], %eax

Segun esto, estaria reservando en el stack tanto espacio como sea
necesario para guardar el arreglo.

> el programa lo he probado con numeros mas grandes que 61 y no se me ha caido...
> de todas formas, al compilar da ni una queja, y alojar memoria el el stack 
> segun el valor de una variable... (!)

Ok, tengo que acotar que el problema parece ser que al llegar a un
cierto tope escribiendo en el arreglo, empieza a escribir en la variable
que viene despues en el stack.  O sea creo que algo asi deberia mostrar
el problema -- sin embargo, el programa funciona perfectamente y el
canario no se muere.

#include <stdio.h>
#include <stdlib.h>

struct foo
{
    int     bar;
};

int buggy(struct foo *a_foo)
{
    int     tam = a_foo->bar;
    char   *valor[tam];
    int     canario = 0x7e7e7e7e;
    int     i;

    printf("canario: %d\n", canario);

    for (i = 0; i < tam; i++)
    {
        valor[tam] = "hey";
    }

    printf("canario: %d (%d veces)\n", canario, i);

    return canario;
}

int main(int argc, char **argv)
{
    struct foo a_foo;

    if (argc >= 2)
        a_foo.bar = atoi(argv[1]);
    else
        a_foo.bar = 100;

    printf("ret: %d\n", buggy(&a_foo));

	return 0;
}

-- 
Alvaro Herrera                                http://www.CommandPrompt.com/
PostgreSQL Replication, Consulting, Custom Development, 24x7 support


Más información sobre la lista de distribución Linux