commit b61c09be419e67ad0ab7811bddab65cc2cb22ee0
Author: Dov Grobgeld <dov.grobgeld@gmail.com>
Date:   Thu Oct 29 23:13:07 2026 +0200

    Fix the non-security bugs from the OSS scanner report

    - bidi: local_bracket_stack had its dimensions swapped, giving wrong
      bracket pairing (ANT-2026-8V04RHZF).
    - bidi: a full BD16 stack now stops pairing only for its own isolating
      run sequence, and the stack is reset when a sequence starts
      (ANT-2026-YIWCEVFV).
    - bidi: don't carry bracket pairing state from one isolate into the
      next sibling isolate (ANT-2026-2XBZK082).
    - bidi: an overflow isolate is not a valid isolate (X5a-X5c), and X7
      checks the overflow counts before the stack top (ANT-2026-DCIJ6HFH).
    - bidi: debug level dump no longer reads past char_from_level_array
      (ANT-2026-9ZU4LY2S).
    - fribidi-caprtl2utf8: UTF-8 output no longer overflows the line buffer
      (ANT-2026-68IW0EN5).
    - fribidi_unicode_to_charset: NUL-terminate for an unknown charset
      (ANT-2026-QKI78P14).

    Adds CapRTL isolate test lines, test-debug-deep-levels and
    test-charset-not-found.

    Reported by Anthropic's OSS Scanner.

    Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

 bin/fribidi-caprtl2utf8.c          |  11 ++--
 lib/fribidi-bidi.c                 | 107
 +++++++++++++++++++++++++------------
 lib/fribidi-char-sets.c            |   6 ++-
 test/Makefile.am                   |   6 ++-
 test/meson.build                   |  12 +++++
 test/test-charset-not-found.c      |  50 +++++++++++++++++
 test/test-debug-deep-levels.c      |  71 ++++++++++++++++++++++++
 test/test_CapRTL_isolate.input     |  10 ++++
 test/test_CapRTL_isolate.reference |  10 ++++
 9 files changed, 243 insertions(+), 40 deletions(-)

commit aa57457552950f4ad40d62379ddc33c43d7cfa47
Author: Dov Grobgeld <dov.grobgeld@gmail.com>
Date:   Thu Oct 29 23:07:40 2026 +0200

    lib: fix findings from OSS scanner report

    - fribidi_remove_bidi_marks: rebuild position maps from the kept
      entries only and ignore out-of-range (-1) entries, fixing an
      out-of-bounds write before the caller's map.
      Discovered by Anthropic's OSS Scanner, as vulnerability
      ANT-2026-0OR4AS4J.
    - fribidi_cap_rtl_to_unicode: compare input as unsigned char so bytes
      >= 0x80 map to '?' on unsigned-char ABIs instead of over-reading
      the table.
      Discovered by Anthropic's OSS Scanner, as vulnerability
      ANT-2026-YY0KNE3C.
    - Check the unchecked allocations in fribidi_reorder_line(),
      fribidi_log2vis() (ar_props) and the bracket stack rows.
      Discovered by Anthropic's OSS Scanner, as vulnerability
      ANT-2026-TDC51TQN.
    - Cache the forward adjacent-run search over chains of PDI runs, making
      back-to-back isolates linear. Adds test-isolate-chain.
      Discovered by Anthropic's OSS Scanner, as vulnerability
      ANT-2026-1QOXAAEB.
    - Record enclosed-strong flags per bracket pair during BD16 so N0b/N0c
      no longer rescan the runs between each pair. Adds a fuzzing seed.
      Discovered by Anthropic's OSS Scanner, as vulnerability
      ANT-2026-XY4AFPYN.

    Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

 lib/fribidi-bidi.c                                 | 149
 +++++++++++++++------
 lib/fribidi-char-sets-cap-rtl.c                    |   5 +-
 lib/fribidi.c                                      |  12 +-
 test/Makefile.am                                   |   5 +-
 ...w-unit-127f5556f3c0145bd02da2c985a56e4a8baf0195 | Bin 0 -> 131072 bytes
 test/meson.build                                   |   6 +
 test/test-isolate-chain.c                          | 130
 ++++++++++++++++++
 7 files changed, 258 insertions(+), 49 deletions(-)

commit d2f3e1f4946e7cef9789e1c3ebdb4a60d4314c7f
Author: Dov Grobgeld <dov.grobgeld@gmail.com>
Date:   Thu Oct 15 21:31:49 2026 +0300

    test: don't let make dist regenerate the .input files

    The .reference.input suffix rule made `make distdir` rebuild a test's
    .input from its .reference whenever the .reference had a newer mtime,
    as can happen after a fresh checkout. That overwrote the distributed
    inputs with fribidi's own --test output and made `make distcheck` fail
    in run.tests.

    Replace the suffix rule with a plain `references` target that
    regenerates the .reference files from the .input files, which is what
    the old target was meant to do.

    Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

 test/Makefile.am | 23 ++++++++++-------------
 1 file changed, 10 insertions(+), 13 deletions(-)

