[TUT] Memory overflow, Null-terminated y Sizeof
#1
¿Que veremos en este tutorial?
-Final de cadenas.
-Desbordamiento de memoria.
-Operador sizeof.


Glosario
- Array : (variable multidimensional / matriz / vector)
- String : (cadena de caracteres)
- Null-terminated[/b] : (final de cadenas)
- Memory overflow / Buffer overrun : (Desbordamiento de búfer)
- Celda : (cell: El único tipo de dato en pawn, equivale a un entero de 32bits)
- Length : (len / largo: Conteo de caracteres desde el inicio hasta encontrar un final de cadena NULL)
______________________________________________________________________________


Final de cadenas (Null-terminated):
Esto es algo básico y doy por hecho de que el 90% de los que lean esto ya lo saben.

Para los pocos que no lo sepan:
Las cadenas de caracteres siempre tienen un carácter extra que indica el final del mismo, el carácter es '^0', o simplemente NULL (cero). Esa es la razón por la que siempre se agrega una celda extra a la matriz que lo contiene.


Código para entender mejor:
Código PHP:
// Charsmax es un alias de sizeof que deja una celda extra para el final de cadena
#define charsmax(%1) (sizeof(%1)-1)

// Valido
new myvar[2] = "a" // sizeof = 2  -  Valor en memoria: [ 97, 0 ]
new myvar[] = "a" // sizeof = 2  -  Valor en memoria: [ 97, 0 ]
new myvar[3] = "a" // sizeof = 3  -  Valor en memoria: [ 97, 0, 0 ]

// ERROR, invalido ( no compila )
new myvar[1] = "a" 

Código PHP:
// Valido
new myvar[2]

