Cryptopp.dll Место чтения нарушения прав доступа 0x74736554

Я пытаюсь использовать cryptopp, приведенный ниже код вызывает нарушение прав доступа в функции stringsource. Что может быть возможной причиной этого? Ранее я успешно запускал подобный код без особых различий.

AesHelper.cpp

#include "dll.h"#include "AesHelper.h"
#include "aes.h"using CryptoPP::AES;
#include "ccm.h"using CryptoPP::CBC_Mode;

#include "filters.h"using CryptoPP::StringSink;
using CryptoPP::StringSource;
using CryptoPP::StreamTransformationFilter;

#include "hex.h"using CryptoPP::HexEncoder;
using CryptoPP::HexDecoder;

#include <string>
using namespace std;

#include "osrng.h"using CryptoPP::AutoSeededRandomPool;

byte AesHelper::_key[AES::DEFAULT_KEYLENGTH];
byte AesHelper::_iv[AES::BLOCKSIZE];

void AesHelper::encrypt(const char* str, char ** outIv, char ** encrypted )
{
try
{
AutoSeededRandomPool prng;

byte key[AES::DEFAULT_KEYLENGTH];
prng.GenerateBlock(key, sizeof(key));

byte iv[AES::BLOCKSIZE];
prng.GenerateBlock(iv, sizeof(iv));

string cipher, encoded;
string plain = "CBC Test Mode";

CBC_Mode<AES>::Encryption e;
e.SetKeyWithIV(key, sizeof(key), iv);

// The StreamTransformationFilter removes
//  padding as required.
StreamTransformationFilter *stf = new StreamTransformationFilter(e,
new StringSink(cipher),
CryptoPP::BlockPaddingSchemeDef::ZEROS_PADDING
);

StringSource s(plain, true, stf); // This line cause Access Violation

StreamTransformationFilter filter(e);
filter.Put((const byte*)plain.data(), plain.size());
filter.MessageEnd();

const size_t ret = filter.MaxRetrievable();
cipher.resize(ret);
filter.Get((byte*)cipher.data(), cipher.size());

//encode the cipher to hexadecimal
StringSource(cipher, true,
new HexEncoder(
new StringSink(encoded)
) // HexEncoder
); // StringSource//set the output parameter
outIv = (char**)_iv;
encrypted = (char**)cipher.c_str();
}
catch(const CryptoPP::Exception& e)
{
cerr << "exception : " << e.what() << endl;
exit(1);
}

}

ошибка

Необработанное исключение в 0x550714CA (cryptopp.dll) в
PaymentManager.exe: 0xC0000005: место чтения нарушения прав доступа
0x74736554.

cryptopp.dll! memcpy (unsigned char * dst, unsigned char * src, unsigned long count) Строка 188 Неизвестно

ОБНОВИТЬ :
Проблема решена после того, как и DLL и Exe программа «Release». Но теперь появилась новая проблема.
в этой строке проблема также в функции stringsource

StringSource(cipher, true,
new HexEncoder(
new StringSink(encoded)
) // HexEncoder
); // StringSource

ошибка

PaymentManager.exe вызвал точку останова.

Программа останавливается на

void __cdecl _free_base (void * pBlock) {

int retval = 0;if (pBlock == NULL)
return;

RTCCALLBACK(_RTC_Free_hook, (pBlock, 0));

retval = HeapFree(_crtheap, 0, pBlock); // program stop at this line
if (retval == 0)
{
errno = _get_errno_from_oserr(GetLastError());
} }

0

Решение

Я не знаю эту библиотеку, но, как я вижу StringSource получить std::string в качестве первого параметра. В этом случае вы должны быть абсолютно уверены, что и DLL, и ваша программа скомпилированы и связаны с одним и тем же STL, с одинаковыми компиляторами и их параметрами.

2

Другие решения

0x74736554 является шестнадцатеричным для четырех символов ASCII "tseT" (big-endian) или "Test" (little-endian) — последний из которых является именно байтами с индексами 4-7 вашего string plain, Тот факт, что StringSource конструктор пытается прочитать этот адрес предполагает, что ваш исполняемый файл и DLL не согласны с тем, что std::string похоже. В частности, библиотека разыменовывает адрес памяти по смещению 4 от объекта, который вы передаете, но объект, который вы передаете, не имеет действительного значения указателя там.

Другими словами, string вы передаете (или, возможно, какой-то его подобъект) в памяти выглядит так:

Offset    0      1      2      3      4      5      6      7
+------+------+------+------+------+------+------+------+--
Value  | 0x43 | 0x42 | 0x43 | 0x20 | 0x54 | 0x65 | 0x73 | 0x74 | ...
| 'C'  | 'B'  | 'C'  | ' '  | 'T'  | 'e'  | 's'  | 't'  | ...
+------+------+------+------+------+------+------+------+--

Но библиотека воспринимает это так:

Offset    0      1      2      3      4      5      6      7
+------+------+------+------+------+------+------+------+--
Value  |           ?????           | Pointer to character data | ...
+------+------+------+------+------+------+------+------+--

Я понял все это, просто осознав, что адрес, вызывающий ошибку, целиком состоит из значений ASCII, которые соответствуют значениям из исходного кода.

Причиной этого почти наверняка является то, что ваш код и библиотека используют разные std::string реализации, которые имеют разные макеты объектов. Это точно такая же проблема, как Выделение и освобождение памяти через границы модуля. Чтобы передавать объекты C ++ между модулями (то есть основным исполняемым файлом и любыми DLL-библиотеками, которые он загружает), оба модуля должны согласовать расположение объекта. Если модули были скомпилированы в разное время, вам нужно больше работать, чтобы убедиться, что они скомпилированы с одинаковыми заголовочными файлами.

Если вы компилируете DLL из исходного кода, то проще всего убедиться, что и DLL, и ваш исполняемый файл используют одну и ту же реализацию стандартной библиотеки C ++. Если вы используете библиотеку DLL, которая уже была скомпилирована кем-то другим, вам нужно попросить их или проверить документацию, чтобы найти стандартную библиотеку C ++, для которой она была скомпилирована, а затем скомпилировать исполняемый файл для той же библиотеки.

Если вы не можете этого сделать, то следующим лучшим решением будет избежать передачи объектов C ++ через границы модуля в все случаи — используйте только API, которые принимают предопределенные типы данных (например, целые числа и необработанные указатели) или типы данных, определенные в заголовочных файлах DLL. Это полностью исключит проблему, но также сделает ваш код намного труднее писать, так как вы больше не можете передавать или получать std::string,

2

В дополнение к ответам Бориса и Адама, я видел, что это вызывает проблему в Linux (я понимаю, что вы находитесь в Windows):

    StringSource(cipher, true,
new HexEncoder(
new StringSink(encoded)
) // HexEncoder
); // StringSource

Анонимные объявления являются законными C / C ++. Но конкретная версия GCC (около 4.3 или 4.4 или 4.5) слишком рано начнет запускать деструкторы в сгенерированном коде. Я говорил об этом с Джонатаном Уэйкли еще в 2011 году, но так и не смог выяснить причину. Вот поток, который заставил m начать смотреть на него: Запуск примеров RSA и некоторые проблемы установки.

Обходной путь был просто:

    StringSource ss(cipher, true,
new HexEncoder(
new StringSink(encoded)
) // HexEncoder
); // StringSource
0
По вопросам рекламы ammmcru@yandex.ru
Adblock
detector