From c61ce962cfdef3fc756850132eb9f76cb7a57ba5 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Thu, 10 Jun 2021 17:33:29 -0600 Subject: [PATCH] [buffer] In hb_buffer_get_positions(), return NULL if inside message callback As discussed in https://github.com/harfbuzz/harfbuzz/issues/2468#issuecomment-645666066 Part of fixing https://github.com/harfbuzz/harfbuzz/issues/2468 --- src/hb-buffer.cc | 16 +++++++++++++--- src/hb-buffer.hh | 9 +++++++++ util/options.cc | 2 +- 3 files changed, 23 insertions(+), 4 deletions(-) diff --git a/src/hb-buffer.cc b/src/hb-buffer.cc index 8cad6ab8e..b125e1cea 100644 --- a/src/hb-buffer.cc +++ b/src/hb-buffer.cc @@ -1363,6 +1363,11 @@ hb_buffer_get_glyph_infos (hb_buffer_t *buffer, * Returns @buffer glyph position array. Returned pointer * is valid as long as @buffer contents are not modified. * + * If buffer did not have positions before, the positions will be + * initialized to zeros, unless this function is called from + * within a buffer message callback (see hb_buffer_set_message_func()), + * in which case %NULL is returned. + * * Return value: (transfer none) (array length=length): * The @buffer glyph position array. * The value valid as long as buffer has not been modified. @@ -1373,12 +1378,17 @@ hb_glyph_position_t * hb_buffer_get_glyph_positions (hb_buffer_t *buffer, unsigned int *length) { - if (!buffer->have_positions) - buffer->clear_positions (); - if (length) *length = buffer->len; + if (!buffer->have_positions) + { + if (unlikely (buffer->message_depth)) + return nullptr; + + buffer->clear_positions (); + } + return (hb_glyph_position_t *) buffer->pos; } diff --git a/src/hb-buffer.hh b/src/hb-buffer.hh index 8b432b5f9..33d6e6c66 100644 --- a/src/hb-buffer.hh +++ b/src/hb-buffer.hh @@ -128,6 +128,9 @@ struct hb_buffer_t hb_buffer_message_func_t message_func; void *message_data; hb_destroy_func_t message_destroy; + unsigned message_depth; /* How deeply are we inside a message callback? */ +#else + static constexpr unsigned message_depth = 0u; #endif /* Internal debugging. */ @@ -400,10 +403,16 @@ struct hb_buffer_t #else if (!messaging ()) return true; + + message_depth++; + va_list ap; va_start (ap, fmt); bool ret = message_impl (font, fmt, ap); va_end (ap); + + message_depth--; + return ret; #endif } diff --git a/util/options.cc b/util/options.cc index caf8233f7..da2495025 100644 --- a/util/options.cc +++ b/util/options.cc @@ -454,7 +454,7 @@ shape_options_t::add_options (option_parser_t *parser) {"cluster-level", 0, 0, G_OPTION_ARG_INT, &this->cluster_level, "Cluster merging level (default: 0)", "0/1/2"}, {"normalize-glyphs",0, 0, G_OPTION_ARG_NONE, &this->normalize_glyphs, "Rearrange glyph clusters in nominal order", nullptr}, {"verify", 0, 0, G_OPTION_ARG_NONE, &this->verify, "Perform sanity checks on shaping results", nullptr}, - {"num-iterations", 'n', 0, G_OPTION_ARG_INT, &this->num_iterations, "Run shaper N times (default: 1)", "N"}, + {"num-iterations", 'n', 0, G_OPTION_ARG_INT, &this->num_iterations, "Run shaper N times (default: 1)", "N"}, {nullptr} }; parser->add_group (entries,