Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

[インデックス 12142] ファイルの概要

このコミットは、Go言語のドキュメンテーションツールであるgodocにおける、サンプルコード抽出時のインデックス範囲チェックのバグ修正に関するものです。具体的には、godocがGoのソースコードからExample関数を抽出し、その本体をHTML表示用に整形する際に発生していた、不適切なスライス操作によるパニック(実行時エラー)を修正しています。

コミット

commit 775f0058acb166ef10e1e34f492bef482f950aa8
Author: Robert Griesemer <gri@golang.org>
Date:   Wed Feb 22 11:25:21 2012 -0800

    godoc: proper index range checking when extracting example code
    
    Fixes #3092.
    
    R=golang-dev, rsc
    CC=golang-dev
    https://golang.org/cl/5683075

GitHub上でのコミットページへのリンク

https://github.com/golang/go/commit/775f0058acb166ef10e1e34f492bef482f950aa8

元コミット内容

godoc: proper index range checking when extracting example code

Fixes #3092.

R=golang-dev, rsc
CC=golang-dev
https://golang.org/cl/5683075

変更の背景

このコミットは、Go言語のIssue #3092「godoc crashes on Example functions with empty bodies」を修正するために行われました。

godocは、Goのソースコード内に記述されたExample関数(func ExampleFoo()のような形式)を特別なものとして扱い、その関数本体のコードを抽出してドキュメンテーションに含める機能を持っています。これにより、ユーザーは関数の使用例を直接ドキュメントで確認できます。

しかし、godocExample関数のコードを抽出する際、そのコードが空のブロック{}である場合、または非常に短い場合に、不適切なインデックス操作によってプログラムがクラッシュするというバグが存在しました。具体的には、抽出されたコード文字列から外側の波括弧{}を削除しようとする際に、文字列の長さが想定よりも短いためにインデックスが範囲外となり、パニックが発生していました。

このバグは、特にテストやドキュメンテーションの初期段階で、空のExample関数が記述される場合に顕在化し、godocの安定性を損ねていました。

前提知識の解説

godocツール

godocは、Go言語のソースコードからドキュメンテーションを生成するための公式ツールです。Goのコードコメント、関数シグネチャ、構造体定義などを解析し、HTML形式で整形されたドキュメントを生成します。特に、Example関数はgodocによって特別に扱われ、その関数本体のコードが実行可能なサンプルとしてドキュメントに埋め込まれます。

Example関数

Go言語では、func ExampleFoo()のようにExampleというプレフィックスを持つ関数を記述することで、その関数をドキュメンテーションのサンプルコードとして利用できます。これらの関数は、go testコマンドによってテストとして実行され、標準出力に期待される出力が記述されている場合は、その出力が一致するかどうかも検証されます。godocはこれらの関数を解析し、ドキュメントにコードスニペットとして表示します。

Go言語のスライス(Slice)

Go言語のスライスは、配列の一部を参照するための軽量なデータ構造です。s[low : high]という形式で記述され、lowからhigh-1までの要素を含む新しいスライスを生成します。

  • lowは開始インデックス(inclusive)。
  • highは終了インデックス(exclusive)。
  • lowが省略された場合は0がデフォルト。
  • highが省略された場合はスライスの長さがデフォルト。

スライス操作において、lowhighが元のスライスの有効なインデックス範囲(0からlen(s)まで)を超えると、ランタイムパニック(panic: runtime error: slice bounds out of range)が発生します。

token.FileSetdoc.Example

  • token.FileSet: Goのソースコードを解析する際に、ファイルの位置情報(行番号、列番号など)を管理するための構造体です。
  • doc.Example: godocExample関数を解析した結果を格納する構造体で、サンプルコードの文字列(Codeフィールド)や期待される出力(Outputフィールド)などを含みます。

技術的詳細

この修正は、src/cmd/godoc/godoc.goファイルのexample_htmlFunc関数内で行われています。この関数は、Example関数のコードをHTML表示用に整形する役割を担っています。

元のコードでは、抽出されたcode文字列が波括弧で始まる場合(if len(code) > 0 && code[0] == '{')、それが関数本体のコードであると判断し、外側の波括弧を削除する処理を行っていました。

元のコード:

if len(code) > 0 && code[0] == '{' {
    // ...
    code = code[2 : len(code)-2] // ここが問題
}

このcode = code[2 : len(code)-2]という行が問題でした。

  • code[2]は、文字列の3番目の文字(インデックス2)からスライスを開始することを意味します。
  • len(code)-2は、文字列の末尾から2文字手前(インデックスlen(code)-3)まででスライスを終了することを意味します。

例えば、code"{}"(長さ2)の場合、code[2 : len(code)-2]code[2 : 0]となり、これは不正なスライス範囲です(開始インデックスが終了インデックスより大きい)。また、code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 さらに、code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]code[2 : 1]となり、これも不正です。 code"{a}"(長さ3)の場合、code[2 : len(code)-2]はcode[2 : 1]となり、これは不正なスライス範囲です。

修正後のコード:

