Merge commit 'f401792595dd7760f531e8a3bd2336e9033bd45a'
authorMichael Niedermayer <michaelni@gmx.at>
Sat, 18 Oct 2014 19:31:08 +0000 (21:31 +0200)
committerMichael Niedermayer <michaelni@gmx.at>
Sat, 18 Oct 2014 19:33:04 +0000 (21:33 +0200)
* commit 'f401792595dd7760f531e8a3bd2336e9033bd45a':
  vf_drawtext: Do not leak the mmapped textfile

Conflicts:
libavfilter/vf_drawtext.c

See: 6956b048d8198dce5126c8942dece21cfb1a7978
Merged-by: Michael Niedermayer <michaelni@gmx.at>
1  2 
libavfilter/vf_drawtext.c

index 4ab96dc46acd98a5fafff8ba31fa4a64af4fc3b0,d954fdf2cda447ea27be77ee489de4630374970b..cf570643552f5229b07d86144d751e02420ac7ed
@@@ -442,145 -370,8 +442,145 @@@ static int load_font_fontconfig(AVFilte
  fail:
      FcPatternDestroy(best);
      return err;
 +}
 +#endif
 +
 +static int load_font(AVFilterContext *ctx)
 +{
 +    DrawTextContext *s = ctx->priv;
 +    int err;
 +
 +    /* load the face, and set up the encoding, which is by default UTF-8 */
 +    err = load_font_file(ctx, s->fontfile, 0);
 +    if (!err)
 +        return 0;
 +#if CONFIG_LIBFONTCONFIG
 +    err = load_font_fontconfig(ctx);
 +    if (!err)
 +        return 0;
  #endif
-     if (!(tmp = av_realloc(s->text, textbuf_size + 1))) {
 +    return err;
 +}
 +
 +static int load_textfile(AVFilterContext *ctx)
 +{
 +    DrawTextContext *s = ctx->priv;
 +    int err;
 +    uint8_t *textbuf;
 +    uint8_t *tmp;
 +    size_t textbuf_size;
 +
 +    if ((err = av_file_map(s->textfile, &textbuf, &textbuf_size, 0, ctx)) < 0) {
 +        av_log(ctx, AV_LOG_ERROR,
 +               "The text file '%s' could not be read or is empty\n",
 +               s->textfile);
 +        return err;
 +    }
 +
++    if (textbuf_size > SIZE_MAX - 1 || !(tmp = av_realloc(s->text, textbuf_size + 1))) {
 +        av_file_unmap(textbuf, textbuf_size);
 +        return AVERROR(ENOMEM);
 +    }
 +    s->text = tmp;
 +    memcpy(s->text, textbuf, textbuf_size);
 +    s->text[textbuf_size] = 0;
 +    av_file_unmap(textbuf, textbuf_size);
 +
 +    return 0;
 +}
 +
 +static inline int is_newline(uint32_t c)
 +{
 +    return c == '\n' || c == '\r' || c == '\f' || c == '\v';
 +}
 +
 +#if CONFIG_LIBFRIBIDI
 +static int shape_text(AVFilterContext *ctx)
 +{
 +    DrawTextContext *s = ctx->priv;
 +    uint8_t *tmp;
 +    int ret = AVERROR(ENOMEM);
 +    static const FriBidiFlags flags = FRIBIDI_FLAGS_DEFAULT |
 +                                      FRIBIDI_FLAGS_ARABIC;
 +    FriBidiChar *unicodestr = NULL;
 +    FriBidiStrIndex len;
 +    FriBidiParType direction = FRIBIDI_PAR_LTR;
 +    FriBidiStrIndex line_start = 0;
 +    FriBidiStrIndex line_end = 0;
 +    FriBidiLevel *embedding_levels = NULL;
 +    FriBidiArabicProp *ar_props = NULL;
 +    FriBidiCharType *bidi_types = NULL;
 +    FriBidiStrIndex i,j;
 +
 +    len = strlen(s->text);
 +    if (!(unicodestr = av_malloc_array(len, sizeof(*unicodestr)))) {
 +        goto out;
 +    }
 +    len = fribidi_charset_to_unicode(FRIBIDI_CHAR_SET_UTF8,
 +                                     s->text, len, unicodestr);
 +
 +    bidi_types = av_malloc_array(len, sizeof(*bidi_types));
 +    if (!bidi_types) {
 +        goto out;
 +    }
 +
 +    fribidi_get_bidi_types(unicodestr, len, bidi_types);
 +
 +    embedding_levels = av_malloc_array(len, sizeof(*embedding_levels));
 +    if (!embedding_levels) {
 +        goto out;
 +    }
 +
 +    if (!fribidi_get_par_embedding_levels(bidi_types, len, &direction,
 +                                          embedding_levels)) {
 +        goto out;
 +    }
 +
 +    ar_props = av_malloc_array(len, sizeof(*ar_props));
 +    if (!ar_props) {
 +        goto out;
 +    }
 +
 +    fribidi_get_joining_types(unicodestr, len, ar_props);
 +    fribidi_join_arabic(bidi_types, len, embedding_levels, ar_props);
 +    fribidi_shape(flags, embedding_levels, len, ar_props, unicodestr);
 +
 +    for (line_end = 0, line_start = 0; line_end < len; line_end++) {
 +        if (is_newline(unicodestr[line_end]) || line_end == len - 1) {
 +            if (!fribidi_reorder_line(flags, bidi_types,
 +                                      line_end - line_start + 1, line_start,
 +                                      direction, embedding_levels, unicodestr,
 +                                      NULL)) {
 +                goto out;
 +            }
 +            line_start = line_end + 1;
 +        }
 +    }
 +
 +    /* Remove zero-width fill chars put in by libfribidi */
 +    for (i = 0, j = 0; i < len; i++)
 +        if (unicodestr[i] != FRIBIDI_CHAR_FILL)
 +            unicodestr[j++] = unicodestr[i];
 +    len = j;
 +
 +    if (!(tmp = av_realloc(s->text, (len * 4 + 1) * sizeof(*s->text)))) {
 +        /* Use len * 4, as a unicode character can be up to 4 bytes in UTF-8 */
 +        goto out;
 +    }
 +
 +    s->text = tmp;
 +    len = fribidi_unicode_to_charset(FRIBIDI_CHAR_SET_UTF8,
 +                                     unicodestr, len, s->text);
 +    ret = 0;
 +
 +out:
 +    av_free(unicodestr);
 +    av_free(embedding_levels);
 +    av_free(ar_props);
 +    av_free(bidi_types);
 +    return ret;
  }
 +#endif
  
  static av_cold int init(AVFilterContext *ctx)
  {