2009-05-27 9 views
1

Pufferüberlaufprobleme sind bekannt. Daher waren wir mit Standardbibliotheksfunktionen wie wcscat_s() gesegnet. Und die netten Leute von Microsoft haben ähnliche sichere String-Funktionen wie StringCbCat() erstellt.C++ (wirklich) Safe Standard String Suche?

Aber ich habe ein Problem, wo ich ein wenig Speicher für eine Zeichenfolge suchen muss. Die Standard-Library-Funktion:

wcsstr(wchar_t* pMem, wchar_t* pStr) 

scheint groß, aber ... Manchmal mein Gedächtnis enthält Müll, manchmal Strings. Und wenn es Müll ist, laufe ich manchmal von einer zugewiesenen Speicherseite ab, [= Zugriffsverletzung]. Ich kann meine eigene Funktion ja schreiben. Aber meine Frage ist, ob es eine „normale“ Funktion ist sicher String-Suche zu tun, wie zum Beispiel:

"wcsstr_s(wchar_t* pMem, size_t uiSize, wchar_t* pStr)" ? 

Thanx

[EDIT] Dank und ein großes Lob an Charles Bailey für eine perfekte Antwort auf meinen Frage. Danke auch an andere für ihre Bemühungen.

Und an diejenigen von euch, die die Sanftheit meines Szenarios bezweifelt haben: Ja, natürlich wäre es gut, keinen Müll in meiner Erinnerung zu haben. Aber ich kann mir mehrere Szenarien vorstellen, in denen diese Situation auftreten könnte. In meinem speziellen Fall ist es Reverse-Engineering, und die Erinnerung, die ich suche, ist in Wirklichkeit nicht "meine Erinnerung", sie gehört zu einem anderen Prozess, den ich nicht kontrollieren kann.

(Ein anderes hypothetisches Szenario könnte eine heikle Debug-Situation, wo beschädigte Speicher werden muss aufgespürt.)

+1

ich neugierig bin. In welchem ​​Anwendungsfall suchen Sie nach einer Teilzeichenfolge in einer Zeichenfolge, die * möglicherweise * müllig ist? Und Entschuldigung, nein, ich kenne keine Standard-Wide-Char-Bitroutine, die eine Abgrenzung zählt. –

+4

Scheint eher eine C-Frage als C++. Wenn Sie sicher sein wollen, verwenden Sie std :: string oder std:; wstring. –

+0

Was wäre in diesem Fall? Die Länge des zugewiesenen Puffers beginnt bei pMem? – ralphtheninja

Antwort

2

Unter der Annahme, dass Ihr pStr null beendet wird und dass uiSize ist die Anzahl der wchar_t lesbarer Speicher bei pMem:

wchar_t* pSubStr = std::search(pMem, pMem + uiSize, pStr, pStr + std::wcslen(pStr)); 

// Optionally, change to the 'conventional' strstr return value 
if(pSubStr == pMem + uiSize) 
    pSubStr = 0; 
+0

Perfect! Vielen Dank! – Adam

6

Wahrscheinlich nicht die Antwort, die Sie gesucht haben, aber vielleicht die beste Lösung wäre hier richtig zu initialisieren Ihre Zeichenfolgen und Zeiger. Wenn Sie Ihr Gedächtnis Müll enthält, warum nicht die anständige Sache tun und

yourString[0] = '\0'; 

gesetzt, wenn es wirklich nur ein beliebiges Bit des Puffers ist, könnten Sie besser dran etwas wie memcmp mit und schieben Sie den Zeiger des Speicherpuffer entlang N Zeichen (N ist die Anzahl der Zeichen, an denen Sie interessiert sind, abzüglich der Länge der Zeichenfolge, die Sie vergleichen). Das ist vielleicht nicht die effizienteste Umsetzung, sollte aber ein ziemlich robuster Ansatz sein, denke ich.

[Bearbeiten] Ihre Frage fasziniert mich genug, ein wenig zu experimentieren. Vorausgesetzt, dass Sie scheinen für mehr C-Stil Antwort zu suchen, ist hier ein wenig Code-Snippet ich kam mit erarbeiten auf meinem memcmp Vorschlag:

// SearchingMemoryForStrings.cpp : Defines the entry point for a win32 consol application 
// Purpose : Demonstrates a way to search a section of memory for a particular string 
// 

#include <stdio.h> 
#include <string.h> 

#define VALUE_NOT_FOUND (-1) 