commit 1bc998e28538055a8ce7ebc920be69ef7816ad1d
Author: vera-rubin <322284620+vera-rubin@users.noreply.github.com>
Date:   Wed Oct 14 20:23:24 2026 +0000

    lib: reset isolates at paragraph boundaries in direction scan

 lib/fribidi-bidi.c        |  2 ++
 test/Makefile.am          |  5 +++--
 test/meson.build          |  6 ++++++
 test/test-par-direction.c | 46
 ++++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 57 insertions(+), 2 deletions(-)

commit 78854f85fbff6afe19d04714ac2fe42e2cdd09dc
Author: Dov Grobgeld <dov.grobgeld@gmail.com>
Date:   Wed Oct 14 21:53:06 2026 +0300

    lib: fix integer overflow in run-pool allocation on 32-bit

    run_pool_chunk_new() computed the allocation size as
    sizeof(chunk) + capacity * sizeof(FriBidiRun), which can wrap a 32-bit
    size_t while chunk->capacity still recorded the large value, leading to
    a heap-buffer-overflow. Reject sizes that don't fit in size_t,
    and guard
    the capacity doubling in run_pool_alloc() against signed overflow.

    Fixes #256

 lib/fribidi-run.c | 21 +++++++++++++++++++--
 1 file changed, 19 insertions(+), 2 deletions(-)

commit 24f15eee832eafa5d63319b666d50e488668ce31
Author: Dov Grobgeld <dov.grobgeld@gmail.com>
Date:   Thu Sep 24 17:49:52 2026 +0300

    bin: fix stack-buffer-overflow in CapRTL/UTF-8 output expansion

    outstring was sized to MAX_STR_LEN but fribidi_unicode_to_charset can
    expand each character up to 2x for CapRTL or 4x for UTF-8, overflowing
    the stack buffer on long input. Size it for the worst case plus NUL.

    Fixes #232

 bin/fribidi-main.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

commit 7c5c6f01ba15908a33ed4604eb71d99f13188359
Author: Jamaika1 <lukaszcz18@wp.pl>
Date:   Wed Sep 23 08:04:00 2026 +0200

    Add debug logging for reading bracket data file

 gen.tab/gen-brackets-tab.c | 2 ++
 1 file changed, 2 insertions(+)

commit 4c914a92e94a9fe4f30ae83a1130099841566448
Author: Jamaika1 <lukaszcz18@wp.pl>
Date:   Mon Sep 21 13:25:55 2026 +0200

    Deleting duplicate lines

 lib/run.h | 2 --
 1 file changed, 2 deletions(-)

commit 1d42f35e26f7ee4cde23a4103ace0f9f4f86a1aa
Author: Dov Grobgeld <dov.grobgeld@gmail.com>
Date:   Sun Sep 20 11:39:41 2026 +0300

    bin: don't run help2man on a cross-built binary

    The autotools man page rule executed the freshly built fribidi binary
    to feed help2man, which fails when that binary targets a different
    host than the build machine. Skip regeneration (falling back to a
    pre-shipped man page if present) when cross-compiling, matching the
    meson build's existing behavior.

 bin/Makefile.am | 14 ++++++++++++++
 configure.ac    |  2 ++
 2 files changed, 16 insertions(+)

commit b93119f5fdc7ea47672cc304c1455ffa6dfe7536
Author: Dov Grobgeld <dov.grobgeld@gmail.com>
Date:   Sun Sep 20 08:37:40 2026 +0300

    Bumped version to 1.0.17

 NEWS         | 20 +++++++++++++++++++-
 configure.ac |  2 +-
 meson.build  |  2 +-
 3 files changed, 21 insertions(+), 3 deletions(-)

commit 3b4be7ece88d8f725985398dfa4b393e8bed12c3
Author: Dov Grobgeld <dov.grobgeld@gmail.com>
Date:   Sun Sep 20 00:47:26 2026 +0300

    lib: resolve FSI base direction in one linear pass, not per-FSI rescan

    X5c resolution of an FSI's effective direction rescanned the tail of
    the run list from every FSI character to find its first local strong
    character, using for_run_list(fsi_pp, pp) (which walks to the list
    sentinel, not just to the matching PDI). A paragraph containing many
    FSI characters, or an FSI with no strong character before its matching
    PDI, made this quadratic -- 64k chained FSI characters took ~1.6s.

    The early-exit was also dead code: it checked the outer, already-
    established valid_isolate_count instead of the just-declared local
    isolate_count, which can never go negative, so the scan almost always
    ran to the end of the run list regardless of where the matching PDI
    actually was.

    Replace both with a single linear preprocessing pass (still over the
    untouched run list, before the X1-X8 loop mutates it) that resolves
    every FSI's direction at once, using an explicit growable stack to
    skip nested isolates: a strong character only ever resolves whichever
    isolate is on top of the stack, which is exactly the "only direct
    content counts" semantics of X5c. The result is cached on the FSI's
    own run (new fsi_base_level field on the internal, non-public
    FriBidiRun struct) for O(1) lookup in the main loop.

    run_list_encode_bidi_types() already inspects every character's type
    once to build the run-length-encoded list, and already special-cases
    isolate-initiator characters (to force them into their own run); track
    whether any were seen there for free, and skip the whole precompute
    pass when none were -- the common case, since most text has no
    isolates at all -- rather than doing a full, guaranteed-no-op pass
    over the run list for it.

    Verified: full test suite, BidiTest.txt/BidiCharacterTest.txt
    conformance (zero errors), valgrind-clean on a 5000-deep nested-FSI
    stress case, and 64k chained FSI characters down from ~1.6s to ~0.002s
    (now scales linearly).

 lib/fribidi-bidi.c | 107
 +++++++++++++++++++++++++++++++++++++++++------------
 lib/fribidi-run.c  |  12 +++++-
 lib/run.h          |   8 +++-
 3 files changed, 100 insertions(+), 27 deletions(-)

