Commit 8d2b29ef988aa86489e36be50fa881335b81363e
1 parent
b51a5b2c
Fix segmentation fault with use of QPDFWriter::setOutputMemory
Showing
5 changed files
with
31 additions
and
21 deletions
ChangeLog
| 1 | +2012-09-06 Jay Berkenbilt <ejb@ql.org> | ||
| 2 | + | ||
| 3 | + * Bug fix: Writing after calling QPDFWriter::setOutputMemory() | ||
| 4 | + would cause a segmentation fault because of an internal field not | ||
| 5 | + being initialized, rendering that method useless. This has been | ||
| 6 | + corrected. | ||
| 7 | + | ||
| 1 | 2012-08-11 Jay Berkenbilt <ejb@ql.org> | 8 | 2012-08-11 Jay Berkenbilt <ejb@ql.org> |
| 2 | 9 | ||
| 3 | * 3.0.1: release | 10 | * 3.0.1: release |
TODO
| 1 | -3.0.2 | ||
| 2 | -===== | ||
| 3 | - | ||
| 4 | - * QPDFWriter::setOutputMemory segfaults without setStaticID because | ||
| 5 | - it doesn't set this->filename. Be sure to have a test case that | ||
| 6 | - exercises this. Check the function that sets the ID carefully to | ||
| 7 | - make sure other cases aren't missed. | ||
| 8 | - | ||
| 9 | General | 1 | General |
| 10 | ======= | 2 | ======= |
| 11 | 3 |
libqpdf/QPDFWriter.cc
| @@ -120,6 +120,7 @@ QPDFWriter::setOutputFile(char const* description, FILE* file, bool close_file) | @@ -120,6 +120,7 @@ QPDFWriter::setOutputFile(char const* description, FILE* file, bool close_file) | ||
| 120 | void | 120 | void |
| 121 | QPDFWriter::setOutputMemory() | 121 | QPDFWriter::setOutputMemory() |
| 122 | { | 122 | { |
| 123 | + this->filename = "memory buffer"; | ||
| 123 | this->buffer_pipeline = new Pl_Buffer("qpdf output"); | 124 | this->buffer_pipeline = new Pl_Buffer("qpdf output"); |
| 124 | to_delete.push_back(this->buffer_pipeline); | 125 | to_delete.push_back(this->buffer_pipeline); |
| 125 | initializePipelineStack(this->buffer_pipeline); | 126 | initializePipelineStack(this->buffer_pipeline); |
| @@ -1492,7 +1493,7 @@ QPDFWriter::generateID() | @@ -1492,7 +1493,7 @@ QPDFWriter::generateID() | ||
| 1492 | std::string seed; | 1493 | std::string seed; |
| 1493 | seed += QUtil::int_to_string((int)QUtil::get_current_time()); | 1494 | seed += QUtil::int_to_string((int)QUtil::get_current_time()); |
| 1494 | seed += " QPDF "; | 1495 | seed += " QPDF "; |
| 1495 | - seed += filename; | 1496 | + seed += this->filename; |
| 1496 | seed += " "; | 1497 | seed += " "; |
| 1497 | if (trailer.hasKey("/Info")) | 1498 | if (trailer.hasKey("/Info")) |
| 1498 | { | 1499 | { |
qpdf/qtest/qpdf.test
| @@ -149,7 +149,7 @@ $td->runtest("remove page we don't have", | @@ -149,7 +149,7 @@ $td->runtest("remove page we don't have", | ||
| 149 | $td->NORMALIZE_NEWLINES); | 149 | $td->NORMALIZE_NEWLINES); |
| 150 | # ---------- | 150 | # ---------- |
| 151 | $td->notify("--- Miscellaneous Tests ---"); | 151 | $td->notify("--- Miscellaneous Tests ---"); |
| 152 | -$n_tests += 47; | 152 | +$n_tests += 48; |
| 153 | 153 | ||
| 154 | $td->runtest("qpdf version", | 154 | $td->runtest("qpdf version", |
| 155 | {$td->COMMAND => "qpdf --version"}, | 155 | {$td->COMMAND => "qpdf --version"}, |
| @@ -322,6 +322,11 @@ $td->runtest("swap and replace", | @@ -322,6 +322,11 @@ $td->runtest("swap and replace", | ||
| 322 | $td->runtest("check output", | 322 | $td->runtest("check output", |
| 323 | {$td->FILE => "a.pdf"}, | 323 | {$td->FILE => "a.pdf"}, |
| 324 | {$td->FILE => "test14-out.pdf"}); | 324 | {$td->FILE => "test14-out.pdf"}); |
| 325 | +# Test 14 also exercises writing to memory without static ID. | ||
| 326 | +$td->runtest("check non-static ID version", | ||
| 327 | + {$td->COMMAND => "./diff-ignore-ID-version a.pdf b.pdf"}, | ||
| 328 | + {$td->STRING => "okay\n", $td->EXIT_STATUS => 0}, | ||
| 329 | + $td->NORMALIZE_NEWLINES); | ||
| 325 | 330 | ||
| 326 | $td->runtest("C API info key functions", | 331 | $td->runtest("C API info key functions", |
| 327 | {$td->COMMAND => "qpdf-ctest 16 minimal.pdf '' a.pdf"}, | 332 | {$td->COMMAND => "qpdf-ctest 16 minimal.pdf '' a.pdf"}, |
qpdf/test_driver.cc
| @@ -646,17 +646,22 @@ void runtest(int n, char const* filename1, char const* filename2) | @@ -646,17 +646,22 @@ void runtest(int n, char const* filename1, char const* filename2) | ||
| 646 | } | 646 | } |
| 647 | 647 | ||
| 648 | // Exercise writing to memory buffer | 648 | // Exercise writing to memory buffer |
| 649 | - QPDFWriter w(pdf); | ||
| 650 | - w.setOutputMemory(); | ||
| 651 | - w.setStaticID(true); | ||
| 652 | - w.setStreamDataMode(qpdf_s_preserve); | ||
| 653 | - w.write(); | ||
| 654 | - Buffer* b = w.getBuffer(); | ||
| 655 | - FILE* f = QUtil::fopen_wrapper(std::string("open a.pdf"), | ||
| 656 | - fopen("a.pdf", "wb")); | ||
| 657 | - fwrite(b->getBuffer(), b->getSize(), 1, f); | ||
| 658 | - fclose(f); | ||
| 659 | - delete b; | 649 | + for (int i = 0; i < 2; ++i) |
| 650 | + { | ||
| 651 | + QPDFWriter w(pdf); | ||
| 652 | + w.setOutputMemory(); | ||
| 653 | + // Exercise setOutputMemory with and without static ID | ||
| 654 | + w.setStaticID(i == 0); | ||
| 655 | + w.setStreamDataMode(qpdf_s_preserve); | ||
| 656 | + w.write(); | ||
| 657 | + Buffer* b = w.getBuffer(); | ||
| 658 | + std::string const filename = (i == 0 ? "a.pdf" : "b.pdf"); | ||
| 659 | + FILE* f = QUtil::fopen_wrapper("open " + filename, | ||
| 660 | + fopen(filename.c_str(), "wb")); | ||
| 661 | + fwrite(b->getBuffer(), b->getSize(), 1, f); | ||
| 662 | + fclose(f); | ||
| 663 | + delete b; | ||
| 664 | + } | ||
| 660 | } | 665 | } |
| 661 | else if (n == 15) | 666 | else if (n == 15) |
| 662 | { | 667 | { |