diff --git a/libqpdf/QPDF_encryption.cc b/libqpdf/QPDF_encryption.cc index 43bc62ba..6ab51a03 100644 --- a/libqpdf/QPDF_encryption.cc +++ b/libqpdf/QPDF_encryption.cc @@ -141,14 +141,20 @@ QPDF::trim_user_password(std::string& user_password) return; } - char const* p = 0; - while ((p = strchr(cstr, '\x28')) != 0) + char const* p1 = cstr; + char const* p2 = 0; + while ((p2 = strchr(p1, '\x28')) != 0) { - if (memcmp(p, padding_string, len - (p - cstr)) == 0) + if (memcmp(p2, padding_string, len - (p2 - cstr)) == 0) { - user_password = user_password.substr(0, p - cstr); + user_password = user_password.substr(0, p2 - cstr); return; } + else + { + QTC::TC("qpdf", "QPDF_encryption skip 0x28"); + p1 = p2 + 1; + } } } diff --git a/qpdf/qpdf.testcov b/qpdf/qpdf.testcov index 1f8238e0..cf9aed20 100644 --- a/qpdf/qpdf.testcov +++ b/qpdf/qpdf.testcov @@ -253,3 +253,4 @@ QPDFWriter skip ADBE 0 QPDFWriter remove existing Extensions 0 QPDFWriter skip Extensions 0 QPDFWriter preserve ADBE 0 +QPDF_encryption skip 0x28 0 diff --git a/qpdf/test_driver.cc b/qpdf/test_driver.cc index f8294889..bd403345 100644 --- a/qpdf/test_driver.cc +++ b/qpdf/test_driver.cc @@ -88,6 +88,23 @@ void runtest(int n, char const* filename1, char const* filename2) // the test suite to see how the test is invoked to find the file // that the test is supposed to operate on. + if (n == 0) + { + // Throw in some random test cases that don't fit anywhere + // else. This is in addition to whatever else is going on in + // test 0. + + // The code to trim user passwords looks for 0x28 (which is + // "(") since it marks the beginning of the padding. Exercise + // the code to make sure it skips over 0x28 characters that + // aren't part of padding. + std::string password( + "1234567890123456789012(45678\x28\xbf\x4e\x5e"); + assert(password.length() == 32); + QPDF::trim_user_password(password); + assert(password == "1234567890123456789012(45678"); + } + QPDF pdf; PointerHolder file_buf; FILE* filep = 0;