commit 1d2a74c043350d631fe6efcfb4c67dcf60ee0b58
Author: Dov Grobgeld <dov.grobgeld@gmail.com>
Date:   Sun Sep 20 00:16:26 2026 +0300

    ci: capture the real test-suite.log from distcheck's nested rebuild

    The distcheck target rebuilds and re-checks the distributed tarball in
    fribidi-*/_build/sub/, so a test failure there produces its own
    test-suite.log at that nested path. The upload step only ever grabbed
    test/test-suite.log (the outer `make check` log), so a distcheck-only
    failure left us with an artifact showing PASS/FAIL 0 - no diagnostic
    value. Upload both locations, and drop the now-redundant duplicate
    upload step.

 .github/workflows/make.yml | 11 ++++-------
 1 file changed, 4 insertions(+), 7 deletions(-)

commit 347c8ce033f1bb389415d3395007303fe14862a4
Author: Dov Grobgeld <dov.grobgeld@gmail.com>
Date:   Sat Sep 19 23:57:02 2026 +0300

    lib: replace N0 bracket-pairing linked list with a flat sorted array

    BD16 bracket-pair collection for N0 resolution used a singly-linked
    list
    (FriBidiPairingNode) built with one malloc() per matched bracket pair,
    sorted afterwards with a recursive linked-list merge sort, and
    torn down
    with a second per-node free() pass.

    Replace it with a growable flat array (geometric growth, so the common
    case of few brackets stays within one small allocation) sorted with
    qsort() by the open bracket's position, mirroring the same allocator-
    pressure fix already applied to FriBidiRun nodes in the previous
    commit.
    The N0b/N0c resolution logic is untouched; only how pairs are
    collected,
    sorted, and iterated changed (index into the array instead of walking
    ->next).

    Verified: full test suite, BidiTest.txt/BidiCharacterTest.txt
    conformance
    (zero errors), ASan fuzz sweep, and three targeted bracket-heavy stress
    cases (5000 non-nested pairs, 200-deep nesting, scattered unmatched
    brackets) producing byte-identical embedding levels before and after.

 lib/fribidi-bidi.c | 180
 +++++++++++++++++++++++++----------------------------
 1 file changed, 86 insertions(+), 94 deletions(-)

commit 8e582c64adb48bb7fede316ca291a6338ca76620
Author: Dov Grobgeld <dov.grobgeld@gmail.com>
Date:   Sat Sep 19 23:52:30 2026 +0300

    lib: pool-allocate FriBidiRun nodes in embedding-level resolution

    fribidi_get_par_embedding_levels_ex() and its helpers
    (run_list_encode_bidi_types,
    shadow_run_list, merge_with_prev) create and destroy FriBidiRun
    nodes in large
    numbers while resolving one paragraph's levels, previously via
    an individual
    malloc()/free() per node. Profiling against SheenBidi showed this phase
    dominating FriBidi's per-character cost by 2.3-2.6x, well beyond
    what the rule
    logic itself should cost.

    Replace the per-node malloc/free with a growable arena
    (FriBidiRunPool),
    created once per top-level call and sized to the paragraph length,
    freed in
    one shot when the call is done. The UBA rule logic and every
    linked-list
    operation are unchanged; only the memory backing the nodes moved from
    scattered individual allocations to a couple of contiguous
    slabs. Individual
    "frees" of pool-owned runs become no-ops (the memory becomes
    unreachable
    garbage until the whole pool is released).

    Verified against FriBidi's own test suite, the full Unicode
    BidiTest.txt and
    BidiCharacterTest.txt conformance corpora (zero errors), and an
    AddressSanitizer fuzz sweep (known crash regressions + 2000 random
    inputs,
    zero errors/leaks). Cuts level-resolution time by ~20-33% depending
    on input
    size.

 lib/fribidi-bidi.c |  28 ++++++----
 lib/fribidi-run.c  | 161
 ++++++++++++++++++++++++++++++++++++++++-------------
 lib/run.h          |  49 +++++++++++++---
 3 files changed, 181 insertions(+), 57 deletions(-)

