c++stringparameter-passingwincrypt

Access Violation exception before entering into a function


I have this function which simply encrypts a string (this function works fine, and tested).

DWORD SomeObj::Encrypt(string * To_Enc) {
    DWORD text_len = (To_Enc->length());
    if (!CryptEncrypt(this->hKey,
        NULL,  // hHash = no hash
        1,  // Final
        0,     // dwFlags
       (PBYTE)(*To_Enc).c_str(), //*pbData
       &text_len,  //*pdwDataLen
       128)) {      //dwBufLen
       return SERVER_ERROR;
    }
    return SERVER_SUCCESS;
}

And I have this piece of code:

string s= "stringTest";

Encrypt(&s);

which simply call the function passing the pointer of a string.

The program is causing an access violation exception right when it calls the function Encrypt(&s), I guess that it's something about the parameter &s being passed but I can't figure this out. Any idea from your experience ?


Solution

  • This answer will reiterate important points already made in the comments, with example code.

    Your current code:

    DWORD SomeObj::Encrypt(string * To_Enc) {
        DWORD text_len = (To_Enc->length());
        if (!CryptEncrypt(this->hKey,
            NULL,  // hHash = no hash
            1,  // Final
            0,     // dwFlags
           (PBYTE)(*To_Enc).c_str(), //*pbData
           &text_len,  //*pdwDataLen
           128)) {      //dwBufLen
           return SERVER_ERROR;
        }
        return SERVER_SUCCESS;
    }
    

    On the line:

    (PBYTE)(*To_Enc).c_str(), //*pbData

    Note that you are casting away const-ness from the pointer value returned from the c_str() method call.

    This should immediately be a red flag; there may be times when casting away const-ness is a valid use case, but it is more the exception than the rule.

    Untested, but using a temporary, mutable buffer should solve your problem, such as:

    #include <cstddef>
    #include <vector>
    ...
    DWORD SomeObj::Encrypt(string * To_Enc) {
        std::vector<std::string::value_type> vecBuffer(To_Enc->length() * 3, 0);  // use the maximum value that could be output, possibly some multiple of the length of 'To_Enc'
        std::size_t nIndex = 0; 
        for (auto it = To_Enc->cbegin(); it != To_End->cend(); ++it)
        {
            vecBuffer[nIndex++] = *it;
        }
        DWORD text_len = (To_Enc->length());
        if (!CryptEncrypt(this->hKey,
            NULL,  // hHash = no hash
            1,  // Final
            0,     // dwFlags
           reinterpret_cast<PBYTE>(&vecBuffer[0]), //*pbData
           &text_len,  //*pdwDataLen
           vecBuffer.size())) {      //dwBufLen
           return SERVER_ERROR;
        }
        To_Enc->assign(&vecBuffer[0], text_len);  // assumes 'text_len' is returned with the new length of the buffer
        return SERVER_SUCCESS;
    }