From 4eec476431bbe2f6ef77abac06e1ddbb4eb4840c Mon Sep 17 00:00:00 2001 From: Arseny Tolmachev Date: Fri, 17 Apr 2026 09:17:26 +0900 Subject: [PATCH 1/2] fix: out-of-bounds read in NumericUnkMaker::checkPeriod for trailing digit+period MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `checkPeriod` bounded the lookahead with `pos + 1 < codepoints.size()`, but the index it actually read was `posPeriod + 1 = start + pos + 1`. On the second pass of `spawnNodes` (start > 0) the two diverge, so inputs like `10.` or `ほげ4.` read one past the end of the codepoint vector and caused the crash reported in #157. Bound the lookahead against the absolute index instead. Dropped the now-dead `pos + 1` check so the condition reflects what is actually being guarded. Added regression tests for `10.` and `ほげ4.`; both abort on the prior code under libstdc++ debug mode / ASan. Closes #157. --- src/core/analysis/numeric_creator.cc | 2 +- src/core/analysis/numeric_creator_test.cc | 21 +++++++++++++++++++++ 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/src/core/analysis/numeric_creator.cc b/src/core/analysis/numeric_creator.cc index 9dd3d16c..52cbd47e 100644 --- a/src/core/analysis/numeric_creator.cc +++ b/src/core/analysis/numeric_creator.cc @@ -245,7 +245,7 @@ size_t NumericUnkMaker::checkPeriod(const CodepointStorage &codepoints, if (pos == 0) return 0; if (!codepoints[posPeriod].hasClass(PeriodClass)) return 0; if (!codepoints[posPeriod - 1].hasClass(charClass_)) return 0; - if (pos + 1 < codepoints.size() && + if (posPeriod + 1 < codepoints.size() && codepoints[posPeriod + 1].hasClass(charClass_)) return 1; return 0; diff --git a/src/core/analysis/numeric_creator_test.cc b/src/core/analysis/numeric_creator_test.cc index 92c78fe0..1e87e0df 100644 --- a/src/core/analysis/numeric_creator_test.cc +++ b/src/core/analysis/numeric_creator_test.cc @@ -243,6 +243,27 @@ TEST_CASE("do not make numeric unk nodes ends with period") { CHECK(env.numNodeSeeds() == 1); } +// Regression for ku-nlp/jumanpp#157: trailing digit+period caused a read +// past the end of the codepoint vector during the second spawnNodes pass +// (start > 0), because checkPeriod bounded the lookahead against `pos` +// instead of the absolute position `start + pos`. +TEST_CASE("multi-digit number followed by trailing period does not crash") { + NumericTestEnv env{"x,l1\nほげ,l2\n"}; + env.analyze("10."); + CHECK(env.contains("10", 0, "l1")); + CHECK(env.contains("0", 1, "l1")); + CHECK(!env.contains("10.", 0, "l1")); + CHECK(!env.contains("0.", 1, "l1")); + CHECK(env.numNodeSeeds() == 2); +} + +TEST_CASE("digit+period preceded by non-numeric context does not crash") { + NumericTestEnv env{"x,l1\nほげ,l2\n"}; + env.analyze("ほげ4."); + CHECK(env.contains("4", 2, "l1")); + CHECK(!env.contains("4.", 2, "l1")); +} + TEST_CASE("do not make numeric unk nodes starts with period") { NumericTestEnv env{"x,l1\nほげ,l2\n"}; env.analyze(".4"); From 6a3e63c4cc42626fc234eb7a801d85c7d6709b73 Mon Sep 17 00:00:00 2001 From: Arseny Tolmachev Date: Fri, 17 Apr 2026 09:35:00 +0900 Subject: [PATCH 2/2] build: bump actions/checkout to v5 v4 runs on Node 20, which GitHub is forcing off the runners in September 2026. v5 runs on Node 24 and is a drop-in replacement. Surfaced as a warning annotation on the CI modernization run. --- .github/workflows/cmake.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/cmake.yml b/.github/workflows/cmake.yml index 400224cf..8f9a86df 100644 --- a/.github/workflows/cmake.yml +++ b/.github/workflows/cmake.yml @@ -52,7 +52,7 @@ jobs: shell: bash steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 - name: Install dependencies (Ubuntu) if: startsWith(matrix.os, 'ubuntu-')