commit 9793c192b7086066cf65b509f36871b8e3fe071d
Author: Dov Grobgeld <dov.grobgeld@gmail.com>
Date:   Sat Sep 19 23:23:32 2026 +0300

    fribidi_reorder_line: implement L2 reordering in linear time

    The previous implementation of UAX#9 rule L2 rescanned the whole line
    once per embedding level, from max_level down to 1, costing
    O(len * max_level) with max_level up to 125. Replace it with a
    one-pass, run-based algorithm (grouping the line into maximal
    same-level runs and merging them via a level-ordered stack, ported
    from Behdad's linear-reorder.c) that runs in O(len) instead.

    Output is unchanged: full test suite, including the BidiTest and
    BidiCharacterTest conformance suites, still passes. Addresses #30.

 lib/fribidi-bidi.c | 255
 ++++++++++++++++++++++++++++++++++++++++++++++++-----
 1 file changed, 234 insertions(+), 21 deletions(-)

commit eedd5f0345be0a921eb42a8e823fd8cfa4f5bc74
Author: Dov Grobgeld <dov.grobgeld@gmail.com>
Date:   Sat Sep 19 23:00:47 2026 +0300

    test: include stdbool.h in test-reorder-nsm.c

    Fixes Ubuntu CI build failure: false was undeclared because
    stdbool.h was never included.

 test/test-reorder-nsm.c | 1 +
 1 file changed, 1 insertion(+)

commit 3fa5b9ed696e98d98ae510883a195f9494ed7bed
Author: Dov Grobgeld <dov.grobgeld@gmail.com>
Date:   Sat Sep 19 22:54:24 2026 +0300

    meson: fix parallel build race for test-reorder-nsm

    test-reorder-nsm was missing fribidi_unicode_version_h as a source,
    so Meson didn't order its generation before compiling the test,
    causing a fatal error under parallel builds (as seen in CI).

 test/meson.build | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

commit 37abe37bb3ce7260f424a05c02fcc5954fda739d
Author: Dov Grobgeld <dov.grobgeld@gmail.com>
Date:   Sat Sep 19 22:49:47 2026 +0300

    gen-unicode-version: fix MSVC link failure by avoiding strncasecmp

    The previous portable_strcasestr() fallback for MinGW still called
    strncasecmp(), which doesn't exist on MSVC (LNK2019: unresolved
    external symbol strncasecmp), breaking the windows-latest/msvc CI job.

    Replace it with a hand-rolled case-insensitive comparison that needs
    no platform-specific function at all.

 gen.tab/gen-unicode-version.c | 33 +++++++++++++++++++++++++++++----
 1 file changed, 29 insertions(+), 4 deletions(-)

commit 6502e052fc79918bab1ba1c3447f9ca37f0c39d3
Author: Dov Grobgeld <dov.grobgeld@gmail.com>
Date:   Sat Sep 19 22:47:40 2026 +0300

    Fix fribidi_set_reorder_nsm()/fribidi_set_mirroring() not affecting
    fribidi_log2vis()

    When fribidi_log2vis() was undeprecated and moved from
    fribidi-deprecated.c
    into fribidi.c, it kept its own private copy of the module-level
    "flags"
    variable instead of sharing the one mutated by
    fribidi_set_reorder_nsm()
    and fribidi_set_mirroring() in fribidi-deprecated.c. As a result,
    calling
    fribidi_set_reorder_nsm(FALSE) had no effect on fribidi_log2vis(),
    which
    silently kept reordering non-spacing marks.

    Share a single _fribidi_legacy_api_flags variable between the two files
    so the setters work again, and add a regression test reproducing the
    Hebrew example from the issue.

    Fixes #136

 lib/fribidi-deprecated.c | 13 +++++----
 lib/fribidi.c            | 10 +++++--
 test/Makefile.am         | 15 ++++++++--
 test/meson.build         |  6 ++++
 test/test-reorder-nsm.c  | 76
 ++++++++++++++++++++++++++++++++++++++++++++++++
 5 files changed, 110 insertions(+), 10 deletions(-)

commit 009e8f32e83fa9a852707179200220816f30ac1a
Author: Dov Grobgeld <dov.grobgeld@gmail.com>
Date:   Sat Sep 19 22:37:50 2026 +0300

    gen-arabic-shaping-tab: fix remaining -Wformat= mismatch on
    MinGW/Windows

    The (long) cast only wrapped (maxshaped - minshaped + 1), so
    multiplying
    by sizeof(FriBidiChar) (size_t) promoted the product back to a 64-bit
    unsigned type on targets where long is 32-bit but size_t is 64-bit,
    mismatching the %ld format specifier. Cast the whole expression
    instead.

 gen.tab/gen-arabic-shaping-tab.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

commit c06b3beae2add3f4b64fa940c318149e9944e9a6
Author: Dov Grobgeld <dov.grobgeld@gmail.com>
Date:   Sat Sep 19 22:31:38 2026 +0300

    gen-unicode-version: replace non-portable strcasestr with a portable
    fallback

    strcasestr() is a glibc/BSD extension not declared by the MinGW
    (Strawberry Perl) toolchain used on GitHub's windows-latest runner,
    causing an implicit-declaration compile error there.

    Fixes the windows-latest gcc build failure in
    https://github.com/fribidi/fribidi/actions/runs/35463831280

 gen.tab/gen-unicode-version.c | 23 ++++++++++++++++++++++-
 1 file changed, 22 insertions(+), 1 deletion(-)

commit 2f40e9ae14ed4f8f3602fda4785d210fce7d87fe
Author: Dov Grobgeld <dov.grobgeld@gmail.com>
Date:   Sat Sep 19 22:20:44 2026 +0300

    Define _FRIBIDI_TYPE_SENTINEL/_FRIBIDI_PAR_SENTINEL in both enum
    branches

    They were only enum members in the sizeof(int)==4 && !__cplusplus
    branch, leaving them undefined when FriBidiCharType/FriBidiParType
    fall back to plain uint32_t, breaking consumers (e.g. Pango) that
    switch on them in that configuration.

    Fixes #216

 lib/fribidi-bidi-types.h | 6 ++++++
 1 file changed, 6 insertions(+)

