Pufferüberlaufproblemen
-
Hi
wie bekomme ich denn ein char in ein std::tr1::array?
Habe das mal gegooglt aber nichts zu gefunden.
-
Analog wie beim herkömmlichen Array. Statt
char array[32]; array[7] = 'h';schreibst du
std::tr1::array<char, 32> array; array[7] = 'h';Und im Debug-Modus sollte Folgendes in einer Assertion enden:
array[32] = 'h';Falls du allerdings einen voll funktionsfähigen String und nicht nur einen
char-Puffer suchst, ist vielleichtstd::stringetwas komfortabler, da diese Klasse auch zur Laufzeit die Grösse ändern oder direkt von einem C-String konstruiert werden kann.
-
oh. Da ist mir wohl ein Fehler unterlaufen. Ich meine wie ich ein char array in einen std::tr1::array kopieren kann.
-
Initialisierung, wobei das Template-Argument
Sizemindestens der Länge des Stringliterals entsprechen muss (hier 6):std::tr1::array<char, Size> array = {"hallo"};Nachträglich:
std::tr1::array<char, Size> array; const char* cString = "hallo"; std::copy(cString, cString + std::strlen(cString) + 1, array.begin());Du könntest auch
strcpy()benutzen, allerdings würdest du so den Vorteil geprüfter Iteratoren im Debug-Modus verlieren. Oder wenn du das öfter brauchst, kannst du selbst eine Funktion schreiben:typedef std::tr1::array<char, 32> CharArray; void AssignString(CharArray& array, const char* source) { // Setze Iterator dest auf Anfang des Ziel-Arrays array CharArray::iterator dest = array.begin(); // Kopiere solange noch Platz in dest und Nullterminierung noch nicht erreicht while (dest != array.end() && *source != '\0') *dest++ = *source++; // Füge neue Nullterminierung hinzu *(dest-1) = '\0'; } int main() { CharArray array; AssignString(array, "hallo"); }Wenn der übergebene String zu lang ist, wird er abgeschnitten. Die Nullterminierung ist entweder gleich wie beim
source-String oder sie steht im letzten Element des Arrays, falls dersource-String zu gross ist. Der Grund, wieso der Code hier vergleichsweise kompliziert ist, besteht darin, dassstd::tr1::arraynicht auf Strings (schon gar nicht die aus C) ausgelegt wurde. Dafür wäre vielleicht wie gesagtstd::stringkomfortabler.
-
OK Code sieht jetzt wie folgt aus gibt aber ein:
Debug Assertation Failed!
Programm C:\Users\***\test.exe
File: C:\program files(x86)\mircosoft visual studio 10.0\vc\include\xstring
Line:167Expression: string interator + offset out of range
Hört sich so an als ob er auf Speicher außerhalb seiner Berechtigung schreibt.
main.cpp
// Überschrift erzeugen g_pLogfile->WriteTopic ("Test"); // Allocate array for getting ImageBase addresses of // all drivers present in system. DWORD dwBufferLen = GetImageBaseAddrArrayLen(); LPVOID* pImageBaseAddrArray = (LPVOID*)new BYTE[ dwBufferLen ]; DWORD dwBytesReturned = 0; // Get the ImageBaseAddresses of all drivers. EnumDeviceDrivers( pImageBaseAddrArray, // array of load addresses dwBufferLen, // size of array as 0. &dwBytesReturned ); // Get the total number of drivers. calculate it by // total size in bytes/sizeof(void*) DWORD nDrivers = dwBufferLen / sizeof(LPVOID); PVOID OldValue = NULL; for( DWORD Index = 0; Index < nDrivers; ++Index ) { // Get Device Driver informations. string sDriverBaseName; string sDriverFileName; GetDriverInfo( pImageBaseAddrArray[ Index], sDriverBaseName, sDriverFileName ); // \??\ / int iFindIdxMD5Question = sDriverFileName.find( "\\??\\" ); int iExistQuestion = 0; if ( iFindIdxMD5Question != -1 ) { sDriverFileName.erase( 0, 4 ); iExistQuestion = 1; } // \Windows\System32 int iFindIdxMD5Win = sDriverFileName.find( "\\Windows\\System32" ); if ( iFindIdxMD5Win != -1 ) sDriverFileName.replace( iFindIdxMD5Win, 17, sSysDir ); // \WINDOWS\System32 int iFindIdxMD5Win2 = sDriverFileName.find( "\\WINDOWS\\System32" ); if ( iFindIdxMD5Win2 != -1 ) sDriverFileName.replace( iFindIdxMD5Win, 17, sSysDir ); // \SystemRoot\System32 int iFindIdxMD5SysRoot = sDriverFileName.find( "\\SystemRoot\\System32" ); if ( iFindIdxMD5SysRoot != -1 ) sDriverFileName.replace( iFindIdxMD5SysRoot, 20, sSysDir ); // \SystemRoot\system32 int iFindIdxMD5SysRoot2 = sDriverFileName.find( "\\SystemRoot\\system32" ); if ( iFindIdxMD5SysRoot2 != -1 ) sDriverFileName.replace( iFindIdxMD5SysRoot2, 20, sSysDir ); // \SystemRoot\SysWOW64 int iFindIdxMD5SysWOW64 = sDriverFileName.find( "\\SystemRoot" ); if ( iFindIdxMD5SysWOW64 != -1 ) sDriverFileName.replace( iFindIdxMD5SysWOW64, 11, sWinDir ); // C:\Windows\SysWOW64 int iFindIdxMD5C = sDriverFileName.find( "C:\\" ); if ( iFindIdxMD5C == -1 ) sDriverFileName.insert( 0, "C:\\" ); // calculating MD5 HANDLE hFile; DWORD dwNumRead = -1; if(IsWow64()) if (!WOW64DisableFsRedirection(&OldValue)) printf("WOW64DisableFsRedirection doesn´t work\n"); hFile = CreateFile(sDriverFileName.c_str(), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL); if (!WOW64RevertFsRedirection(OldValue)) printf("WOW64RevertFsRedirection doesn´t work\n"); if(hFile == INVALID_HANDLE_VALUE) { g_pLogfile->Textout ("ERROR: INVALID_HANDLE_VALUE" + sDriverFileName); } else { //GetFileSize to determine size of buffer for ReadFile DWORD BufferSize = GetFileSize(hFile,NULL); cout << "Buffer: " << BufferSize <<endl; char* ReadBuffer = new char [BufferSize];// create a new char * to hold the buffer using the filesize //Read from the file: if(!ReadFile(hFile, ReadBuffer, BufferSize+1, &dwNumRead,NULL)) { printf ("ReadFile Fail"); return 1; } //To close the file: CloseHandle(hFile); string hash; MD5Hash((BYTE*)ReadBuffer, BufferSize, hash); delete ReadBuffer; if ( iExistQuestion == 1) sDriverFileName.insert( 0, "\\??\\"); g_pLogfile->Textout (sDriverBaseName + " : " + sDriverFileName + " : " + hash); } } cout << "done"; delete (BYTE*)pImageBaseAddrArray; // Logfile schließen g_pLogfile->Del (); Sleep(5000);MD5.h
#include <string> void MD5Hash(BYTE hash[],int sz,std::string cString);MD5.cpp
#include <iostream> #include <windows.h> #include <wincrypt.h> #include <fstream> #include <array> #include "MD5.h" using namespace std; const int MD5LEN = 16; void MD5Hash(BYTE hash[],int sz, string cString) { tr1::array<char, 32> sec,finalhash; copy(cString.begin(), cString.end() + 1, sec.begin()); HCRYPTPROV hProv = 0,hHash = 0; BYTE rgbHash[MD5LEN]; DWORD cbHash = 0; //char finalhash[32], dig[] = "0123456789abcdef"; char dig[] = "0123456789abcdef"; unsigned int l = 0; CryptAcquireContext(&hProv, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT); CryptCreateHash(hProv, CALG_MD5, 0, 0, &hHash); CryptHashData(hHash, hash, sz, 0); cbHash = MD5LEN; CryptGetHashParam(hHash, HP_HASHVAL, rgbHash, &cbHash, 0); for(DWORD i = 0; i < cbHash; i++) { finalhash[l] = dig[rgbHash[i] >> 4]; l++; finalhash[l] = dig[rgbHash[i] & 0xf]; l++; } //for(l = 32; l < strlen(finalhash); l++) finalhash[l] = 0; fill(finalhash.begin(), finalhash.end(), 0); copy(finalhash.begin(), finalhash.end(), sec.begin()); CryptDestroyHash(hHash); CryptReleaseContext(hProv, 0); }
-
Wo genau tritt der Fehler auf?
-
Debug Modus :
Wenn ich es richtig lokalisiert habe ich folgender Zeile:copy(cString.begin(), cString.end() + 1, sec.begin());Fehler gefunden
Es muss so heißen:copy(cString.begin(), cString.end(), sec.begin());
-
Bekommt nun kein Ergebnis von MD5Hash zurück.
#include <iostream> #include <windows.h> #include <wincrypt.h> #include <fstream> #include <array> #include "MD5.h" using namespace std; const int MD5LEN = 16; void MD5Hash(BYTE hash[], int sz, string cString) { tr1::array<char, 32> sec,finalhash; HCRYPTPROV hProv = 0,hHash = 0; BYTE rgbHash[MD5LEN]; DWORD cbHash = 0; //char finalhash[32], dig[] = "0123456789abcdef"; char dig[] = "0123456789abcdef"; unsigned int l = 0; CryptAcquireContext(&hProv, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT); CryptCreateHash(hProv, CALG_MD5, 0, 0, &hHash); CryptHashData(hHash, hash, sz, 0); cbHash = MD5LEN; CryptGetHashParam(hHash, HP_HASHVAL, rgbHash, &cbHash, 0); for(DWORD i = 0; i < cbHash; i++) { finalhash[l] = dig[rgbHash[i] >> 4]; l++; finalhash[l] = dig[rgbHash[i] & 0xf]; l++; } //for(l = 32; l < strlen(finalhash); l++) finalhash[l] = 0; fill(finalhash.begin(), finalhash.end(), 0); copy(finalhash.begin(), finalhash.end(), sec.begin()); CryptDestroyHash(hHash); CryptReleaseContext(hProv, 0); copy(sec.begin(), sec.end(), cString.begin()); }main.cpp
// Überschrift erzeugen g_pLogfile->WriteTopic ("Test"); // Allocate array for getting ImageBase addresses of // all drivers present in system. DWORD dwBufferLen = GetImageBaseAddrArrayLen(); LPVOID* pImageBaseAddrArray = (LPVOID*)new BYTE[ dwBufferLen ]; DWORD dwBytesReturned = 0; // Get the ImageBaseAddresses of all drivers. EnumDeviceDrivers( pImageBaseAddrArray, // array of load addresses dwBufferLen, // size of array as 0. &dwBytesReturned ); // Get the total number of drivers. calculate it by // total size in bytes/sizeof(void*) DWORD nDrivers = dwBufferLen / sizeof(LPVOID); PVOID OldValue = NULL; for( DWORD Index = 0; Index < nDrivers; ++Index ) { // Get Device Driver informations. string sDriverBaseName; string sDriverFileName; GetDriverInfo( pImageBaseAddrArray[ Index], sDriverBaseName, sDriverFileName ); // \??\ / int iFindIdxMD5Question = sDriverFileName.find( "\\??\\" ); int iExistQuestion = 0; if ( iFindIdxMD5Question != -1 ) { sDriverFileName.erase( 0, 4 ); iExistQuestion = 1; } // \Windows\System32 int iFindIdxMD5Win = sDriverFileName.find( "\\Windows\\System32" ); if ( iFindIdxMD5Win != -1 ) sDriverFileName.replace( iFindIdxMD5Win, 17, sSysDir ); // \WINDOWS\System32 int iFindIdxMD5Win2 = sDriverFileName.find( "\\WINDOWS\\System32" ); if ( iFindIdxMD5Win2 != -1 ) sDriverFileName.replace( iFindIdxMD5Win, 17, sSysDir ); // \SystemRoot\System32 int iFindIdxMD5SysRoot = sDriverFileName.find( "\\SystemRoot\\System32" ); if ( iFindIdxMD5SysRoot != -1 ) sDriverFileName.replace( iFindIdxMD5SysRoot, 20, sSysDir ); // \SystemRoot\system32 int iFindIdxMD5SysRoot2 = sDriverFileName.find( "\\SystemRoot\\system32" ); if ( iFindIdxMD5SysRoot2 != -1 ) sDriverFileName.replace( iFindIdxMD5SysRoot2, 20, sSysDir ); // \SystemRoot\SysWOW64 int iFindIdxMD5SysWOW64 = sDriverFileName.find( "\\SystemRoot" ); if ( iFindIdxMD5SysWOW64 != -1 ) sDriverFileName.replace( iFindIdxMD5SysWOW64, 11, sWinDir ); // C:\Windows\SysWOW64 int iFindIdxMD5C = sDriverFileName.find( "C:\\" ); if ( iFindIdxMD5C == -1 ) sDriverFileName.insert( 0, "C:\\" ); // calculating MD5 HANDLE hFile; DWORD dwNumRead = -1; if(IsWow64()) if (!WOW64DisableFsRedirection(&OldValue)) printf("WOW64DisableFsRedirection doesn´t work\n"); hFile = CreateFile(sDriverFileName.c_str(), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL); if (!WOW64RevertFsRedirection(OldValue)) printf("WOW64RevertFsRedirection doesn´t work\n"); if(hFile == INVALID_HANDLE_VALUE) { g_pLogfile->Textout ("ERROR: INVALID_HANDLE_VALUE" + sDriverFileName); } else { //GetFileSize to determine size of buffer for ReadFile DWORD BufferSize = GetFileSize(hFile,NULL); cout << "Buffer: " << BufferSize <<endl; char* ReadBuffer = new char [BufferSize];// create a new char * to hold the buffer using the filesize //Read from the file: if(!ReadFile(hFile, ReadBuffer, BufferSize+1, &dwNumRead,NULL)) { printf ("ReadFile Fail"); return 1; } //To close the file: CloseHandle(hFile); string hash; MD5Hash((BYTE*)ReadBuffer, BufferSize, hash); delete ReadBuffer; if ( iExistQuestion == 1) sDriverFileName.insert( 0, "\\??\\"); g_pLogfile->Textout (sDriverBaseName + " : " + sDriverFileName + " : " + hash); } } cout << "done"; delete (BYTE*)pImageBaseAddrArray; // Logfile schließen g_pLogfile->Del (); Sleep(5000);
-
Als erstes würde ich nur C-Strings
cStringnennen.std::stringist ein C++-String...
Du darfst nicht über den
end()-Iterator hinaus zugreifen. Was geht, ist der Zugriff peroperator[]mit dem Indexsize()– sofern dieconst-Version aufgerufen wird.tr1::array<char, 32> sec,finalhash; copy(cString.begin(), cString.end(), sec.begin())Hier hast du auch ein Problem, falls
cStringmehr als 32 Elemente enthält. Die Nullterminierung musst du zudem selbst schreiben.Statt des
end()-Iterators könntest du Folgendes schreiben:cString.begin() + std::min(32u, cString.size())
-
pc-jedi schrieb:
Bekommt nun kein Ergebnis von MD5Hash zurück.
Nächstes Mal bitte das Problem genauer beschreiben...
Dein
std::stringmuss als Referenz übergeben werden, falls er als Output-Parameter benutzt werden soll.
-
Warum geht folgende Zeile nicht?
copy(finalhash.begin(), finalhash.end(), cString->begin());
-
Nexus schrieb:
Nächstes Mal bitte das Problem genauer beschreiben...

-
Oh, ja

Also ich bekomme folgende Fehlermeldung:Debug Assertation Failed!
Programm C:\Users\***\test.exe
File: C:\program files(x86)\mircosoft visual studio 10.0\vc\include\xstring
Line:167Expression: string interator + offset out of range
in folgender Zeil:
copy(finalhash.begin(), finalhash.end(), cString->begin());finalhash ist ein std::tr1::array<char, 32>
cString ist ein Zeiger auf ein std::stringWenn ich die Fehlermeldung richtig deute, dann wird hier irgendwie in undefinierten Bereich geschrieben.
-
Ist
cStringzu diesem Zeitpunkt leer (oder zu klein)? Falls ja, und du lediglich hinten einfügen möchtest, könntest dustd::back_inserter()aus dem<iterator>-Header benutzen.std::copy(finalhash.begin(), finalhash.end(), std::back_inserter(*cString));Oder einfach
std::string::assign(), um den kompletten String zu überschreiben:cString->assign(finalhash.begin(), finalhash.end());Gibt es eigentlich einen Grund, wieso du Zeiger auf
std::stringverwendest? Und ich würde immer noch einen anderen Namen alscStringwählen.
-
Hi
Alles geht.
Vielen Dank
Gibt es eigentlich einen Grund, wieso du Zeiger auf std::string verwendest?
Nein eigendlich nicht hätte das auch einfach über einen Rückgabewert machen können.
Und ich würde immer noch einen anderen Namen als cString wählen.
Habe den einfach noch nicht umbenannt.