From 87f0fe1394dea443b31db4c76e3f3d6c8541e4db Mon Sep 17 00:00:00 2001 From: Erik Dubbelboer Date: Fri, 20 Mar 2026 15:27:24 +0900 Subject: [PATCH] Update securego/gosec from 2.23.0 to 2.25.0 (#2161) --- .github/workflows/security.yml | 2 +- bytesconv.go | 48 +++++++++++++++++++++++++++------- peripconn.go | 8 +++--- prefork/prefork.go | 25 +++++++++++++----- tcplisten/tcplisten.go | 15 ++++++++++- 5 files changed, 74 insertions(+), 24 deletions(-) diff --git a/.github/workflows/security.yml b/.github/workflows/security.yml index c164891..56dc890 100644 --- a/.github/workflows/security.yml +++ b/.github/workflows/security.yml @@ -16,6 +16,6 @@ jobs: steps: - uses: actions/checkout@v6 - name: Run Gosec Security Scanner - uses: securego/gosec@v2.23.0 + uses: securego/gosec@v2.25.0 with: args: '-exclude=G103,G104,G304,G402 ./...' diff --git a/bytesconv.go b/bytesconv.go index f497c8e..7350e8b 100644 --- a/bytesconv.go +++ b/bytesconv.go @@ -85,24 +85,24 @@ func ParseIPv4(dst net.IP, ipStr []byte) (net.IP, error) { if n < 0 { return dst, fmt.Errorf("cannot find dot in ipStr %q", ipStr) } - v, err := ParseUint(b[:n]) + octet, parsed, err := parseIPv4Octet(b[:n]) if err != nil { + if errors.Is(err, errIPv4PartTooLarge) { + return dst, fmt.Errorf("cannot parse ipStr %q: ip part cannot exceed 255: parsed %d", ipStr, parsed) + } return dst, fmt.Errorf("cannot parse ipStr %q: %w", ipStr, err) } - if v > 255 { - return dst, fmt.Errorf("cannot parse ipStr %q: ip part cannot exceed 255: parsed %d", ipStr, v) - } - dst[i] = byte(v) + dst[i] = octet b = b[n+1:] } - v, err := ParseUint(b) + octet, parsed, err := parseIPv4Octet(b) if err != nil { + if errors.Is(err, errIPv4PartTooLarge) { + return dst, fmt.Errorf("cannot parse ipStr %q: ip part cannot exceed 255: parsed %d", ipStr, parsed) + } return dst, fmt.Errorf("cannot parse ipStr %q: %w", ipStr, err) } - if v > 255 { - return dst, fmt.Errorf("cannot parse ipStr %q: ip part cannot exceed 255: parsed %d", ipStr, v) - } - dst[3] = byte(v) + dst[3] = octet return dst, nil } @@ -141,6 +141,7 @@ func ParseUint(buf []byte) (int, error) { var ( errEmptyInt = errors.New("empty integer") + errIPv4PartTooLarge = errors.New("ip part cannot exceed 255") errUnexpectedFirstChar = errors.New("unexpected first char found. Expecting 0-9") errUnexpectedTrailingChar = errors.New("unexpected trailing char found. Expecting 0-9") errTooLongInt = errors.New("too long int") @@ -171,6 +172,33 @@ func parseUintBuf(b []byte) (int, int, error) { return v, n, nil } +func parseIPv4Octet(b []byte) (byte, int, error) { + if len(b) == 0 { + return 0, 0, errEmptyInt + } + + var ( + octet byte + parsed int + ) + for i := range len(b) { + c := b[i] + k := c - '0' + if k > 9 { + if i == 0 { + return 0, parsed, errUnexpectedFirstChar + } + return 0, parsed, errUnexpectedTrailingChar + } + parsed = parsed*10 + int(k) + if octet > 25 || (octet == 25 && k > 5) { + return 0, parsed, errIPv4PartTooLarge + } + octet = octet*10 + k + } + return octet, parsed, nil +} + // ParseUfloat parses unsigned float from buf. func ParseUfloat(buf []byte) (float64, error) { // The implementation of parsing a float string is not easy. diff --git a/peripconn.go b/peripconn.go index de8dcd9..8734fdb 100644 --- a/peripconn.go +++ b/peripconn.go @@ -2,6 +2,7 @@ package fasthttp import ( "crypto/tls" + "encoding/binary" "net" "sync" ) @@ -136,10 +137,7 @@ func ip2uint32(ip net.IP) uint32 { } func uint322ip(ip uint32) net.IP { - b := make([]byte, 4) - b[0] = byte(ip >> 24) - b[1] = byte(ip >> 16) - b[2] = byte(ip >> 8) - b[3] = byte(ip) + b := make(net.IP, net.IPv4len) + binary.BigEndian.PutUint32(b, ip) return b } diff --git a/prefork/prefork.go b/prefork/prefork.go index 0737815..ac90a67 100644 --- a/prefork/prefork.go +++ b/prefork/prefork.go @@ -136,13 +136,24 @@ func (p *Prefork) setTCPListenerFiles(addr string) error { } func (p *Prefork) doCommand() (*exec.Cmd, error) { - // #nosec G204 - cmd := exec.Command(os.Args[0], os.Args[1:]...) - cmd.Stdout = os.Stdout - cmd.Stderr = os.Stderr - cmd.Env = append(os.Environ(), preforkChildEnvVariable+"=1") - cmd.ExtraFiles = p.files - err := cmd.Start() + executable, err := os.Executable() + if err != nil { + return nil, err + } + + args := make([]string, len(os.Args)) + args[0] = executable + copy(args[1:], os.Args[1:]) + + cmd := &exec.Cmd{ + Path: executable, + Args: args, + Stdout: os.Stdout, + Stderr: os.Stderr, + Env: append(os.Environ(), preforkChildEnvVariable+"=1"), + ExtraFiles: p.files, + } + err = cmd.Start() return cmd, err } diff --git a/tcplisten/tcplisten.go b/tcplisten/tcplisten.go index c492360..fd94337 100644 --- a/tcplisten/tcplisten.go +++ b/tcplisten/tcplisten.go @@ -66,8 +66,14 @@ func (cfg *Config) NewListener(network, addr string) (net.Listener, error) { return nil, err } + fdUintptr, err := safeIntToUintptr(fd) + if err != nil { + unix.Close(fd) + return nil, fmt.Errorf("unexpected convert socket fd int to uintptr: %w", err) + } + name := fmt.Sprintf("reuseport.%d.%s.%s", os.Getpid(), network, addr) - file := os.NewFile(uintptr(fd), name) + file := os.NewFile(fdUintptr, name) ln, err := net.FileListener(file) if err != nil { file.Close() @@ -190,3 +196,10 @@ func safeIntToUint32(i int) (uint32, error) { } return uint32(ui), nil } + +func safeIntToUintptr(i int) (uintptr, error) { + if i < 0 { + return 0, errors.New("value is negative, cannot convert to uintptr") + } + return uintptr(i), nil +}