commit b041bc040b6cd577172af04bb7e7cebf256614e2
Author: Dov Grobgeld <dov.grobgeld@gmail.com>
Date:   Sat Sep 19 22:15:23 2026 +0300

    gen-arabic-shaping-tab: fix -Wformat-overflow warning on GCC 14

    The usage message had two %s placeholders but only one file argument
    was ever passed, leaving the second as a null argument to die3().
    Drop the unused second placeholder and die3 helper.

    Fixes https://github.com/fribidi/fribidi/issues/208

 gen.tab/gen-arabic-shaping-tab.c | 17 ++---------------
 1 file changed, 2 insertions(+), 15 deletions(-)

commit 35b85e191381167fc0e9a23a07f1e89203663b16
Author: Dov Grobgeld <dov.grobgeld@gmail.com>
Date:   Sat Sep 19 22:11:12 2026 +0300

    Update Unicode character databases to v18.0.0

    Also fix version detection in gen-unicode-version: Unicode 18's
    ReadMe.txt lowercases "version" (was "Version"), which broke the
    case-sensitive strstr/sscanf parser and left FRIBIDI_UNICODE_VERSION
    undetected.

    Fixes https://github.com/fribidi/fribidi/issues/226

 NEWS                                           |    5 +
 gen.tab/gen-unicode-version.c                  |    6 +-
 gen.tab/unidata/ArabicShaping.txt              |  227 +++--
 gen.tab/unidata/BidiBrackets.txt               |    8 +-
 gen.tab/unidata/BidiMirroring.txt              |   22 +-
 gen.tab/unidata/ReadMe.txt                     |   28 +-
 gen.tab/unidata/UnicodeData.txt                | 1271
 +++++++++++++++++++++++-
 test/unicode-conformance/BidiCharacterTest.txt |   12 +-
 test/unicode-conformance/BidiTest.txt          |   10 +-
 9 files changed, 1433 insertions(+), 156 deletions(-)

commit ac4ab094bd9e318b2e9fc29ac01b90d583d3449e
Author: Dov Grobgeld <dov.grobgeld@gmail.com>
Date:   Sat Sep 19 22:02:31 2026 +0300

    Fix quadratic behavior in N0 bracket pairing preceding-strong search

    The N0c rule scanned backward from each bracket pair's opening
    bracket to the start of the string to find a preceding strong
    character. For long runs of bracket pairs with no strong content
    (e.g. many "[]" or "[!]" pairs), this made the whole algorithm
    O(n^2), causing multi-second delays on inputs of a few hundred KB.

    Replace the per-pair backward scan with a single forward sweep
    cursor that tracks the most recently seen strong character's level
    per isolate level, looked up in O(1) per pair instead of rescanned
    from scratch each time.

    Fixes https://github.com/fribidi/fribidi/issues/163

 lib/fribidi-bidi.c | 37 +++++++++++++++++++++++++++----------
 1 file changed, 27 insertions(+), 10 deletions(-)

commit 501d587df5e0f950f264ac98eb0d2593591d1a40
Author: panzhe <panzhe@kylinos.cn>
Date:   Wed Sep 2 15:53:06 2026 +0800

    Fix out-of-bounds read on trailing '_'

    Check for the end of input before reading the second byte of
    a '_' escape, and emit a literal '_' for a trailing lone one.

 lib/fribidi-char-sets-cap-rtl.c | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

commit 2d4ee9ede470dc04ff8917ecf007c51ffd91a7ee
Author: Dov Grobgeld <dov.grobgeld@gmail.com>
Date:   Sat Sep 19 21:46:35 2026 +0300

    fribidi-main: fix truncation of lines/output containing embedded
    NUL bytes

    fribidi_main used fgets()+strlen() to determine line length, so any
    embedded NUL byte in the input was mistaken for the end of the line,
    silently dropping the rest of it. The converted output was similarly
    printed with printf("%s", ...), which stops at the first NUL byte
    produced by the charset conversion (e.g. for U+0000).

    Track the number of bytes actually read on input, and write the
    converted output with its known length via fwrite() instead of
    relying on NUL-terminated string semantics.

    Fixes #252

 bin/fribidi-main.c | 59
 +++++++++++++++++++++++++++++++++++++++++-------------
 1 file changed, 45 insertions(+), 14 deletions(-)

commit c928e4c77549de59e057f72bbbec1e38ce8b43bd
Author: youdie006 <xncb135@korea.ac.kr>
Date:   Wed Aug 19 10:01:03 2026 +0900

    Pair brackets by canonical equivalence only, per UAX #9 BD16

    The bracket-table generator (gen.tab/gen-brackets-tab.c,
    read_unicode_data_txt_equivalence) reads a character's decomposition
    mapping
    (field 5 of UnicodeData.txt) and folds the partner bracket to that
    value, but it
    did not skip compatibility (<tag>) decompositions - it only stepped
    over the tag
    text and then read the hex that followed. UAX #9 BD16 pairs brackets
    using
    canonical equivalence only. As a result the fullwidth forms U+FF08
    / U+FF09
    (<wide> 0028 / <wide> 0029) were made equivalent to ASCII ( / )
    and given the
    same bracket id, so they mispair with ASCII parentheses.

    Restrict bracket-equivalence folding to canonical decompositions:
    when field 5
    begins with a <...> tag, it is a compatibility decomposition and is
    not treated
    as an equivalence for bracket folding. Canonical mappings (bare
    hex, e.g.
    U+2329 -> U+3008) still fold. A guard also prevents writing a sentinel
    -1 into
    the equivalence table.

    Fixes #233.

 gen.tab/gen-brackets-tab.c | 29 ++++++++++++++++++-----------
 1 file changed, 18 insertions(+), 11 deletions(-)