copy(myvarcharsmax(myvar), "a"

Código PHP:
// ERROR, invalido ( solo hay espacio para el carácter NULL  )
new myvar[1]

// En este caso, charsmax devuelve 0, por lo que no copia ningún dato
copy(myvarcharsmax(myvar), "a"// Valor en memoria: [ 0 ]


// Forzamos el copiado
copy(cadena_buffer1"a"// Valor en memoria: [ 97 ]

/* En este punto nos metemos en el Memory overflow, 
ya que el carácter NULL que indica el final de la cadena se copio fuera del área asigna, 
pudiendo provocar fallos drásticos. */ 



______________________________________________________________________________


Desbordamiento de buffer (Memory overflow o buffer overrun):
Es un error que se produce cuando se copian datos sobrepasando la área de memoria asignada al buffer (la variable de salida). Los bytes sobrantes se almacenan en zonas de memoria adyacentes, sobrescribiendo su contenido original, que probablemente pertenecían a datos o código almacenados en memoria. ( En otra palabras,podes cagarla mal ).

Como vimos en el ultimo ejemplo de Final de cadenas, al tratar de copiar datos sin tener el espacio suficiente proboca un Memory overflow.

Para los recién iniciados es difícil entender solo con palabras, mejor les dejo ejemplos.

Vamos a aprovechar que la área de memoria de las variables static son asignadas consecutivamente según el orden en que son creadas.

Simple Memory overflow:
Código PHP:
static buffer[1// sizeof = 1  - Valor en memoria: [ 0 ]
static string[] = "hola" // sizeof = 5  - Valor en memoria: [ 104, 111, 108, 97, 0 ]
/* Valor en memoria de 'buffer' + 'string' : [ ... ( 0 ), ( 104, 111, 108, 97, 0 ) ... ] */


server_print("[%s]"string// Imprime "[hola]"

copy(buffer1"a"// El carácter NULL sobrepasa el área asignada a 'buffer' y se escribe en el área asignada a 'string'

/* Valores en memoria:
- 'buffer': [ 97 ]
- 'cadena': [ *0, 111, 108, 97, 0 ]
- 'buffer' + 'string': [ ... ( 97 ), ( 0, 111, 108, 97, 0 ) ... ]
*/

server_print("[%s]"string// Imprime "[]"
server_print("[%s]"buffer// Imprime "[a]" 

¿Que pasaría si removemos el carácter NULL manualmente ?
Código PHP:
// Removemos el carácter NULL
string[0] = 'h' // Valor en memoria: [ 104, 111, 108, 97, 0 ]
/* Valor en memoria de 'buffer' + 'string' : [ ... ( 97 ), ( 104, 111, 108, 97, 0 ) ... ] */


server_print("[%s]"string// Imprime "[hola]"

/*
- Se va a imprimir todo hasta que encuentre el carácter NULL en el área de memoria de 'string'
- 'buffer' + 'string' : [ (97), (104, 111, 108, 97, 0) ]
*/
server_print("[%s]"buffer// Imprime "[ahola]" 

La importancia del carácter [i]NULL en un string[/i]
Código PHP:
// Trataremos de re-crear dos strings carácter por carácter

static bad_str[] = { 'h''o''l''a'' ' // Invalido, falta el carácter NULL
static str[] = { 'm''u''n''d''o'// Valido

server_print("[%s]"str// Imprime "[mundo]"


/* Podes adivinar que pasaría si tratamos de imprimir 'bad_str' ? */
server_print("[%s]"bad_str// Imprime "[hola mundo]"
/* Como ya saben al no encontrar el carácter NULL sigue recorriendo la memoria hasta encontrar uno */ 

Hasta ahora los Memory overflow fueron controlados, pero que podría llegar a pasar ?.
Solo prueben algo así...
Código PHP:
new overflow[1]
arrayset(overflow19999


______________________________________________________________________________


Sizeof:
Sizeof es un operador que devuelve la cantidad de celdas de una variable/matriz/array/vector.

Ejemplos:

En variables normales
Código PHP:
new var, var2[2], var3[999], var4[3][8]

server_print("[%d]"sizeof var) // Imprime [1] 
server_print("[%d]"sizeof var2// Imprime [2] 
server_print("[%d]"sizeof var3// Imprime [999] 
server_print("[%d]"sizeof var4// Imprime [3] 
server_print("[%d]"sizeof var4[]) // Imprime [8] 

+Info: https://amxmodx-es.com/Thread-TUT-Llaves...les-y-char

En enum
Código PHP:
enum _:_data_struct // = 10
{
    
item1// 0        +1
    
item2[2], // 1    +2
    
item3[6], // 3    +6 
    
item_max // 9    +1
}

new 
data[_data_struct// Es lo mismo que data[10]


server_print("[%d]",  _data_struct// Imprime el tamaño total del enum "[10]"
server_print("[%d]",  sizeof data// Imprime "[10]"
server_print("[%d]",  sizeof g_data[item2]) // Imprime "[2]"
server_print("[%d]",  sizeof g_data[item3]) // Imprime "[6]"

server_print("[%d][%d][%d][%d]",  item1item2item3item_max// Imprime "[0][1][3][9]"

/* Enum overflow */
copy(dataitem_max"123456789")
server_print("data:[%s] - item2:[%s] - item3:[%s]"datadata[item2], data[item3])

/* data:[123456789] - item2:[23456789] - item3:[456789]" */ 


Espero que mis explicaciones y ejemplos sean entendibles para todos, soy muy malo expresándome.
Responder
#2
no me quedo claro lo de Memory overflow, lo de caracter null si e.e

se agradece que estes aportando asi
Ingeniero agrónomo y desarrollador de Software.

tutoriales-allied
buscas un zp?

"La imitación es la forma más sincera de admiración con la que puede pagar la mediocridad a la grandeza"

Merci Alliedmodders pour m'introduire dans la programmation.
Responder
#3
Buena info, me quedaron en claro varias cosas.


(30/09/2014, 08:11 PM)roccoxx escribió: no me quedo claro lo de Memory overflow

Overflow = "Desbordar"

Más o menos para que entiendas. Esto sucede cuando, por ejemplo, le asignas una cantidad de celdas a matriz/array/vector y se sobre pasa el límite, causando como consecuencia que la cantidad de bytes que sobre se "guarden" en partes de memoria contigua, sobrescribiendo los datos de esa "otra" memoria en lo que podrías terminar arruinando esos valores.
Believe, be yourself and don't hold on to just one dream ❤

https://github.com/FEDERICOMB96
Responder
#4
(30/09/2014, 08:23 PM)Federicomb escribió: Buena info, me quedaron en claro varias cosas.


(30/09/2014, 08:11 PM)roccoxx escribió: no me quedo claro lo de Memory overflow

Overflow = "Desbordar"

Más o menos para que entiendas. Esto sucede cuando, por ejemplo, le asignas una cantidad de celdas a matriz/array/vector y se sobre pasa el límite, causando como consecuencia que la cantidad de bytes que sobre se "guarden" en partes de memoria contigua, sobrescribiendo los datos de esa "otra" memoria en lo que podrías terminar arruinando esos valores.

"Es un error que se produce cuando se copian datos sobrepasando la área de memoria asignada al buffer (la variable de salida). Los bytes sobrantes se almacenan en zonas de memoria adyacentes, sobrescribiendo su contenido original, que probablemente pertenecían a datos o código almacenados en memoria. ( En otra palabras,podes cagarla mal " lo volvi a leer y me quedo claro, eso por leerlo a las apuradas, gracias igual.

espero tu otro tut destro e.e
Ingeniero agrónomo y desarrollador de Software.

tutoriales-allied
buscas un zp?

"La imitación es la forma más sincera de admiración con la que puede pagar la mediocridad a la grandeza"

Merci Alliedmodders pour m'introduire dans la programmation.
Responder
#5
Hubiera echo imágenes para explicar mejor las áreas/zonas de memoria, pero con mi inet 3G me es imposible ahora :\.
Responder
#6
no quiero arruinarla... pero para que sirve esto.. o sea en que caso?? aprendo pawn de a poco Sonrisa
Responder
#7
Buenisimo destro tengo muchas dudas con sizeof y chars.

Cuando pueda me lo pongo a estudiar.

EDIT:

Hacemos vaquita y le pagamos inet de 12mb a Destro?
Responder
#8
(09/11/2014, 04:52 PM)niko1921 escribió: no quiero arruinarla... pero para que sirve esto.. o sea en que caso?? aprendo pawn de a poco Sonrisa

Es para que tengas en cuenta mas que nada...
Responder
#9
Código PHP:
new overflow[1]
arrayset(overflow19999
Que sucedería?
Responder


Salto de foro:


Usuarios navegando en este tema: 1 invitado(s)