Source: libass
Version: 1:0.15.0-1
Severity: normal
Tags: patch

Hi,

as you may already have noticed libass 0.15.1 was released recently and fixes
many bugs. I believe at least one of those fixes needs to be pulled into 
Debian.

0.15.0 introduced a regression leading to reliable crashes on some files with
embedded fonts. Without this fix some subtitle files will be plain unplayable
and cause the libass-using application to segfault.
Attached a patch with the relevant upstream commits as 'fix-emf-crash.patch';
it's rebased to apply cleanly on top of current Debian master.

Furthermore, 0.15.1 includes another fix for an older embedded font bug
preventing most libass-API-users from actually utilising embedded fonts as 
they only worked with a specific API-call order. This prevents eg VLC from 
correctly displaying subtitles with embedded fonts. Applying this fix on 
libass' side, will instantly make embedded fonts work in VLC, without further 
changes being neccesary.
I believe, while less severe than crashing, it would be a very good idea to 
also backport this fix to Debian.
Attached a patch with the relevant upstream commits as 'fix-emf-render.patch';
it's rebased to apply cleanly on Debian master + previous patch.


However, as upstream's release notes state, 0.15.1 is a pure bugfix release 
with no actual API changes or additions and there are a number of additional
bugfixes. Perhaps a full upgrade to 0.15.1 would also be a good idea?
But then again, the "Hard Freeze" already started and I'm not sure what the 
guidelines say about pure bugfix releases from an upstream that doesn't 
regularly provide stable bugfix releases.
So, I just thought I'd mention it and leave it up to your judgement :)