commit 58895678b768ceaf8d8b3bc69f5c6f56c8e1513d
Author: Nikolas Nyby <nikolas@gnu.org>
Date:   Wed Aug 19 16:13:49 2026 -0400

    Remove unused appveyor yaml file

 appveyor.yml | 24 ------------------------
 1 file changed, 24 deletions(-)

commit 814410f3ace8f3109724a26e033301b8d430ffdb
Author: nikolas <nikolas@gnu.org>
Date:   Wed Aug 19 16:12:07 2026 -0400

    github actions: Use current python version

 .github/workflows/meson.yml | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

commit 5d829288e00b9dd709c8050f469ad0b2737f822c
Author: Nikolas Nyby <nikolas@gnu.org>
Date:   Wed Aug 12 13:23:07 2026 -0400

    Update old FSF address

    Still more work to do here - just updated some main parts.

 COPYING              | 25 +++++++++++--------------
 README.md            |  4 ++--
 lib/fribidi-arabic.c |  3 +--
 lib/fribidi-arabic.h |  3 +--
 4 files changed, 15 insertions(+), 20 deletions(-)

commit 76bfd37fdc2c7e8e2b9eaeee91945e9c63d25e09
Author: Nikolas Nyby <nikolas@gnu.org>
Date:   Wed Aug 12 13:02:09 2026 -0400

    Remove unnecessary custom prototypes for getenv and getopt

    Include `<stdlib.h>` in windows environments, to fix windows build.

    Closes #220.

 bin/getopt.c | 16 ++--------------
 bin/getopt.h | 14 --------------
 2 files changed, 2 insertions(+), 28 deletions(-)

commit 0e6c9561cedc5b1fe9cc1b0ad7f58936e7fed80a
Author: Nikolas Nyby <nikolas@gnu.org>
Date:   Wed Aug 12 11:33:25 2026 -0400

    Remove unused travis file

 .travis.yml | 33 ---------------------------------
 1 file changed, 33 deletions(-)

commit 32957fdd98b0cb34369dbc49b23ebffa328bb8e8
Author: Nikolas Nyby <nikolas@gnu.org>
Date:   Wed Aug 12 10:59:24 2026 -0400

    github actions: Install help2man to fix ubuntu build

 .github/workflows/make.yml | 8 ++++++--
 Makefile.am                | 2 ++
 2 files changed, 8 insertions(+), 2 deletions(-)

commit 6aa4b20ef7159771c619f787e644a7e814e5320b
Author: nikolas <nikolas@gnu.org>
Date:   Wed Aug 12 10:42:21 2026 -0400

    Update TODO - remove readme item

    20 years later - it looks like fribidi now has a readme.

 TODO | 6 ------
 1 file changed, 6 deletions(-)

commit 04a8cb7a3674717e509c79cd6ee3e127d0c75f4c
Author: Matthias Clasen <mclasen@redhat.com>
Date:   Wed Aug 12 07:35:39 2026 -0400

    Don't require help2man unless building docs

    help2man isn't universally available, and requiring it
    is disruptive to ci builds. To avoid the new dependency,
    use -Ddocs=false.

 bin/meson.build | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

commit ee2edf744abf1728e03cd5ac63b5f1a2f95d047d
Author: أحمد المحمودي (Ahmed El-Mahmoudy)
<aelmahmoudy@users.sourceforge.net>
Date:   Sun Oct 12 16:08:24 2025 +0200

    Generate fribidi.1 man page

    Closes #227

 bin/Makefile.am | 10 ++++++++++
 bin/meson.build | 27 +++++++++++++++++++++++++++
 2 files changed, 37 insertions(+)

commit 6b744dd4361c394990070152a2572bddfe334c8d
Author: Nikolas Nyby <nikolas@gnu.org>
Date:   Tue Aug 11 19:47:55 2026 -0400

    Fix typos in docs: "an string" -> "a string"

 lib/fribidi-bidi-types.h    | 4 ++--
 lib/fribidi-brackets.h      | 2 +-
 lib/fribidi-char-sets.h     | 4 ++--
 lib/fribidi-joining-types.h | 4 ++--
 lib/fribidi.h               | 4 ++--
 5 files changed, 9 insertions(+), 9 deletions(-)

commit 8b7510ce8a5d0158d2422ad2fb95d1d2b4a8aaf7
Author: Nikolas Nyby <nikolas@gnu.org>
Date:   Tue Aug 11 19:35:33 2026 -0400

    github actions: Update python version to 3.12

 .github/workflows/meson.yml | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

