Repository: opencontainers/runc
File: exec.go (Go)

Code before:
			p.Capabilities.Permitted = append(p.Capabilities.Permitted, c)
			p.Capabilities.Ambient = append(p.Capabilities.Ambient, c)
		}
	}
	// append the passed env variables
	p.Env = append(p.Env, context.StringSlice("env")...)

	// Always set tty to false, unless explicitly enabled from CLI.
	p.Terminal = context.Bool("tty")
	if context.IsSet("no-new-privs") {
		p.NoNewPrivileges = context.Bool("no-new-privs")
	}
	// Override the user, if passed.
	if user := context.String("user"); user != "" {
		uidString, gidString, doesHaveGid := strings.Cut(user, ":")
		if doesHaveGid {
			gid, err := strconv.Atoi(gidString)
			if err != nil {
				return nil, fmt.Errorf("bad gid: %w", err)
			}
			p.User.GID = uint32(gid)
		}
		uid, err := strconv.Atoi(uidString)
		if err != nil {
			return nil, fmt.Errorf("bad uid: %w", err)
		}
		p.User.UID = uint32(uid)
	}
	for _, gid := range context.Int64Slice("additional-gids") {
		if gid < 0 {
			return nil, fmt.Errorf("additional-gids must be a positive number %d", gid)
		}
		p.User.AdditionalGids = append(p.User.AdditionalGids, uint32(gid))
	}
	return p, validateProcessSpec(p)
}


Review comment (suggestion):
It's common in go to use short variable names when the distance between defining and using them is short; also to [avoid type suffixes](https://google.github.io/styleguide/go/decisions.html#variable-names) (like `String` here`)

In situations like this, `ok` is also a common name (instead of the `doesHaveGid`); while `doesHaveGid` is somewhat more descriptive, it's likely clear from the code what it's handling; using `ok` can reduce cognitive overload, as a reader can recognize the pattern without understanding if `doesHaveGid` has additional purpose or (due to the longer name) possibly used further away from its declaration.

e.g., this could look like;

```go
uid, gid, ok := strings.Cut(user, ":")
if ok {
	v, err := strconv.Atoi(gid)
	if err != nil {
		return nil, fmt.Errorf("bad gid: %w", err)
	}
	p.User.GID = uint32(v)
}
v, err := strconv.Atoi(uid)
if err != nil {
    return nil, fmt.Errorf("bad uid: %w", err)
}
p.User.UID = uint32(v)
```

Somewhat orthogonal to this PR (as it's existing code), but wondering if the `strconv.Atoi(gid)` would be better replaced with `strconv.ParseUint(gid, 10, 32)`, given that we're ultimately casting to a `uint32`; i.e. `strconv.Atoi("4294967296")` will result in gid (uint32) `0`.

Code after:
			p.Capabilities.Permitted = append(p.Capabilities.Permitted, c)
			p.Capabilities.Ambient = append(p.Capabilities.Ambient, c)
		}
	}
	// append the passed env variables
	p.Env = append(p.Env, context.StringSlice("env")...)

	// Always set tty to false, unless explicitly enabled from CLI.
	p.Terminal = context.Bool("tty")
	if context.IsSet("no-new-privs") {
		p.NoNewPrivileges = context.Bool("no-new-privs")
	}
	// Override the user, if passed.
	if user := context.String("user"); user != "" {
		uids, gids, ok := strings.Cut(user, ":")
		if ok {
			gid, err := strconv.Atoi(gids)
			if err != nil {
				return nil, fmt.Errorf("bad gid: %w", err)
			}
			p.User.GID = uint32(gid)
		}
		uid, err := strconv.Atoi(uids)
		if err != nil {
			return nil, fmt.Errorf("bad uid: %w", err)
		}
		p.User.UID = uint32(uid)
	}
	for _, gid := range context.Int64Slice("additional-gids") {
		if gid < 0 {
			return nil, fmt.Errorf("additional-gids must be a positive number %d", gid)
		}
		p.User.AdditionalGids = append(p.User.AdditionalGids, uint32(gid))
	}
	return p, validateProcessSpec(p)
}