]> granicus.if.org Git - libass/commitdiff
Fix parsing of unusual Alignment values in ASS style definitions
authorOleg Oshmyan <chortos@inbox.lv>
Fri, 3 Feb 2017 19:34:13 +0000 (21:34 +0200)
committerOleg Oshmyan <chortos@inbox.lv>
Tue, 14 Feb 2017 17:43:04 +0000 (19:43 +0200)
Handle large and negative values except INT32_MIN like VSFilter.
This avoids both overflow and inconsistent internal state.

This fixes https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=523.

VSFilter handles INT32_MIN like a mix of \an1, \an2 and \an3:

  * Vertical alignment is bottom.
  * Lines within the event are center-aligned.
  * Without \pos or \move, the center of the event is aligned
    with the right edge of the screen minus MarginR.
  * With \pos or \move, the left edge of the event is aligned
    with the position point.
  * Without \org, the rotation origin is aligned
    with the horizontal center of the event.
  * (With \org, the rotation origin is as specified.)

If we wanted to emulate this in libass, the cleanest way would be to
introduce a new horizontal alignment constant for this purpose that
would be used only for ASS style definitions with Alignment INT32_MIN.
This commit makes no attempt to do this and instead arbitrarily picks
\an2 for style definitions with Alignment -INT_MAX-1, which equals
INT32_MIN if int is int32_t. The fact that int is platform-dependent
is one of the reasons for this. We could change Alignment to be int32_t
instead of int for perfect VSFilter compatibility, but the same applies
to many other fields that currently use platform-dependent types.

libass/ass.c

index e8cefc50653e42a541660cde43b6a47a3a6592da..3a94290996d30131c5dea957cb3d241d3480d71c 100644 (file)
@@ -24,6 +24,7 @@
 #include <string.h>
 #include <assert.h>
 #include <errno.h>
+#include <limits.h>
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <inttypes.h>
@@ -241,12 +242,20 @@ static long long string2timecode(ASS_Library *library, char *p)
  */
 static int numpad2align(int val)
 {
-    int res, v;
-    v = (val - 1) / 3;          // 0, 1 or 2 for vertical alignment
-    if (v != 0)
-        v = 3 - v;
-    res = ((val - 1) % 3) + 1;  // horizontal alignment
-    res += v * 4;
+    if (val < -INT_MAX)
+        // Pick an alignment somewhat arbitrarily. VSFilter handles
+        // INT32_MIN as a mix of 1, 2 and 3, so prefer one of those values.
+        val = 2;
+    else if (val < 0)
+        val = -val;
+
+    int res = ((val - 1) % 3) + 1;  // horizontal alignment
+    if (val <= 3)
+        res |= VALIGN_SUB;
+    else if (val <= 6)
+        res |= VALIGN_CENTER;
+    else
+        res |= VALIGN_TOP;
     return res;
 }