Não.
O "tipo de dados" de uma variável é relevante apenas no código fonte (e mesmo assim apenas em alguns idiomas). Diz ao compilador como tratar a variável.
Esses tipos de dados de alto nível não existem como tal no código compilado (nativo). Eles podem afetar as instruções que um compilador gera, mas as próprias instruções não se importam se os dados representam um caractere ou um número.
Variáveis não existem no hardware. No hardware, você tem locais de memória e as instruções que os operam.
Uma variável pode ser vista como uma visualização dos dados em um local de memória - se você olhar de soslaio e olhar para a mesma memória de maneira um pouco diferente (uma variável diferente com um tipo diferente referente à mesma localização), o mesmo valor binário pode ter um significado diferente .
Por exemplo, o byte 0x41 pode ser interpretado como o caractere codificado em UTF-8 A
. Também pode ser interpretado como o número inteiro de byte único 65
. Também pode ser interpretado como um byte em um número inteiro de vários bytes ou número de ponto flutuante, ou um byte em uma codificação de caracteres de vários bytes. Poderia ser o bitset 0b1000001
. Tudo a partir do mesmo byte no mesmo local da memória. Na linguagem C, você pode ver esse efeito transmitindo para esses diferentes tipos.
Quando você tem um "buffer overflow", está fazendo algo fora dos limites esperados pelo seu compilador ou idioma. Mas, no que diz respeito ao hardware 1 , você está gravando bytes (únicos ou múltiplos) em um local de memória. Um local de memória não possui um "tipo". De fato, o hardware nem sabe que qualquer conjunto específico de bytes cria uma matriz ou buffer no seu código.
Sempre que você acessar o local da memória em seu código, as instruções serão executadas conforme definido originalmente. por exemplo, se eles esperavam um número lá, eles agiriam em quaisquer bytes de dados como se fossem um número.
Para usar seu exemplo, assumindo que você int
é um número inteiro assinado de 4 bytes (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|
+-------------+--------------------------------------------------------+
Você pode ver que o int
local da memória agora contém 0xEFBEADDE
, assumindo um sistema big-endian 2 . Este é o int assinado de 32 bits -272716322
. Agora, se você interpretar a mesma memória que um int ( uint
) não assinado , seria 4022250974
. Para exatamente os mesmos dados na memória, o significado depende inteiramente de como você os visualiza.
1 Existem alguns mecanismos que impedem que você grave em regiões protegidas da memória e travam o programa se você tentar fazê-lo.
2 x86 é na verdade little-endian, o que significa que você interpreta os bytes que compõem um valor maior ao contrário. Assim, no x86, você teria 0xDEADBEEF
, dando assinado -559038737
ou não 3735928559
.