3
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

kuromojiにヌル文字<0x00>を渡すとエラーになる

Last updated at Posted at 2018-07-30

現象

Qiitaの記事を日々textlintでチェックしていると、たま~に以下のようなエラーが出る。

TypeError: Cannot read property 'length' of undefined
    at ViterbiBuilder.build (~\node_modules\kuromoji\src\viterbi\ViterbiBuilder.js:53:48)
    at Tokenizer.getLattice (~\node_modules\kuromoji\src\Tokenizer.js:126:33)
    at Tokenizer.tokenizeForSentence (~\node_modules\kuromoji\src\Tokenizer.js:81:24)
    at ~\node_modules\kuromo
jin\lib\kuromojin.js:60:26
    at <anonymous>

catchしてスキップすればいいだけなので困ってはいないが、原因調査。

結論

タイトルどおり、Qiitaの記事に0x00(NUL)が含まれていたから。

動作検証環境

  • Windows7 64bit
  • node.js v9.3.0
  • textlint@10.2.1
  • kuromoji@0.1.2
  • text-encoding@0.6.4

原因stringの確認

エラーが出る投稿を確認した。
端末への出力をコピペしたものでは再現しなかったので、
直接ファイルに書き出すことに。
ファイルを読み込んだstringをチェックすることでエラーが再現した
→ stringとtextlint以外の部分がエラーに関与している可能性がなくなった

ファイルを確認すると、通常、あまり目にしない内容が含まれていることが確認できた。

(画像は投稿内容を短く加工後)

2018-07-20_11h27_52.png

2018-07-20_11h27_34.png

一応原因の切り分け

textlintに渡してエラーが出たことを確認したコード

const TextLintEngine = require('textlint').TextLintEngine;
const engine = new TextLintEngine();

const fs = require('fs');
searchTarget = fs.readFileSync('out.txt').toString();

;(async () =>{
        const result = await engine.executeOnText(searchTarget).catch(e => { 
            console.log('textlint error', e);
            console.log(searchTarget)
            return [{messages : []}];
        });
})()

バックトレースがkuromojiなので、textlintの確認はこれぐらいで。

kuromoji単体で0x00が原因で発生するかを別途installして確認する。

const kuromoji = require("kuromoji");

const path = require("path");
const kuromojiDir = path.dirname(require.resolve("kuromoji"));
const option = {dicPath: path.join(kuromojiDir, "..", "dict")}

const TextDecoder = require('text-encoding').TextDecoder;
const nullbyte = (new TextDecoder).decode(Uint8Array.of(0x00))
kuromoji.builder(option).build(function (err, tokenizer) {
    // tokenizer is ready
    var path = tokenizer.tokenize(nullbyte);
    console.log(path);
});

このコードでも同じエラーが出たので、

  • textlint関係なく
  • 前後の文字列関係なく

kuromojiに0x00を渡すとエラーになると決めつけた。

(kuromojiだともうすこしエラーが詳細に)

~\node_modules\kuromoji\src\viterbi\Viterb
iBuilder.js:53
            for (var i = 0; i < token_info_ids.length; i++) {
                                               ^

TypeError: Cannot read property 'length' of undefined
    at ViterbiBuilder.build (~\node_module
s\kuromoji\src\viterbi\ViterbiBuilder.js:53:48)
(後略)

参考


メモ

ワークアラウンドで回避するなら事前に置換?

null文字はlengthを持っていないのかと思ったが、そうでもないようなので、やはりパーサ側の処理が原因のようだ。

const nullbyte = (new TextDecoder).decode(Uint8Array.of(0x00))
console.log('null', nullbyte.length) // 1

ただ本当に現状はクリティカルな問題ではないので放置している。
(なので原因究明が出来てなくて、Issueも送れていません)

3
1
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?