当字符串包含 %2C 时,C++ 中的 std::string 不完整

Incomplete std::string in c++ when the string contains %2C


直接看我的回答,忽略后面的文字...

我正在尝试通过 C++ 使用 openssl CLI 读取 x509 证书。 (是的,我知道 OpenSSL 也有一个 C API,但这对我的问题并不重要)。 OpenSSL 版本为 1.1.0g,gcc 编译器为 7.4.0

所以,我想执行命令 openssl x509 -noout -text -in certFile.cer 并获取输出。

我尝试使用三种不同的 C++ 解决方案:

这是我正在使用的一段代码(如您所见,我还尝试添加 stdbuf -o 0 以避免缓冲)

string execCommandAndGetOutput_withPopen(const char* cmd, int* result)
{
        std::array<char, 1024> buffer;
        std::string output;
        string cmd_unbuf;
        cmd_unbuf.append("stdbuf -o 0 ");
        cmd_unbuf.append(cmd);
        cmd_unbuf.append(" 2>&1");
        FILE* pipe = popen(cmd_unbuf.c_str(), "r");
        if (!pipe) {
              throw std::runtime_error("popen() failed!");
        }
        while (fgets(buffer.data(), buffer.size(), pipe) != nullptr) {
              output += buffer.data();
        }
        *result = pclose(pipe);
        return output;
}

string execCommandAndGetOutput_withSystem(const char* cmd, int* result)
{
        std::string output;
        string cmd_unbuf;
        cmd_unbuf.append("stdbuf -o 0 ");
        cmd_unbuf.append(cmd);
        cmd_unbuf.append(" > /tmp/temp 2>&1");
        int  cmdResult = system(cmd_unbuf.c_str());
        std::ifstream file("/tmp/temp");
        std::string fileContent((std::istreambuf_iterator<char>(file)), std::istreambuf_iterator<char>());
        remove("/tmp/temp");
        *result = cmdResult;
        return fileContent;
}

在使用第二个功能时,我尝试不删除临时文件,并查看其内容,内容是完整的。所以在 system() 调用中不是问题。

在所有情况下,我得到的字符串都不完整。特别是它总是在同一点停止,特别是在 URL 的中间,就在 %2CO 之前。但是 AFAIK,这应该不是问题,%2 应该只是一个昏迷,html-编码。

我尝试检查字符串大小,我得到的字符串大小为 4262,应该远离其最大值。

我也在两台机器上试过了:第一台机器出现问题,是我所有的程序都安装了,也是我出现错误的地方。在第二台机器上,我的开发机器,我只是在开发时 运行 进行了一些测试,我从来没有注意到这个问题,输入相同。注意两台机器都是Ubuntu server 18.04.3.

所以我的想法是:

我没有想法...有人有什么建议吗?一些特定的 C 库要检查?其他想法?

编辑:

即使我不会 post 证书受影响,我也可以 post 线路受影响。这是完整的行:

URI:ldap://directory.swisssign.net/CN=DA32F949F851CC9871660CD9CEB6DB923F094BEF%2CO=SwissSign%2CC=CH?certificateRevocationList?base?objectClass=cRLDistributionPoint

但我只得到:

URI:ldap://directory.swisssign.net/CN=DA32F949F851CC9871660CD9CEB6DB923F094BEF

我也尝试在命令中添加| grep -A 10 'X509v3 CRL Distribution Points:'(这样我就可以排除问题是字符串的长度),输出是一样的,字符串是t运行满足。所以问题似乎与字符 %2C 有某种关系。

有什么想法吗?

编辑 2:

更改主题

编辑 3:

我正在调试一个错误,这就是我打印字符串的原因....不幸的是我使用 syslog() 来打印它...我想 2%C 被解释为 format

如果字符串中的 %2C 出现问题,请确保您没有使用某些使用 format 的函数,例如 printfsyslog

就我而言,在调试错误时,我正在使用 syslog 打印包含“%2C”的字符串,这造成了混淆...