Autor
|
Tema: Memoria segura en Windows Win32? (Leído 4,960 veces)
|
t4r0x
Desconectado
Mensajes: 92
|
Buenas a todos quisiera saber si alguien me puede decir como puedo implementar un codigo el cual me asegura en no escribir mas bytes que el tamaño del buffer destino.
Lo que pasa es que en un proyecto tengo que crear memoria dinamica para muchas estructuras las cuales mantiene informacion en diferentes partes del proyecto usando HeapAlloc pero accidentalmente ya sea por mal calculos o mal escritura a la hora de escribir coidigo podria sobrepasar el tamaño de la memoria retornada por Heapalloc y lo peor de todos es que Windows no me dice cuando sobre escribo más del tamaño, ningun excepcion o algo así podrian darme alguna idea?
Si la idea es en C/C++ tambien me ayudaria gracias
|
|
« Última modificación: 31 Julio 2014, 23:33 pm por t4r0x »
|
En línea
|
|
|
|
Eternal Idol
Kernel coder
Moderador
Desconectado
Mensajes: 5.966
Israel nunca torturó niños, ni lo volverá a hacer.
|
Tenes que encapsular el acceso - al menos para escritura - a la memoria en cuestion para nunca acceder a la misma directamente, por ejemplo usando funciones propias que lo primero que hagan sea llamar a HeapSize y comprobar si debe o no continuar ...
|
|
|
En línea
|
La economía nunca ha sido libre: o la controla el Estado en beneficio del Pueblo o lo hacen los grandes consorcios en perjuicio de éste. Juan Domingo Perón
|
|
|
t4r0x
Desconectado
Mensajes: 92
|
Tenes que encapsular el acceso - al menos para escritura - a la memoria en cuestion para nunca acceder a la misma directamente, por ejemplo usando funciones propias que lo primero que hagan sea llamar a HeapSize y comprobar si debe o no continuar ...
Gracias eso me funciona para hacer una funcion tipo memcpy y comprobar pero como haria si por ejemplo tengo un array de algun tipo y no acceder a un indice superior al limite osea estaria accediendo a memoria no resevada, tambien situaciones donde pueda escribir mal un codigo puntero = HeapAlloc(sizeof(typedef de estructura)); // en este caso un incorrecto typedef o tamaño incorrecto puntero->miembro = valor; puntero->miembro = valor; ... podria estar accediendo a miembros pero que no hay memoria reservada para ellos.
|
|
|
En línea
|
|
|
|
Eternal Idol
Kernel coder
Moderador
Desconectado
Mensajes: 5.966
Israel nunca torturó niños, ni lo volverá a hacer.
|
Gracias eso me funciona para hacer una funcion tipo memcpy y comprobar pero como haria si por ejemplo tengo un array de algun tipo y no acceder a un indice superior al limite osea estaria accediendo a memoria no resevada, tambien situaciones donde pueda escribir mal un codigo Eso ya no seria assembly pero la respuesta es la misma, no accedes directamente, tenes una funcion (metodo de la clase si hablamos de C++) que comprueba el limite del array. puntero = HeapAlloc(sizeof(typedef de estructura)); // en este caso un incorrecto typedef o tamaño incorrecto puntero->miembro = valor; puntero->miembro = valor; ...
podria estar accediendo a miembros pero que no hay memoria reservada para ellos. Seguimos en la misma, no uses HeapAlloc directamente, usa un constructor de C++ o una funcion de inicializacion. Usa codigo seguro para todo ...
|
|
|
En línea
|
La economía nunca ha sido libre: o la controla el Estado en beneficio del Pueblo o lo hacen los grandes consorcios en perjuicio de éste. Juan Domingo Perón
|
|
|
t4r0x
Desconectado
Mensajes: 92
|
Eso ya no seria assembly pero la respuesta es la misma, no accedes directamente, tenes una funcion (metodo de la clase si hablamos de C++) que comprueba el limite del array.
Seguimos en la misma, no uses HeapAlloc directamente, usa un constructor de C++ o una funcion de inicializacion. Usa codigo seguro para todo ...
Ya te entiendo muchas gracias!
|
|
|
En línea
|
|
|
|
Eternal Idol
Kernel coder
Moderador
Desconectado
Mensajes: 5.966
Israel nunca torturó niños, ni lo volverá a hacer.
|
De nadas
|
|
|
En línea
|
La economía nunca ha sido libre: o la controla el Estado en beneficio del Pueblo o lo hacen los grandes consorcios en perjuicio de éste. Juan Domingo Perón
|
|
|
x64core
Desconectado
Mensajes: 1.908
|
Cuidado con HeapSize ya que este podría no retornar el mismo valor pasado a HeapAlloc, la función retorna el tamaño del buffer, este podría ser mayor debido a un posible alineamiento, esos bytes adicionales son validos a usar, así que donde podría haber un error copiando un numero mayor de bytes que el numero supuestos a reservados, serian copiados correctamente.
En mi experiencia podría decir que para aplicaciones donde se requiera gran uso de memoria dinámica del heap y quieran mantener control de ella además de prevenir cualquier fuga de memoria es mejor crear tu propio heap privado para la aplicación ( HeapCreate ) y reservar memoria desde ese heap así al final o en cualquier punto del programa que queramos comprobar cualquier fuga podemos validar los nodos eso ahorra un montón de tiempo en depuración.
Además si es C++ se implementa una clase como te dijo Eternal Idol, el acceso a esa memoria no seria de ninguna manera directa y la implementación de HeapAlloc o wrapper a ella debería retornar un descriptor no un puntero a la memoria en sí, ya que si se retorna el puntero, este podría ser manipulado y también estar apuntando a memoria no reservada o en el peor de los casos a memoria valida pero de al bloque que esperamos a copiar sino a otro.
|
|
|
En línea
|
|
|
|
t4r0x
Desconectado
Mensajes: 92
|
Cuidado con HeapSize ya que este podría no retornar el mismo valor pasado a HeapAlloc, la función retorna el tamaño del buffer, este podría ser mayor debido a un posible alineamiento, esos bytes adicionales son validos a usar, así que donde podría haber un error copiando un numero mayor de bytes que el numero supuestos a reservados, serian copiados correctamente.
En mi experiencia podría decir que para aplicaciones donde se requiera gran uso de memoria dinámica del heap y quieran mantener control de ella además de prevenir cualquier fuga de memoria es mejor crear tu propio heap privado para la aplicación ( HeapCreate ) y reservar memoria desde ese heap así al final o en cualquier punto del programa que queramos comprobar cualquier fuga podemos validar los nodos eso ahorra un montón de tiempo en depuración.
Además si es C++ se implementa una clase como te dijo Eternal Idol, el acceso a esa memoria no seria de ninguna manera directa y la implementación de HeapAlloc o wrapper a ella debería retornar un descriptor no un puntero a la memoria en sí, ya que si se retorna el puntero, este podría ser manipulado y también estar apuntando a memoria no reservada o en el peor de los casos a memoria valida pero de al bloque que esperamos a copiar sino a otro.
Gracias por eso, lo que no entiendo es eso del descriptor podrias decirme como es que funciona? tambien vuelvo a retomar el tema ya que no logro aun hacer lo que se supone que se debe este es mi codigo: class MiMemoria { public: void* MyMalloc(int Size); void MyFree(void* Pointer); void MyMemcpy(void* Dest, void* Src, int size); private:
};
void* MiMemoria::MyMalloc(int Size) { return HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, Size); }
void MiMemoria::MyFree(void* Pointer) { HeapFree(GetProcessHeap(), 0, Pointer); }
void MyMemcpy(void* Dest, void* Src, int Size) { int Memsize; Memsize = HeapSize(GetProcessHeap(), 0, Dest);
if (Memsize > Size) { memcpy(Dest, Src, Size); } else { printf("Error!\n"); } } o MASM: .386 .model flat,stdcall
include masm32rt.inc
.code
MyMalloc proc MySize:DWORD invoke GetProcessHeap invoke HeapAlloc,eax,HEAP_ZERO_MEMORY,MySize ret MyMalloc endp
MyFree proc Pointer:LPVOID invoke GetProcessHeap invoke HeapFree,eax,0,Pointer ret MyFree endp
MyMemcpy proc Dest:LPVOID,Src:LPVOID,MySize:DWORD invoke GetProcessHeap invoke HeapSize,eax,0,Dest .if eax > MySize invoke RtlMoveMemory,Dest,Src,MySize .else print chr$("Error!\n") .endif ret MyMemcpy endp
end
por favor diganme si lo estoy haciendo bien pero en la funcion MyMemcpy no funciona al veces, además intente hacer algo asi: MiMemoria Test1; MY_TYPE* Tipo1; Tipo1 = Test1.MyMalloc(sizeof(MY_TYPE)); Test1.MyMemcpy(&Tipo1->Miembro1,&Variable_Test_1,sizeof(Variable_Test_1)); Test1.MyMemcpy(&Tipo1->Miembro2,&Variable_Test_2,sizeof(Variable_Test_2)); Test1.MyMemcpy(&Tipo1->Miembro3,&Variable_Test_3,sizeof(Variable_Test_3)); Test1.MyMemcpy(&Tipo1->Miembro4,&Variable_Test_4,sizeof(Variable_Test_4)); me dio error creo que es el puntero, y quiero preguntarles si es buena practica hacer eso es que veo que cada vez que quiero establecer un miembro tendria que llamar a muchas funciones, nose si esta bien o no... y el codigo lo veo bien 'raro' en lugar de solo hacer esto Tipo1->Miembro1 = Variable_Test_1; Tipo1->Miembro2 = Variable_Test_2; Tipo1->Miembro3 = Variable_Test_3; Tipo1->Miembro4 = Variable_Test_4; eso se mira mas normal creo...
|
|
|
En línea
|
|
|
|
Eternal Idol
Kernel coder
Moderador
Desconectado
Mensajes: 5.966
Israel nunca torturó niños, ni lo volverá a hacer.
|
http://en.wikipedia.org/wiki/Handle_%28computing%29En definitiva son punteros indirectos, una manera MUY sencilla de implementarlos es usando un array, cada indice es un HANDLE y ese elemento del array es un puntero, el programa trabaja con los HANDLEs e internamente se hace la referencia al puntero. En lenguajes de bajo nivel lo normal es trabajar con la memoria directamente (en C++ tambien podes usar los contenedores de la STL), es mucho mas eficiente el codigo correcto que encapsular todo, es decir esto "pero accidentalmente ya sea por mal calculos o mal escritura a la hora de escribir" no sucede con un codigo bien escrito ... Test1.MyMemcpy( &Tipo1->Miembro1,&Variable_Test_1,sizeof(Variable_Test_1)); HeapSize dice que le pases: A pointer to the memory block whose size the function will obtain. This is a pointer returned by the HeapAlloc or HeapReAlloc function. No sera el caso evidentemente, solo Tipo1 en si mismo es un puntero devuelto por HeapAlloc. En fin, es tu codigo, no esta completo y lo escribiste en dos lenguajes asi que depuralo para ver cual es el problema.
|
|
|
En línea
|
La economía nunca ha sido libre: o la controla el Estado en beneficio del Pueblo o lo hacen los grandes consorcios en perjuicio de éste. Juan Domingo Perón
|
|
|
t4r0x
Desconectado
Mensajes: 92
|
http://en.wikipedia.org/wiki/Handle_%28computing%29En definitiva son punteros indirectos, una manera MUY sencilla de implementarlos es usando un array, cada indice es un HANDLE y ese elemento del array es un puntero, el programa trabaja con los HANDLEs e internamente se hace la referencia al puntero. En lenguajes de bajo nivel lo normal es trabajar con la memoria directamente (en C++ tambien podes usar los contenedores de la STL), es mucho mas eficiente el codigo correcto que encapsular todo, es decir esto "pero accidentalmente ya sea por mal calculos o mal escritura a la hora de escribir" no sucede con un codigo bien escrito ... Test1.MyMemcpy( &Tipo1->Miembro1,&Variable_Test_1,sizeof(Variable_Test_1)); HeapSize dice que le pases: A pointer to the memory block whose size the function will obtain. This is a pointer returned by the HeapAlloc or HeapReAlloc function. No sera el caso evidentemente, solo Tipo1 en si mismo es un puntero devuelto por HeapAlloc. En fin, es tu codigo, no esta completo y lo escribiste en dos lenguajes asi que depuralo para ver cual es el problema. Yo pense que en lenguajes de bajo nivel como ensamblador, C y C++ es donde se usaba mas cosas seguras como esto que estoy intentando hacer... pero si, en programas en ensamblador, C , C++ creo que no he visto clases que encapsuland el acceso a memoria... la verda me he desanimado a continuar esta clase y mejor intentar a escribir solo codigo bien escrito pero si me pueden decir si esta bien o no, realmente el buen habito es acostumbrarse a lenguajes de bajo nivel y escribir codigo buen seguro sin hacer tantas clases? asi es como hacen los profesionales? por ejemplo asi es como programas como chrome, firefox son escritos? gracias por eso.
|
|
|
En línea
|
|
|
|
|
|