if n := len(code); n >= 2 && code[0] == '{' && code[n-1] == '}' {
    // remove surrounding braces
    code = code[1 : n-1]
    // ...
}

変更点:

  1. if条件にn := len(code); n >= 2が追加されました。これは、code文字列の長さが少なくとも2文字({}を含むため)であることを確認しています。これにより、空の文字列や1文字の文字列に対してスライス操作が行われるのを防ぎます。
  2. code[0] == '{' && code[n-1] == '}'という条件が追加され、文字列が実際に波括弧で囲まれていることを厳密にチェックしています。
  3. 波括弧を削除するスライス操作がcode = code[1 : n-1]に変更されました。
    • code[1]は、文字列の2番目の文字(インデックス1)からスライスを開始することを意味します。
    • n-1は、文字列の末尾から1文字手前(インデックスn-2)まででスライスを終了することを意味します。

この変更により、code"{}"(長さ2)の場合、code[1 : 1]となり、これは空のスライスを正しく返します。code"{a}"(長さ3)の場合、code[1 : 2]となり、"a"を正しく返します。これにより、インデックス範囲外エラーが解消され、godocが安定して動作するようになりました。

コアとなるコードの変更箇所

--- a/src/cmd/godoc/godoc.go
+++ b/src/cmd/godoc/godoc.go
@@ -524,11 +524,11 @@ func example_htmlFunc(funcName string, examples []*doc.Example, fset *token.File
 		out := eg.Output
 
 		// additional formatting if this is a function body
-		if len(code) > 0 && code[0] == '{' {
-			// unindent
-			code = strings.Replace(code, "\n    ", "\n", -1)
-			// remove surrounding braces
-			code = code[2 : len(code)-2]
+		if n := len(code); n >= 2 && code[0] == '{' && code[n-1] == '}' {
+			// remove surrounding braces
+			code = code[1 : n-1]
+			// unindent
+			code = strings.Replace(code, "\n    ", "\n", -1)
 			// remove output comment
 			if loc := exampleOutputRx.FindStringIndex(code); loc != nil {
 				code = strings.TrimSpace(code[:loc[0]])

コアとなるコードの解説

変更されたのはsrc/cmd/godoc/godoc.goファイルのexample_htmlFunc関数内の以下の部分です。

// 変更前
if len(code) > 0 && code[0] == '{' {
    // unindent
    code = strings.Replace(code, "\n    ", "\n", -1)
    // remove surrounding braces
    code = code[2 : len(code)-2]
    // remove output comment
    if loc := exampleOutputRx.FindStringIndex(code); loc != nil {
        code = strings.TrimSpace(code[:loc[0]])
    }
}

// 変更後
if n := len(code); n >= 2 && code[0] == '{' && code[n-1] == '}' {
    // remove surrounding braces
    code = code[1 : n-1]
    // unindent
    code = strings.Replace(code, "\n    ", "\n", -1)
    // remove output comment
    if loc := exampleOutputRx.FindStringIndex(code); loc != nil {
        code = strings.TrimSpace(code[:loc[0]])
    }
}

主要な変更点は以下の通りです。

  1. 条件式の強化:

    • 変更前: len(code) > 0 && code[0] == '{'
    • 変更後: n := len(code); n >= 2 && code[0] == '{' && code[n-1] == '}' 新しい条件式では、まずcodeの長さをnに格納し、その長さが2以上であることを確認しています(n >= 2)。これは、波括弧{}で囲まれた文字列が少なくとも2文字の長さを持つ必要があるためです。さらに、文字列の最初の文字が{であり、最後の文字が}であることを厳密にチェックしています(code[0] == '{' && code[n-1] == '}')。これにより、不正な形式の文字列に対して波括弧削除処理が実行されるのを防ぎ、より堅牢なチェックを実現しています。
  2. 波括弧削除ロジックの修正:

    • 変更前: code = code[2 : len(code)-2]
    • 変更後: code = code[1 : n-1] この行がパニックの原因でした。変更前は、文字列の先頭から2文字、末尾から2文字を削除しようとしていました。これは、例えば"{}"のような短い文字列の場合にインデックスが範囲外になる原因となっていました。 変更後では、code[1 : n-1]とすることで、文字列のインデックス1(2番目の文字)から、末尾の1文字手前(インデックスn-2)までをスライスしています。これにより、先頭の{と末尾の}が正確に削除され、残りのコード本体が抽出されます。このスライス操作は、文字列の長さが2以上であれば常に安全に実行できます。
  3. 処理順序の変更:

    • 変更前は「unindent」の後に「remove surrounding braces」が行われていました。
    • 変更後は「remove surrounding braces」の後に「unindent」が行われています。 この順序変更は、機能的には大きな影響を与えませんが、波括弧を削除してからインデントを調整する方が、より自然な処理フローと言えます。

これらの変更により、godocは空のExample関数や短いExample関数に対しても安全にコードを抽出し、パニックを起こすことなくドキュメンテーションを生成できるようになりました。

関連リンク

参考にした情報源リンク