| Commit message (Collapse) | Author | Age | Files | Lines |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Unlike for some other Style fields, VSFilters (and libass) do not clamp
negative Fontsize values to zero. Instead the value remains negative
throughout parsing and in rendering something close to the absolute
value is used. It is not exactly the absolute value, but a bit more than
it and the difference is larger than what would expected from different
rounding modes. I'm not sure when this reinterpretation of negative
values takes place. It's possible this happens not in VSFilters but GDI.
With \fs commands it is not possible to directly specify negative
fontsizes as \fs- and \fs+ already have a special different effect
altering the fontsize in relation to the current one (and here negative
values are discarded).
Apart from the VSFilter incompatibility, negative Fontsizes also crash
libass either by failing an assert or if those are disabled by a
stack-overflow. To fix the crashes and come closer to VSFilter take the
absolute value of the fontsize after all parsing is done. We cannot take
the absolute value earlier, because tags like \fs- and \fs+ need to work
with the original negative value to achieve VSFilter-like results.
The crashes were initially discovered by AFL++.
Samples:
assert-fail_id:000000,sig:06,src:000002,time:929185,execs:48480,op:arith8,pos:343,val:-4
fuzzer_w3:id:000248,sig:06,src:000288,time:2365972,execs:107653,op:havoc,rep:8
Fixes https://github.com/libass/libass/issues/610
|
| |
|
| |
|
| |
|
|
|
|
| |
Not used since a0bf40896a4295964bba56dc7edfa020af761f5e.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
The two shifts could be used with too large or negative shift operands
which is undefined behaviour. To avoid UB but keep VSFilter
compatibility, simulate the practical effects of such shifts on x86
Windows instead of directly using a simple shift.
The simulated behaviour matches MSYS2's gcc. Clang, gcc and tcc were
observed to exhibit different behaviour on Linux, iff the operand was
a compile-time constant (they would use an arithmetic right shift
instead). Ideally this should be checked against MSVC, but it seems
unlikely to deviate since the related x86 instruction SHL/SAL
is documented to mask the upper three bits of the count operand.
The > 0 check is not present in VSFilter, but we'd like to avoid
negative scales and the only possible negative value is INT32_MIN
i.e. -2^31. Luckily using zero instead of the (font_scale / INT32_MIN)
won't make much difference here.
In guliverkli2 parsed drawing coordinates are also int32_t in canvas
space and only later multiplied by (64 * m_scale{x,y}) where m_scale
combines canvas and drawing scale and is a double. The result is then
cast back to int32_t, meaning coordinates absolutley larger than or
equal to min(2^(25 + draw_scale_exp) / canvas_scale{x,y}, INT32_MAX)
will be turned into INT32_MIN. For the \p32 case this means any drawing
without overflow will be at most 2×2 canvas units large. If only some
coordinates overflow the result can cover more.
In xy-VSFilter drawing coordinates are floating point numbers and parsed
as 64-bit IEEE floats, then multiplied by 64 and cast to int32_t. Here
a truncation already happens before the scaling values are applied,
so any coordinate larger than 2^25 turn into INT32_MIN during initial
parsing. For the \p32 this means a non-overflowing drawing is at most
1/32×1/32 canvas units large.
As a consequence of this parsing difference, drawing coordinates larger
than 2^25 are non-portable showing different behaviour in guliverkli2-
and xy-VSFilter. Thus treating \p32 as an effective \fscx0 seems
unproblematic, since even when scaling the default height of 288
up to a UHD frame size, 1/32×1/32 canvas units don't extend beyond 1/4
pixel, which unless stacked won't be too noticeable.
The remaining left shifts in ass_render.c, should all be safe as they
shift a constant 1 and use macros defined by us as the shift operands
and blur_radius which is limited to 100.
Found by AFL++ and UBSAN.
Samples
assert-fail+shift9999999_fuzzer_w3:id:000159,sig:04,src:000968+000719,time:452375,execs:57769,op:splice,rep:16
shift125_id:000001,sig:04,src:000008+000014,time:526595,execs:18418,op:splice,rep:8
shift-neg_id:000000,sig:04,src:000008+000014,time:466566,execs:18013,op:splice,rep:16
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Casting floating point values to an integer type is undefined
behaviour if it's not a regular number or the integral part cannot be
represented in the integer type.
This fixes issues found by UBSAN in libass' public OSS-Fuzz corpus
where NAN ("be") or a too large value ("k") was casted to int.
Sample IDs (one instance each there are duplicates):
OSSFuzz-3617a28ea3900c2603059049ce4c70c01a535a3e
OSSFuzz-292a3032ea273cc9dbaaa0a4291dd84e0cc07c65
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
This continues our transition towards fixed-width types to
improve VSFilter compatibility regardless of the platform libass
is compiled for.
Local variables are also switched to int32_t,
but struct members are left as is for now.
By dropping mystrtoi, which was only used by argtoi, we also fix
float-cast-overflow issues in it identified by UBSAN in libass'
public OSS-Fuzz corpus. mystroi32 does not suffer from this problem.
Sample ID (one instance there are duplicates):
OSSFuzz-123cf9a553c5745854037a52e87947721257f1f3fb
|
|
|
|
| |
mystrtoll was not used since 7913e4a64c704a3b82719d70920b5b153b43d254
|
| |
|
|
|
|
|
|
|
|
| |
If fontdata hasn't been allocated yet and an empty line occured
NULL was passed to memcpy which is always undefined behaviour
(and there was pointer arithmetic on NULL which is also UB).
Found by AFL++ and UBSAN.
|
|
|
|
|
|
|
|
| |
path->points can be NULL and any pointer arithmetic
on NULL, even NULL + 0, is undefined behaviour.
The rest of the function should be safe with NULL.
Found by AFL++ and UBSAN.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
On Windows, symbols from dynamic-link libraries are replaced by
pointers that are filled at runtime after loading the libraries.
These pointers are given names prefixed by __imp_ and declared
in an "import library" that accompanies the main library and is
statically linked into consumers that want to use the DLL.
For a function symbol, an additional stub function is generated
with the original name that simply forwards to a matching __imp_
function-pointer call.
In C, an imported function can be declared in two ways:
void foo();
ends up calling the stub and wasting a jump at runtime; while
__declspec(dllimport) void foo();
replaces foo() calls by (*__imp_foo)() at compile-time (not link-time),
which ends up being a simple optimization.
For imported objects, stubs are impossible, so only
the __imp_ pointers exist and dllimport is mandatory.
Many libraries, including libass, export only functions
and avoid dllimport in their header files for simplicity.
In contrast, FriBidi exports some functions and some objects, so it
cannot neglect dllimport. Its solution is to declare all symbols in its
header files with dllimport except if FRIBIDI_LIB_STATIC is defined.
When libass is compiled without FRIBIDI_LIB_STATIC and linked against a
FriBidi static library, references to FriBidi imports try to use __imp_
symbols (due to the dllimport declarations), but they do not exist,
so the linking step fails.
In general, libass cannot know whether it will be linked to static
or dynamic FriBidi. For example, one can build a static libass.lib
to embed in a larger project that uses a shared FriBidi.dll. So we cannot
tell on our own, without the builder's input, whether we would need
to go through __imp_ object pointers or reference objects directly.
However, libass does not use any objects from FriBidi. We use only functions,
and functions are always safe to use without dllimport, because at link-time
the symbol is sure to resolve either to the actual function in the static
library or to the stub function in the import library.
As a result, we can simply always define FRIBIDI_LIB_STATIC to drop the
dllimport declarations, and we will always produce static and dynamic
libraries that work equally well with static and dynamic FriBidi.
This logic is Windows-specific, and it is plausible that FRIBIDI_LIB_STATIC
may break other platforms, so define it only on Windows.
Note: FriBidi tries to add the FRIBIDI_LIB_STATIC macro when using
`pkg-config --static --cflags`. However, this works only in one of the many
pkg-config implementations, pkgconf, and notably not [yet] in the original
freedesktop.org pkg-config. Even if it did work consistently, we would still
need either to assume we always want --static or to make a possibly incorrect
guess as to what kind of linking will ultimately be used for FriBidi.
And even if --static is always fine on Windows, we might want to avoid it
on other platforms, complicating build logic that people using other build
systems would need to replicate.
|
| |
|
| |
|
|
|
|
|
|
|
| |
Since the margins are taken into account and the isotropic-scaling
factor cancels out during PAR calculation, calling ass_set_pixel_aspect
is only required if the preferable ass_set_storage_size was not called
or potentially if non-isotropic scaling is involved.
|
|
|
|
|
|
|
|
|
|
| |
- DirectWrite fontprovider had no doc comment
- font directories are not searched recursively
- storage size affects more than just PAR and blur
- the formula for PAR in (only) the docs was inverted
- some comments still referred to "fontconfig"
when any system fontprovider was meant
- ass_render_frame's change indicator can have false positives
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
The cpuid instruction was only introduced after i486, meaning
there are ix86 CPUs on which our default configuration will
build but crash during runtime when cpuid is executed.
To avoid this, check for the instructions availability by
testing if bit 21 of EFLAGS is writable as documented by
AMD, Cyrix, Intel and NexGen.
AMD, p.165:
https://www.amd.com/system/files/TechDocs/24594.pdf
Cyrix, p.10:
https://www.ardent-tool.com/CPU/docs/Cyrix/MII/94329_2.pdf
Intel, ch.3 p.190:
https://www.intel.com/content/dam/www/public/us/en/documents/manuals/64-ia-32-architectures-software-developer-instruction-set-reference-manual-325383.pdf
NexGen:
https://www.ardent-tool.com/CPU/docs/NexGen/cpuid.pdf
|
|
|
|
|
|
|
|
| |
If a higher then supported leaf is requested, at least Intel processors
will silently return the data of the highest supported leaf,
invalidating the following feature tests.
Reported in: https://github.com/libass/libass/pull/603
|
|
|
|
|
|
|
| |
Omission in commit c629be7d70548aea282ea4890c51094055ec66e2.
This lets consumers detect whether the compile-time
ASS_FEATURE_WHOLE_TEXT_LAYOUT enum constant exists.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
While the deprecated attribute wass added to GCC in
https://gcc.gnu.org/git/?p=gcc.git;a=commit;h=e23bd2185fae41772d012231e005b789b3a9e6dc
first released in GCC 3.1.0, support for an argument was only added in
https://gcc.gnu.org/git/?p=gcc.git;a=commit;h=9b86d6bb25587db93a322bf5778e9892aaa8b776
first released in GCC 4.5.0.
Since we did not check for argument support before,
building with a GCC between the above two changes was broken.
The commit assumes Clang always supported an argument,
but that has not actually been verified.
Reported in https://github.com/libass/libass/issues/595
|
| |
|
| |
|
|
|
|
| |
Fixes https://github.com/libass/libass/issues/594.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
There used to be a FIXME comment about this,
but it was removed in commit 27cc03363cfbddb9877cd547327d56405653add7.
Reordering works fine without this *most of the time*, but this is still
a bug. It affects one thing only: trailing whitespace in each line/run.
Of course, we remove trailing U+0020 SPACE characters from each line
regardless of bidi, but Unicode bidi recognizes other whitespace,
and we can now also have trailing U+0020 within in-line runs.
With right-to-left base direction, all trailing whitespace within
each line (after line wrapping) or run are to be placed at the leftmost
end in visual order (even if that whitespace is nominally part
of a left-to-right embed). Conversely, with our current code that
always tells FriBidi the base direction is left-to-right here,
trailing whitespace is always placed at the rightmost end of each line,
even if it is inside right-to-left text (which makes it appear
as *leading* whitespace to the reader).
We treat explicit line breaks \N as paragraph separators,
where each paragraph can have its own base direction. Therefore,
we must remember each paragraph's resolved direction separately.
|
|
|
|
|
|
|
|
|
|
|
| |
Without WHOLE_TEXT_LAYOUT, follow VSFilter
and reset the baseline for each run.
With WHOLE_TEXT_LAYOUT, try to shear each line as a whole.
There are still issues though:
* \fscx0 glyphs are skipped and do not contribute any shear;
* applying shear to each glyph and then scaling it together with
the shear makes little sense for whole lines to begin with.
|
|
|
|
|
| |
These calls don't perform any bidi or compute anything clever.
They just fetch some Unicode properties for each code point.
|
|
|
|
| |
This can be reverted by enabling ASS_FEATURE_WHOLE_TEXT_LAYOUT.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
When WHOLE_TEXT_LAYOUT is disabled, keep calling HarfBuzz with no context at
all. It might seem sensible to give it the whole VSFilter-run as context so
it could shape Arabic correctly across font fallback in case of weird fonts,
but it seems that Uniscribe doesn't behave like this in VSFilter.
For testing that, I created a font with only two glyphs: an isolated ain
and a medial ain; and a GSUB medi lookup that links them together.
Setting \fnMyTestFont on an Arabic word with a medial ain, libass
with WHOLE_TEXT_LAYOUT (i. e. HarfBuzz with context) showed the medial
shape, but VSFilter (i. e. Uniscribe) showed the isolated shape.
BorderStyle 3 confirmed that VSFilter was treating the string
as a single run and therefore passing it to GDI/Uniscribe as a whole.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Fixes https://code.google.com/archive/p/libass/issues/111.
Fixes https://github.com/libass/libass/issues/226 if it was not fixed
by commit c93cb3dbfb7357179379ffd19ff973cf062e2129 already.
The old ("sane") behavior of running bidi on each event as a whole*
can be restored by setting the new ASS_FEATURE_WHOLE_TEXT_LAYOUT.
Additionally, in a nod to ASS files and on-the-fly format converters
that use libass's nonstandard Encoding -1 for bidi base direction
autodetection, make Encoding -1 force WHOLE_TEXT_LAYOUT processing
for individual events even when the ASS_Feature is disabled.
* Note: we treat explicit line breaks \N as paragraph separators,
and effectively bidi is run on each "paragraph" separately.
This is standard bidi behavior. Of particular relevance
to libass, this is exactly what WebVTT mandates.
|
|
|
|
|
|
|
|
|
|
|
| |
We detect x86 and enable building asm code in `configure`.
However, before this commit, we don't actually use that code
unless we detect x86 via the C compiler's predefined macros.
We could check more macros to support more C compilers,
but what we really want is to use the same trigger
for both building and using this code. To that end,
add ARCH_X86 to config.h iff x86 asm is being built.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Currently, we use `INTEL` to denote any supported x86 variant
and `X64` to denote specifically x86-64 (and previously used
`X86` to denote 32-bit x86).
`INTEL` is a subpar name for two reasons:
* Intel has produced notable non-x86 architectures (Itanium).
* x86-64 was designed and patented not by Intel but by AMD.
This is currently only used in configure.ac and Makefile.am,
so it does not matter much. However, the next commit will expose
a config.h macro flagging the whole x86 family, which non-Autotools
users will have to set manually, so this will cease being a purely
internal choice and will start confusing users.
Instead, the most generic name for the whole family that is in common
use and does not suffer from such problems is "x86", so use `X86`.
The switch is slightly complicated by the fact our configure.ac and
Makefile.am used to use `X86` as in Microsoft's naming scheme, where "x86"
means "32-bit x86". Ideally, we would use another equally good name for
the family that is free from this ambiguity; however, I know no such name.
(Indeed, `X86` as a name for 32-bit x86 is problematic even if one
disregards x86-64, because 16-bit x86 exists as well. This commit
technically leaves configure.ac to lie about 16-bit x86 by setting
`X86=false`, but we have no 16-bit assembler code, so the new use of
`X86` should be viewed as a name for "any *supported* variant of x86".)
To somewhat highlight that we're no longer using Microsoft's scheme,
also switch the name for the x86-64 architecture from `X64` to `X86_64`.
This should also make it more intuitively obvious that one (X86_64) is
a subset of the other (X86). This is also a more standard name with a
clearer etymology, and we already use this name in our `ASFLAGS`.
|
|
|
|
|
|
|
|
| |
Current code uses fractional sizes and truncates the box's
coordinates to integers, so the box tends to be bigger
on the left and top than on the right and bottom.
Instead, lround() the sizes and add them symmetrically on all sides.
|
|
|
|
|
| |
If a conversion fails for a non-Unicode font, let
font fallback happen instead of displaying bogus glyphs.
|
|
|
|
|
|
|
|
|
| |
Use Windows native API to convert Unicode to MBCS on Windows,
then use iconv if not on Windows and iconv is available.
Do nothing if neither is available.
fix: `ass_font_index_magic` now doesn't mangle codepoint if
charmap isn't Microsoft's.
|
| |
|
| |
|
|
|
|
|
|
| |
This is purely an internal refactor.
With the existing and currently planned boolean
features, a bit flag will scale better.
|
|
|
|
|
|
|
|
|
| |
The removed check compared some bits from the vendor string to the ones
from "GenuineIntel". This blocked AVX and AVX2 from being used on
AMD- and other non-Intel-CPUs and even on Intel-CPUs if run in a
hypervisor or VM which changes the vendor string (eg " KVMKVMKVM ").
Drop the vendor check to utilise AVX on all supporting CPUs.
|
| |
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
ZWJ and the characters next to it may be separated into different shape
runs by bidi, script or font-fallback splitting. Nevertheless, ZWJ must
affect Arabic-script characters on both sides of itself. This is noted
in the description of the Unicode bidirectional algorithm [TR9-Joiners]
and matches the observed behavior of VSFilter (GDI/Uniscribe).
Fixes https://github.com/libass/libass/issues/545.
We could more easily pass the whole event text to HarfBuzz rather than
single out ZWJ and ZWNJ, but that would produce results different from
VSFilter's: it shapes each high-level run in isolation; and in the rare
case that Arabic text is set in a font that is missing some glyphs,
GDI/Uniscribe apply font fallback and choose isolated/initial/final
letter forms for each section separately, without joining the letters
from different fonts together (which HarfBuzz would do if we gave it the
full surrounding context), unless an explicit ZWJ is placed in between.
Unlike ZWJ, I have not been able to produce a test for ZWNJ that would
confirm whether VSFilter does this for ZWNJ as well. It should not matter
for Arabic as the boundaries are non-joining by default, but it might
make a difference for Indic scripts or others. It seems to make sense,
so in absence of evidence to the contrary, this commit applies the same
treatment to ZWNJ as well.
[TR9-Joiners]: https://unicode.org/reports/tr9/#Joiners
|
|
|
|
| |
This is dramatically faster on files with large drawings.
|
|
|
|
|
|
|
| |
This is a very fast hash function for the cache system
The version of the header corresponds to
https://github.com/wangyi-fudan/wyhash/commit/166f35228204b97ddd8ddead6b7a00467c91fdf6
|
| |
|
| |
|
| |
|
| |
|
|
|
|
|
|
| |
Processing of DECO_ROTATE has moved after ASS_Outline conversion too.
All relevant outline processing functions have moved into ass_outline.c.
outline_convert() now expects preallocated outline to reduce reallocations.
|
| |
|
|
|
|
|
|
|
|
|
| |
Max-blending is more correct than previous addition-blending
in case of small (less than pixel) outline offsets.
Fixes buffer overrun (up to 16 bytes read past rst->tile)
in add_bitmaps() in case of engine->tile_order < engine->align_order
(AVX2 assembly with LARGE_TILES disabled) due to insufficient padding.
|