Digamos que tiene una matriz de caracteres C char buf[15]
. Digamos que la variable int set_me = 0
tiene sus datos almacenados en una ubicación de memoria directamente después char buf[15]
. Si me desbordara buf
con una cadena "aaabbbcccdddeee\xef\xbe\xad\xde"
, ¿ set_me
cambiaría el tipo de datos de un entero a una matriz de caracteres?
8
Respuestas:
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 byte65
. 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 bitset0b1000001
. 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
int
es un entero de 4 bytes con signo (32 bits):Puede ver que la
int
ubicación de la memoria de ahora contiene0xEFBEADDE
, 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 su4022250974
lugar. 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-559038737
o sin firmar3735928559
.fuente
0xdeadbeef
, en una arquitectura x86, ¿ocuparía menos espacio en la memoria que su contraparte decimal3735928559
?0xDEADBEEF
se almacena en la memoria como0x30 0x78 0x44 0x45 0x41 0x44 0x42 0x45 0x45 0x46
.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" :)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.
fuente