From a5a03c77bf0842e0592d2be8129bca0b2bd3bb60 Mon Sep 17 00:00:00 2001 From: cui fliter Date: Tue, 5 Dec 2023 11:38:06 +0800 Subject: [PATCH] Fix exception when file type contains colon (#817) Signed-off-by: cui fliter Co-authored-by: Alexey Alexandrov --- internal/driver/fetch.go | 24 +++++++++++++++--------- internal/driver/fetch_test.go | 22 +++++++++++++++++++--- 2 files changed, 34 insertions(+), 12 deletions(-) diff --git a/internal/driver/fetch.go b/internal/driver/fetch.go index 584c5d85..95204a39 100644 --- a/internal/driver/fetch.go +++ b/internal/driver/fetch.go @@ -492,17 +492,23 @@ mapping: func fetch(source string, duration, timeout time.Duration, ui plugin.UI, tr http.RoundTripper) (p *profile.Profile, src string, err error) { var f io.ReadCloser - if sourceURL, timeout := adjustURL(source, duration, timeout); sourceURL != "" { - ui.Print("Fetching profile over HTTP from " + sourceURL) - if duration > 0 { - ui.Print(fmt.Sprintf("Please wait... (%v)", duration)) + // First determine whether the source is a file, if not, it will be treated as a URL. + if _, openErr := os.Stat(source); openErr == nil { + if isPerfFile(source) { + f, err = convertPerfData(source, ui) + } else { + f, err = os.Open(source) } - f, err = fetchURL(sourceURL, timeout, tr) - src = sourceURL - } else if isPerfFile(source) { - f, err = convertPerfData(source, ui) } else { - f, err = os.Open(source) + sourceURL, timeout := adjustURL(source, duration, timeout) + if sourceURL != "" { + ui.Print("Fetching profile over HTTP from " + sourceURL) + if duration > 0 { + ui.Print(fmt.Sprintf("Please wait... (%v)", duration)) + } + f, err = fetchURL(sourceURL, timeout, tr) + src = sourceURL + } } if err == nil { defer f.Close() diff --git a/internal/driver/fetch_test.go b/internal/driver/fetch_test.go index 8a6a5535..c3d04b61 100644 --- a/internal/driver/fetch_test.go +++ b/internal/driver/fetch_test.go @@ -192,12 +192,28 @@ func TestFetch(t *testing.T) { type testcase struct { source, execName string } - - for _, tc := range []testcase{ + ts := []testcase{ {path + "go.crc32.cpu", ""}, {path + "go.nomappings.crash", "/bin/gotest.exe"}, {"http://localhost/profile?file=cppbench.cpu", ""}, - } { + } + // Test that paths with a colon character are recognized as file paths + // if the file exists, rather than as a URL. We have to skip this test + // on Windows since the colon char is not allowed in Windows paths. + if runtime.GOOS != "windows" { + src := filepath.Join(path, "go.crc32.cpu") + dst := filepath.Join(t.TempDir(), "go.crc32.cpu_2023-11-11_01:02:03") + data, err := os.ReadFile(src) + if err != nil { + t.Fatalf("read src file %s failed: %#v", src, err) + } + err = os.WriteFile(dst, data, 0644) + if err != nil { + t.Fatalf("create dst file %s failed: %#v", dst, err) + } + ts = append(ts, testcase{dst, ""}) + } + for _, tc := range ts { p, _, _, err := grabProfile(&source{ExecName: tc.execName}, tc.source, nil, testObj{}, &proftest.TestUI{T: t}, &httpTransport{}) if err != nil { t.Fatalf("%s: %s", tc.source, err)