kuromoji에 빈 문자 <0x00> 를 전달하는 중 오류 발생

현상.


매일 textlint에서 Qita 기사를 검사하면 간혹 다음과 같은 오류가 발생할 수 있습니다.
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>
그냥 캣츠가 넘어가면 돼요. 그래서 곤란한 건 없지만 원인 조사예요.

결론


제목과 같이 Qita의 글에는 0x00(NUL)가 담겼다.

동작 검증 환경

  • Windows7 64bit
  • node.js v9.3.0
  • [email protected]
  • [email protected]
  • [email protected]
  • 원인string의 확인


    오류가 발생한 투고를 확인했다.
    터미널에 출력을 복사하지 않았기 때문에
    서류에 직접 쓰다.
    파일 읽기string 검사, 오류 재현
    →string과textlint 이외의 부분은 오류에 참여할 수 없습니다
    서류를 확인한 뒤 통상 흔치 않은 내용이 포함된 것을 확인했다.
    (이미지는 단순 가공 후)


    일단 원인을 분리하다


    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가 원인으로 발생했는지 확인합니다.
    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와 무관
  • 앞뒤 문자열과 무관
  • 쿠로모지0x00에게 주기로 한 말은 오류가 된다.
    (쿠로모지라면 오류가 더 상세해진다)
    ~\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)
    (後略)
    

    참고 자료


  • azu/kuromojin: Provide a high level wrapper for kuromoji.js
    textlint에서 사용하는 래퍼이지만 쿠로모지의 호출 방법의 코드를 사용했습니다.

  • JavaScript、Node.js에서 문자열과 바이트 열의 상호 변환 - Qiita 0x00 문자열의 제작 방법
    Node.js에 다른 포장을 설치해야 할지 몰라서 큰 도움이 됐어요.
  • takuyaa/kuromoji.js: JavaScript implementation of Japanese morphological analyzer
  • inexorabletash/text-encoding: Polyfill for the Encoding Living Standard's API
  • 메모지


    만약 업무상 회피한다면 사전에 교체할 수 있습니까?
    나는 null 문자가 length가 없는 줄 알았는데, 그게 아닌 것 같아. 파라 측의 처리 때문이야.
    const nullbyte = (new TextDecoder).decode(Uint8Array.of(0x00))
    console.log('null', nullbyte.length) // 1
    
    다만 현재 상황이 정말 중요한 문제가 아니기 때문에 내버려 두다.
    (이 때문에 원인을 규명할 수 없고, 이슈를 발송할 수 없음)

    좋은 웹페이지 즐겨찾기