Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

fix: incorrect conversion between integer types #2605

Merged
merged 7 commits into from
Feb 7, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 18 additions & 4 deletions syft/format/syftjson/to_syft_model.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ package syftjson

import (
"fmt"
"io/fs"
"math"
"os"
"path"
"strconv"
Expand Down Expand Up @@ -76,14 +78,12 @@ func toSyftFiles(files []model.File) sbom.Artifacts {
for _, f := range files {
coord := f.Location
if f.Metadata != nil {
mode, err := strconv.ParseInt(strconv.Itoa(f.Metadata.Mode), 8, 64)
fm, err := safeFileModeConvert(f.Metadata.Mode)
if err != nil {
log.Warnf("invalid mode found in file catalog @ location=%+v mode=%q: %+v", coord, f.Metadata.Mode, err)
mode = 0
fm = 0
}

fm := os.FileMode(mode)

ret.FileMetadata[coord] = file.Metadata{
FileInfo: stereoscopeFile.ManualInfo{
NameValue: path.Base(coord.RealPath),
Expand Down Expand Up @@ -135,6 +135,20 @@ func toSyftFiles(files []model.File) sbom.Artifacts {
return ret
}

func safeFileModeConvert(val int) (fs.FileMode, error) {
if val < math.MinInt32 || val > math.MaxInt32 {
// Value is out of the range that int32 can represent
return 0, fmt.Errorf("value %d is out of the range that int32 can represent", val)
}

// Safe to convert to os.FileMode
mode, err := strconv.ParseInt(strconv.Itoa(val), 8, 64)
if err != nil {
return 0, err
}
return os.FileMode(mode), nil
}

func toSyftLicenses(m []model.License) (p []pkg.License) {
for _, l := range m {
p = append(p, pkg.License{
Expand Down
45 changes: 45 additions & 0 deletions syft/format/syftjson/to_syft_model_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@ package syftjson

import (
"errors"
"io/fs"
"math"
"os"
"testing"

"github.com/stretchr/testify/assert"
Expand Down Expand Up @@ -471,3 +474,45 @@ func Test_deduplicateErrors(t *testing.T) {
})
}
}

func Test_safeFileModeConvert(t *testing.T) {
tests := []struct {
name string
val int
want fs.FileMode
wantErr bool
}{
{
// fs.go ModePerm 511 = FileMode = 0777 // Unix permission bits :192
name: "valid perm",
val: 777,
want: os.FileMode(511), // 777 in octal equals 511 in decimal
wantErr: false,
},
{
name: "outside int32 high",
val: int(math.MaxInt32) + 1,
want: 0,
wantErr: true,
},
{
name: "outside int32 low",
val: int(math.MinInt32) - 1,
want: 0,
wantErr: true,
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got, err := safeFileModeConvert(tt.val)
if tt.wantErr {
assert.Error(t, err)
assert.Equal(t, tt.want, got)
return
}
assert.NoError(t, err)
assert.Equal(t, tt.want, got)
})
}
}
Loading