Commit 16a23368e738be88669f4fbf4d3341dd473519c7
1 parent
8f5de08c
Fix infinite loop trimming passwords with ( in them
Showing
3 changed files
with
28 additions
and
4 deletions
libqpdf/QPDF_encryption.cc
| @@ -141,14 +141,20 @@ QPDF::trim_user_password(std::string& user_password) | @@ -141,14 +141,20 @@ QPDF::trim_user_password(std::string& user_password) | ||
| 141 | return; | 141 | return; |
| 142 | } | 142 | } |
| 143 | 143 | ||
| 144 | - char const* p = 0; | ||
| 145 | - while ((p = strchr(cstr, '\x28')) != 0) | 144 | + char const* p1 = cstr; |
| 145 | + char const* p2 = 0; | ||
| 146 | + while ((p2 = strchr(p1, '\x28')) != 0) | ||
| 146 | { | 147 | { |
| 147 | - if (memcmp(p, padding_string, len - (p - cstr)) == 0) | 148 | + if (memcmp(p2, padding_string, len - (p2 - cstr)) == 0) |
| 148 | { | 149 | { |
| 149 | - user_password = user_password.substr(0, p - cstr); | 150 | + user_password = user_password.substr(0, p2 - cstr); |
| 150 | return; | 151 | return; |
| 151 | } | 152 | } |
| 153 | + else | ||
| 154 | + { | ||
| 155 | + QTC::TC("qpdf", "QPDF_encryption skip 0x28"); | ||
| 156 | + p1 = p2 + 1; | ||
| 157 | + } | ||
| 152 | } | 158 | } |
| 153 | } | 159 | } |
| 154 | 160 |
qpdf/qpdf.testcov
| @@ -253,3 +253,4 @@ QPDFWriter skip ADBE 0 | @@ -253,3 +253,4 @@ QPDFWriter skip ADBE 0 | ||
| 253 | QPDFWriter remove existing Extensions 0 | 253 | QPDFWriter remove existing Extensions 0 |
| 254 | QPDFWriter skip Extensions 0 | 254 | QPDFWriter skip Extensions 0 |
| 255 | QPDFWriter preserve ADBE 0 | 255 | QPDFWriter preserve ADBE 0 |
| 256 | +QPDF_encryption skip 0x28 0 |
qpdf/test_driver.cc
| @@ -88,6 +88,23 @@ void runtest(int n, char const* filename1, char const* filename2) | @@ -88,6 +88,23 @@ void runtest(int n, char const* filename1, char const* filename2) | ||
| 88 | // the test suite to see how the test is invoked to find the file | 88 | // the test suite to see how the test is invoked to find the file |
| 89 | // that the test is supposed to operate on. | 89 | // that the test is supposed to operate on. |
| 90 | 90 | ||
| 91 | + if (n == 0) | ||
| 92 | + { | ||
| 93 | + // Throw in some random test cases that don't fit anywhere | ||
| 94 | + // else. This is in addition to whatever else is going on in | ||
| 95 | + // test 0. | ||
| 96 | + | ||
| 97 | + // The code to trim user passwords looks for 0x28 (which is | ||
| 98 | + // "(") since it marks the beginning of the padding. Exercise | ||
| 99 | + // the code to make sure it skips over 0x28 characters that | ||
| 100 | + // aren't part of padding. | ||
| 101 | + std::string password( | ||
| 102 | + "1234567890123456789012(45678\x28\xbf\x4e\x5e"); | ||
| 103 | + assert(password.length() == 32); | ||
| 104 | + QPDF::trim_user_password(password); | ||
| 105 | + assert(password == "1234567890123456789012(45678"); | ||
| 106 | + } | ||
| 107 | + | ||
| 91 | QPDF pdf; | 108 | QPDF pdf; |
| 92 | PointerHolder<char> file_buf; | 109 | PointerHolder<char> file_buf; |
| 93 | FILE* filep = 0; | 110 | FILE* filep = 0; |