Неполный std :: string в c ++, когда строка содержит% 2C - PullRequest
1 голос
/ 18 октября 2019

Просто прочитайте мой ответ напрямую, игнорируйте следующий текст ...

Я пытаюсь прочитать сертификат x509, используя CLI openssl через C ++. (Да, я знаю, что OpenSSL также имеет C API, но это не важно для моего вопроса). Версия OpenSSL - 1.1.0g, а компилятор gcc - 7.4.0

Итак, я хочу выполнить команду openssl x509 -noout -text -in certFile.cer и получить вывод.

Я пытался использовать три различных решения C ++:

  • popen(), для получения выходных данных
  • system(), добавление в конце команды > temp.txt для перенаправления вывода и затем чтение из него
  • system(), используя команду openssl x509 -noout -text -in certFile.cer -out tempFile, так что мне не нужно перенаправлять вывод, но вывод записывается в файл. Затем я читаю файл.

Это фрагмент кода, который я использую (как вы можете видеть, я также пытался добавить 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 18.04.3.

Так что мои идеи были такими:

  • %2 - странный символ, но, похоже, не
  • string слишком большой, но, кажется, не
  • машины разные ... да, может быть, что какой-то пакет отличается, но библиотеки C ++ должны быть одинаковыми ... Я не 100% уверен, но насколько я проверял, они ...

У меня нет идей ... у кого-то есть какие-то предложения? Какую-то конкретную библиотеку C для проверки? Другие идеи?

Редактировать:

Даже если я не отправлю затронутый сертификат, я могу опубликовать затронутую строку. Это полная строка:

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:' в команду (чтобы исключить, что проблема заключалась вдлина строки), а на выходе то же самое, строка усекается. Похоже, проблема связана с каким-то персонажем %2C.

Есть идеи?

Изменить 2:

Изменить тему

Редактировать 3:

Я отлаживал ошибку, поэтому печатал строку ... к сожалению, я использовал syslog() для ее печати ... Полагаю,2%C было интерпретировано как format

1 Ответ

1 голос
/ 21 октября 2019

Если %2C в строке вызывает проблему, убедитесь, что вы не используете какую-либо функцию, которая использует format, например printf или syslog

В моем случае, пока я отлаживалошибка, я печатал строку, содержащую "% 2C", используя syslog, и это привело к путанице ...

...