commit 208ba6f2f1f1b6597889f86e6f587fe76722385e
Author: Nikolas Nyby <nikolas@gnu.org>
Date:   Tue Aug 11 19:33:34 2026 -0400

    Update github actions versions

 .github/workflows/make.yml  | 8 ++++----
 .github/workflows/meson.yml | 6 +++---
 2 files changed, 7 insertions(+), 7 deletions(-)

commit 054aa85889ee934cf0607d144a38ce8ce47e8600
Author: nikolas <nikolas@gnu.org>
Date:   Tue Aug 11 19:23:35 2026 -0400

    Add GNU Mailutils to USERS

 USERS | 1 +
 1 file changed, 1 insertion(+)

commit 069a7e3d31e6aa74f2068a8e0804106ce7906639
Author: Firas Khana <firasuke@gmail.com>
Date:   Wed Jun 3 00:04:41 2026 +0300

    Fix typo

 configure.ac | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

commit 5c85a174650ab8ef106ce85f13bcf2950d3fc65f
Author: David Maciejak <david.maciejak@gmail.com>
Date:   Wed Apr 1 10:03:50 2026 -0400

    Fix error handling for file operations

    read_data is not closing properly used file descriptors.

 gen.tab/gen-brackets-tab.c | 14 +++++++++++---
 1 file changed, 11 insertions(+), 3 deletions(-)

commit 94b3ab8c0016f58d55884b8c98acfc234403e0e3
Author: David Maciejak <david.maciejak@gmail.com>
Date:   Wed Apr 1 10:09:06 2026 -0400

    Fix stack buffer overflow when parsing equivalence

    If the equivalence is overly long it will crash.

 gen.tab/gen-brackets-tab.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

commit b28f43bd3e8e31a5967830f721bab218c1aa114c
Author: Felix Xing <fxing@qnx.com>
Date:   Mon Jan 27 12:57:36 2025 -0500

    remove compiler flag "-ansi"

 meson.build | 4 ----
 1 file changed, 4 deletions(-)

commit cfc71cda065db859d8b4f1e3c6fe5da7ab02469a
Author: Havard Graff <havard@pexip.com>
Date:   Wed Oct 11 12:27:36 2023 +0200

    debug: don't pass a comma "," in a #define

    Clang does not accept that, and errors out like so:

    ../../../../pexip/external/fribidi/lib/fribidi.c:84:3: error:
    expected expression
      DBG ("in fribidi_remove_bidi_marks");
      ^
    ../../../../pexip/external/fribidi/lib/debug.h:84:32: note: expanded
    from macro 'DBG'
            if (fribidi_debug_status()) { MSG(FRIBIDI ": " s "\n"); } \
                                          ^
    ../../../../pexip/external/fribidi/lib/debug.h:57:2: note: expanded
    from macro 'MSG'
            FRIBIDI_FPRINTF(FRIBIDI_STDERR_ s); \
            ^
    ../../../../pexip/external/fribidi/lib/debug.h:50:26: note: expanded
    from macro 'FRIBIDI_FPRINTF'
    # define FRIBIDI_FPRINTF fprintf
                             ^
    /usr/include/x86_64-linux-gnu/bits/stdio2.h:113:62: note: expanded
    from macro 'fprintf'
      __fprintf_chk (stream, __USE_FORTIFY_LEVEL - 1, __VA_ARGS__)

 lib/debug.h | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

commit 68162babff4f39c4e2dc164a5e825af93bda9983
Author: Dov Grobgeld <dov.grobgeld@gmail.com>
Date:   Wed Sep 25 21:03:03 2024 +0300

    Add test/test-suite.log as an artifact on CI failure

 .github/workflows/make.yml | 7 +++++++
 1 file changed, 7 insertions(+)

commit 348b60a9e7cca2ad8438a58fd2dd14ca6dd68aeb
Author: Dov Grobgeld <dov.grobgeld@gmail.com>
Date:   Tue Sep 24 22:11:17 2024 +0300

    Bump version to 1.0.16

 NEWS         | 5 +++++
 configure.ac | 2 +-
 meson.build  | 2 +-
 3 files changed, 7 insertions(+), 2 deletions(-)

commit cd9aa01f1ddac0164749f74ec499a2e105eec1e0
Author: Khaled Hosny <khaled@aliftype.com>
Date:   Tue Sep 24 17:06:52 2024 +0300

    Fix CI failure

    Error: This request has been automatically failed because it uses
    a deprecated version of `actions/upload-artifact: v2`. Learn more:
    https://github.blog/changelog/2024-02-13-deprecation-notice-v1-and-v2-of-the-artifact-actions/

 .github/workflows/make.yml  | 4 ++--
 .github/workflows/meson.yml | 2 +-
 2 files changed, 3 insertions(+), 3 deletions(-)

commit 34bdc85bf0d8ac8e21719e9e264f49734d31a76c
Author: Khaled Hosny <khaled@aliftype.com>
Date:   Tue Sep 24 16:24:57 2024 +0300

    Update Unicode character databases to v16.0.0

 gen.tab/unidata/ArabicShaping.txt |   60 +-
 gen.tab/unidata/BidiBrackets.txt  |    8 +-
 gen.tab/unidata/BidiMirroring.txt |   15 +-
 gen.tab/unidata/ReadMe.txt        |   11 +-
 gen.tab/unidata/UnicodeData.txt   | 5203
 ++++++++++++++++++++++++++++++++++++-
 5 files changed, 5254 insertions(+), 43 deletions(-)

