From b7882f0b43714c0a60be1f1e810f7b5022947c05 Mon Sep 17 00:00:00 2001 From: Vladimir Smirnov Date: Thu, 16 Nov 2017 16:49:00 +0100 Subject: [PATCH] Add a sanity check for git ls-remote output This should fix panics for cases where `git ls-remote` contains unepxected lines (e.x. some extra warnings from ssh) Related to #1379 --- CHANGELOG.md | 1 + gps/vcs_source.go | 16 ++++++++++++++++ 2 files changed, 17 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index a3cd6e2efa..3acd01bddb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ BUG FIXES: * Releases targeting Windows now have a `.exe` suffix (#1291). * Adaptively recover from dirty and corrupted git repositories in cache (#1279). * Suppress git password prompts in more places (#1357). +* Validate `git ls-remote` output and ignore all malformed lines (#1379) IMPROVEMENTS: diff --git a/gps/vcs_source.go b/gps/vcs_source.go index 71f4cf8767..8deb33df4e 100644 --- a/gps/vcs_source.go +++ b/gps/vcs_source.go @@ -10,6 +10,7 @@ import ( "fmt" "os" "path/filepath" + "regexp" "strings" "github.com/Masterminds/semver" @@ -117,6 +118,10 @@ func (bs *baseVCSSource) exportRevisionTo(ctx context.Context, r Revision, to st return fs.CopyDir(bs.repo.LocalPath(), to) } +var ( + gitHashRE = regexp.MustCompile(`^[a-f0-9]{40}$`) +) + // gitSource is a generic git repository implementation that should work with // all standard git remotes. type gitSource struct { @@ -238,6 +243,10 @@ func (s *gitSource) exportRevisionTo(ctx context.Context, rev Revision, to strin return nil } +func (s *gitSource) isValidHash(hash []byte) bool { + return gitHashRE.Match(hash) +} + func (s *gitSource) listVersions(ctx context.Context) (vlist []PairedVersion, err error) { r := s.repo @@ -298,6 +307,13 @@ func (s *gitSource) listVersions(ctx context.Context) (vlist []PairedVersion, er vlist = make([]PairedVersion, len(all)) for _, pair := range all { var v PairedVersion + // Valid `git ls-remote` output should start with hash, be at least + // 45 chars long and 40th character should be '\t' + // + // See: https://github.com/golang/dep/pull/1160#issuecomment-328843519 + if len(pair) < 45 || pair[40] != '\t' || !s.isValidHash(pair[:40]) { + continue + } if string(pair[41:]) == "HEAD" { // If HEAD is present, it's always first headrev = Revision(pair[:40])