Hi,
During the play with pdftocairo, occasionally I found that
an invalid option can cause SEGV in pdftocairo;
$ pdftocairo -f 2 -l 1 -svg sample.pdf sample.svg
Segmentation fault.
The background is simple.
989 cairoOut = new CairoOutputDev();
990 cairoOut->startDoc(doc);
991 if (sz != 0)
992 crop_w = crop_h = sz;
993 pg_num_len = numberOfCharacters(doc->getNumPages());
994 for (pg = firstPage; pg <= lastPage; ++pg) {
...
1040 if (pg == firstPage)
1041 beginDocument(outputFileName, output_w, output_h);
1042 beginPage(output_w, output_h);
1043 renderPage(doc, cairoOut, pg, pg_w, pg_h, output_w, output_h);
1044 endPage(imageFileName);
1045 }
1046 endDocument();
As you can see, the document initialization is done in the loop.
If invalid start/end pages are given (e.g. in upside-down order),
the beginDocument() is not invoked but endDocument() is invoked.
623 static void endDocument()
624 {
625 cairo_status_t status;
626
627 if (printing) {
628 cairo_surface_finish(surface);
629 status = cairo_surface_status(surface);
630 if (status)
631 error(errInternal, -1, "cairo error: {0:s}\n",
cairo_status_to_string(status));
632 cairo_surface_destroy(surface);
633 fclose(output_file);
634 }
635 }
If endDocument() is invoked without beginDocument(), uninitialized
surface and output_file are referred, therefore, SEGV is caused.
The easiest fix would be NULL-initialization (not needed in C++?) of
surface & output_file, and checking NULL before referring them in
endDocument(). Patch is attached.
Regards,
mpsuzuki
diff --git a/utils/pdftocairo.cc b/utils/pdftocairo.cc
index f6ddaae..243cdcf 100644
--- a/utils/pdftocairo.cc
+++ b/utils/pdftocairo.cc
@@ -625,12 +625,16 @@ static void endDocument()
cairo_status_t status;
if (printing) {
- cairo_surface_finish(surface);
- status = cairo_surface_status(surface);
- if (status)
- error(errInternal, -1, "cairo error: {0:s}\n", cairo_status_to_string(status));
- cairo_surface_destroy(surface);
- fclose(output_file);
+ if (surface) {
+ cairo_surface_finish(surface);
+ status = cairo_surface_status(surface);
+ if (status)
+ error(errInternal, -1, "cairo error: {0:s}\n", cairo_status_to_string(status));
+ cairo_surface_destroy(surface);
+ }
+ if (output_file) {
+ fclose(output_file);
+ }
}
}
@@ -984,6 +988,8 @@ int main(int argc, char *argv[]) {
cairoOut = new CairoOutputDev();
cairoOut->startDoc(doc);
+ surface = NULL;
+ output_file = NULL;
if (sz != 0)
crop_w = crop_h = sz;
pg_num_len = numberOfCharacters(doc->getNumPages());
_______________________________________________
poppler mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/poppler