在 VM 上 运行 时 cURL MIME 数据损坏
cURL MIME data corruption when run on VM
我 运行 遇到了一个看起来很奇怪的问题。
首先,它只发生在 Ubuntu 18.04 上 运行 在 Windows 10 主机之上的 VMWare 上。
我正在使用 CURL 发送多部分请求,一旦传递给 curl_mime_data 的数据大小超过一定数量,它就会被破坏,某种偏移量会被开头覆盖,例如,'abcdefgh' 将变为 'abcabcabc'。
我在接收方和发送方的 Wireshark 中都看到了这个损坏的数据,所以它确实是以这种方式发送的。
我设法使用下面的玩具程序重现了该行为:
#include <fstream>
#include <iostream>
#include <memory>
#include <stdlib.h>
#include <sys/wait.h>
#include <unistd.h>
#include <assert.h>
#include <curl/curl.h>
int main(int argc, char **argv)
{
curl_global_init(0);
CURL *curl = curl_easy_init();
curl_mime *form = nullptr;
curl_mimepart *field = nullptr;
CURLcode res = CURLE_OK;
form = curl_mime_init(curl);
std::ifstream t("test.json");
if (!t.good())
{
return 1;
}
std::string str;
t.seekg(0, std::ios::end);
str.reserve(t.tellg());
t.seekg(0, std::ios::beg);
str.assign(std::istreambuf_iterator<char>(t), std::istreambuf_iterator<char>());
size_t totalsize = 0;
{
field = curl_mime_addpart(form);
res = curl_mime_data(field, (const char *)str.c_str(), str.size());
{
FILE *f = fopen("out.json", "w");
fprintf(f, "%s", str.c_str());
fclose(f);
}
res = curl_mime_name(field, "response");
assert(res == CURLE_OK);
}
curl_easy_setopt(curl, CURLOPT_TIMEOUT, 10);
curl_easy_setopt(curl, CURLOPT_URL, "http://1.2.3.4");
curl_easy_setopt(curl, CURLOPT_MIMEPOST, form);
res = curl_easy_perform(curl);
assert(res == CURLE_OK);
curl_mime_free(form);
curl_easy_cleanup(curl);
curl_global_cleanup();
return 0;
}
这里我正在读取一个示例文件以从磁盘发送并在传递给 curl 进行比较之前将其刷新回。此时,没有任何区别,但发送的值与原始文件的内容不同。
如开头所述,这仅发生在非常特定的环境中,即 Ubuntu 18.04 on VMWare Workstation 12 on Windows 10。
就此而言,上述 ubuntu 的两个不同实例。
当 运行 开启时不会发生这种情况:
- 同一个 VMWare 上的 Centos
- Docker 所述 Ubuntu
内的容器
- Windows主机
我有点不知道去哪里看或者可能是什么原因造成的。我正在使用 libcurl 7.56 和 gcc 7.3.0
你能给我一些想法吗?我使用 libcurl 错了吗?还有什么可能是错误的或值得尝试的?
更新
刚刚在 Ubuntu 16.04 上测试过,数据也已损坏。至于我使用的数据,这里是原始的json文件https://www.dropbox.com/s/gfk0b61tyel68wu/test.json?dl=0 and what I'm getting from Wireshark https://www.dropbox.com/s/dwlzwhn755c51cf/bad.json?dl=0 问题从第779行开始。(这是一个由json生成器创建的随机json,不是一个真实的数据)
更新 2
这似乎是 curl 7.56 的问题。看起来,不管这是什么,它已经在 curl 7.61.1(目前最新)中得到修复。甚至进一步的调查表明,它被修复的确切提交是 5f9e2ca09b57d82baf239039835b3b06dc41bbc5
据我所知,这个特定的错误已在 this commit "mime: fix the content reader to handle >16K data properly"
中修复
我 运行 遇到了一个看起来很奇怪的问题。
首先,它只发生在 Ubuntu 18.04 上 运行 在 Windows 10 主机之上的 VMWare 上。
我正在使用 CURL 发送多部分请求,一旦传递给 curl_mime_data 的数据大小超过一定数量,它就会被破坏,某种偏移量会被开头覆盖,例如,'abcdefgh' 将变为 'abcabcabc'。
我在接收方和发送方的 Wireshark 中都看到了这个损坏的数据,所以它确实是以这种方式发送的。 我设法使用下面的玩具程序重现了该行为:
#include <fstream>
#include <iostream>
#include <memory>
#include <stdlib.h>
#include <sys/wait.h>
#include <unistd.h>
#include <assert.h>
#include <curl/curl.h>
int main(int argc, char **argv)
{
curl_global_init(0);
CURL *curl = curl_easy_init();
curl_mime *form = nullptr;
curl_mimepart *field = nullptr;
CURLcode res = CURLE_OK;
form = curl_mime_init(curl);
std::ifstream t("test.json");
if (!t.good())
{
return 1;
}
std::string str;
t.seekg(0, std::ios::end);
str.reserve(t.tellg());
t.seekg(0, std::ios::beg);
str.assign(std::istreambuf_iterator<char>(t), std::istreambuf_iterator<char>());
size_t totalsize = 0;
{
field = curl_mime_addpart(form);
res = curl_mime_data(field, (const char *)str.c_str(), str.size());
{
FILE *f = fopen("out.json", "w");
fprintf(f, "%s", str.c_str());
fclose(f);
}
res = curl_mime_name(field, "response");
assert(res == CURLE_OK);
}
curl_easy_setopt(curl, CURLOPT_TIMEOUT, 10);
curl_easy_setopt(curl, CURLOPT_URL, "http://1.2.3.4");
curl_easy_setopt(curl, CURLOPT_MIMEPOST, form);
res = curl_easy_perform(curl);
assert(res == CURLE_OK);
curl_mime_free(form);
curl_easy_cleanup(curl);
curl_global_cleanup();
return 0;
}
这里我正在读取一个示例文件以从磁盘发送并在传递给 curl 进行比较之前将其刷新回。此时,没有任何区别,但发送的值与原始文件的内容不同。
如开头所述,这仅发生在非常特定的环境中,即 Ubuntu 18.04 on VMWare Workstation 12 on Windows 10。 就此而言,上述 ubuntu 的两个不同实例。 当 运行 开启时不会发生这种情况:
- 同一个 VMWare 上的 Centos
- Docker 所述 Ubuntu 内的容器
- Windows主机
我有点不知道去哪里看或者可能是什么原因造成的。我正在使用 libcurl 7.56 和 gcc 7.3.0
你能给我一些想法吗?我使用 libcurl 错了吗?还有什么可能是错误的或值得尝试的?
更新
刚刚在 Ubuntu 16.04 上测试过,数据也已损坏。至于我使用的数据,这里是原始的json文件https://www.dropbox.com/s/gfk0b61tyel68wu/test.json?dl=0 and what I'm getting from Wireshark https://www.dropbox.com/s/dwlzwhn755c51cf/bad.json?dl=0 问题从第779行开始。(这是一个由json生成器创建的随机json,不是一个真实的数据)
更新 2
这似乎是 curl 7.56 的问题。看起来,不管这是什么,它已经在 curl 7.61.1(目前最新)中得到修复。甚至进一步的调查表明,它被修复的确切提交是 5f9e2ca09b57d82baf239039835b3b06dc41bbc5
据我所知,这个特定的错误已在 this commit "mime: fix the content reader to handle >16K data properly"
中修复