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

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

このコミットは、doc/go1.2.txt ファイルに対する変更であり、Go 1.2 リリースノートのドキュメントの一部です。具体的には、text/template パッケージに関する記述が追記されています。

コミット

commit c0148303afafefeebdfd6e4cae072f4b7963ec74
Author: Rob Pike <r@golang.org>
Date:   Tue Aug 27 14:33:05 2013 +1000

    doc/go1.2.txt: dereference pointer values when evaluating args for escape funcs
    
    R=golang-dev, adg
    CC=golang-dev
    https://golang.org/cl/13262043

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

https://github.com/golang/go/commit/c0148303afafefeebdfd6e4cae072f4b7963ec74

元コミット内容

doc/go1.2.txt: dereference pointer values when evaluating args for escape funcs

このコミットメッセージは、Go 1.2 のリリースノートに、text/template パッケージにおけるエスケープ関数(escape funcs)の引数評価時にポインタ値がデリファレンスされるようになったという変更点を追記したことを示しています。

変更の背景

Go言語の text/template パッケージは、HTMLやXMLなどのテキスト出力を生成する際に、クロスサイトスクリプティング(XSS)などのセキュリティ脆弱性を防ぐために、自動エスケープ機能を提供しています。この自動エスケープは、テンプレート内で表示されるデータが、そのコンテキスト(HTML属性、JavaScript文字列など)に応じて適切にエスケープされるように設計されています。

しかし、Go 1.2 より前のバージョンでは、エスケープ関数にポインタが渡された場合、そのポインタが指す値ではなく、ポインタ自体が評価されてしまうという挙動がありました。これは、特に構造体のフィールドがポインタ型である場合や、関数がポインタを返す場合に問題となり得ました。例えば、*string 型のフィールドを持つ構造体をテンプレートに渡し、そのフィールドを表示しようとした場合、期待される文字列ではなく、ポインタのアドレスがそのまま出力されてしまう可能性がありました。

このコミットは、このような挙動を修正し、エスケープ関数が引数を評価する際に、ポインタ値であればそのポインタが指す実際の値をデリファレンスして使用するように変更されたことを、Go 1.2 のリリースノートに明記するために行われました。これにより、開発者が意図した通りの安全な出力が保証されるようになります。

前提知識の解説

Go言語の text/template パッケージ

text/template パッケージは、Go言語でテキストベースの出力を生成するためのテンプレートエンジンです。HTML、XML、プレーンテキストなど、様々な形式のドキュメントを動的に生成するのに使用されます。主な特徴として、以下が挙げられます。

  • データ駆動型: 構造体、マップ、スライスなどのGoのデータ構造をテンプレートに渡して、そのデータに基づいて出力を生成します。
  • アクション: テンプレート内では、{{.FieldName}} のようにデータフィールドにアクセスしたり、{{range .Items}}...{{end}} のようにループを回したり、{{if .Condition}}...{{end}} のように条件分岐を行ったりする「アクション」を使用できます。
  • 関数: テンプレート内でカスタム関数を定義して呼び出すことができます。
  • 自動エスケープ: HTMLコンテキストでのXSS攻撃を防ぐために、デフォルトで自動エスケープ機能が有効になっています。これにより、ユーザー入力などの信頼できないデータがHTMLに挿入される際に、特殊文字が自動的に変換されます。

ポインタのデリファレンス

Go言語におけるポインタは、変数のメモリアドレスを保持する型です。ポインタ変数の前に * 演算子を付けることで、そのポインタが指すメモリアドレスに格納されている値にアクセスできます。この操作を「デリファレンス(間接参照)」と呼びます。

例えば、var x int = 10var p *int = &x がある場合、*px の値である 10 を返します。

エスケープ関数とセキュリティ

