C++ Libcurl causing write access violation in readfunction callback on larger content


C++ Libcurl causing write access violation in readfunction callback on larger content



I am working on a C++ project where I am using libcurl to send an email over SMTP. The code is pretty much working for small content, however, on larger emails, its throwing a write access violation and I can't see any reason why.



Below is how I am using the curl function to send mail:


curl = curl_easy_init();
//curl_easy_setopt(curl, CURLOPT_FORBID_REUSE, 1);
if (curl)
{
if (this->useVerboseOutput)
{
curl_easy_setopt(curl, CURLOPT_VERBOSE, 1);
}
curl_easy_setopt(curl, CURLOPT_URL, smtpAddress.c_str());


if (this->useTLS)
{
curl_easy_setopt(curl, CURLOPT_USE_SSL, (long)CURLUSESSL_ALL);
}
if (this->useAuthentication)
{
if (this->username.empty() || this->password.empty())
{
throw logic_error("SMTP username or password has not been set but authentication is enabled");
}
curl_easy_setopt(curl, CURLOPT_USERNAME, this->username.c_str());
curl_easy_setopt(curl, CURLOPT_PASSWORD, this->password.c_str());
}

curl_easy_setopt(curl, CURLOPT_MAIL_FROM, this->fromAddress.c_str());
curl_easy_setopt(curl, CURLOPT_MAIL_RCPT, recipients);
curl_easy_setopt(curl, CURLOPT_READDATA, this);
curl_easy_setopt(curl, CURLOPT_READFUNCTION, &EmailSender::invoke_write_data);
curl_easy_setopt(curl, CURLOPT_UPLOAD, 1L);

//Send the message
res = curl_easy_perform(curl);



Below is the read function call back


size_t EmailSender::invoke_write_data(void *data, size_t size, size_t nmemb, void* pInstance)
{
return ((EmailSender*)pInstance)->payload_source(data, size, nmemb);
}

size_t EmailSender::payload_source(void *ptr, size_t size, size_t nmemb)
{
//struct upload_status *upload_ctx = (struct upload_status*)userp;
const char *data;

if ((size == 0) || (nmemb == 0) || ((size*nmemb) < 1)) {
return 0;
}

if (this->upload_ctx.lines_read < this->lineArray.size())
{
data = this->lineArray.at(this->upload_ctx.lines_read).c_str();
}
else
{
return 0;
}

if (data) {
size_t len = strlen(data);
memcpy(ptr, data, len);
this->upload_ctx.lines_read++;

return len;
}

return 0;
}



Its crashing on the line this->upload_ctx.lines_read++; after the 5th call (there are 6 lines in the vector lineArray and upload_ctx->lines_read is 5.


this->upload_ctx.lines_read++;



The full error message is:


Exception thrown at 0x00007FFF4E8F16D7 (vcruntime140d.dll) in myapp.exe: 0xC0000005: Access violation writing location 0x00000205CC8AC000.



This question has not received enough attention.





As you can see in the code, I have a static method which is called by the libcurl read function, this then casts the userp pointer back to the class instance to call my function which does the work. If it was related to this, it wouldn't work on any of the requests, not just large ones would have an issue
– Boardy
Jul 3 at 16:09




1 Answer
1



According to the documentation of CURLOPT_READFUNCTION:


CURLOPT_READFUNCTION


#include <curl/curl.h>
size_t read_callback(char *buffer, size_t size, size_t nitems, void *instream);
CURLcode curl_easy_setopt(CURL *handle, CURLOPT_READFUNCTION, read_callback);



Pass a pointer to your callback function, as the prototype shows above.



This callback function gets called by libcurl as soon as it needs to read data in order to send it to the peer - like if you ask it to upload or post data to the server. The data area pointed at by the pointer buffer should be filled up with at most size multiplied with nitems number of bytes by your function.


size


nitems



You wrote:


size_t len = strlen(data);
memcpy(ptr, data, len);



Since len only depends on your data to send, and since you do not check it is less than size*nitems (nmemb for you), you might write out of the buffer allocated by libcurl, hence invoke undefined behavior.


len


size*nitems


nmemb



Since you work by line but libcurl works by byte, you will need to rework your application to keep track of partially written lines, or drop the notion of line altogether.






By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Popular posts from this blog

api-platform.com Unable to generate an IRI for the item of type

How to set up datasource with Spring for HikariCP?

Display dokan vendor name on Woocommerce single product pages