Application crashes due to invalid .mo translation files generated during the build #47

Closed
opened 2026-07-04 05:16:28 -07:00 by serrebi · 2 comments
Owner

The BlindRSS application (version 1.79.0) crashes immediately on startup when it attempts to load translations from the .mo files produced by the automated build process.

Preconditions

  • BlindRSS binary build 1.79.0 is used.
  • The application is launched on Windows with the Russian locale active, so the UI is expected to be displayed in Russian by default.

Steps to Reproduce

  1. Launch BlindRSS.exe.

Actual Behavior

  • The application starts but terminates almost immediately.
  • It only manages to create the rss.db file.
  • No other configuration files are created.
  • There are no clear error messages in the console or logs indicating the root cause.

Expected Behavior

  • The application should start successfully and display the user interface in Russian.
  • All configuration files should be created as usual, and the application should operate normally.

Additional Observations

  • Removing the Russian .mo file fixes the crash: If the file _internal\locale\ru\LC_MESSAGES\blindrss.mo is removed from the distribution, BlindRSS starts successfully with the English UI and works as intended.
  • Manually compiled .mo works correctly: When taking the blindrss.po file from the repository and compiling it into blindrss.mo using the standard msgfmt utility (from GNU gettext), and then placing that file into the application directory, BlindRSS launches correctly with the Russian interface.

This confirms that the issue is specifically with the .mo files generated during the automated build, not with the translation content itself or the runtime environment.

Root Cause Analysis

The build process uses a custom Python script (tools/compile_translations.py) to compile .po files into .mo format, instead of relying on the official GNU gettext toolchain. This custom implementation contains several critical flaws relative to the MO file specification:

  1. Incorrect handling of plural forms. The script concatenates msgid and msgid_plural with a \0 separator and stores plural translations as a single \0-separated string. This does not match the MO format specification, where plural forms are represented as multiple distinct entries. As a result, the gettext runtime cannot correctly resolve plural translations, leading to undefined behavior or crashes.
  2. Missing 4‑byte alignment for string data. The MO format requires that each string (both original and translated) starts at an address aligned to a 4‑byte boundary. The current script writes strings contiguously without padding, causing misaligned reads by the runtime. This can lead to reading garbage data, buffer overruns, or immediate termination on some platforms (especially Windows).
  3. Inaccurate offset calculations. The script calculates offsets for the string tables in a way that does not properly account for the alignment requirements and the exact layout of the MO header and index tables. This results in the runtime accessing incorrect memory regions when looking up translations.
  4. Lack of validation. Unlike msgfmt, the custom script does not validate the input .po file for common issues (e.g., mismatched format specifiers in %s, %d, etc.). Any subtle error in the PO file is silently transformed into a corrupted MO file.

Because POEdit and msgfmt implement the MO format specification correctly, manually compiled files work as expected, further isolating the problem to the custom compilation script.

Recommendation

Discontinue the use of the custom tools/compile_translations.py script for generating .mo files. Instead, integrate the standard GNU gettext msgfmt utility into the build pipeline. This will ensure:

  • Full compliance with the MO file format specification.
  • Correct handling of plural forms, fuzzy flags, and continued strings.
  • Proper alignment and offset calculations.
  • Built‑in validation of translation catalogs.

Adopting the standard tooling will eliminate the risk of generating invalid MO files and prevent future crashes related to translation loading.

The BlindRSS application (version 1.79.0) crashes immediately on startup when it attempts to load translations from the `.mo` files produced by the automated build process. #### Preconditions - BlindRSS binary build 1.79.0 is used. - The application is launched on Windows with the Russian locale active, so the UI is expected to be displayed in Russian by default. #### Steps to Reproduce 1. Launch `BlindRSS.exe`. #### Actual Behavior - The application starts but terminates almost immediately. - It only manages to create the `rss.db` file. - No other configuration files are created. - There are no clear error messages in the console or logs indicating the root cause. #### Expected Behavior - The application should start successfully and display the user interface in Russian. - All configuration files should be created as usual, and the application should operate normally. #### Additional Observations - **Removing the Russian `.mo` file fixes the crash:** If the file `_internal\locale\ru\LC_MESSAGES\blindrss.mo` is removed from the distribution, BlindRSS starts successfully with the English UI and works as intended. - **Manually compiled `.mo` works correctly:** When taking the `blindrss.po` file from the repository and compiling it into `blindrss.mo` using the standard `msgfmt` utility (from GNU gettext), and then placing that file into the application directory, BlindRSS launches correctly with the Russian interface. This confirms that the issue is specifically with the `.mo` files generated during the automated build, not with the translation content itself or the runtime environment. ### Root Cause Analysis The build process uses a custom Python script (`tools/compile_translations.py`) to compile `.po` files into `.mo` format, instead of relying on the official GNU gettext toolchain. This custom implementation contains several critical flaws relative to the MO file specification: 1. **Incorrect handling of plural forms.** The script concatenates `msgid` and `msgid_plural` with a `\0` separator and stores plural translations as a single `\0`-separated string. This does not match the MO format specification, where plural forms are represented as multiple distinct entries. As a result, the gettext runtime cannot correctly resolve plural translations, leading to undefined behavior or crashes. 2. **Missing 4‑byte alignment for string data.** The MO format requires that each string (both original and translated) starts at an address aligned to a 4‑byte boundary. The current script writes strings contiguously without padding, causing misaligned reads by the runtime. This can lead to reading garbage data, buffer overruns, or immediate termination on some platforms (especially Windows). 3. **Inaccurate offset calculations.** The script calculates offsets for the string tables in a way that does not properly account for the alignment requirements and the exact layout of the MO header and index tables. This results in the runtime accessing incorrect memory regions when looking up translations. 4. **Lack of validation.** Unlike `msgfmt`, the custom script does not validate the input `.po` file for common issues (e.g., mismatched format specifiers in `%s`, `%d`, etc.). Any subtle error in the PO file is silently transformed into a corrupted MO file. Because POEdit and `msgfmt` implement the MO format specification correctly, manually compiled files work as expected, further isolating the problem to the custom compilation script. ### Recommendation Discontinue the use of the custom `tools/compile_translations.py` script for generating `.mo` files. Instead, integrate the standard GNU gettext `msgfmt` utility into the build pipeline. This will ensure: - Full compliance with the MO file format specification. - Correct handling of plural forms, fuzzy flags, and continued strings. - Proper alignment and offset calculations. - Built‑in validation of translation catalogs. Adopting the standard tooling will eliminate the risk of generating invalid MO files and prevent future crashes related to translation loading. <!-- forgejo-github-sync: issue github=serrebidev/BlindRSS#48 -->
Author
Owner

On the latest versions the bug is no longer reproducible.

On the latest versions the bug is no longer reproducible. <!-- forgejo-github-sync: comment github=serrebidev/BlindRSS#48/4887931789 -->
Author
Owner

This issue is fully resolved with the release of v1.80.3, which rolls back the problematic gettext internationalization changes and ensures stable .mo translation compilation and runtime behavior.

This issue is fully resolved with the release of v1.80.3, which rolls back the problematic gettext internationalization changes and ensures stable .mo translation compilation and runtime behavior. <!-- forgejo-github-sync: comment github=serrebidev/BlindRSS#48/4888019554 -->
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
serrebi/BlindRSS#47
No description provided.