Webアプリケーションにおいて、ユーザーが入力したデータや外部から取得したデータをそのままHTMLに出力すると、悪意のあるスクリプトが埋め込まれて実行されるクロスサイトスクリプティング(XSS)攻撃のリスクがあります。これを防ぐために、出力するデータに含まれる特殊文字(例: <, >, &, ", ')を、HTMLエンティティ(例: &lt;, &gt;, &amp;, &quot;, &#39;)に変換する処理が必要です。この処理を「エスケープ」と呼びます。

text/template パッケージの自動エスケープ機能は、このエスケープ処理を自動的に行ってくれるため、開発者が手動でエスケープ処理を記述する手間を省き、セキュリティを向上させます。

技術的詳細

このコミットが言及している変更は、text/template パッケージの内部的な挙動に関するものです。Go 1.2 より前のバージョンでは、テンプレートエンジンがエスケープ処理を行う際に、引数としてポインタが渡された場合、そのポインタが指す実際の値ではなく、ポインタそのものの値(メモリアドレス)をエスケープしようとしていました。これは、多くの場合、開発者の意図とは異なる出力となり、場合によっては予期せぬ情報漏洩や、エスケープが不完全になる原因となる可能性がありました。

例えば、以下のようなGoのコードとテンプレートを考えます。

package main

import (
	"html/template"
	"os"
)

type Data struct {
	Name *string
}

func main() {
	name := "<b>Alice</b>"
	data := Data{Name: &name}

	tmpl, err := template.New("test").Parse(`Hello, {{.Name}}!`)
	if err != nil {
		panic(err)
	}
	tmpl.Execute(os.Stdout, data)
}

Go 1.2 より前のバージョンでは、{{.Name}} の部分で *string 型の Name フィールドが評価される際に、name 変数のアドレス(例: 0xc000010200 のような値)がそのまま出力されてしまう可能性がありました。しかし、Go 1.2 以降では、text/template パッケージがこのポインタを自動的にデリファレンスし、<b>Alice</b> という文字列が取得され、さらにHTMLエスケープが適用されて &lt;b&gt;Alice&lt;/b&gt; と出力されるようになります。

この変更は、text/template パッケージの内部で、値の評価ロジックが改善されたことを意味します。具体的には、テンプレートエンジンが値を取得する際に、それがポインタ型であるかどうかをチェックし、もしポインタであれば、そのポインタが nil でない限り、自動的にデリファレンスしてその先の値を使用するようになりました。これにより、テンプレートの記述がより直感的になり、ポインタを扱う際の予期せぬ挙動が解消されました。

この修正は、Go言語の「実用性」と「安全性」を重視する設計思想を反映しています。開発者がポインタを意識することなく、期待通りの安全な出力を得られるようにするための改善と言えます。

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

このコミット自体は、Go言語のソースコード(text/template パッケージの実装)を変更するものではなく、Go 1.2 のリリースノートドキュメント (doc/go1.2.txt) に一行追記するものです。

--- a/doc/go1.2.txt
+++ b/doc/go1.2.txt
@@ -71,6 +71,7 @@ syscall: implemented Sendfile for Darwin, added Syscall9 for Darwin/amd64 (CL 10
 testing: AllocsPerRun is now quantized to an integer (the type is still float64) (CL 9837049).
 testing: add TB interface (intersection of T and B's methods) (CL 12962043).
 text/template: add comparison functions (CL 13091045).
+text/template: dereference pointer values when evaluating args escape funcs (CL 13257043).
 time: Allow Parse and Format to handle time zone offsets with seconds (CL 8132044)
 time: patterns require non-lowercase letter to follow Mon, Jan etc (CL 12448044).
 unicode: add In, a nicer-to-use but equivalent version of IsOneOf (CL 11672044).

追加された行は以下の通りです。

+text/template: dereference pointer values when evaluating args escape funcs (CL 13257043).

この行は、Go 1.2 のリリースノートに、text/template パッケージの変更点として「エスケープ関数が引数を評価する際にポインタ値をデリファレンスするようになった」という情報を追加しています。括弧内の CL 13257043 は、この機能変更が実際に行われたコードレビューのチェンジリスト(Change List)番号を示しています。

コアとなるコードの解説

前述の通り、このコミット自体はドキュメントの変更であり、Goのランタイムやライブラリのコードそのものを変更するものではありません。しかし、このドキュメントの変更が指し示している実際のコード変更は、Goの text/template パッケージの内部、特に値の評価とエスケープ処理を行う部分に存在します。

具体的な変更は、Goのソースコードリポジトリにおける CL 13257043 に対応するコミット(またはその関連コミット)で行われました。このチェンジリストでは、text/template パッケージがテンプレートの実行時に値を解決するロジックが修正され、ポインタ型が検出された場合に自動的にデリファレンスされるようになりました。

この修正は、主に reflect パッケージを使用して値の型を検査し、ポインタであれば reflect.Value.Elem() メソッドを呼び出してその先の値を取得する、という形で実装されたと考えられます。これにより、テンプレートエンジンは、ポインタの背後にある実際のデータに対してエスケープ処理を適用できるようになり、より堅牢なセキュリティと直感的なテンプレート記述が可能になりました。

関連リンク

参考にした情報源リンク

  • Go言語の公式ドキュメント
  • Go言語のソースコードリポジトリ (特に text/template パッケージの変更履歴)
  • Go言語のチェンジリストシステム (Gerrit)
  • Go 1.2 リリースノートに関する議論やブログ記事 (当時の情報)
  • Go言語におけるポインタとリフレクションに関する一般的な知識
  • Webセキュリティ(XSS)とエスケープ処理に関する一般的な知識

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

このコミットは、doc/go1.2.txt ファイルに対する変更であり、Go 1.2 リリースノートのドキュメントの一部です。具体的には、text/template パッケージに関する記述が追記されています。

コミット

commit c0148303afafefeebdfd6e4cae072f4b7963ec74
Author: Rob Pike <r@golang.org>
Date:   Tue Aug 27 14:33:05 2013 +1000

    doc/go1.2.txt: dereference pointer values when evaluating args for escape funcs
    
    R=golang-dev, adg
    CC=golang-dev
    https://golang.org/cl/13262043

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

https://github.com/golang/go/commit/c0148303afafefeebdfd6e4cae072f4b7963ec74

元コミット内容

doc/go1.2.txt: dereference pointer values when evaluating args for escape funcs

このコミットメッセージは、Go 1.2 のリリースノートに、text/template パッケージにおけるエスケープ関数(escape funcs)の引数評価時にポインタ値がデリファレンスされるようになったという変更点を追記したことを示しています。

変更の背景

Go言語の text/template パッケージは、HTMLやXMLなどのテキスト出力を生成する際に、クロスサイトスクリプティング(XSS)などのセキュリティ脆弱性を防ぐために、自動エスケープ機能を提供しています。この自動エスケープは、テンプレート内で表示されるデータが、そのコンテキスト(HTML属性、JavaScript文字列など)に応じて適切にエスケープされるように設計されています。

しかし、Go 1.2 より前のバージョンでは、エスケープ関数にポインタが渡された場合、そのポインタが指す値ではなく、ポインタ自体が評価されてしまうという挙動がありました。これは、特に構造体のフィールドがポインタ型である場合や、関数がポインタを返す場合に問題となり得ました。例えば、*string 型のフィールドを持つ構造体をテンプレートに渡し、そのフィールドを表示しようとした場合、期待される文字列ではなく、ポインタのアドレスがそのまま出力されてしまう可能性がありました。

このコミットは、このような挙動を修正し、エスケープ関数が引数を評価する際に、ポインタ値であればそのポインタが指す実際の値をデリファレンスして使用するように変更されたことを、Go 1.2 のリリースノートに明記するために行われました。これにより、開発者が意図した通りの安全な出力が保証されるようになります。

前提知識の解説

Go言語の text/template パッケージ

text/template パッケージは、Go言語でテキストベースの出力を生成するためのテンプレートエンジンです。HTML、XML、プレーンテキストなど、様々な形式のドキュメントを動的に生成するのに使用されます。主な特徴として、以下が挙げられます。

  • データ駆動型: 構造体、マップ、スライスなどのGoのデータ構造をテンプレートに渡して、そのデータに基づいて出力を生成します。
  • アクション: テンプレート内では、{{.FieldName}} のようにデータフィールドにアクセスしたり、{{range .Items}}...{{end}} のようにループを回したり、{{if .Condition}}...{{end}} のように条件分岐を行ったりする「アクション」を使用できます。
  • 関数: テンプレート内でカスタム関数を定義して呼び出すことができます。
  • 自動エスケープ: HTMLコンテキストでのXSS攻撃を防ぐために、デフォルトで自動エスケープ機能が有効になっています。これにより、ユーザー入力などの信頼できないデータがHTMLに挿入される際に、特殊文字が自動的に変換されます。

ポインタのデリファレンス

Go言語におけるポインタは、変数のメモリアドレスを保持する型です。ポインタ変数の前に * 演算子を付けることで、そのポインタが指すメモリアドレスに格納されている値にアクセスできます。この操作を「デリファレンス(間接参照)」と呼びます。

例えば、var x int = 10var p *int = &x がある場合、*px の値である 10 を返します。

エスケープ関数とセキュリティ

Webアプリケーションにおいて、ユーザーが入力したデータや外部から取得したデータをそのままHTMLに出力すると、悪意のあるスクリプトが埋め込まれて実行されるクロスサイトスクリプティング(XSS)攻撃のリスクがあります。これを防ぐために、出力するデータに含まれる特殊文字(例: <, >, &, ", ')を、HTMLエンティティ(例: &lt;, &gt;, &amp;, &quot;, &#39;)に変換する処理が必要です。この処理を「エスケープ」と呼びます。

text/template パッケージの自動エスケープ機能は、このエスケープ処理を自動的に行ってくれるため、開発者が手動でエスケープ処理を記述する手間を省き、セキュリティを向上させます。

技術的詳細

このコミットが言及している変更は、text/template パッケージの内部的な挙動に関するものです。Go 1.2 より前のバージョンでは、テンプレートエンジンがエスケープ処理を行う際に、引数としてポインタが渡された場合、そのポインタが指す実際の値ではなく、ポインタそのものの値(メモリアドレス)をエスケープしようとしていました。これは、多くの場合、開発者の意図とは異なる出力となり、場合によっては予期せぬ情報漏洩や、エスケープが不完全になる原因となる可能性がありました。

例えば、以下のようなGoのコードとテンプレートを考えます。

package main

import (
	"html/template"
	"os"
)

type Data struct {
	Name *string
}

func main() {
	name := "<b>Alice</b>"
	data := Data{Name: &name}

	tmpl, err := template.New("test").Parse(`Hello, {{.Name}}!`)
	if err != nil {
		panic(err)
	}
	tmpl.Execute(os.Stdout, data)
}

Go 1.2 より前のバージョンでは、{{.Name}} の部分で *string 型の Name フィールドが評価される際に、name 変数のアドレス(例: 0xc000010200 のような値)がそのまま出力されてしまう可能性がありました。しかし、Go 1.2 以降では、text/template パッケージがこのポインタを自動的にデリファレンスし、<b>Alice</b> という文字列が取得され、さらにHTMLエスケープが適用されて &lt;b&gt;Alice&lt;/b&gt; と出力されるようになります。

この変更は、text/template パッケージの内部で、値の評価ロジックが改善されたことを意味します。具体的には、テンプレートエンジンが値を取得する際に、それがポインタ型であるかどうかをチェックし、もしポインタであれば、そのポインタが nil でない限り、自動的にデリファレンスしてその先の値を使用するようになりました。これにより、テンプレートの記述がより直感的になり、ポインタを扱う際の予期せぬ挙動が解消されました。

この修正は、Go言語の「実用性」と「安全性」を重視する設計思想を反映しています。開発者がポインタを意識することなく、期待通りの安全な出力を得られるようにするための改善と言えます。

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

このコミット自体は、Go言語のソースコード(text/template パッケージの実装)を変更するものではなく、Go 1.2 のリリースノートドキュメント (doc/go1.2.txt) に一行追記するものです。

--- a/doc/go1.2.txt
+++ b/doc/go1.2.txt
@@ -71,6 +71,7 @@ syscall: implemented Sendfile for Darwin, added Syscall9 for Darwin/amd64 (CL 10
 testing: AllocsPerRun is now quantized to an integer (the type is still float64) (CL 9837049).
 testing: add TB interface (intersection of T and B's methods) (CL 12962043).
 text/template: add comparison functions (CL 13091045).
+text/template: dereference pointer values when evaluating args escape funcs (CL 13257043).
 time: Allow Parse and Format to handle time zone offsets with seconds (CL 8132044)
 time: patterns require non-lowercase letter to follow Mon, Jan etc (CL 12448044).
 unicode: add In, a nicer-to-use but equivalent version of IsOneOf (CL 11672044).

追加された行は以下の通りです。

+text/template: dereference pointer values when evaluating args escape funcs (CL 13257043).

この行は、Go 1.2 のリリースノートに、text/template パッケージの変更点として「エスケープ関数が引数を評価する際にポインタ値をデリファレンスするようになった」という情報を追加しています。括弧内の CL 13257043 は、この機能変更が実際に行われたコードレビューのチェンジリスト(Change List)番号を示しています。

コアとなるコードの解説

前述の通り、このコミット自体はドキュメントの変更であり、Goのランタイムやライブラリのコードそのものを変更するものではありません。しかし、このドキュメントの変更が指し示している実際のコード変更は、Goの text/template パッケージの内部、特に値の評価とエスケープ処理を行う部分に存在します。

具体的な変更は、Goのソースコードリポジトリにおける CL 13257043 に対応するコミット(またはその関連コミット)で行われました。このチェンジリストでは、text/template パッケージがテンプレートの実行時に値を解決するロジックが修正され、ポインタ型が検出された場合に自動的にデリファレンスされるようになりました。

この修正は、主に reflect パッケージを使用して値の型を検査し、ポインタであれば reflect.Value.Elem() メソッドを呼び出してその先の値を取得する、という形で実装されたと考えられます。これにより、テンプレートエンジンは、ポインタの背後にある実際のデータに対してエスケープ処理を適用できるようになり、より堅牢なセキュリティと直感的なテンプレート記述が可能になりました。

関連リンク

参考にした情報源リンク

  • Go言語の公式ドキュメント
  • Go言語のソースコードリポジトリ (特に text/template パッケージの変更履歴)
  • Go言語のチェンジリストシステム (Gerrit)
  • Go 1.2 リリースノートに関する議論やブログ記事 (当時の情報)
  • Go言語におけるポインタとリフレクションに関する一般的な知識
  • Webセキュリティ(XSS)とエスケープ処理に関する一般的な知識