Here's the relevant part of upstream's release text:
> This is purely a bug fix and polish release, with no significant API or ABI
> changes.
>
> The only API change is that `ass_add_font` is now declared to accept
> `const char *`. Previously it took only `char *`, but const has worked in
> practice since the very first standalone libass release.
>
> [Full text with a list of all fixes:
>  https://github.com/libass/libass/releases/tag/0.15.1 ]


Cheers
Nils König

-- System Information:
Debian Release: 11.0
  APT prefers unstable
  APT policy: (500, 'unstable')
Architecture: amd64 (x86_64)

Kernel: Linux 5.10.0-0.bpo.5-amd64 (SMP w/16 CPU threads)
Locale: LANG=en_GB.UTF-8, LC_CTYPE=en_GB.UTF-8 (charmap=UTF-8), LANGUAGE not set
Shell: /bin/sh linked to /bin/dash
Init: openrc (via /run/openrc)
PID 1: openrc-init
LSM: AppArmor: enabled
From 4830494fcdcf2cf67f35d92cade1a60713a2fdd1 Mon Sep 17 00:00:00 2001
From: Oleg Oshmyan <chor...@inbox.lv>
Date: Tue, 27 Oct 2020 15:46:04 +0200
Subject: [PATCH 1/2] Fix crashes on some files with embedded fonts

Squashed from upstream commits 017137471d0043e0321e377ed8da48e45a3ec632
and 59eb317aaa495ad5331c9efdf8d7bf3d860c2992

== Commit message from 017137471d0043e0321e377ed8da48e45a3ec632:
decode_font: fix subtraction broken by change to unsigned type

This caused a one-byte buffer overwrite and an assertion failure.

Regression in commit 910211f1c0078e37546f73e95306724358b89be2.

Discovered by OSS-Fuzz.

Fixes https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=26674.
Fixes https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=26678.

== Commit Message from 59eb317aaa495ad5331c9efdf8d7bf3d860c2992
Match more types and format specifiers to size_t fontdata_used

Omissions in commit 910211f1c0078e37546f73e95306724358b89be2.

Microsoft's C library does not support %zu until Universal CRT
(Visual Studio 2015). At worst, this verbose-level message will
look wrong and be useless.
---
 libass/ass.c | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/libass/ass.c b/libass/ass.c
index 428a332..51fa201 100644
--- a/libass/ass.c
+++ b/libass/ass.c
@@ -820,7 +820,7 @@ static unsigned char *decode_chars(const unsigned char *src,
                                    unsigned char *dst, size_t cnt_in)
 {
     uint32_t value = 0;
-    for (int i = 0; i < cnt_in; i++)
+    for (size_t i = 0; i < cnt_in; i++)
         value |= (uint32_t) ((src[i] - 33u) & 63) << 6 * (3 - i);
 
     *dst++ = value >> 16;
@@ -850,14 +850,14 @@ static int decode_font(ASS_Track *track)
     size_t dsize;                  // decoded size
     unsigned char *buf = 0;
 
-    ass_msg(track->library, MSGL_V, "Font: %d bytes encoded data",
+    ass_msg(track->library, MSGL_V, "Font: %zu bytes encoded data",
             track->parser_priv->fontdata_used);
     size = track->parser_priv->fontdata_used;
     if (size % 4 == 1) {
         ass_msg(track->library, MSGL_ERR, "Bad encoded data size");
         goto error_decode_font;
     }
-    buf = malloc(size / 4 * 3 + FFMAX(size % 4 - 1, 0));
+    buf = malloc(size / 4 * 3 + FFMAX(size % 4, 1) - 1);
     if (!buf)
         goto error_decode_font;
     q = buf;
@@ -871,7 +871,7 @@ static int decode_font(ASS_Track *track)
         q = decode_chars(p, q, 3);
     }
     dsize = q - buf;
-    assert(dsize == size / 4 * 3 + FFMAX(size % 4 - 1, 0));
+    assert(dsize == size / 4 * 3 + FFMAX(size % 4, 1) - 1);
 
     if (track->library->extract_fonts) {
         ass_add_font(track->library, track->parser_priv->fontname,
-- 
2.20.1

From 168062a76dfad2741af4d920fdde36e61f8c9cb6 Mon Sep 17 00:00:00 2001
From: Oneric <one...@oneric.stub>
Date: Fri, 26 Mar 2021 16:28:29 +0100
Subject: [PATCH 2/2] Fix embedded fonts for libass users

eg VLC can't properly display subs with embedded fonts without this

Squashed from upstream commits 8701c535d63551b6d42d396c106e844d5b0f4abd
and 1140b6b885c89d37eef13dc1f31f144e9a76a4d7 and rebased on top of
Debian's master branch

== Commit message from 8701c535d63551b6d42d396c106e844d5b0f4abd
library: replace grow_array with ASS_REALLOC_ARRAY

The latter has overflow protections for size_t indexation and element
size > 1, the former none whatsoever. Change all related vars to size_t.
Additionally, switch to exponential buffer growth.

== Commit message from 1140b6b885c89d37eef13dc1f31f144e9a76a4d7
Fix embedded and memory fonts

Previously only both only worked when ass_set_fonts was called after all
embedded and memory fonts were already added. Especially for embedded
fonts this meant it won't work for most users, except mpv, including our
own utilities, even if extract_fonts was set.

Now that it works, enable extract_fonts in our utilities.

GitHub: fixes #266
---
 compare/compare.c       |  1 +
 libass/ass_fontselect.c | 24 +++++++++++++++++-------
 libass/ass_fontselect.h | 11 ++++++++---
 libass/ass_library.c    | 20 ++++----------------
 libass/ass_library.h    |  2 +-
 libass/ass_render.c     |  6 ++++++
 libass/ass_render.h     |  1 +
 libass/ass_render_api.c |  2 +-
 profile/profile.c       |  1 +
 test/test.c             |  1 +
 10 files changed, 41 insertions(+), 28 deletions(-)

diff --git a/compare/compare.c b/compare/compare.c
index 3e71ba2..88e0b78 100644
--- a/compare/compare.c
+++ b/compare/compare.c
@@ -535,6 +535,7 @@ int main(int argc, char *argv[])
         return 1;
     }
     ass_set_message_cb(lib, msg_callback, NULL);
+    ass_set_extract_fonts(lib, true);
 
     ItemList list;
     if (!init_items(&list)) {
diff --git a/libass/ass_fontselect.c b/libass/ass_fontselect.c
index fed0415..bea05eb 100644
--- a/libass/ass_fontselect.c
+++ b/libass/ass_fontselect.c
@@ -987,9 +987,8 @@ static void process_fontdata(ASS_FontProvider *priv, ASS_Library *library,
  */
 static ASS_FontProvider *
 ass_embedded_fonts_add_provider(ASS_Library *lib, ASS_FontSelector *selector,
-                                FT_Library ftlib)
+                                FT_Library ftlib, size_t *num_emfonts)
 {
-    int i;
     ASS_FontProvider *priv = ass_font_provider_new(selector, &ft_funcs, NULL);
     if (priv == NULL)
         return NULL;
@@ -998,8 +997,9 @@ ass_embedded_fonts_add_provider(ASS_Library *lib, ASS_FontSelector *selector,
         load_fonts_from_dir(lib, lib->fonts_dir);
     }
 
-    for (i = 0; i < lib->num_fontdata; ++i)
+    for (size_t i = 0; i < lib->num_fontdata; i++)
         process_fontdata(priv, lib, ftlib, i);
+    *num_emfonts = lib->num_fontdata;
 
     return priv;
 }
@@ -1033,9 +1033,8 @@ struct font_constructors font_constructors[] = {
  * \return newly created font selector
  */
 ASS_FontSelector *
-ass_fontselect_init(ASS_Library *library,
-                    FT_Library ftlibrary, const char *family,
-                    const char *path, const char *config,
+ass_fontselect_init(ASS_Library *library, FT_Library ftlibrary, size_t *num_emfonts,
+                    const char *family, const char *path, const char *config,
                     ASS_DefaultFontProvider dfp)
 {
     ASS_FontSelector *priv = calloc(1, sizeof(ASS_FontSelector));
@@ -1048,7 +1047,7 @@ ass_fontselect_init(ASS_Library *library,
     priv->index_default = 0;
 
     priv->embedded_provider = ass_embedded_fonts_add_provider(library, priv,
-            ftlibrary);
+            ftlibrary, num_emfonts);
 
     if (priv->embedded_provider == NULL) {
         ass_msg(library, MSGL_WARN, "failed to create embedded font provider");
@@ -1132,3 +1131,14 @@ void ass_map_font(const ASS_FontMapping *map, int len, const char *name,
         }
     }
 }
+
+size_t ass_update_embedded_fonts(ASS_Library *lib, ASS_FontSelector *selector,
+                                 FT_Library ftlib, size_t num_loaded)
+{
+    if (!selector->embedded_provider)
+        return num_loaded;
+
+    for (size_t i = num_loaded; i < lib->num_fontdata; i++)
+        process_fontdata(selector->embedded_provider, lib, ftlib, i);
+    return lib->num_fontdata;
+}
diff --git a/libass/ass_fontselect.h b/libass/ass_fontselect.h
index a239a94..56c12d7 100644
--- a/libass/ass_fontselect.h
+++ b/libass/ass_fontselect.h
@@ -225,9 +225,8 @@ void ass_map_font(const ASS_FontMapping *map, int len, const char *name,
                   ASS_FontProviderMetaData *meta);
 
 ASS_FontSelector *
-ass_fontselect_init(ASS_Library *library,
-                    FT_Library ftlibrary, const char *family,
-                    const char *path, const char *config,
+ass_fontselect_init(ASS_Library *library, FT_Library ftlibrary, size_t *num_emfonts,
+                    const char *family, const char *path, const char *config,
                     ASS_DefaultFontProvider dfp);
 char *ass_font_select(ASS_FontSelector *priv, ASS_Library *library,
                       ASS_Font *font, int *index, char **postscript_name,
@@ -287,4 +286,10 @@ bool ass_get_font_info(ASS_Library *lib, FT_Library ftlib, const char *path,
  */
 void ass_font_provider_free(ASS_FontProvider *provider);
 
+/**
+ * \brief Update embedded and memory fonts
+ */
+size_t ass_update_embedded_fonts(ASS_Library *lib, ASS_FontSelector *selector,
+                                 FT_Library ftlib, size_t num_loaded);
+
 #endif                          /* LIBASS_FONTSELECT_H */
diff --git a/libass/ass_library.c b/libass/ass_library.c
index 6ee5f81..7efb45f 100644
--- a/libass/ass_library.c
+++ b/libass/ass_library.c
@@ -95,24 +95,13 @@ void ass_set_style_overrides(ASS_Library *priv, char **list)
         *q = strdup(*p);
 }
 
-static int grow_array(void **array, int nelem, size_t elsize)
-{
-    if (!(nelem & 31)) {
-        void *ptr = realloc(*array, (nelem + 32) * elsize);
-        if (!ptr)
-            return 0;
-        *array = ptr;
-    }
-    return 1;
-}
-
 void ass_add_font(ASS_Library *priv, char *name, char *data, int size)
 {
-    int idx = priv->num_fontdata;
+    size_t idx = priv->num_fontdata;
     if (!name || !data || !size)
         return;
-    if (!grow_array((void **) &priv->fontdata, priv->num_fontdata,
-                    sizeof(*priv->fontdata)))
+    if (!(idx & (idx - 32)) && // power of two >= 32, or zero --> time for realloc
+            !ASS_REALLOC_ARRAY(priv->fontdata, FFMAX(2 * idx, 32)))
         return;
 
     priv->fontdata[idx].name = strdup(name);
@@ -135,8 +124,7 @@ error:
 
 void ass_clear_fonts(ASS_Library *priv)
 {
-    int i;
-    for (i = 0; i < priv->num_fontdata; ++i) {
+    for (size_t i = 0; i < priv->num_fontdata; i++) {
         free(priv->fontdata[i].name);
         free(priv->fontdata[i].data);
     }
diff --git a/libass/ass_library.h b/libass/ass_library.h
index 8144f8e..674e06c 100644
--- a/libass/ass_library.h
+++ b/libass/ass_library.h
@@ -33,7 +33,7 @@ struct ass_library {
     char **style_overrides;
 
     ASS_Fontdata *fontdata;
-    int num_fontdata;
+    size_t num_fontdata;
     void (*msg_callback)(int, const char *, va_list, void *);
     void *msg_callback_data;
 };
diff --git a/libass/ass_render.c b/libass/ass_render.c
index 559daf0..dc1d663 100644
--- a/libass/ass_render.c
+++ b/libass/ass_render.c
@@ -2859,6 +2859,12 @@ ass_start_frame(ASS_Renderer *render_priv, ASS_Track *track,
 
     ass_lazy_track_init(render_priv->library, render_priv->track);
 
+    if (render_priv->library->num_fontdata != render_priv->num_emfonts) {
+        assert(render_priv->library->num_fontdata > render_priv->num_emfonts);
+        render_priv->num_emfonts = ass_update_embedded_fonts(render_priv->library,
+            render_priv->fontselect, render_priv->ftlibrary, render_priv->num_emfonts);
+    }
+
     ass_shaper_set_kerning(render_priv->shaper, track->Kerning);
     ass_shaper_set_language(render_priv->shaper, track->Language);
     ass_shaper_set_level(render_priv->shaper, render_priv->settings.shaper);
diff --git a/libass/ass_render.h b/libass/ass_render.h
index 803b577..fba2189 100644
--- a/libass/ass_render.h
+++ b/libass/ass_render.h
@@ -292,6 +292,7 @@ struct ass_renderer {
     ASS_Library *library;
     FT_Library ftlibrary;
     ASS_FontSelector *fontselect;
+    size_t num_emfonts;
     ASS_Settings settings;
     int render_id;
     ASS_Shaper *shaper;
diff --git a/libass/ass_render_api.c b/libass/ass_render_api.c
index 319758d..70cf174 100644
--- a/libass/ass_render_api.c
+++ b/libass/ass_render_api.c
@@ -155,7 +155,7 @@ void ass_set_fonts(ASS_Renderer *priv, const char *default_font,
     if (priv->fontselect)
         ass_fontselect_free(priv->fontselect);
     priv->fontselect = ass_fontselect_init(priv->library, priv->ftlibrary,
-            default_family, default_font, config, dfp);
+            &priv->num_emfonts, default_family, default_font, config, dfp);
 }
 
 void ass_set_selective_style_override_enabled(ASS_Renderer *priv, int bits)
diff --git a/profile/profile.c b/profile/profile.c
index e7f64f5..b89d10b 100644
--- a/profile/profile.c
+++ b/profile/profile.c
@@ -49,6 +49,7 @@ static void init(int frame_w, int frame_h)
     }
 
     ass_set_message_cb(ass_library, msg_callback, NULL);
+    ass_set_extract_fonts(ass_library, 1);
 
     ass_renderer = ass_renderer_init(ass_library);
     if (!ass_renderer) {
diff --git a/test/test.c b/test/test.c
index 6726fed..c378e48 100644
--- a/test/test.c
+++ b/test/test.c
@@ -99,6 +99,7 @@ static void init(int frame_w, int frame_h)
     }
 
     ass_set_message_cb(ass_library, msg_callback, NULL);
+    ass_set_extract_fonts(ass_library, 1);
 
     ass_renderer = ass_renderer_init(ass_library);
     if (!ass_renderer) {
-- 
2.20.1

Attachment: signature.asc
Description: PGP signature

Reply via email to