[cairo] Fixing NULL dereference with _cairo_nil and the getters

Chris Wilson chris at chris-wilson.co.uk
Thu May 10 05:00:17 PDT 2007


Currently the cairo_t getters are written under the assumption that they
can operate safely on any cairo_t including _cairo_nil, e.g.

cairo_operator_t
cairo_get_operator (cairo_t *cr)
{
    return _cairo_gstate_get_operator (cr->gstate);
}

At the moment _cairo_nil.gstate is NULL and so this causes a NULL
deference within _cairo_gstate_get_operator(). The minimal fix would
appear to be fixup _cairo_nil to have a valid gstate:
--- a/src/cairo.c
+++ b/src/cairo.c
@@ -48,7 +48,7 @@ static const cairo_t _cairo_nil = {
   CAIRO_REF_COUNT_INVALID,     /* ref_count */
   CAIRO_STATUS_NO_MEMORY,      /* status */
   { 0, 0, 0, NULL },           /* user_data */
-  NULL,                                /* gstate */
+  (cairo_gstate_t *) _cairo_nil.gstate_tail,   /* gstate */
   {{                           /* gstate_tail */
     0
   }},

However, AIUI, this would cause the dynamic linker to have to fixup the
structure and thus move it from its read-only mapping.

The other option is add guards to all the getters, viz
cairo_operator_t
cairo_get_operator (cairo_t *cr)
{
    if (cr->ref_count == CAIRO_REF_COUNT_INVALID)
	return CAIRO_GSTATE_OPERATOR_DEFAULT;

    return _cairo_gstate_get_operator (cr->gstate);
}

So I'm soliciting opinions on the method to use, or perhaps there is a
third way?
--
Chris Wilson


More information about the cairo mailing list