[インデックス 12167] ファイルの概要
このコミットは、Go言語の仕様書(doc/go_spec.html)に、インポートパスに関する実装上の制限(implementation restriction)を追加するものです。具体的には、インポートパスに使用できる文字の種類をUnicodeの特定のカテゴリに限定し、一部のASCII文字を禁止する規定が追記されました。これにより、Goコンパイラがインポートパスを解釈する際の互換性と堅牢性が向上します。
コミット
- コミットハッシュ:
ac4055b2c5a81047271d8a0b830b657820a29698 - Author: Robert Griesemer gri@golang.org
- Date: Wed Feb 22 23:51:25 2012 -0800
- 変更ファイル:
doc/go_spec.html(1ファイル) - 変更行数: 10行追加, 1行削除
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/ac4055b2c5a81047271d8a0b830b657820a29698
元コミット内容
go spec: import path implementation restriction
R=rsc, r, r, adg
CC=golang-dev
https://golang.org/cl/5688074
変更の背景
Go言語のインポートパスは、パッケージを一意に識別し、そのソースコードの場所を示す重要な役割を担っています。しかし、インポートパスに使用できる文字に明確な制限がない場合、以下のような問題が発生する可能性があります。
- ファイルシステムとの互換性: オペレーティングシステムやファイルシステムによっては、ファイル名やパスに使用できる文字に制限があります。例えば、Windowsでは特定の記号がパスに使用できません。Goのインポートパスがこれらの制限を考慮しないと、異なる環境間でのコードの移植性やビルドの安定性が損なわれる可能性があります。
- URLエンコーディングの問題: Goのインポートパスは、多くの場合、バージョン管理システムのリポジトリパス(例: GitHubのURL)と関連付けられます。URLとして解釈される際に、特殊文字が誤ってエンコードされたり、予期せぬ動作を引き起こしたりする可能性があります。
- セキュリティ上の懸念(Punycode攻撃など): 視覚的に類似したUnicode文字(ホモグラフ)を使用して、正規のインポートパスを偽装する「Punycode攻撃」のようなセキュリティリスクが存在します。これにより、悪意のあるパッケージが正規のパッケージであるかのように見せかけ、開発者をだます可能性があります。
- パーサーの実装の複雑化: インポートパスに非常に広範な文字セットを許可すると、コンパイラやツールがインポートパスを解析する際のロジックが複雑になり、バグの原因となる可能性があります。
これらの問題を未然に防ぎ、Goエコシステム全体の堅牢性とセキュリティを向上させるために、インポートパスに使用できる文字に明示的な制限を設ける必要がありました。このコミットは、その制限をGo言語の公式仕様書に明記するものです。
前提知識の解説
Go言語のインポートパス
Go言語では、他のパッケージのコードを利用するためにimport文を使用します。import文に続く文字列が「インポートパス」です。例えば、import "fmt"の場合、"fmt"がインポートパスです。このインポートパスは、Goツールチェインがパッケージのソースコードを見つけるための論理的な識別子として機能します。通常、インポートパスはファイルシステムのパスや、GitHubなどのリモートリポジトリのURLと関連付けられます。
Unicodeの一般カテゴリ(General Categories)
Unicodeは、世界中の文字を統一的に扱うための文字コード標準です。Unicodeの各文字には、「一般カテゴリ(General Category)」と呼ばれるプロパティが割り当てられています。これは、文字の種類(例: 文字、数字、記号、句読点など)を示す分類です。このコミットで言及されているカテゴリは以下の通りです。
- L (Letter): アルファベットや漢字など、文字として使われる文字。
Lu(Uppercase Letter): 大文字Ll(Lowercase Letter): 小文字Lt(Titlecase Letter): タイトルケース文字Lm(Modifier Letter): 修飾文字Lo(Other Letter): その他の文字
- M (Mark): アクセント記号や結合文字など、他の文字と組み合わせて使われる文字。
Mn(Nonspacing Mark): 非スペーシングマークMc(Spacing Mark): スペーシングマークMe(Enclosing Mark): 囲みマーク
- N (Number): 数字。
Nd(Decimal Digit Number): 10進数字Nl(Letter Number): 文字数字(例: ローマ数字)No(Other Number): その他の数字
- P (Punctuation): 句読点。
Pc(Connector Punctuation): 接続句読点(例: アンダーバー)Pd(Dash Punctuation): ダッシュ句読点Ps(Open Punctuation): 開始句読点(例:()Pe(Close Punctuation): 終了句読点(例:))Pi(Initial Quote): 開始引用符Pf(Final Quote): 終了引用符Po(Other Punctuation): その他の句読点
- S (Symbol): 記号。
Sm(Math Symbol): 数学記号Sc(Currency Symbol): 通貨記号Sk(Modifier Symbol): 修飾記号So(Other Symbol): その他の記号
これらのカテゴリは、Unicode文字をその用途や特性に基づいて分類するために使用されます。このコミットでは、「Graphic characters without spaces」(スペースを含まない図形文字)として、これらのカテゴリの文字がインポートパスに許可されることを示しています。
技術的詳細
このコミットによってGo言語の仕様書に追加された実装上の制限は、Goコンパイラがインポートパスをどのように解釈すべきかについて、より厳密なガイドラインを提供します。
追加された規定は以下の通りです。
Implementation restriction: A compiler may restrict ImportPaths to non-empty strings using only characters belonging to Unicode's L, M, N, P, and S general categories (the Graphic characters without spaces) and may also exclude the ASCII characters
!"#$%&'()*,-:;<=>?[\]^{|}~`.
この規定を分解して解説します。
non-empty strings: インポートパスは空文字列であってはならないことを意味します。これは当然の要件であり、空のインポートパスは意味をなしません。using only characters belonging to Unicode's L, M, N, P, and S general categories:- これは、インポートパスに使用できる文字が、Unicodeの「文字(Letter)」「マーク(Mark)」「数字(Number)」「句読点(Punctuation)」「記号(Symbol)」のいずれかのカテゴリに属する文字に限定されることを意味します。
- これらのカテゴリは、一般的に「スペースを含まない図形文字(Graphic characters without spaces)」と総称されます。つまり、制御文字、区切り文字(スペース、タブ、改行など)、未割り当てのコードポイントなどはインポートパスに使用できません。
- この制限により、インポートパスが視覚的に明確で、ファイルシステムやURLのパスとして適切に扱える文字セットに限定されます。
and may also exclude the ASCII characters !\"#$%&'()*,-:;<=>?[\\]^{|}~`:- さらに、Goコンパイラは、上記のUnicodeカテゴリに属する文字であっても、特定のASCII記号をインポートパスから除外することができると規定されています(
may also exclude)。 - 除外される可能性のあるASCII記号は以下の通りです:
!(感嘆符)"(二重引用符)#(シャープ)$(ドル記号)%(パーセント)&(アンパサンド)'(アポストロフィ)((左括弧))(右括弧)*(アスタリスク),(カンマ)-(ハイフン):(コロン);(セミコロン)<(小なり記号)=(等号)>(大なり記号)?(疑問符)[(左角括弧)\(バックスラッシュ)](右角括弧)^(キャレット)`(バッククォート){(左波括弧)|(縦棒)}(右波括弧)~(チルダ)
- これらの記号の多くは、シェルコマンド、正規表現、URL、ファイルシステムパスなどで特別な意味を持つため、インポートパスでの使用を制限することで、予期せぬ挙動やセキュリティ上の脆弱性を防ぐことができます。例えば、
:はWindowsのドライブレターやURLのスキーム区切り文字として、/や\はパス区切り文字として、*や?はワイルドカードとして使われることがあります。 - この「除外できる」という表現は、コンパイラの実装者が、特定の環境やセキュリティ要件に基づいてこれらの文字の使用をさらに制限する裁量を持つことを意味します。
- さらに、Goコンパイラは、上記のUnicodeカテゴリに属する文字であっても、特定のASCII記号をインポートパスから除外することができると規定されています(
この変更は、Go言語のインポートパスが、異なるプラットフォームやツールチェイン間で一貫して、かつ安全に扱われることを保証するための重要なステップです。
コアとなるコードの変更箇所
このコミットによる変更は、Go言語の仕様書を記述したHTMLファイルである doc/go_spec.html のみに適用されています。
--- a/doc/go_spec.html
+++ b/doc/go_spec.html
@@ -1,6 +1,6 @@
<!--{
"Title": "The Go Programming Language Specification",
- "Subtitle": "Version of February 22, 2012"
+ "Subtitle": "Version of February 23, 2012"
}-->
<!--
@@ -5096,6 +5096,15 @@ it is typically a substring of the full file name of the compiled
package and may be relative to a repository of installed packages.
</p>
+<p>
+Implementation restriction: A compiler may restrict ImportPaths to
+non-empty strings using only characters belonging to
+<a href="http://www.unicode.org/versions/Unicode6.0.0/">Unicode's</a>
+L, M, N, P, and S general categories (the Graphic characters without
+spaces) and may also exclude the ASCII characters
+<code>!"#$%&'()*,:;<=>?[\\]^`{|}</code>.
+</p>
+
<p>
Assume we have compiled a package containing the package clause
<code>package math</code>, which exports function <code>Sin</code>, and
主な変更点は以下の2点です。
- 仕様書のバージョン日付の更新:
- "Subtitle": "Version of February 22, 2012"+ "Subtitle": "Version of February 23, 2012"これは、仕様書が更新された日付を反映するものです。 - インポートパスに関する実装制限の追加:
既存のインポートパスに関する説明の段落の後に、新しい
<p>タグで囲まれた段落が追加されています。この段落が、前述のインポートパスの文字制限に関する記述です。
コアとなるコードの解説
追加されたHTMLスニペットは、Go言語の公式仕様書に、インポートパスの文字に関する「実装上の制限」を明文化するものです。
<p>
Implementation restriction: A compiler may restrict ImportPaths to
non-empty strings using only characters belonging to
<a href="http://www.unicode.org/versions/Unicode6.0.0/">Unicode's</a>
L, M, N, P, and S general categories (the Graphic characters without
spaces) and may also exclude the ASCII characters
<code>!"#$%&'()*,:;<=>?[\\]^`{|}</code>.
</p>
<p>タグは、新しい段落を定義しています。Implementation restriction:: これは、Go言語の仕様の一部でありながら、コンパイラの実装者が特定の制約を課すことを許可する「実装上の制限」であることを明示しています。これは、仕様の柔軟性を保ちつつ、実用的な制約を設けるための一般的な手法です。A compiler may restrict ImportPaths to non-empty strings using only characters belonging to ...: コンパイラがインポートパスを、空でない文字列で、かつUnicodeのL, M, N, P, Sカテゴリに属する文字のみを使用するように制限できることを述べています。<a href="http://www.unicode.org/versions/Unicode6.0.0/">Unicode's</a>: Unicodeのバージョン6.0.0へのリンクが張られており、この仕様がどのUnicodeバージョンに基づいているかを示しています。L, M, N, P, and S general categories (the Graphic characters without spaces): 前述のUnicode一般カテゴリの略称と、それらが「スペースを含まない図形文字」であることを補足しています。and may also exclude the ASCII characters <code>!"#$%&'()*,:;<=>?[\\]^{|}.: さらに、コンパイラが特定のASCII記号(HTMLエンティティで記述されているものを含む)をインポートパスから除外できることを示しています。&は&、<は<、>は>`を表します。
この追加により、Go言語のインポートパスの定義がより明確になり、Goコンパイラや関連ツールがインポートパスを処理する際の挙動に一貫性を持たせることが可能になります。また、開発者はインポートパスに使用できる文字について、より具体的なガイドラインを得ることができます。
関連リンク
- Go Code Review: https://golang.org/cl/5688074
参考にした情報源リンク
- boldlygo.tech: https://vertexaisearch.cloud.google.com/grounding-api-redirect/AUZIYQFhHai2JAXSh4x4dZ3M-PN0yi0O20PRe0--kpZ6Tx_ON8r-P5ti3_J-cdjmgVT_wQ6bMNlUMfK1By_yXohI6cMj0EcJUNZ57qyD5uKgQ1mDZf_2uFiv2Ic8kigUeAxfUzjdx9u6hXTOFDoUFYI5AXvwWigybCVO7A==
- golangbridge.org: https://vertexaisearch.cloud.google.com/grounding-api-redirect/AUZIYQFYhciMbvvN3eufpBdHsYtpCo34-Vq43hWLmjLNbewpRiEIEuvCMNy4_u-lnfD6ZDJo7ZCmGPX_c1OTrPnHgylLCuZuf60N2qN3tcye-8sUa10lgdjXIP9P3XxiXYA6TzQQ1Hvj6VGW0_9Z7Wo-9wH8d8Pgwyg=
- github.com (Go issue discussion): https://vertexaisearch.cloud.google.com/grounding-api-redirect/AUZIYQFplLeEh3-8qlq6z-61xXYhewPlA6ad2zbWWhsdqDEfZi1AQoQEdepsIHunyNTtrGmoNduDG98G6SwbYgcBRDJl91RyrOjEAddN6fI1_2GY3J4BMWKSMThspNioQ-9E3C-cOhZh
- github.com (Punycode attacks discussion): https://vertexaisearch.cloud.google.com/grounding-api-redirect/AUZIYQGwsyNVJp4gTmlgSLeJQXWubWNF3Zr7fxOkBz9NXdF2Hg8mOIsLBRgjdAFGrwzWl6nueo8rzWd87ay1X8lGtFYSToS8Xb0Nq4YqiiDlNw5NbIzCa7s8-HscUUfCINVHkJ1sHI-y