¿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:
______________________________________________________________________________
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:
¿Que pasaría si removemos el carácter NULL manualmente ?
La importancia del carácter [i]NULL en un string[/i]
Hasta ahora los Memory overflow fueron controlados, pero que podría llegar a pasar ?.
Solo prueben algo así...
______________________________________________________________________________
Sizeof:
Sizeof es un operador que devuelve la cantidad de celdas de una variable/matriz/array/vector.
Ejemplos:
En variables normales
+Info: https://amxmodx-es.com/Thread-TUT-Llaves...les-y-char
En enum
Espero que mis explicaciones y ejemplos sean entendibles para todos, soy muy malo expresándome.
-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(myvar, charsmax(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(myvar, charsmax(myvar), "a") // Valor en memoria: [ 0 ]
// Forzamos el copiado
copy(cadena_buffer, 1, "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(buffer, 1, "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', 0 } // 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(overflow, 1, 9999)
______________________________________________________________________________
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]", item1, item2, item3, item_max) // Imprime "[0][1][3][9]"
/* Enum overflow */
copy(data, item_max, "123456789")
server_print("data:[%s] - item2:[%s] - item3:[%s]", data, data[item2], data[item3])
/* data:[123456789] - item2:[23456789] - item3:[456789]" */
Espero que mis explicaciones y ejemplos sean entendibles para todos, soy muy malo expresándome.
Tutoriales:
Aportes:
[API] Advanced Vault System - [API] sXe Injected Events - [Modulo] MySQL Threads 1.2 - [API] OldMenu 1.1
[TOOL] AMXX-Editor v2.2 (new)
MyAnimeList
Aportes:
[API] Advanced Vault System - [API] sXe Injected Events - [Modulo] MySQL Threads 1.2 - [API] OldMenu 1.1
[TOOL] AMXX-Editor v2.2 (new)
MyAnimeList