mirror of
https://gitlab.freedesktop.org/cairo/cairo.git
synced 2026-04-21 08:50:43 +02:00
pdf: Properly pass on stdio write errors
cairo-pdf was silently ignoring write errors in _cairo_pdf_surface_finish(). Any write errors that happened here ended up setting a "status" variable, but the value in this variable was then unused. This commit fixes this bug by passing this error on to the caller. Additionally, this also adds a test case for this behaviour based on writing to /dev/full. This file is non-standard and thus the test first checks that this file exists and is writable before trying to write to it. This bug was found based on a report from Knut Petersen [0]. [0]: https://lists.cairographics.org/archives/cairo/2021-July/029281.html Signed-off-by: Uli Schlachter <psychon@znc.in>
This commit is contained in:
parent
b408352d45
commit
2fbd53a6b3
4 changed files with 25 additions and 6 deletions
|
|
@ -1515,7 +1515,7 @@ _cairo_pdf_interchange_free_outlines (cairo_pdf_surface_t *surface)
|
|||
_cairo_array_fini (&ic->outline);
|
||||
}
|
||||
|
||||
cairo_int_status_t
|
||||
void
|
||||
_cairo_pdf_interchange_fini (cairo_pdf_surface_t *surface)
|
||||
{
|
||||
cairo_pdf_interchange_t *ic = &surface->interchange;
|
||||
|
|
@ -1539,8 +1539,6 @@ _cairo_pdf_interchange_fini (cairo_pdf_surface_t *surface)
|
|||
free (ic->docinfo.creator);
|
||||
free (ic->docinfo.create_date);
|
||||
free (ic->docinfo.mod_date);
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
cairo_int_status_t
|
||||
|
|
|
|||
|
|
@ -355,7 +355,7 @@ _cairo_utf8_to_pdf_string (const char *utf8, char **str_out);
|
|||
cairo_private cairo_int_status_t
|
||||
_cairo_pdf_interchange_init (cairo_pdf_surface_t *surface);
|
||||
|
||||
cairo_private cairo_int_status_t
|
||||
cairo_private void
|
||||
_cairo_pdf_interchange_fini (cairo_pdf_surface_t *surface);
|
||||
|
||||
cairo_private cairo_int_status_t
|
||||
|
|
|
|||
|
|
@ -2329,7 +2329,9 @@ _cairo_pdf_surface_finish (void *abstract_surface)
|
|||
|
||||
_cairo_surface_clipper_reset (&surface->clipper);
|
||||
|
||||
return _cairo_pdf_interchange_fini (surface);
|
||||
_cairo_pdf_interchange_fini (surface);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
static cairo_int_status_t
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@
|
|||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#if CAIRO_HAS_PS_SURFACE
|
||||
#include <cairo-ps.h>
|
||||
|
|
@ -165,11 +166,29 @@ test_surface (const cairo_test_context_t *ctx,
|
|||
|
||||
if (status != CAIRO_STATUS_WRITE_ERROR) {
|
||||
cairo_test_log (ctx,
|
||||
"%s: Error: expected \"write error\", but received \"%s\".\n",
|
||||
"%s: Error: expected \"write error\" from bad_write(), but received \"%s\".\n",
|
||||
backend, cairo_status_to_string (status));
|
||||
return CAIRO_TEST_FAILURE;
|
||||
}
|
||||
|
||||
/* test propagation of file errors - for now this is unix-only */
|
||||
if (access("/dev/full", W_OK) == 0) {
|
||||
surface = file_constructor ("/dev/full", WIDTH_IN_POINTS, HEIGHT_IN_POINTS);
|
||||
cairo_surface_finish (surface);
|
||||
status = cairo_surface_status (surface);
|
||||
cairo_surface_destroy (surface);
|
||||
|
||||
if (status != CAIRO_STATUS_WRITE_ERROR) {
|
||||
cairo_test_log (ctx,
|
||||
"%s: Error: expected \"write error\" from /dev/full, but received \"%s\".\n",
|
||||
backend, cairo_status_to_string (status));
|
||||
return CAIRO_TEST_FAILURE;
|
||||
}
|
||||
} else {
|
||||
cairo_test_log (ctx,
|
||||
"/dev/full does not exist; skipping write test.\n");
|
||||
}
|
||||
|
||||
/* construct the real surface */
|
||||
wc.ctx = ctx;
|
||||
wc.status = CAIRO_TEST_SUCCESS;
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue