Repository navigation
Bump OpenCC ABI version to 1.4 to prevent librime loading ABI-incompatible v1.3.2 builds - #1377
Conversation
|
We should probably change the minor ABI version to 1.4 as there are several breaking changes introduced by the 1.3.2 release. |
3b1b814 to
4dbc8ae
Compare
Updated:) |
|
Please correct me if I’m wrong: the simplest fix is to deprecate 1.3.2 and release 1.4.0 without API changes. The ABI has already changed, so the clean fix is to expose that as a new ABI/API version. I don’t think we need to retrofit the new API to preserve legacy behavior, especially if that would give PipelineConverter::GetConversionChain() a best-effort meaning that is not semantically precise. |
4dbc8ae to
72d5765
Compare
72d5765 to
c02a622
Compare
that makes sense. I’ve updated this PR to only expose the ABI break by bumping the CMake SOVERSION to 1.4. One related note: librime still seems to have a separate source-level assumption that GetConversionChain() is always non-null. With the new normalization pipeline, OpenCC may return a PipelineConverter, whose GetConversionChain() can legitimately be nullptr. So the ABI bump should prevent old librime binaries from silently loading an incompatible OpenCC, but librime may still need a small follow-up fix to handle a null GetConversionChain() when rebuilt against the new OpenCC API. |
|
Yeah, that’s a real issue. I think a cleaner approach may be to keep PipelineConverter semantics unchanged and introduce one more abstraction layer e.g. ConfigBasedConverter. The idea is that PipelineConverter itself still does not have a single well-defined conversion chain, so PipelineConverter::GetConversionChain() should not need to pretend otherwise. However, in practice, external users have been treating the converter object as a way to introspect the config. For that use case, a config-backed converter could preserve the user-facing behavior: internally it executes a two-stage pipeline, as normalization followed by the traditional conversion flow. In ConfigBasedConverter, GetConversionChain() would return the main conversion chain from the config, not an arbitrary stage of a generic Pipeline Converter. Separately, I think we can avoid hardcoding OPENCC_ABI_VERSION as 1.4. If we release this as 1.4.0, the existing SOVERSION ${OPENCC_VERSION_MAJOR}.${OPENCC_VERSION_MINOR} logic will naturally produce 1.4. |
…ion is configured (#1380) Introduce ConfigBasedConverter to correctly expose the main conversion chain when a normalization pre-pass is present, resolving a null-pointer crash in downstream consumers such as librime. Also bumps the CMake/Bazel fallback version to 1.4.0 and tightens the installed public header set. Note: dev builds derived from untagged commits may still report package version 1.3.2.dev…; the SOVERSION is explicitly pinned to 1.4 by the preceding commit (#1377) and is unaffected by the git-tag-derived package version. Detailed Changes: - **ConfigBasedConverter** (new private class): - Wraps normConverter + mainConverter; delegates GetConversionChain() to mainConverter so callers always receive a valid non-null ConversionChain. - Replaces PipelineConverter in Config.cpp when a normalization field is present. - **Public header cleanup**: - DictConverter.hpp, PhraseExtract.hpp, UTF8StringSlice.hpp moved from LIBOPENCC_HEADERS to LIBOPENCC_PRIVATE_HEADERS (CLI-tool internals, not library API). - BinaryDict.hpp, DartsDict.hpp likewise moved to private (were incorrectly appended to the public list). - **Version fallback**: cmake/GitVersion.cmake minor 3→4, revision 2→0; MODULE.bazel version 1.3.2→1.4.0. - **Regression test**: NormalizationGetConversionChainIsNonNull verifies GetConversionChain() is non-null and delegates to the main chain, not the normalization chain.
This crash was caused by #1359
Root Cause
Recent OpenCC configs can include a
normalizationpre-pass. When normalization is present,Configwraps the normal converter stages in aPipelineConverter.PipelineConverter::GetConversionChain()previously returnednullptrbecause a pipeline does not have a single conversion chain. However, librime's Simplifier code inspects OpenCC throughconverter_->GetConversionChain()->GetConversions()and assumes the returned chain is non-null. With a pipeline-backed converter, that assumption becomes a null pointer dereference, causing the input method to crash when switching to Simplified Chinese.There is also a separate ABI risk from the recent C++ API/interface changes: downstream C++ consumers built against the old
libopencc.so.1.3ABI can still load the new library because the SONAME did not change.Fix
PipelineConverter::GetConversionChain()return the last stage's conversion chain, matching the existing best-effort behavior ofGetSegmentation().PipelineConverter::GetConversionChain()normalizationexposing a non-null main conversion chainOPENCC_ABI_VERSIONto1.3.2for CMakeSOVERSION, so ABI-incompatible downstream C++ consumers are forced to relink instead of silently loading the wrong library.Verification
git diff --checkg++ -std=c++17 -fsyntax-only ... src/ConversionChainTest.cppg++ -std=c++17 -fsyntax-only ... src/ConfigTest.cppnormalizationnow returns a non-null conversion chain.Full CMake/Bazel test runs were not available in this environment because
cmakeandbazelare not installed.