[インデックス 15946] ファイルの概要
コミット
commit ce99bb2caf26d4c052636847c913906fb5974c34
Author: Rémy Oudompheng <oudomphe@phare.normalesup.org>
Date: Tue Mar 26 08:20:10 2013 +0100
cmd/gc: fix nil pointer dereferences.
Fixes #5119.
R=golang-dev, dvyukov, dave, rsc
CC=golang-dev
https://golang.org/cl/7838050
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/ce99bb2caf26d4c052636847c913906fb5974c34
元コミット内容
このコミットは、Goコンパイラ(cmd/gc
)におけるnilポインタ参照解除のバグを修正するものです。具体的には、Issue 5119で報告された問題に対処しています。
変更の背景
このコミットは、Goコンパイラ(cmd/gc
)が特定の状況下でnilポインタ参照解除を引き起こし、コンパイラがクラッシュするバグ(Issue 5119)を修正するために作成されました。このバグは、型チェックが失敗した際に、後続の処理で不正な型情報(T
やS
といった特殊な型シンボル、あるいはbroke
フラグが設定された型)が渡されることで発生していました。特に、メソッドの追加や型の比較を行う際に、これらの不正な型がnilポインタ参照解除を引き起こす可能性がありました。
コンパイラのクラッシュは、開発者にとって非常に深刻な問題であり、開発体験を著しく損ないます。そのため、このような安定性に関わるバグは優先的に修正されるべきものです。この修正は、コンパイラの堅牢性を高め、より安定した開発環境を提供することを目的としています。
前提知識の解説
このコミットの理解には、以下のGoコンパイラの内部構造に関する知識が必要です。
cmd/gc
: Go言語の公式コンパイラの一部であり、Goソースコードを機械語に変換する主要なコンポーネントです。C言語で書かれており、Go言語の進化とともにGo言語自体で書き直される(cmd/compile
)ことになりますが、このコミット時点ではまだC言語ベースです。Type
構造体: Goコンパイラ内部で型情報を表現するための構造体です。Go言語のプリミティブ型(int, stringなど)、構造体、関数、インターフェースなど、あらゆる型の詳細がこの構造体に格納されます。T
: Goコンパイラ内部で「不正な型」や「未解決の型」を示す特殊なType
ポインタです。型チェックが失敗した場合などにこの値が使われることがあります。S
: Goコンパイラ内部で「シンボルが見つからない」または「匿名型」を示す特殊なSym
ポインタです。Type
構造体のsym
フィールドがこれに設定されることがあります。broke
フィールド:Type
構造体内のブール値で、その型が何らかの理由で「壊れている」または「不正である」ことを示します。通常、型チェックの段階でエラーが検出された場合に設定されます。
Sym
構造体: Goコンパイラ内部でシンボル(変数名、関数名、型名など)を表現するための構造体です。Node
構造体: 抽象構文木(AST)のノードを表現する構造体です。コンパイラはソースコードをパースしてASTを構築し、このASTを元にコード生成を行います。addmethod
関数:src/cmd/gc/dcl.c
に存在する関数で、型にメソッドを追加する処理を担当します。レシーバの型やメソッドのシグネチャを解析し、コンパイラ内部のデータ構造に登録します。methcmp
関数:src/cmd/gc/subr.c
に存在する関数で、メソッドの比較を行うための関数です。主に、インターフェースの実装チェックや、メソッドセットの構築などで使用されます。assignconv
関数:src/cmd/gc/subr.c
に存在する関数で、代入や型変換の際に型の互換性をチェックする関数です。
これらの内部構造は、Goコンパイラがどのように型情報を管理し、メソッドを処理し、型チェックを行うかを理解する上で不可欠です。nilポインタ参照解除は、これらの内部構造のポインタが予期せずNULL
になったり、T
やS
のような特殊な値が渡されたりした際に、その後の処理でこれらのポインタをデリファレンスしようとすることで発生します。
技術的詳細
このコミットは、Goコンパイラ内の2つのファイル、src/cmd/gc/dcl.c
とsrc/cmd/gc/subr.c
に対して修正を加えています。主な目的は、nilポインタ参照解除を防ぐための防御的なチェックを追加することです。
src/cmd/gc/dcl.c
における修正
addmethod
関数は、型にメソッドを追加する際に呼び出されます。元のコードでは、t
がT
(不正な型)である場合に、その後のt->broke
やt->sym
へのアクセスでnilポインタ参照解除が発生する可能性がありました。
修正では、以下のチェックが追加されました。
if(f == T) {
t = pa;
if(t == T) // rely on typecheck having complained before
return;
// ... 既存のコード ...
}
この変更により、f
がT
である場合にt
にpa
が代入されますが、そのt
がさらにT
である場合(つまり、レシーバの型自体が不正である場合)は、それ以上処理を進めずにreturn
するようになりました。コメントにある「rely on typecheck having complained before」は、この時点で既に型チェックがエラーを報告しているはずなので、ここではコンパイラのクラッシュを防ぐことに専念し、重複してエラーを報告する必要はないという意図を示しています。
また、既存のif(t->broke)
チェックの前に、if(t != T)
というチェックが追加され、t
が不正な型T
でないことを確認してからt->broke
にアクセスするように変更されました。これにより、t
がT
である場合にt->broke
へのアクセスでクラッシュするのを防ぎます。
src/cmd/gc/subr.c
における修正
methcmp
関数は、2つの型a
とb
のメソッドを比較する際に使用されます。元のコードでは、a->sym
やb->sym
に直接アクセスしていましたが、a
やb
のsym
フィールドがS
(匿名型やシンボルが見つからない状態)である場合に、strcmp
が不正なポインタをデリファレンスしようとする可能性がありました。
修正では、strcmp
を呼び出す前に、a->sym
やb->sym
がS
であるかどうかのチェックが追加されました。
if(a->sym == S && b->sym == S)
return 0; // 両方Sなら等しいとみなす
if(a->sym == S)
return -1; // aがSならaを小さいとみなす(ソート順に影響)
if(b->sym == S)
return 1; // bがSならbを小さいとみなす(ソート順に影響)
i = strcmp(a->sym->name, b->sym->name);
この変更により、a->sym
やb->sym
がS
である特殊なケースが適切に処理され、strcmp
に不正なポインタが渡されることがなくなりました。S
は匿名型を示すため、比較においては特別な扱いが必要です。両方がS
であれば等しいとみなし、片方だけがS
であれば、S
でない方を優先するような比較順序を定義しています。
assignconv
関数は、代入や型変換の際に呼び出されます。元のコードでは、n->type
がT
である場合にのみ早期リターンしていましたが、n->type
が有効な型であってもbroke
フラグが設定されている場合に、その後の処理で問題が発生する可能性がありました。
修正では、以下のチェックが追加されました。
if(n == N || n->type == T || n->type->broke)
return n;
これにより、n->type
がT
であるか、またはn->type->broke
が真である場合にも早期リターンするようになりました。これは、型が「壊れている」状態であれば、それ以上その型を使った処理を進めるべきではないという防御的なアプローチです。これにより、不正な型情報が後続のコンパイラフェーズに伝播し、さらなるクラッシュを引き起こすのを防ぎます。
これらの修正は、コンパイラの内部処理におけるnilポインタ参照解除の脆弱性を特定し、それらを堅牢なチェックで補強することで、コンパイラの安定性を大幅に向上させています。
コアとなるコードの変更箇所
src/cmd/gc/dcl.c
--- a/src/cmd/gc/dcl.c
+++ b/src/cmd/gc/dcl.c
@@ -1339,6 +1339,8 @@ addmethod(Sym *sf, Type *t, int local, int nointerface)\n f = methtype(pa, 1);\n if(f == T) {\n t = pa;\n+ if(t == T) // rely on typecheck having complained before\n+ return;\n if(t != T) {\n if(isptr[t->etype]) {\n if(t->sym != S) {\
@@ -1347,10 +1349,8 @@ addmethod(Sym *sf, Type *t, int local, int nointerface)\n }\n t = t->type;\n }\n-\t\t}\n-\t\tif(t->broke) // rely on typecheck having complained before\n-\t\t\treturn;\n-\t\tif(t != T) {\n+\t\t\tif(t->broke) // rely on typecheck having complained before\n+\t\t\t\treturn;\n \t\t\tif(t->sym == S) {\n \t\t\t\tyyerror(\"invalid receiver type %T (%T is an unnamed type)\", pa, t);\n \t\t\t\treturn;\
src/cmd/gc/subr.c
--- a/src/cmd/gc/subr.c
+++ b/src/cmd/gc/subr.c
@@ -714,6 +714,12 @@ methcmp(const void *va, const void *vb)\n \n a = *(Type**)va;\n b = *(Type**)vb;\n+ if(a->sym == S && b->sym == S)\n+ return 0;\n+ if(a->sym == S)\n+ return -1;\n+ if(b->sym == S)\n+ return 1;\n i = strcmp(a->sym->name, b->sym->name);\n if(i != 0)\n return i;\
@@ -1393,7 +1399,7 @@ assignconv(Node *n, Type *t, char *context)\n Node *r, *old;\n char *why;\n \n-\tif(n == N || n->type == T)\n+\tif(n == N || n->type == T || n->type->broke)\n \t\treturn n;\n \n \told = n;\
コアとなるコードの解説
src/cmd/gc/dcl.c
の addmethod
関数
- 変更前:
if(f == T) { t = pa; if(t != T) { // ... } } if(t->broke) // rely on typecheck having complained before return; if(t != T) { // ... }
- 変更後:
この修正のポイントは、if(f == T) { t = pa; if(t == T) // rely on typecheck having complained before return; // ここで早期リターンを追加 if(t != T) { // ... } // t->broke のチェックがこのブロック内に移動し、t != T のチェックと統合 if(t->broke) // rely on typecheck having complained before return; } // 変更なし
f == T
(メソッドの型が不正)の場合に、レシーバの型t
もT
であるならば、それ以上処理を進めずに早期リターンするようにした点です。これにより、不正な型情報が原因で発生する可能性のある後続のnilポインタ参照解除を防ぎます。また、t->broke
のチェックがif(t != T)
のブロックの外から内側に移動し、t
がT
でないことを確認した上でbroke
フラグにアクセスするように変更されました。これにより、t
がT
である場合にt->broke
へのアクセスでクラッシュするのを防ぎます。
src/cmd/gc/subr.c
の methcmp
関数
- 変更前:
a = *(Type**)va; b = *(Type**)vb; i = strcmp(a->sym->name, b->sym->name); // ...
- 変更後:
この修正は、a = *(Type**)va; b = *(Type**)vb; if(a->sym == S && b->sym == S) // 両方のシンボルがS(匿名型など)の場合 return 0; // 等しいとみなす if(a->sym == S) // aのシンボルがSの場合 return -1; // aを小さいとみなす if(b->sym == S) // bのシンボルがSの場合 return 1; // bを小さいとみなす i = strcmp(a->sym->name, b->sym->name); // ...
a->sym
やb->sym
がS
(匿名型やシンボルが見つからない状態)である特殊なケースをstrcmp
の呼び出し前に処理することで、不正なポインタがstrcmp
に渡されるのを防ぎます。S
は匿名型を示すため、通常のシンボル名比較とは異なる扱いが必要です。この変更により、methcmp
関数がより堅牢になりました。
src/cmd/gc/subr.c
の assignconv
関数
- 変更前:
if(n == N || n->type == T) return n;
- 変更後:
この修正は、if(n == N || n->type == T || n->type->broke) // n->type->broke のチェックを追加 return n;
assignconv
関数が処理するNode
の型がT
(不正な型)であるだけでなく、n->type->broke
が真である場合(型が壊れている状態)にも早期リターンするように変更しました。これにより、壊れた型情報が後続の処理に伝播し、コンパイラのクラッシュを引き起こすのを未然に防ぎます。これは、コンパイラの堅牢性を高めるための防御的なプログラミングの一例です。
これらの変更は、Goコンパイラの内部で型情報がどのように扱われるか、そして不正な型情報がどのように伝播して問題を引き起こすかを理解していることを示しています。nilポインタ参照解除は、コンパイラのような複雑なシステムではよくある問題であり、このような防御的なチェックの追加はシステムの安定性にとって非常に重要です。
関連リンク
- Go Issue 5119: https://github.com/golang/go/issues/5119
- Go CL 7838050: https://golang.org/cl/7838050
参考にした情報源リンク
- Go言語の公式ドキュメント
- Goコンパイラのソースコード
- Go言語のIssueトラッカー (Issue 5119)
- Go言語のコードレビューシステム (CL 7838050)
- C言語におけるポインタと構造体の概念
- コンパイラ設計の基本原則(抽象構文木、型システムなど)
[インデックス 15946] ファイルの概要
コミット
commit ce99bb2caf26d4c052636847c913906fb5974c34
Author: Rémy Oudompheng <oudomphe@phare.normalesup.org>
Date: Tue Mar 26 08:20:10 2013 +0100
cmd/gc: fix nil pointer dereferences.
Fixes #5119.
R=golang-dev, dvyukov, dave, rsc
CC=golang-dev
https://golang.org/cl/7838050
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/ce99bb2caf26d4c052636847c913906fb5974c34
元コミット内容
このコミットは、Goコンパイラ(cmd/gc
)におけるnilポインタ参照解除のバグを修正するものです。具体的には、Issue 5119で報告された問題に対処しています。
変更の背景
このコミットは、Goコンパイラ(cmd/gc
)が特定の状況下でnilポインタ参照解除を引き起こし、コンパイラがクラッシュするバグ(Issue 5119)を修正するために作成されました。このバグは、型チェックが失敗した際に、後続の処理で不正な型情報(T
やS
といった特殊な型シンボル、あるいはbroke
フラグが設定された型)が渡されることで発生していました。特に、メソッドの追加や型の比較を行う際に、これらの不正な型がnilポインタ参照解除を引き起こす可能性がありました。
コンパイラのクラッシュは、開発者にとって非常に深刻な問題であり、開発体験を著しく損ないます。そのため、このような安定性に関わるバグは優先的に修正されるべきものです。この修正は、コンパイラの堅牢性を高め、より安定した開発環境を提供することを目的としています。
前提知識の解説
このコミットの理解には、以下のGoコンパイラの内部構造に関する知識が必要です。
cmd/gc
: Go言語の公式コンパイラの一部であり、Goソースコードを機械語に変換する主要なコンポーネントです。C言語で書かれており、Go言語の進化とともにGo言語自体で書き直される(cmd/compile
)ことになりますが、このコミット時点ではまだC言語ベースです。Type
構造体: Goコンパイラ内部で型情報を表現するための構造体です。Go言語のプリミティブ型(int, stringなど)、構造体、関数、インターフェースなど、あらゆる型の詳細がこの構造体に格納されます。T
: Goコンパイラ内部で「不正な型」や「未解決の型」を示す特殊なType
ポインタです。型チェックが失敗した場合などにこの値が使われることがあります。S
: Goコンパイラ内部で「シンボルが見つからない」または「匿名型」を示す特殊なSym
ポインタです。Type
構造体のsym
フィールドがこれに設定されることがあります。broke
フィールド:Type
構造体内のブール値で、その型が何らかの理由で「壊れている」または「不正である」ことを示します。通常、型チェックの段階でエラーが検出された場合に設定されます。
Sym
構造体: Goコンパイラ内部でシンボル(変数名、関数名、型名など)を表現するための構造体です。Node
構造体: 抽象構文木(AST)のノードを表現する構造体です。コンパイラはソースコードをパースしてASTを構築し、このASTを元にコード生成を行います。addmethod
関数:src/cmd/gc/dcl.c
に存在する関数で、型にメソッドを追加する処理を担当します。レシーバの型やメソッドのシグネチャを解析し、コンパイラ内部のデータ構造に登録します。methcmp
関数:src/cmd/gc/subr.c
に存在する関数で、メソッドの比較を行うための関数です。主に、インターフェースの実装チェックや、メソッドセットの構築などで使用されます。assignconv
関数:src/cmd/gc/subr.c
に存在する関数で、代入や型変換の際に型の互換性をチェックする関数です。
これらの内部構造は、Goコンパイラがどのように型情報を管理し、メソッドを処理し、型チェックを行うかを理解する上で不可欠です。nilポインタ参照解除は、これらの内部構造のポインタが予期せずNULL
になったり、T
やS
のような特殊な値が渡されたりした際に、その後の処理でこれらのポインタをデリファレンスしようとすることで発生します。
技術的詳細
このコミットは、Goコンパイラ内の2つのファイル、src/cmd/gc/dcl.c
とsrc/cmd/gc/subr.c
に対して修正を加えています。主な目的は、nilポインタ参照解除を防ぐための防御的なチェックを追加することです。
src/cmd/gc/dcl.c
における修正
addmethod
関数は、型にメソッドを追加する際に呼び出されます。元のコードでは、t
がT
(不正な型)である場合に、その後のt->broke
やt->sym
へのアクセスでnilポインタ参照解除が発生する可能性がありました。
修正では、以下のチェックが追加されました。
if(f == T) {
t = pa;
if(t == T) // rely on typecheck having complained before
return;
// ... 既存のコード ...
}
この変更により、f
がT
である場合にt
にpa
が代入されますが、そのt
がさらにT
である場合(つまり、レシーバの型自体が不正である場合)は、それ以上処理を進めずにreturn
するようになりました。コメントにある「rely on typecheck having complained before」は、この時点で既に型チェックがエラーを報告しているはずなので、ここではコンパイラのクラッシュを防ぐことに専念し、重複してエラーを報告する必要はないという意図を示しています。
また、既存のif(t->broke)
チェックの前に、if(t != T)
というチェックが追加され、t
が不正な型T
でないことを確認してからt->broke
にアクセスするように変更されました。これにより、t
がT
である場合にt->broke
へのアクセスでクラッシュするのを防ぎます。
src/cmd/gc/subr.c
における修正
methcmp
関数は、2つの型a
とb
のメソッドを比較する際に使用されます。元のコードでは、a->sym
やb->sym
に直接アクセスしていましたが、a
やb
のsym
フィールドがS
(匿名型やシンボルが見つからない状態)である場合に、strcmp
が不正なポインタをデリファレンスしようとする可能性がありました。
修正では、strcmp
を呼び出す前に、a->sym
やb->sym
がS
であるかどうかのチェックが追加されました。
if(a->sym == S && b->sym == S)
return 0; // 両方Sなら等しいとみなす
if(a->sym == S)
return -1; // aがSならaを小さいとみなす(ソート順に影響)
if(b->sym == S)
return 1; // bがSならbを小さいとみなす(ソート順に影響)
i = strcmp(a->sym->name, b->sym->name);
この変更により、a->sym
やb->sym
がS
である特殊なケースが適切に処理され、strcmp
に不正なポインタが渡されることがなくなりました。S
は匿名型を示すため、比較においては特別な扱いが必要です。両方がS
であれば等しいとみなし、片方だけがS
であれば、S
でない方を優先するような比較順序を定義しています。
assignconv
関数は、代入や型変換の際に呼び出されます。元のコードでは、n->type
がT
である場合にのみ早期リターンしていましたが、n->type
が有効な型であってもbroke
フラグが設定されている場合に、その後の処理で問題が発生する可能性がありました。
修正では、以下のチェックが追加されました。
if(n == N || n->type == T || n->type->broke)
return n;
これにより、n->type
がT
であるか、またはn->type->broke
が真である場合にも早期リターンするようになりました。これは、型が「壊れている」状態であれば、それ以上その型を使った処理を進めるべきではないという防御的なアプローチです。これにより、不正な型情報が後続のコンパイラフェーズに伝播し、さらなるクラッシュを引き起こすのを防ぎます。
これらの修正は、コンパイラの内部処理におけるnilポインタ参照解除の脆弱性を特定し、それらを堅牢なチェックで補強することで、コンパイラの安定性を大幅に向上させています。
コアとなるコードの変更箇所
src/cmd/gc/dcl.c
--- a/src/cmd/gc/dcl.c
+++ b/src/cmd/gc/dcl.c
@@ -1339,6 +1339,8 @@ addmethod(Sym *sf, Type *t, int local, int nointerface)\n f = methtype(pa, 1);\n if(f == T) {\n t = pa;\n+ if(t == T) // rely on typecheck having complained before\n+ return;\n if(t != T) {\n if(isptr[t->etype]) {\n if(t->sym != S) {\
@@ -1347,10 +1349,8 @@ addmethod(Sym *sf, Type *t, int local, int nointerface)\n }\n t = t->type;\n }\n-\t\t}\n-\t\tif(t->broke) // rely on typecheck having complained before\n-\t\t\treturn;\n-\t\tif(t != T) {\n+\t\t\tif(t->broke) // rely on typecheck having complained before\n+\t\t\t\treturn;\n \t\t\tif(t->sym == S) {\n \t\t\t\tyyerror(\"invalid receiver type %T (%T is an unnamed type)\", pa, t);\n \t\t\t\treturn;\
src/cmd/gc/subr.c
--- a/src/cmd/gc/subr.c
+++ b/src/cmd/gc/subr.c
@@ -714,6 +714,12 @@ methcmp(const void *va, const void *vb)\n \n a = *(Type**)va;\n b = *(Type**)vb;\n+ if(a->sym == S && b->sym == S)\n+ return 0;\n+ if(a->sym == S)\n+ return -1;\n+ if(b->sym == S)\n+ return 1;\n i = strcmp(a->sym->name, b->sym->name);\n if(i != 0)\n return i;\
@@ -1393,7 +1399,7 @@ assignconv(Node *n, Type *t, char *context)\n Node *r, *old;\n char *why;\n \n-\tif(n == N || n->type == T)\n+\tif(n == N || n->type == T || n->type->broke)\n \t\treturn n;\n \n \told = n;\
コアとなるコードの解説
src/cmd/gc/dcl.c
の addmethod
関数
- 変更前:
if(f == T) { t = pa; if(t != T) { // ... } } if(t->broke) // rely on typecheck having complained before return; if(t != T) { // ... }
- 変更後:
この修正のポイントは、if(f == T) { t = pa; if(t == T) // rely on typecheck having complained before return; // ここで早期リターンを追加 if(t != T) { // ... } // t->broke のチェックがこのブロック内に移動し、t != T のチェックと統合 if(t->broke) // rely on typecheck having complained before return; } // 変更なし
f == T
(メソッドの型が不正)の場合に、レシーバの型t
もT
であるならば、それ以上処理を進めずに早期リターンするようにした点です。これにより、不正な型情報が原因で発生する可能性のある後続のnilポインタ参照解除を防ぎます。また、t->broke
のチェックがif(t != T)
のブロックの外から内側に移動し、t
がT
でないことを確認した上でbroke
フラグにアクセスするように変更されました。これにより、t
がT
である場合にt->broke
へのアクセスでクラッシュするのを防ぎます。
src/cmd/gc/subr.c
の methcmp
関数
- 変更前:
a = *(Type**)va; b = *(Type**)vb; i = strcmp(a->sym->name, b->sym->name); // ...
- 変更後:
この修正は、a = *(Type**)va; b = *(Type**)vb; if(a->sym == S && b->sym == S) // 両方のシンボルがS(匿名型など)の場合 return 0; // 等しいとみなす if(a->sym == S) // aのシンボルがSの場合 return -1; // aを小さいとみなす if(b->sym == S) // bのシンボルがSの場合 return 1; // bを小さいとみなす i = strcmp(a->sym->name, b->sym->name); // ...
a->sym
やb->sym
がS
(匿名型やシンボルが見つからない状態)である特殊なケースをstrcmp
の呼び出し前に処理することで、不正なポインタがstrcmp
に渡されるのを防ぎます。S
は匿名型を示すため、通常のシンボル名比較とは異なる扱いが必要です。この変更により、methcmp
関数がより堅牢になりました。
src/cmd/gc/subr.c
の assignconv
関数
- 変更前:
if(n == N || n->type == T) return n;
- 変更後:
この修正は、if(n == N || n->type == T || n->type->broke) // n->type->broke のチェックを追加 return n;
assignconv
関数が処理するNode
の型がT
(不正な型)であるだけでなく、n->type->broke
が真である場合(型が壊れている状態)にも早期リターンするように変更しました。これにより、壊れた型情報が後続の処理に伝播し、コンパイラのクラッシュを引き起こすのを未然に防ぎます。これは、コンパイラの堅牢性を高めるための防御的なプログラミングの一例です。
これらの変更は、Goコンパイラの内部で型情報がどのように扱われるか、そして不正な型情報がどのように伝播して問題を引き起こすかを理解していることを示しています。nilポインタ参照解除は、コンパイラのような複雑なシステムではよくある問題であり、このような防御的なチェックの追加はシステムの安定性にとって非常に重要です。
関連リンク
- Go Issue 5119: https://github.com/golang/go/issues/5119
- Go CL 7838050: https://golang.org/cl/7838050
参考にした情報源リンク
- Go言語の公式ドキュメント
- Goコンパイラのソースコード
- Go言語のIssueトラッカー (Issue 5119)
- Go言語のコードレビューシステム (CL 7838050)
- C言語におけるポインタと構造体の概念
- コンパイラ設計の基本原則(抽象構文木、型システムなど)