@@ -147,6 +147,42 @@ func TestNtSecurityDescriptor_Involution(t *testing.T) {
147147 }
148148}
149149
150+ // TestNtSecurityDescriptor_Marshal_UnsetOwnerGroup verifies that marshalling a
151+ // descriptor whose Owner/Group were never populated (as produced by
152+ // NewSecurityDescriptor) writes OffsetOwner/OffsetGroup = 0 and emits no SID
153+ // bytes, rather than an invalid S-0-0-0 SID.
154+ func TestNtSecurityDescriptor_Marshal_UnsetOwnerGroup (t * testing.T ) {
155+ ntsd := securitydescriptor .NewSecurityDescriptor ()
156+
157+ data , err := ntsd .Marshal ()
158+ if err != nil {
159+ t .Fatalf ("Marshal() error = %v" , err )
160+ }
161+
162+ if ntsd .Header .OffsetOwner != 0 {
163+ t .Errorf ("OffsetOwner = %d, want 0 for an unset owner" , ntsd .Header .OffsetOwner )
164+ }
165+ if ntsd .Header .OffsetGroup != 0 {
166+ t .Errorf ("OffsetGroup = %d, want 0 for an unset group" , ntsd .Header .OffsetGroup )
167+ }
168+ // With no owner, group, DACL, or SACL set, only the 20-byte header is emitted.
169+ if len (data ) != 20 {
170+ t .Errorf ("Marshal() length = %d, want 20 (header only)" , len (data ))
171+ }
172+
173+ // The descriptor must round-trip with no fabricated owner/group.
174+ parsed := & securitydescriptor.NtSecurityDescriptor {}
175+ if _ , err := parsed .Unmarshal (data ); err != nil {
176+ t .Fatalf ("Unmarshal() error = %v" , err )
177+ }
178+ if parsed .Owner != nil {
179+ t .Errorf ("parsed Owner = %q, want nil" , parsed .Owner .SID .ToString ())
180+ }
181+ if parsed .Group != nil {
182+ t .Errorf ("parsed Group = %q, want nil" , parsed .Group .SID .ToString ())
183+ }
184+ }
185+
150186func TestNtSecurityDescriptor_Unmarshal (t * testing.T ) {
151187 ntsd := securitydescriptor .NewSecurityDescriptor ()
152188
0 commit comments