¿El desbordamiento del búfer cambia el tipo de datos de la variable que está sobrescribiendo? [cerrado]


8

Digamos que tiene una matriz de caracteres C char buf[15]. Digamos que la variable int set_me = 0tiene sus datos almacenados en una ubicación de memoria directamente después char buf[15]. Si me desbordara bufcon una cadena "aaabbbcccdddeee\xef\xbe\xad\xde", ¿ set_mecambiaría el tipo de datos de un entero a una matriz de caracteres?


3
Depende de quién está interpretando los datos. Finalmente todo es binario. Entonces, la forma en que lo interpreta, puede ser un valor entero válido o causar un error de
conversión

Respuestas:


33

No.

El "tipo de datos" de una variable solo es relevante en el código fuente (y aun así solo en algunos idiomas). Le dice al compilador cómo tratar la variable.

Estos tipos de datos de alto nivel no existen como tales en el código compilado (nativo). Pueden afectar las instrucciones que genera un compilador, pero a las instrucciones en sí no les importa si los datos representan un carácter o un número.


Las variables no existen en el hardware. En hardware, tiene ubicaciones de memoria y las instrucciones que operan en ellas.

Una variable podría verse como una vista de los datos en una ubicación de memoria: si entrecierra los ojos y mira la misma memoria de manera ligeramente diferente (una variable diferente con un tipo diferente que se refiere a la misma ubicación), el mismo valor binario puede tener un significado diferente .

Por ejemplo, el byte 0x41 podría interpretarse como el carácter codificado en UTF-8 A. También podría interpretarse como el entero de un solo byte 65. También podría interpretarse como un byte en un número entero de varios bytes o un número de coma flotante, o un byte en una codificación de caracteres de varios bytes. Podría ser el bitset 0b1000001. Todo desde el mismo byte en la misma ubicación de memoria. En el lenguaje C, puede ver este efecto al transmitir a estos diferentes tipos.

Cuando tiene un "desbordamiento de búfer", está haciendo algo fuera de los límites de lo que su compilador o idioma podría esperar. Pero, en lo que respecta al hardware 1 , está escribiendo bytes (ya sean únicos o múltiples) en una ubicación de memoria. Una ubicación de memoria no tiene un "tipo". De hecho, el hardware ni siquiera sabe que un conjunto particular de bytes forma una matriz o búfer en su código.

La próxima vez que acceda a esa ubicación de memoria en su código, las instrucciones se ejecutarán como se definió originalmente. por ejemplo, si esperaban un número allí, actuarían en cualquier byte de datos como si fueran un número.


Para usar su ejemplo, suponiendo que su intes un entero de 4 bytes con signo (32 bits):

+-------------+--------------------------------------------+-----------+
| Source code |                  char[15]                  |    int    |
+-------------+--------------------------------------------------------+
| Memory      |61|61|61|62|62|62|63|63|63|64|64|64|65|65|65|EF|BE|AD|DE|
+-------------+--------------------------------------------------------+

Puede ver que la intubicación de la memoria de ahora contiene 0xEFBEADDE, suponiendo un sistema big-endian 2 . Este es el int firmado de 32 bits -272716322. Ahora, si interpreta la misma memoria que un unsigned int ( uint), sería en su 4022250974lugar. Para exactamente los mismos datos en la memoria, el significado depende completamente de cómo lo veas.


1 Hay algunos mecanismos que le impiden escribir en regiones protegidas de memoria y bloqueará su programa si intenta hacerlo.

2 x86 es en realidad little-endian, lo que significa que interpreta los bytes que forman un valor mayor al revés. Entonces, en x86, en cambio 0xDEADBEEF, tendría , dando firmado -559038737o sin firmar 3735928559.


Entonces 0xdeadbeef, en una arquitectura x86, ¿ocuparía menos espacio en la memoria que su contraparte decimal 3735928559?
Darien Springer

1
@DarienSpringer Ambos tienen exactamente el mismo patrón de bits.
dsstorefile1

2
@DarienSpringer Ambos ocupan 4 bytes de memoria, son la misma secuencia de 4 bytes. Son idénticos en la memoria. Si lo desea, puede considerar que todo es base 2 (binario) en la memoria. Luego, cuando los muestre (convierta en una cadena para la salida), puede elegir una base para mostrar: el hexadecimal es la base 16 y el decimal es la base 10. Las representaciones de las cadenas se almacenan en una ubicación de memoria diferente y pueden usar diferentes cantidades de memoria (ya que cada carácter es un byte separado). La cadena 0xDEADBEEF se almacena en la memoria como 0x30 0x78 0x44 0x45 0x41 0x44 0x42 0x45 0x45 0x46.
Bob

55
@DarienSpringer Dicho de otra manera, un número es el mismo número sin importar en qué base se encuentre. El hexadecimal es una forma conveniente (compacta) de ver binarios. Físicamente, es binario. A los humanos les gusta el decimal, por lo que con mayor frecuencia mostramos los números como decimales. Pero hasta que lleguemos al paso de visualización, todas las operaciones numéricas (sumar, restar, multiplicar, etc.) funcionan en los mismos datos binarios en la memoria.
Bob

1
"Se puede ver que la ubicación de memoria del int ahora es 0xEFBEADDE" Nitpick: Sé que no tenía la intención de esto, pero parece que está diciendo que el int se encuentra en la ubicación de la memoria 0xEFBEADDE. Quizás reformule eso un poco. De lo contrario, esta es una excelente respuesta: me gusta especialmente la analogía de "vista" y la idea de "entrecerrar los ojos" :)
Las carreras de ligereza en órbita

2

Desde una perspectiva C, la respuesta sería "¿Quién sabe? Es un comportamiento indefinido".

Los tipos son un concepto C, no un hardware. Pero las reglas de C no se aplican si su programa tiene Comportamiento indefinido, ese es el significado literal de Comportamiento indefinido en el estándar C. Y los desbordamientos del búfer son una forma de eso.

Inicialmente escribí "las reglas C ya no se aplican", pero de hecho, el comportamiento indefinido es retroactivo. Las reglas C no se aplican a un programa que tendrá un comportamiento indefinido en el futuro.

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.