commit 3826589ea556da613bd42742a169789469e8b635
Author: Dov Grobgeld <dov.grobgeld@gmail.com>
Date:   Fri Jun 7 08:44:28 2024 +0300

    Fix typo in fribidi-caprtl2utf8.c that caused compilation warning

 bin/fribidi-caprtl2utf8.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

commit 2803ff176713a27d7edb57a24bc60c38a02182e9
Author: Dov Grobgeld <dov.grobgeld@gmail.com>
Date:   Fri Jun 7 08:02:00 2024 +0300

    Bumped version to 1.0.15

 NEWS         | 5 +++++
 configure.ac | 2 +-
 meson.build  | 2 +-
 3 files changed, 7 insertions(+), 2 deletions(-)

commit bca04dc3cd3af85a9d9220c430737333634d622a
Author: Dov Grobgeld <dov.grobgeld@gmail.com>
Date:   Thu Apr 25 06:44:01 2024 +0300

    Bumped version to 1.0.14

 NEWS         | 5 +++++
 configure.ac | 2 +-
 meson.build  | 2 +-
 3 files changed, 7 insertions(+), 2 deletions(-)

commit bfb0385ef862cd40af7d5d33648fbb4bfe8eee65
Author: sid-wr <136314541+sid-wr@users.noreply.github.com>
Date:   Wed Mar 20 23:33:41 2024 +0530

    Update unicode character databases to v15.1.0.

 gen.tab/unidata/ReadMe.txt      |  10 +-
 gen.tab/unidata/UnicodeData.txt | 307
 +++++++++++++++++++++++++++++++++++++++-
 2 files changed, 311 insertions(+), 6 deletions(-)

commit e01a424c7cef4e805879ddcdc47f163f2a2f39dc
Author: Dov Grobgeld <dov.grobgeld@gmail.com>
Date:   Sun Mar 17 20:12:54 2024 +0200

    Update unicode character databases to v15.1.0.

 gen.tab/unidata/ArabicShaping.txt |  8 ++++----
 gen.tab/unidata/BidiBrackets.txt  | 10 +++++-----
 gen.tab/unidata/BidiMirroring.txt |  8 ++++----
 3 files changed, 13 insertions(+), 13 deletions(-)

commit 3002ffea02581b514d70c56d972af12082c4e70c
Author: Peng Wu <alexepico@gmail.com>
Date:   Tue Mar 12 13:53:45 2024 +0800

    Update test cases to Unicode 15.1

 test/unicode-conformance/BidiCharacterTest.txt | 6 +++---
 test/unicode-conformance/BidiTest.txt          | 6 +++---
 2 files changed, 6 insertions(+), 6 deletions(-)

commit 5b9a242cbbb0cf27d20da9941667abfc63808c19
Merge: b54871c 4fc34ed
Author: Dov Grobgeld <dov.grobgeld@gmail.com>
Date:   Sat Dec 9 08:30:49 2023 +0200

    Merge pull request #199 from tp-m/meson-fix-with-bin-disabled

    meson: fix build with -Dbin=false and -Dtests=true

commit 4fc34ed77ee985c19acb818dee1ed27054ddd434
Author: Tim-Philipp Müller <tim@centricular.com>
Date:   Sun Jun 4 10:28:43 2023 +0100

    meson: fix build with -Dbin=false and -Dtests=true

    The fribidi binary is needed by the unit test setup, so
    if tests are enabled we need to build it even if binaries
    are disabled. We just won't install it in that case.

    Fixes #198

 bin/meson.build | 8 +++++++-
 meson.build     | 2 +-
 2 files changed, 8 insertions(+), 2 deletions(-)

commit b54871c339dabb7434718da3fed2fa63320997e5
Author: Dov Grobgeld <dov.grobgeld@gmail.com>
Date:   Tue May 16 21:58:46 2023 +0300

    Bumped version to 1.0.13

    - The version change was done without source changes to allow updating
      the tar release file, which was missing man pages. Issue #197.

 NEWS         | 5 +++++
 configure.ac | 2 +-
 meson.build  | 2 +-
 3 files changed, 7 insertions(+), 2 deletions(-)

commit 3c0045876eba692a75cf31ed2cc1d073aee77da2
Merge: 394197c 799eb9c
Author: خالد حسني (Khaled Hosny) <khaled@aliftype.com>
Date:   Tue May 16 16:37:45 2023 +0300

    Merge pull request #191 from eli-schwartz/visibility

    simplify visibility handling

commit 394197cff0402d1c8ea465e8f8704d23215c0b0e
Merge: 3321bd3 06995fb
Author: خالد حسني (Khaled Hosny) <khaled@aliftype.com>
Date:   Tue May 16 02:56:22 2023 +0300

    Merge pull request #195 from tp-m/meson-fixes

    meson: fix two meson warnings

commit 3321bd3010c5cf77fbcd673251563e1e8950299b
Merge: 2c2a014 df75184
Author: خالد حسني (Khaled Hosny) <khaled@aliftype.com>
