Hoje resolvi fazer um tuto bem pequeno sobre "A hora que o bicho pega!". lolz =P
Essa hora acontece para um programador C/C++, não quando quebram o seu software, mas quando você mesmo o faz!
Vamos falar de uma forma muito comum e dúbia em que muitos programadores caem e não sabem o que está acontecendo.. essa forma é o tratamento de unsigned int's como int's comuns.
Vamos entender através de um código bem simples:
#include <windows.h>
#include <stdlib.h>
#define Error_Msg(txt) MessageBox(0,txt,"Error",MB_ICONERROR)
#define Pause system("pause > nul")
int main()
{
int iNum = -48;
unsigned int nNum2 = 48;
if(iNum > nNum2)
Error_Msg("Verifique se a sentença acima esta correta..");
Pause;
}
Segundo o que conhecemos de matemática, é óbvio que "-48" é bem menor do que "48", no entanto a diretiva if não concorda com isso.
É exatamente o que você está pensando, enquanto tratarmos tipos diferentes em uma mesma sentença matemática, um dos dois será convertido.
Nesse caso, o nosso int -48, vira 0xFFFFFFD0.
#include <windows.h>
#include <stdlib.h>
#include <stdio.h>
#define Error_Msg(txt) MessageBox(0,txt,"Error",MB_ICONERROR)
#define Pause system("pause > nul")
int main()
{
int iNum = -48;
unsigned int nNum2 = 48;
if(iNum > nNum2)
Error_Msg("Verifique se a sentença acima esta correta..");
printf("valor de iNum apos a conversao: %u\nEm Hexa: %x", iNum, iNum);
Pause;
}
Se você quiser que o código de certo, você terá que usar um cast no nNum2.
Bem, não vou me prender a isso, mais tarde talvez eu me prenda a explicar como e porque os certos bugs ocorrem..
Vamos a um exemplo desse pequeno erro que resulta num overflow de proporções bíblicas..
#include <windows.h>
#include <stdlib.h>
#include <string>
#include <iostream>
#define Error_Msg(txt) MessageBox(0,txt,"Error",MB_ICONERROR)
#define Pause system("pause > nul")
using namespace std;
int main()
{
HGLOBAL hGlobal;
string m_Str;
cout << "Digite uma string: ";
cin >> m_Str;
hGlobal = GlobalAlloc(0x0040,m_Str.size());
memset(hGlobal, 'M', m_Str.size()-2);
cout << 4[(char*)hGlobal];
GlobalFree(hGlobal);
Pause;
}
Esse é um exemplo bem chulo mas que serve as nossas necessidades.
N'ele nós tentamos alocar uma nova string com vários M's, que terá dois caracteres a menos que a primeira..
memset(hGlobal, 'M', m_Str.size()-2);
Se o usuário fornece menos de 2 caracteres na string, o programa quebra já que memset converte o valor resultante em um unsigned o que gera um overflow enorme.. isso geralmente acontece através da chamada de memcpy, mas eu resolvi ilustrar com memset só para fugir dos padrões.. mas normalmente acontece quando o programador tenta transferir a string digitada pelo usuário para uma Cstring através de memcpy, CopyMemory e la vai o trem.
Se o usuário tem o controle da primeira string tratada por memcpy, então é um possível buffer overflow surgindo no seu código.. e tudo, graças a você. =P
Bem pequenininho como eu prometi.. =]
PS: isso é apenas um pequeno exemplo de como o código pode quebrar, use sua imaginação porque isso ocorre de várias formas muito parecidas.. eu recomendo a leitura de "Writing Secure Code"¹ bem como "Software fault injection: inoculating software against errors", "How to break software" entre outros.. cya
¹:http://www.microsoft.com/mspress/books/5957.aspx