int FindStringInBuffer(const char* pMemBuffer, const size_t& bufferSizeInBytes, const char* pStrToFind) 
{ 
    int stringFound = VALUE_NOT_FOUND; // Return value which will be >= 0 if we find the string we're after 
    const char* pMemToMatch = NULL; // An offset pointer to part of 'pMemBuffer' which we'll feed to memcmp to find 'pStrToFind' 

    // Set up some constants we'll use while searching 
    size_t lenOfStrToFind = strlen(pStrToFind); 
    size_t lastSearchablePosition = bufferSizeInBytes - lenOfStrToFind; 

    // Search the memory buffer, shifting one character at a time for 'pStrToFind' 
    for(size_t i = 0; i <= lastSearchablePosition; i++) { 
     pMemToMatch = &pMemBuffer[i]; 
     if(memcmp(pMemToMatch, pStrToFind, lenOfStrToFind) == 0) { 
      // We found the string we're looking for 
      stringFound = i; 
      break; 
     } 
    } 

    return stringFound; 
} 

void ReportResult(int returnVal, const char* stringToFind) 
{ 
    if(returnVal == VALUE_NOT_FOUND) { 
     // Fail! 
     printf("Error, failed to find '%s' - search function returned %d\n", stringToFind, returnVal); 
    } 
    else { 
     // Win! 
     printf("Success, found '%s' at index %d\n", stringToFind, returnVal); 
    } 
} 

void FindAndReport(const char* pMemBuffer, const size_t& bufferSizeInBytes, const char* pStrToFind) 
{ 
    int result = FindStringInBuffer(pMemBuffer, bufferSizeInBytes, pStrToFind); 
    ReportResult(result, pStrToFind); 
} 

int main(int argc, char* argv[]) 
{ 
    const int SIZE_OF_BUFFER = 1024; // Some aribitrary buffer size 
    char some_memory[SIZE_OF_BUFFER]; // The buffer of randomly assigned memory to look for our string 
    const char* stringToFind = "This test should pass"; 
    const char* stringYouWontFind = "This test should fail"; 

    FindAndReport(some_memory, SIZE_OF_BUFFER, stringYouWontFind); // Should fail gracefully 

    // Set the end of the buffer to the string we're looking for 
    memcpy(&some_memory[SIZE_OF_BUFFER-strlen(stringToFind)], stringToFind, strlen(stringToFind)); 

    FindAndReport(some_memory, SIZE_OF_BUFFER, stringToFind); // Should succeed this time and report an index of 1003 

    // Try adding at some arbitrary position 
    memcpy(&some_memory[100], stringToFind, strlen(stringToFind)); 

    FindAndReport(some_memory, SIZE_OF_BUFFER, stringToFind); // Should still succeed but report the offset as 100 

    FindAndReport(some_memory, SIZE_OF_BUFFER, stringYouWontFind); // Should still fail 


    return 0; 
} 

, die unter Visual Studio 2008 als Win32-Konsole app kompiliert Snippet . Gibt mir die folgende:

Error, failed to find 'This test should fail' - search function returned -1 
Success, found 'This test should pass' at index 1003 
Success, found 'This test should pass' at index 100 
Error, failed to find 'This test should fail' - search function returned -1 

Die FindStringInBuffer Funktion ist das Bit Sie wollen und wenn Sie mit großen Zeichen bewältigen müssen, werden Sie brauchen, um eine Umwandlung zu tun, aber dies sollte zumindest geben Ihnen einige Ideen mit dem du fortfahren kannst. Wenn Sie eine wchar-Version entwickeln, würde mich interessieren, wie die Lösung aussieht (ich habe sie nicht selbst behandelt).

+0

+1 für die bearbeitete memcmp :) – ralphtheninja

2

Es gibt leider immer noch keine "sichere" Standard-Stringbibliothek, die mir bekannt ist. BSD hat strstrstr dafür, aber es ist nicht in der glibc, oder Microsofts libc, soweit ich weiß.Ich kenne keine "gute" Wahl dafür, außer einer eigenen.

Als Referenz die Microsoft sichere String-Bibliothek wird ausführlicher in http://msdn.microsoft.com/en-us/library/wd3wzwts(VS.80).aspx und aufgelisteten (mit Migrationsführer) http://msdn.microsoft.com/en-us/library/bb288454.aspx.

+0

Es gibt safeclib: https://github.com/rurban/safeclib wcsstr_s wird gerade dort hinzugefügt. errno_t wcsstr_s (wchar_t * restrict dest, rsize_t dmax, const wchar_t * restrict src, rsize_t slen, wchar_t ** Teilzeichenfolge beschränken) – rurban