[インデックス 15321] ファイルの概要
このコミットは、Go言語の標準ライブラリであるsyscall
パッケージ内のsecurity_windows.go
ファイルに対する変更です。具体的には、Windowsのセキュリティ識別子(SID)のタイプを定義する定数群において、SidTypeUser
の初期化方法を修正しています。
コミット
commit e378aef1def490cec4b86e2d341a287b5286d01f
Author: Brian Dellisanti <briandellisanti@gmail.com>
Date: Wed Feb 20 15:38:35 2013 +1100
windows: fix syscall.SidTypeUser so following consts have correct values.
Fixes #4844.
R=golang-dev, alex.brainman
CC=golang-dev
https://golang.org/cl/7366043
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/e378aef1def490cec4b86e2d341a287b5286d01f
元コミット内容
windows: fix syscall.SidTypeUser so following consts have correct values.
Fixes #4844.
変更の背景
このコミットは、Go言語のsyscall
パッケージにおけるWindows固有の定数定義に関するバグ(Issue #4844)を修正するために行われました。元のコードでは、iota
というGoの特殊な定数ジェネレータをビットシフト演算子(<<
)と組み合わせて使用していましたが、これが意図しない値を生み出し、後続の定数にも誤った値が割り当てられる原因となっていました。
Windowsのセキュリティ識別子(SID)タイプは、特定の整数値を持つことが期待されます。しかし、SidTypeUser = 1 << iota
という定義では、iota
が0から始まるため、SidTypeUser
は1 << 0
で1
となりますが、その後のSidTypeGroup
などは1 << 1
で2
、SidTypeDomain
は1 << 2
で4
となり、期待される連続した整数値とは異なる値が割り当てられていました。
この問題は、Windows APIが期待するSIDタイプの値とGoの定数定義が一致しないために、syscall
パッケージを利用するアプリケーションが正しく動作しない可能性を示唆していました。
前提知識の解説
Go言語のiota
iota
はGo言語における特殊な定数ジェネレータです。const
ブロック内で使用され、連続する定数に自動的にインクリメントされる整数値を割り当てます。
const
ブロックの最初のiota
は0
に初期化されます。- 同じ
const
ブロック内で、新しいconst
宣言が現れるたびにiota
の値は1
ずつ増加します。 iota
は、明示的に値を指定しない定数に自動的に適用されます。
例1: 基本的なiota
const (
A = iota // A = 0
B // B = 1 (iotaは自動的にインクリメントされる)
C // C = 2
)
例2: iota
と演算子
iota
は他の演算子と組み合わせて使用することもできます。
const (
KB = 1 << (10 * iota) // KB = 1 << 0 = 1
MB // MB = 1 << 10 = 1024
GB // GB = 1 << 20 = 1048576
)
この例では、iota
が0, 1, 2とインクリメントされるにつれて、1 << (10 * iota)
は1 << 0
、1 << 10
、1 << 20
と計算され、それぞれ1、1024、1048576という値になります。
Windowsのセキュリティ識別子(SID)とSIDタイプ
Windowsオペレーティングシステムでは、ユーザーアカウント、グループ、コンピュータ、ドメインなどのセキュリティプリンシパルを一意に識別するためにセキュリティ識別子(SID: Security Identifier)を使用します。SIDは、S-1-5-21-3623811015-3361044348-30300820-1013
のような形式の可変長構造です。
SIDには様々なタイプがあり、それぞれが特定の種類のセキュリティプリンシパルを表します。これらのタイプは、Windows APIによって定義された特定の整数値で識別されます。例えば、SidTypeUser
はユーザーアカウントを表し、SidTypeGroup
はグループを表します。これらのタイプは、セキュリティ関連の操作(例: アクセス制御リストの操作、ユーザー情報の取得)において、SIDの性質を判断するために使用されます。
技術的詳細
このコミットの核心は、Goのiota
と定数定義の組み合わせが、Windows APIが期待する連続した整数値のSIDタイプとどのように衝突したかを理解することです。
元のコードでは、以下のようになっていました。
const (
// do not reorder
SidTypeUser = 1 << iota
SidTypeGroup
SidTypeDomain
SidTypeAlias
// ...
)
この定義では、iota
はconst
ブロックの最初の定数であるSidTypeUser
で0
に初期化されます。
SidTypeUser
は1 << 0
となり、値は1
です。- 次に、
SidTypeGroup
は明示的な値が指定されていないため、iota
がインクリメントされ、前の定数の式が繰り返されます。つまり、SidTypeGroup
は1 << 1
となり、値は2
です。 - 同様に、
SidTypeDomain
は1 << 2
で4
、SidTypeAlias
は1 << 3
で8
となります。
このように、元のコードではSIDタイプが1, 2, 4, 8, ...
という2のべき乗の値として定義されていました。しかし、Windows APIが期待するSIDタイプは、通常、1, 2, 3, 4, ...
のような連続した整数値です。この不一致が、syscall
パッケージがWindowsのセキュリティ機能と正しく連携できない原因となっていました。
修正後のコードは以下の通りです。
const (
// do not reorder
SidTypeUser = 1 + iota
SidTypeGroup
SidTypeDomain
SidTypeAlias
// ...
)
この変更により、SidTypeUser
の定義が1 + iota
に変更されました。
SidTypeUser
は1 + 0
となり、値は1
です。- 次に、
SidTypeGroup
は明示的な値が指定されていないため、iota
がインクリメントされ、前の定数の式が繰り返されます。つまり、SidTypeGroup
は1 + 1
となり、値は2
です。 - 同様に、
SidTypeDomain
は1 + 2
で3
、SidTypeAlias
は1 + 3
で4
となります。
この修正により、SidTypeUser
以降のSIDタイプ定数に1, 2, 3, 4, ...
という連続した整数値が割り当てられるようになり、Windows APIの期待する値と一致するようになりました。これにより、syscall
パッケージがWindowsのセキュリティ機能と正しく連携できるようになり、Issue #4844で報告されたバグが解消されました。
コアとなるコードの変更箇所
--- a/src/pkg/syscall/security_windows.go
+++ b/src/pkg/syscall/security_windows.go
@@ -70,7 +70,7 @@ type UserInfo10 struct {
const (
// do not reorder
- SidTypeUser = 1 << iota
+ SidTypeUser = 1 + iota
SidTypeGroup
SidTypeDomain
SidTypeAlias
コアとなるコードの解説
変更はsrc/pkg/syscall/security_windows.go
ファイルの73行目です。
-
変更前:
SidTypeUser = 1 << iota
iota
は0
から始まるため、SidTypeUser
は1 << 0
で1
となります。- しかし、続く
SidTypeGroup
は1 << 1
で2
、SidTypeDomain
は1 << 2
で4
となり、2のべき乗の値が割り当てられていました。これはWindows APIが期待する連続した整数値のSIDタイプとは異なります。
-
変更後:
SidTypeUser = 1 + iota
iota
は0
から始まるため、SidTypeUser
は1 + 0
で1
となります。- 続く
SidTypeGroup
は1 + 1
で2
、SidTypeDomain
は1 + 2
で3
となり、期待される連続した整数値が割り当てられるようになりました。
この小さな変更により、Goのsyscall
パッケージがWindowsのセキュリティ識別子タイプを正しく解釈し、Windows APIとの互換性が確保されました。
関連リンク
- Go Issue #4844: https://github.com/golang/go/issues/4844
- Go CL 7366043: https://golang.org/cl/7366043 (これは古いGoのコードレビューシステムへのリンクであり、現在はGitHubのコミットページにリダイレクトされるか、アクセスできない場合があります。)
参考にした情報源リンク
- Go言語の
iota
に関する公式ドキュメントやチュートリアル - Windows Security Identifiers (SIDs) のMicrosoft Learnドキュメント
- Go言語の
syscall
パッケージのドキュメント - Go言語のGitHubリポジトリにおけるIssue #4844の議論