From 243d0e61b38247182cc39cd93745a5b365639ed9 Mon Sep 17 00:00:00 2001 From: Prabhu Subramanian Date: Fri, 8 Dec 2023 18:13:27 +0000 Subject: [PATCH] Update tools. go version plugin Signed-off-by: Prabhu Subramanian --- .github/workflows/release.yml | 8 +- .github/workflows/test.yml | 8 +- build.ps1 | 29 ++++--- build.sh | 27 ++++--- package-lock.json | 4 +- package.json | 2 +- packages/arm64/build-arm64.sh | 27 ++++--- packages/arm64/package.json | 2 +- packages/ppc64/package.json | 2 +- thirdparty/goversion/Makefile | 2 +- thirdparty/goversion/README.md | 5 +- thirdparty/goversion/file.go | 83 +++++++++++--------- thirdparty/goversion/io.go | 135 ++++++++++++++++++++++++++++++++ thirdparty/goversion/version.go | 114 ++++++--------------------- thirdparty/goversion/xcoff.go | 56 ++++++------- 15 files changed, 301 insertions(+), 203 deletions(-) create mode 100644 thirdparty/goversion/io.go diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 43c2432..43d113d 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -31,10 +31,10 @@ jobs: ${{ runner.os }}-go- - name: Release run: | - wget https://github.com/upx/upx/releases/download/v4.1.0/upx-4.1.0-amd64_linux.tar.xz - tar -xvf upx-4.1.0-amd64_linux.tar.xz - chmod +x upx-4.1.0-amd64_linux/upx - sudo cp upx-4.1.0-amd64_linux/upx /usr/local/bin/ + wget https://github.com/upx/upx/releases/download/v4.2.1/upx-4.2.1-amd64_linux.tar.xz + tar -xvf upx-4.2.1-amd64_linux.tar.xz + chmod +x upx-4.2.1-amd64_linux/upx + sudo cp upx-4.2.1-amd64_linux/upx /usr/local/bin/ npm config set //npm.pkg.github.com/:_authToken=$GITHUB_TOKEN npm config set //registry.npmjs.org/:_authToken=$NPMJS_AUTH_TOKEN bash build.sh diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 60798d1..7c46ffc 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -32,10 +32,10 @@ jobs: ${{ runner.os }}-go- - name: Build run: | - wget https://github.com/upx/upx/releases/download/v4.1.0/upx-4.1.0-amd64_linux.tar.xz - tar -xvf upx-4.1.0-amd64_linux.tar.xz - chmod +x upx-4.1.0-amd64_linux/upx - sudo cp upx-4.1.0-amd64_linux/upx /usr/local/bin/ + wget https://github.com/upx/upx/releases/download/v4.2.1/upx-4.2.1-amd64_linux.tar.xz + tar -xvf upx-4.2.1-amd64_linux.tar.xz + chmod +x upx-4.2.1-amd64_linux/upx + sudo cp upx-4.2.1-amd64_linux/upx /usr/local/bin/ bash build.sh pip3 install blint blint -i plugins -o /tmp/reports diff --git a/build.ps1 b/build.ps1 index 4b07aed..2a597df 100644 --- a/build.ps1 +++ b/build.ps1 @@ -1,14 +1,17 @@ New-Item -ItemType Directory -Path plugins\goversion -Force New-Item -ItemType Directory -Path plugins\cargo-auditable -Force New-Item -ItemType Directory -Path plugins\osquery -Force +New-Item -ItemType Directory -Path plugins\dosai -Force -Invoke-WebRequest -Uri https://github.com/upx/upx/releases/download/v4.1.0/upx-4.1.0-win64.zip -UseBasicParsing -OutFile upx-4.1.0-win64.zip -Expand-Archive -Path upx-4.1.0-win64.zip -DestinationPath . -Force +Invoke-WebRequest -Uri https://github.com/upx/upx/releases/download/v4.2.1/upx-4.2.1-win64.zip -UseBasicParsing -OutFile upx-4.2.1-win64.zip +Expand-Archive -Path upx-4.2.1-win64.zip -DestinationPath . -Force -Invoke-WebRequest -Uri https://github.com/osquery/osquery/releases/download/5.9.1/osquery-5.9.1.windows_x86_64.zip -UseBasicParsing -OutFile osquery-5.9.1.windows_x86_64.zip -Expand-Archive -Path osquery-5.9.1.windows_x86_64.zip -DestinationPath . -Force -copy "osquery-5.9.1.windows_x86_64\Program Files\osquery\osqueryi.exe" plugins\osquery\osqueryi-windows-amd64.exe -upx-4.1.0-win64\upx.exe -9 --lzma plugins\osquery\osqueryi-windows-amd64.exe +Invoke-WebRequest -Uri https://github.com/osquery/osquery/releases/download/5.10.2/osquery-5.10.2.windows_x86_64.zip -UseBasicParsing -OutFile osquery-5.10.2.windows_x86_64.zip +Expand-Archive -Path osquery-5.10.2.windows_x86_64.zip -DestinationPath . -Force +copy "osquery-5.10.2.windows_x86_64\Program Files\osquery\osqueryi.exe" plugins\osquery\osqueryi-windows-amd64.exe +upx-4.2.1-win64\upx.exe -9 --lzma plugins\osquery\osqueryi-windows-amd64.exe + +Invoke-WebRequest -Uri https://github.com/owasp-dep-scan/dosai/releases/latest/download/Dosai.exe -UseBasicParsing -OutFile plugins/dosai/dosai-windows-amd64.exe set CGO_ENABLED=0 set GOOS=windows @@ -16,7 +19,7 @@ set GOARCH=amd64 New-Item -ItemType Directory -Path plugins\goversion -Force cd thirdparty\goversion go build -ldflags "-H=windowsgui -s -w" -o build\goversion-windows-amd64.exe -..\..\upx-4.1.0-win64\upx.exe -9 --lzma build\goversion-windows-amd64.exe +..\..\upx-4.2.1-win64\upx.exe -9 --lzma build\goversion-windows-amd64.exe copy build\* ..\..\plugins\goversion\ Remove-Item build -Recurse -Force cd ..\.. @@ -24,7 +27,7 @@ cd ..\.. New-Item -ItemType Directory -Path plugins\cargo-auditable -Force cd thirdparty\cargo-auditable go build -ldflags "-H=windowsgui -s -w" -o build\cargo-auditable-windows-amd64.exe -..\..\upx-4.1.0-win64\upx.exe -9 --lzma build\cargo-auditable-windows-amd64.exe +..\..\upx-4.2.1-win64\upx.exe -9 --lzma build\cargo-auditable-windows-amd64.exe copy build\* ..\..\plugins\cargo-auditable\ Remove-Item build -Recurse -Force cd ..\.. @@ -32,12 +35,12 @@ cd ..\.. New-Item -ItemType Directory -Path plugins\trivy -Force cd thirdparty\trivy go build -ldflags "-H=windowsgui -s -w" -o build\trivy-windows-amd64.exe -..\..\upx-4.1.0-win64\upx.exe -9 --lzma build\trivy-windows-amd64.exe +..\..\upx-4.2.1-win64\upx.exe -9 --lzma build\trivy-windows-amd64.exe copy build\* ..\..\plugins\trivy\ Remove-Item build -Recurse -Force cd ..\.. -Remove-Item osquery-5.9.1.windows_x86_64 -Recurse -Force -Remove-Item osquery-5.9.1.windows_x86_64.zip -Recurse -Force -Remove-Item upx-4.1.0-win64 -Recurse -Force -Remove-Item upx-4.1.0-win64.zip -Recurse -Force +Remove-Item osquery-5.10.2.windows_x86_64 -Recurse -Force +Remove-Item osquery-5.10.2.windows_x86_64.zip -Recurse -Force +Remove-Item upx-4.2.1-win64 -Recurse -Force +Remove-Item upx-4.2.1-win64.zip -Recurse -Force diff --git a/build.sh b/build.sh index 04d4e98..4fd7d76 100755 --- a/build.sh +++ b/build.sh @@ -4,23 +4,32 @@ rm -rf plugins/goversion rm -rf plugins/trivy rm -rf plugins/cargo-auditable rm -rf plugins/osquery -mkdir -p plugins/osquery +rm -rf plugins/dosai +mkdir -p plugins/osquery plugins/dosai -wget https://github.com/osquery/osquery/releases/download/5.9.1/osquery-5.9.1.windows_x86_64.zip -unzip osquery-5.9.1.windows_x86_64.zip -cp "osquery-5.9.1.windows_x86_64/Program Files/osquery/osqueryi.exe" plugins/osquery/osqueryi-windows-amd64.exe +wget https://github.com/osquery/osquery/releases/download/5.10.2/osquery-5.10.2.windows_x86_64.zip +unzip osquery-5.10.2.windows_x86_64.zip +cp "osquery-5.10.2.windows_x86_64/Program Files/osquery/osqueryi.exe" plugins/osquery/osqueryi-windows-amd64.exe upx -9 --lzma plugins/osquery/osqueryi-windows-amd64.exe sha256sum plugins/osquery/osqueryi-windows-amd64.exe > plugins/osquery/osqueryi-windows-amd64.exe.sha256 -rm -rf osquery-5.9.1.windows_x86_64 -rm osquery-5.9.1.windows_x86_64.zip +rm -rf osquery-5.10.2.windows_x86_64 +rm osquery-5.10.2.windows_x86_64.zip -wget https://github.com/osquery/osquery/releases/download/5.9.1/osquery-5.9.1_1.linux_x86_64.tar.gz -tar -xvf osquery-5.9.1_1.linux_x86_64.tar.gz +wget https://github.com/osquery/osquery/releases/download/5.10.2/osquery-5.10.2_1.linux_x86_64.tar.gz +tar -xvf osquery-5.10.2_1.linux_x86_64.tar.gz cp opt/osquery/bin/osqueryd plugins/osquery/osqueryi-linux-amd64 upx -9 --lzma plugins/osquery/osqueryi-linux-amd64 sha256sum plugins/osquery/osqueryi-linux-amd64 > plugins/osquery/osqueryi-linux-amd64.sha256 rm -rf etc usr var opt -rm osquery-5.9.1_1.linux_x86_64.tar.gz +rm osquery-5.10.2_1.linux_x86_64.tar.gz + +curl -L https://github.com/owasp-dep-scan/dosai/releases/latest/download/Dosai -o plugins/dosai/dosai-linux-amd64 +chmod +x plugins/dosai/dosai-linux-amd64 +upx -9 --lzma plugins/dosai/dosai-linux-amd64 +sha256sum plugins/dosai/dosai-linux-amd64 > plugins/dosai/dosai-linux-amd64.sha256 + +curl -L https://github.com/owasp-dep-scan/dosai/releases/latest/download/Dosai.exe -o plugins/dosai/dosai-windows-amd64.exe +sha256sum plugins/dosai/dosai-windows-amd64.exe > plugins/dosai/dosai-windows-amd64.exe.sha256 for plug in goversion trivy cargo-auditable do diff --git a/package-lock.json b/package-lock.json index 4ec22bf..7ae22bd 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@cyclonedx/cdxgen-plugins-bin", - "version": "1.4.0", + "version": "1.5.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@cyclonedx/cdxgen-plugins-bin", - "version": "1.4.0", + "version": "1.5.0", "cpu": [ "x64" ], diff --git a/package.json b/package.json index b3d90b4..9b6d45a 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@cyclonedx/cdxgen-plugins-bin", - "version": "1.4.0", + "version": "1.5.0", "description": "Binary plugins to supercharge @cyclonedx/cdxgen npm package", "main": "index.js", "repository": { diff --git a/packages/arm64/build-arm64.sh b/packages/arm64/build-arm64.sh index a1d547f..b466711 100755 --- a/packages/arm64/build-arm64.sh +++ b/packages/arm64/build-arm64.sh @@ -4,22 +4,31 @@ rm -rf plugins/goversion rm -rf plugins/trivy rm -rf plugins/cargo-auditable rm -rf plugins/osquery -mkdir -p plugins/osquery +rm -rf plugins/dosai +mkdir -p plugins/osquery plugins/dosai -wget https://github.com/osquery/osquery/releases/download/5.9.1/osquery-5.9.1.windows_arm64.zip -unzip osquery-5.9.1.windows_arm64.zip -cp "osquery-5.9.1.windows_arm64/Program Files/osquery/osqueryi.exe" plugins/osquery/osqueryi-windows-arm64.exe +wget https://github.com/osquery/osquery/releases/download/5.10.2/osquery-5.10.2.windows_arm64.zip +unzip osquery-5.10.2.windows_arm64.zip +cp "osquery-5.10.2.windows_arm64/Program Files/osquery/osqueryi.exe" plugins/osquery/osqueryi-windows-arm64.exe sha256sum plugins/osquery/osqueryi-windows-arm64.exe > plugins/osquery/osqueryi-windows-arm64.exe.sha256 -rm -rf osquery-5.9.1.windows_arm64 -rm osquery-5.9.1.windows_arm64.zip +rm -rf osquery-5.10.2.windows_arm64 +rm osquery-5.10.2.windows_arm64.zip -wget https://github.com/osquery/osquery/releases/download/5.9.1/osquery-5.9.1_1.linux_aarch64.tar.gz -tar -xvf osquery-5.9.1_1.linux_aarch64.tar.gz +wget https://github.com/osquery/osquery/releases/download/5.10.2/osquery-5.10.2_1.linux_aarch64.tar.gz +tar -xvf osquery-5.10.2_1.linux_aarch64.tar.gz cp opt/osquery/bin/osqueryd plugins/osquery/osqueryi-linux-arm64 upx -9 --lzma plugins/osquery/osqueryi-linux-arm64 sha256sum plugins/osquery/osqueryi-linux-arm64 > plugins/osquery/osqueryi-linux-arm64.sha256 rm -rf etc usr var opt -rm osquery-5.9.1_1.linux_aarch64.tar.gz +rm osquery-5.10.2_1.linux_aarch64.tar.gz + +curl -L https://github.com/owasp-dep-scan/dosai/releases/latest/download/Dosai -o plugins/dosai/dosai-linux-arm64 +chmod +x plugins/dosai/dosai-linux-arm64 +upx -9 --lzma plugins/dosai/dosai-linux-arm64 +sha256sum plugins/dosai/dosai-linux-arm64 > plugins/dosai/dosai-linux-arm64.sha256 + +curl -L https://github.com/owasp-dep-scan/dosai/releases/latest/download/Dosai-windows-arm64.exe -o plugins/dosai/dosai-windows-arm64.exe +sha256sum plugins/dosai/dosai-windows-arm64.exe > plugins/dosai/dosai-windows-arm64.exe.sha256 for plug in goversion trivy cargo-auditable do diff --git a/packages/arm64/package.json b/packages/arm64/package.json index cbb1838..ec08a55 100644 --- a/packages/arm64/package.json +++ b/packages/arm64/package.json @@ -1,6 +1,6 @@ { "name": "@cyclonedx/cdxgen-plugins-bin-arm64", - "version": "1.4.0", + "version": "1.5.0", "description": "Arm64 binary plugins to supercharge @cyclonedx/cdxgen npm package", "main": "index.js", "repository": { diff --git a/packages/ppc64/package.json b/packages/ppc64/package.json index 4ad5c2a..09a677e 100644 --- a/packages/ppc64/package.json +++ b/packages/ppc64/package.json @@ -1,6 +1,6 @@ { "name": "@cyclonedx/cdxgen-plugins-bin-ppc64", - "version": "1.4.0", + "version": "1.5.0", "description": "ppc64 binary plugins to supercharge @cyclonedx/cdxgen npm package", "main": "index.js", "repository": { diff --git a/thirdparty/goversion/Makefile b/thirdparty/goversion/Makefile index be2637a..6117978 100644 --- a/thirdparty/goversion/Makefile +++ b/thirdparty/goversion/Makefile @@ -1,6 +1,6 @@ PATH := $(PATH):/usr/local/go/bin:$HOME/go/bin: appname := goversion -sources := version.go exe.go xcoff.go file.go +sources := version.go exe.go xcoff.go io.go file.go build = CGO_ENABLED=0 GOOS=$(1) GOARCH=$(2) go build -ldflags "-s -w -extldflags=-Wl,-z,now,-z,relro" -o build/$(appname)-$(1)-$(2)$(3) && upx -9 --lzma build/$(appname)-$(1)-$(2)$(3) || true sha = cd build && sha256sum $(appname)-$(1)-$(2)$(3) > $(appname)-$(1)-$(2)$(3).sha256 diff --git a/thirdparty/goversion/README.md b/thirdparty/goversion/README.md index 35e3d18..9174223 100644 --- a/thirdparty/goversion/README.md +++ b/thirdparty/goversion/README.md @@ -1,11 +1,12 @@ # Introduction -The files in this directory were copied from go binary distribution 1.16.5 +The files in this directory were copied from go binary distribution 1.21.4 ``` cp /usr/local/go/src/cmd/go/internal/version/*.go . cp /usr/local/go/src/internal/xcoff/xcoff.go . cp /usr/local/go/src/internal/xcoff/file.go . +cp /usr/local/go/src/internal/saferio/io.go . ``` -Few changes have been made to version.go to make the module compile +Few changes have been made to version.go and file.go to make the module compile diff --git a/thirdparty/goversion/file.go b/thirdparty/goversion/file.go index 068a7e0..e2131a8 100644 --- a/thirdparty/goversion/file.go +++ b/thirdparty/goversion/file.go @@ -167,12 +167,12 @@ func NewFile(r io.ReaderAt) (*File, error) { f.TargetMachine = magic // Read XCOFF file header - if _, err := sr.Seek(0, os.SEEK_SET); err != nil { + if _, err := sr.Seek(0, io.SeekStart); err != nil { return nil, err } var nscns uint16 var symptr uint64 - var nsyms int32 + var nsyms uint32 var opthdr uint16 var hdrsz int switch f.TargetMachine { @@ -204,7 +204,7 @@ func NewFile(r io.ReaderAt) (*File, error) { // Read string table (located right after symbol table). offset := symptr + uint64(nsyms)*SYMESZ - if _, err := sr.Seek(int64(offset), os.SEEK_SET); err != nil { + if _, err := sr.Seek(int64(offset), io.SeekStart); err != nil { return nil, err } // The first 4 bytes contain the length (in bytes). @@ -213,20 +213,22 @@ func NewFile(r io.ReaderAt) (*File, error) { return nil, err } if l > 4 { - if _, err := sr.Seek(int64(offset), os.SEEK_SET); err != nil { - return nil, err - } - f.StringTable = make([]byte, l) - if _, err := io.ReadFull(sr, f.StringTable); err != nil { + st, err := ReadDataAt(sr, uint64(l), int64(offset)) + if err != nil { return nil, err } + f.StringTable = st } // Read section headers - if _, err := sr.Seek(int64(hdrsz)+int64(opthdr), os.SEEK_SET); err != nil { + if _, err := sr.Seek(int64(hdrsz)+int64(opthdr), io.SeekStart); err != nil { return nil, err } - f.Sections = make([]*Section, nscns) + c := SliceCap((**Section)(nil), uint64(nscns)) + if c < 0 { + return nil, fmt.Errorf("too many XCOFF sections (%d)", nscns) + } + f.Sections = make([]*Section, 0, c) for i := 0; i < int(nscns); i++ { var scnptr uint64 s := new(Section) @@ -262,14 +264,14 @@ func NewFile(r io.ReaderAt) (*File, error) { } s.sr = io.NewSectionReader(r2, int64(scnptr), int64(s.Size)) s.ReaderAt = s.sr - f.Sections[i] = s + f.Sections = append(f.Sections, s) } // Symbol map needed by relocation var idxToSym = make(map[int]*Symbol) // Read symbol table - if _, err := sr.Seek(int64(symptr), os.SEEK_SET); err != nil { + if _, err := sr.Seek(int64(symptr), io.SeekStart); err != nil { return nil, err } f.Symbols = make([]*Symbol, 0) @@ -355,7 +357,7 @@ func NewFile(r io.ReaderAt) (*File, error) { // Read csect auxiliary entry (by convention, it is the last). if !needAuxFcn { - if _, err := sr.Seek(int64(numaux-1)*SYMESZ, os.SEEK_CUR); err != nil { + if _, err := sr.Seek(int64(numaux-1)*SYMESZ, io.SeekCurrent); err != nil { return nil, err } } @@ -382,41 +384,46 @@ func NewFile(r io.ReaderAt) (*File, error) { f.Symbols = append(f.Symbols, sym) skip: i += numaux // Skip auxiliary entries - if _, err := sr.Seek(int64(numaux)*SYMESZ, os.SEEK_CUR); err != nil { + if _, err := sr.Seek(int64(numaux)*SYMESZ, io.SeekCurrent); err != nil { return nil, err } } // Read relocations // Only for .data or .text section - for _, sect := range f.Sections { + for sectNum, sect := range f.Sections { if sect.Type != STYP_TEXT && sect.Type != STYP_DATA { continue } - sect.Relocs = make([]Reloc, sect.Nreloc) if sect.Relptr == 0 { continue } - if _, err := sr.Seek(int64(sect.Relptr), os.SEEK_SET); err != nil { + c := SliceCap((*Reloc)(nil), uint64(sect.Nreloc)) + if c < 0 { + return nil, fmt.Errorf("too many relocs (%d) for section %d", sect.Nreloc, sectNum) + } + sect.Relocs = make([]Reloc, 0, c) + if _, err := sr.Seek(int64(sect.Relptr), io.SeekStart); err != nil { return nil, err } for i := uint32(0); i < sect.Nreloc; i++ { + var reloc Reloc switch f.TargetMachine { case U802TOCMAGIC: rel := new(Reloc32) if err := binary.Read(sr, binary.BigEndian, rel); err != nil { return nil, err } - sect.Relocs[i].VirtualAddress = uint64(rel.Rvaddr) - sect.Relocs[i].Symbol = idxToSym[int(rel.Rsymndx)] - sect.Relocs[i].Type = rel.Rtype - sect.Relocs[i].Length = rel.Rsize&0x3F + 1 + reloc.VirtualAddress = uint64(rel.Rvaddr) + reloc.Symbol = idxToSym[int(rel.Rsymndx)] + reloc.Type = rel.Rtype + reloc.Length = rel.Rsize&0x3F + 1 if rel.Rsize&0x80 != 0 { - sect.Relocs[i].Signed = true + reloc.Signed = true } if rel.Rsize&0x40 != 0 { - sect.Relocs[i].InstructionFixed = true + reloc.InstructionFixed = true } case U64_TOCMAGIC: @@ -424,17 +431,19 @@ func NewFile(r io.ReaderAt) (*File, error) { if err := binary.Read(sr, binary.BigEndian, rel); err != nil { return nil, err } - sect.Relocs[i].VirtualAddress = rel.Rvaddr - sect.Relocs[i].Symbol = idxToSym[int(rel.Rsymndx)] - sect.Relocs[i].Type = rel.Rtype - sect.Relocs[i].Length = rel.Rsize&0x3F + 1 + reloc.VirtualAddress = rel.Rvaddr + reloc.Symbol = idxToSym[int(rel.Rsymndx)] + reloc.Type = rel.Rtype + reloc.Length = rel.Rsize&0x3F + 1 if rel.Rsize&0x80 != 0 { - sect.Relocs[i].Signed = true + reloc.Signed = true } if rel.Rsize&0x40 != 0 { - sect.Relocs[i].InstructionFixed = true + reloc.InstructionFixed = true } } + + sect.Relocs = append(sect.Relocs, reloc) } } @@ -508,11 +517,11 @@ func (f *File) DWARF() (*dwarf.Data, error) { // Library name pattern is either path/base/member or base/member func (f *File) readImportIDs(s *Section) ([]string, error) { // Read loader header - if _, err := s.sr.Seek(0, os.SEEK_SET); err != nil { + if _, err := s.sr.Seek(0, io.SeekStart); err != nil { return nil, err } var istlen uint32 - var nimpid int32 + var nimpid uint32 var impoff uint64 switch f.TargetMachine { case U802TOCMAGIC: @@ -534,7 +543,7 @@ func (f *File) readImportIDs(s *Section) ([]string, error) { } // Read loader import file ID table - if _, err := s.sr.Seek(int64(impoff), os.SEEK_SET); err != nil { + if _, err := s.sr.Seek(int64(impoff), io.SeekStart); err != nil { return nil, err } table := make([]byte, istlen) @@ -577,12 +586,12 @@ func (f *File) ImportedSymbols() ([]ImportedSymbol, error) { return nil, nil } // Read loader header - if _, err := s.sr.Seek(0, os.SEEK_SET); err != nil { + if _, err := s.sr.Seek(0, io.SeekStart); err != nil { return nil, err } var stlen uint32 var stoff uint64 - var nsyms int32 + var nsyms uint32 var symoff uint64 switch f.TargetMachine { case U802TOCMAGIC: @@ -606,7 +615,7 @@ func (f *File) ImportedSymbols() ([]ImportedSymbol, error) { } // Read loader section string table - if _, err := s.sr.Seek(int64(stoff), os.SEEK_SET); err != nil { + if _, err := s.sr.Seek(int64(stoff), io.SeekStart); err != nil { return nil, err } st := make([]byte, stlen) @@ -621,13 +630,13 @@ func (f *File) ImportedSymbols() ([]ImportedSymbol, error) { } // Read loader symbol table - if _, err := s.sr.Seek(int64(symoff), os.SEEK_SET); err != nil { + if _, err := s.sr.Seek(int64(symoff), io.SeekStart); err != nil { return nil, err } all := make([]ImportedSymbol, 0) for i := 0; i < int(nsyms); i++ { var name string - var ifile int32 + var ifile uint32 var ok bool switch f.TargetMachine { case U802TOCMAGIC: diff --git a/thirdparty/goversion/io.go b/thirdparty/goversion/io.go new file mode 100644 index 0000000..5be6a6b --- /dev/null +++ b/thirdparty/goversion/io.go @@ -0,0 +1,135 @@ +// Copyright 2022 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package saferio provides I/O functions that avoid allocating large +// amounts of memory unnecessarily. This is intended for packages that +// read data from an [io.Reader] where the size is part of the input +// data but the input may be corrupt, or may be provided by an +// untrustworthy attacker. +package main + +import ( + "io" + "reflect" +) + +// chunk is an arbitrary limit on how much memory we are willing +// to allocate without concern. +const chunk = 10 << 20 // 10M + +// ReadData reads n bytes from the input stream, but avoids allocating +// all n bytes if n is large. This avoids crashing the program by +// allocating all n bytes in cases where n is incorrect. +// +// The error is io.EOF only if no bytes were read. +// If an io.EOF happens after reading some but not all the bytes, +// ReadData returns io.ErrUnexpectedEOF. +func ReadData(r io.Reader, n uint64) ([]byte, error) { + if int64(n) < 0 || n != uint64(int(n)) { + // n is too large to fit in int, so we can't allocate + // a buffer large enough. Treat this as a read failure. + return nil, io.ErrUnexpectedEOF + } + + if n < chunk { + buf := make([]byte, n) + _, err := io.ReadFull(r, buf) + if err != nil { + return nil, err + } + return buf, nil + } + + var buf []byte + buf1 := make([]byte, chunk) + for n > 0 { + next := n + if next > chunk { + next = chunk + } + _, err := io.ReadFull(r, buf1[:next]) + if err != nil { + if len(buf) > 0 && err == io.EOF { + err = io.ErrUnexpectedEOF + } + return nil, err + } + buf = append(buf, buf1[:next]...) + n -= next + } + return buf, nil +} + +// ReadDataAt reads n bytes from the input stream at off, but avoids +// allocating all n bytes if n is large. This avoids crashing the program +// by allocating all n bytes in cases where n is incorrect. +func ReadDataAt(r io.ReaderAt, n uint64, off int64) ([]byte, error) { + if int64(n) < 0 || n != uint64(int(n)) { + // n is too large to fit in int, so we can't allocate + // a buffer large enough. Treat this as a read failure. + return nil, io.ErrUnexpectedEOF + } + + if n < chunk { + buf := make([]byte, n) + _, err := r.ReadAt(buf, off) + if err != nil { + // io.SectionReader can return EOF for n == 0, + // but for our purposes that is a success. + if err != io.EOF || n > 0 { + return nil, err + } + } + return buf, nil + } + + var buf []byte + buf1 := make([]byte, chunk) + for n > 0 { + next := n + if next > chunk { + next = chunk + } + _, err := r.ReadAt(buf1[:next], off) + if err != nil { + return nil, err + } + buf = append(buf, buf1[:next]...) + n -= next + off += int64(next) + } + return buf, nil +} + +// SliceCap returns the capacity to use when allocating a slice. +// After the slice is allocated with the capacity, it should be +// built using append. This will avoid allocating too much memory +// if the capacity is large and incorrect. +// +// A negative result means that the value is always too big. +// +// The element type is described by passing a pointer to a value of that type. +// This would ideally use generics, but this code is built with +// the bootstrap compiler which need not support generics. +// We use a pointer so that we can handle slices of interface type. +func SliceCap(v any, c uint64) int { + if int64(c) < 0 || c != uint64(int(c)) { + return -1 + } + typ := reflect.TypeOf(v) + if typ.Kind() != reflect.Ptr { + panic("SliceCap called with non-pointer type") + } + size := uint64(typ.Elem().Size()) + if size > 0 && c > (1<<64-1)/size { + return -1 + } + if c*size > chunk { + c = uint64(chunk / size) + if c == 0 { + c = 1 + } + } + return int(c) +} diff --git a/thirdparty/goversion/version.go b/thirdparty/goversion/version.go index 2d1fc6e..48689c9 100644 --- a/thirdparty/goversion/version.go +++ b/thirdparty/goversion/version.go @@ -2,18 +2,18 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// Package version implements the ``go version'' command. +// Package version implements the “go version” command. package main import ( - "bytes" - "encoding/binary" + "debug/buildinfo" "fmt" "io/fs" "os" "path/filepath" "runtime" "strings" + ) func main() { @@ -26,7 +26,7 @@ func runVersion(args []string) int { return 0 } - exitStatus := 0 + exitStatus := 0 for _, arg := range args { info, err := os.Stat(arg) if err != nil { @@ -43,13 +43,13 @@ func runVersion(args []string) int { return exitStatus } -// scanDir scans a directory for executables to run scanFile on. +// scanDir scans a directory for binary to run scanFile on. func scanDir(dir string) { filepath.WalkDir(dir, func(path string, d fs.DirEntry, err error) error { if d.Type().IsRegular() || d.Type()&fs.ModeSymlink != 0 { info, err := d.Info() if err != nil { - fmt.Fprintf(os.Stderr, "%s: %v\n", path, err) + fmt.Fprintf(os.Stderr, "%s: %v\n", path, err) return nil } scanFile(path, info) @@ -58,18 +58,24 @@ func scanDir(dir string) { }) } -// isExe reports whether the file should be considered executable. -func isExe(file string, info fs.FileInfo) bool { - if runtime.GOOS == "windows" { - return strings.HasSuffix(strings.ToLower(file), ".exe") +// isGoBinaryCandidate reports whether the file is a candidate to be a Go binary. +func isGoBinaryCandidate(file string, info fs.FileInfo) bool { + if info.Mode().IsRegular() && info.Mode()&0111 != 0 { + return true + } + name := strings.ToLower(file) + switch filepath.Ext(name) { + case ".so", ".exe", ".dll": + return true + default: + return strings.Contains(name, ".so.") } - return info.Mode().IsRegular() && info.Mode()&0111 != 0 } // scanFile scans file to try to report the Go and module versions. // If mustPrint is true, scanFile will report any error reading file. // Otherwise (mustPrint is false, because scanFile is being called -// by scanDir) scanFile prints nothing for non-Go executables. +// by scanDir) scanFile prints nothing for non-Go binaries. func scanFile(file string, info fs.FileInfo) { if info.Mode()&fs.ModeSymlink != 0 { // Accept file symlinks only. @@ -81,91 +87,17 @@ func scanFile(file string, info fs.FileInfo) { info = i } - if !isExe(file, info) { - fmt.Fprintf(os.Stderr, "%s: not executable file\n", file) - return - } - - x, err := openExe(file) + bi, err := buildinfo.ReadFile(file) if err != nil { fmt.Fprintf(os.Stderr, "%s: %v\n", file, err) return - } - defer x.Close() - - vers, mod := findVers(x) - if vers == "" { - fmt.Fprintf(os.Stderr, "%s: go version not found\n", file) return } - fmt.Printf("%s: %s\n", file, vers) - if mod != "" { + fmt.Printf("%s: %s\n", file, bi.GoVersion) + bi.GoVersion = "" // suppress printing go version again + mod := bi.String() + if len(mod) > 0 { fmt.Printf("\t%s\n", strings.ReplaceAll(mod[:len(mod)-1], "\n", "\n\t")) } } - -// The build info blob left by the linker is identified by -// a 16-byte header, consisting of buildInfoMagic (14 bytes), -// the binary's pointer size (1 byte), -// and whether the binary is big endian (1 byte). -var buildInfoMagic = []byte("\xff Go buildinf:") - -// findVers finds and returns the Go version and module version information -// in the executable x. -func findVers(x exe) (vers, mod string) { - // Read the first 64kB of text to find the build info blob. - text := x.DataStart() - data, err := x.ReadData(text, 64*1024) - if err != nil { - return - } - for ; !bytes.HasPrefix(data, buildInfoMagic); data = data[32:] { - if len(data) < 32 { - return - } - } - - // Decode the blob. - ptrSize := int(data[14]) - bigEndian := data[15] != 0 - var bo binary.ByteOrder - if bigEndian { - bo = binary.BigEndian - } else { - bo = binary.LittleEndian - } - var readPtr func([]byte) uint64 - if ptrSize == 4 { - readPtr = func(b []byte) uint64 { return uint64(bo.Uint32(b)) } - } else { - readPtr = bo.Uint64 - } - vers = readString(x, ptrSize, readPtr, readPtr(data[16:])) - if vers == "" { - return - } - mod = readString(x, ptrSize, readPtr, readPtr(data[16+ptrSize:])) - if len(mod) >= 33 && mod[len(mod)-17] == '\n' { - // Strip module framing. - mod = mod[16 : len(mod)-16] - } else { - mod = "" - } - return -} - -// readString returns the string at address addr in the executable x. -func readString(x exe, ptrSize int, readPtr func([]byte) uint64, addr uint64) string { - hdr, err := x.ReadData(addr, uint64(2*ptrSize)) - if err != nil || len(hdr) < 2*ptrSize { - return "" - } - dataAddr := readPtr(hdr) - dataLen := readPtr(hdr[ptrSize:]) - data, err := x.ReadData(dataAddr, dataLen) - if err != nil || uint64(len(data)) < dataLen { - return "" - } - return string(data) -} diff --git a/thirdparty/goversion/xcoff.go b/thirdparty/goversion/xcoff.go index 7b7d83c..8749bbd 100644 --- a/thirdparty/goversion/xcoff.go +++ b/thirdparty/goversion/xcoff.go @@ -8,9 +8,9 @@ package main type FileHeader32 struct { Fmagic uint16 // Target machine Fnscns uint16 // Number of sections - Ftimedat int32 // Time and date of file creation + Ftimedat uint32 // Time and date of file creation Fsymptr uint32 // Byte offset to symbol table start - Fnsyms int32 // Number of entries in symbol table + Fnsyms uint32 // Number of entries in symbol table Fopthdr uint16 // Number of bytes in optional header Fflags uint16 // Flags } @@ -18,11 +18,11 @@ type FileHeader32 struct { type FileHeader64 struct { Fmagic uint16 // Target machine Fnscns uint16 // Number of sections - Ftimedat int32 // Time and date of file creation + Ftimedat uint32 // Time and date of file creation Fsymptr uint64 // Byte offset to symbol table start Fopthdr uint16 // Number of bytes in optional header Fflags uint16 // Flags - Fnsyms int32 // Number of entries in symbol table + Fnsyms uint32 // Number of entries in symbol table } const ( @@ -109,19 +109,19 @@ const ( type SymEnt32 struct { Nname [8]byte // Symbol name Nvalue uint32 // Symbol value - Nscnum int16 // Section number of symbol + Nscnum uint16 // Section number of symbol Ntype uint16 // Basic and derived type specification - Nsclass int8 // Storage class of symbol - Nnumaux int8 // Number of auxiliary entries + Nsclass uint8 // Storage class of symbol + Nnumaux uint8 // Number of auxiliary entries } type SymEnt64 struct { Nvalue uint64 // Symbol value Noffset uint32 // Offset of the name in string table or .debug section - Nscnum int16 // Section number of symbol + Nscnum uint16 // Section number of symbol Ntype uint16 // Basic and derived type specification - Nsclass int8 // Storage class of symbol - Nnumaux int8 // Number of auxiliary entries + Nsclass uint8 // Storage class of symbol + Nnumaux uint8 // Number of auxiliary entries } const SYMESZ = 18 @@ -203,7 +203,7 @@ type AuxSect64 struct { // csect Auxiliary Entry. type AuxCSect32 struct { - Xscnlen int32 // Length or symbol table index + Xscnlen uint32 // Length or symbol table index Xparmhash uint32 // Offset of parameter type-check string Xsnhash uint16 // .typchk section number Xsmtyp uint8 // Symbol alignment and type @@ -218,7 +218,7 @@ type AuxCSect64 struct { Xsnhash uint16 // .typchk section number Xsmtyp uint8 // Symbol alignment and type Xsmclas uint8 // Storage-mapping class - Xscnlenhi int32 // Upper 4 bytes of length or symbol table index + Xscnlenhi uint32 // Upper 4 bytes of length or symbol table index Xpad uint8 // Unused Xauxtype uint8 // Type of auxiliary entry } @@ -274,22 +274,22 @@ const ( // Loader Header. type LoaderHeader32 struct { - Lversion int32 // Loader section version number - Lnsyms int32 // Number of symbol table entries - Lnreloc int32 // Number of relocation table entries + Lversion uint32 // Loader section version number + Lnsyms uint32 // Number of symbol table entries + Lnreloc uint32 // Number of relocation table entries Listlen uint32 // Length of import file ID string table - Lnimpid int32 // Number of import file IDs + Lnimpid uint32 // Number of import file IDs Limpoff uint32 // Offset to start of import file IDs Lstlen uint32 // Length of string table Lstoff uint32 // Offset to start of string table } type LoaderHeader64 struct { - Lversion int32 // Loader section version number - Lnsyms int32 // Number of symbol table entries - Lnreloc int32 // Number of relocation table entries + Lversion uint32 // Loader section version number + Lnsyms uint32 // Number of symbol table entries + Lnreloc uint32 // Number of relocation table entries Listlen uint32 // Length of import file ID string table - Lnimpid int32 // Number of import file IDs + Lnimpid uint32 // Number of import file IDs Lstlen uint32 // Length of string table Limpoff uint64 // Offset to start of import file IDs Lstoff uint64 // Offset to start of string table @@ -306,20 +306,20 @@ const ( type LoaderSymbol32 struct { Lname [8]byte // Symbol name or byte offset into string table Lvalue uint32 // Address field - Lscnum int16 // Section number containing symbol - Lsmtype int8 // Symbol type, export, import flags - Lsmclas int8 // Symbol storage class - Lifile int32 // Import file ID; ordinal of import file IDs + Lscnum uint16 // Section number containing symbol + Lsmtype uint8 // Symbol type, export, import flags + Lsmclas uint8 // Symbol storage class + Lifile uint32 // Import file ID; ordinal of import file IDs Lparm uint32 // Parameter type-check field } type LoaderSymbol64 struct { Lvalue uint64 // Address field Loffset uint32 // Byte offset into string table of symbol name - Lscnum int16 // Section number containing symbol - Lsmtype int8 // Symbol type, export, import flags - Lsmclas int8 // Symbol storage class - Lifile int32 // Import file ID; ordinal of import file IDs + Lscnum uint16 // Section number containing symbol + Lsmtype uint8 // Symbol type, export, import flags + Lsmclas uint8 // Symbol storage class + Lifile uint32 // Import file ID; ordinal of import file IDs Lparm uint32 // Parameter type-check field }