github.com/khulnasoft-lab/tunnel-db@v0.0.0-20231117205118-74e1113bd007/pkg/vulnsrc/osv/range.go (about)

     1  package osv
     2  
     3  import (
     4  	"fmt"
     5  
     6  	mvn "github.com/masahiro331/go-mvn-version"
     7  	"golang.org/x/xerrors"
     8  
     9  	"github.com/khulnasoft-lab/go-gem-version"
    10  	"github.com/khulnasoft-lab/go-npm-version/pkg"
    11  	pep440 "github.com/khulnasoft-lab/go-pep440-version"
    12  	"github.com/khulnasoft-lab/goversion/pkg/semver"
    13  	"github.com/khulnasoft-lab/goversion/pkg/version"
    14  )
    15  
    16  type VersionRange interface {
    17  	Contains(ver string) (bool, error)
    18  	String() string
    19  	SetFixed(fixed string)
    20  	SetLastAffected(lastAffected string)
    21  }
    22  
    23  func NewVersionRange(ecosystem Ecosystem, from string) VersionRange {
    24  	vr := &versionRange{from: from}
    25  	switch ecosystem {
    26  	case EcosystemNpm:
    27  		return &NpmVersionRange{versionRange: vr}
    28  	case EcosystemRubygems:
    29  		return &RubyGemsVersionRange{versionRange: vr}
    30  	case EcosystemPyPI:
    31  		return &PyPIVersionRange{versionRange: vr}
    32  	case EcosystemMaven:
    33  		return &MavenVersionRange{versionRange: vr}
    34  	case EcosystemGo, EcosystemCrates, EcosystemNuGet:
    35  		return &SemVerRange{versionRange: vr}
    36  	case EcosystemPackagist:
    37  		return &DefaultVersionRange{versionRange: vr}
    38  	default:
    39  		return &DefaultVersionRange{versionRange: vr}
    40  	}
    41  }
    42  
    43  // versionRange represents a range of versions
    44  type versionRange struct {
    45  	from       string
    46  	to         string
    47  	toIncluded bool
    48  }
    49  
    50  // constraint returns the range as a constraint string in the expected
    51  // format for semver.NewConstraint
    52  func (r *versionRange) String() string {
    53  	// e.g. {"introduced": "1.2.0"}, {"last_affected": "1.2.0"}
    54  	if r.toIncluded && r.from == r.to {
    55  		return fmt.Sprintf("=%s", r.from)
    56  	}
    57  
    58  	var ver string
    59  	if r.to != "" {
    60  		ver = fmt.Sprintf("<%s", r.to)
    61  		if r.toIncluded {
    62  			ver = fmt.Sprintf("<=%s", r.to)
    63  		}
    64  	}
    65  
    66  	if ver == "" {
    67  		return fmt.Sprintf(">=%s", r.from)
    68  	}
    69  
    70  	// ">=0" can be omitted.
    71  	// e.g. {"introduced": "0", "fixed": "1.2.3"} => "<1.2.3"
    72  	if r.from == "0" {
    73  		return ver
    74  	}
    75  
    76  	return fmt.Sprintf(">=%s, %s", r.from, ver)
    77  }
    78  
    79  func (r *versionRange) SetFixed(fixed string) {
    80  	r.to = fixed
    81  	r.toIncluded = false
    82  }
    83  
    84  func (r *versionRange) SetLastAffected(lastAffected string) {
    85  	r.to = lastAffected
    86  	r.toIncluded = true
    87  }
    88  
    89  type DefaultVersionRange struct {
    90  	*versionRange
    91  }
    92  
    93  func (r *DefaultVersionRange) Contains(ver string) (bool, error) {
    94  	c, err := version.NewConstraints(r.String())
    95  	if err != nil {
    96  		return false, xerrors.Errorf("failed to parse version constraint: %w", err)
    97  	}
    98  
    99  	v, err := version.Parse(ver)
   100  	if err != nil {
   101  		return false, xerrors.Errorf("failed to parse version: %w", err)
   102  	}
   103  
   104  	return c.Check(v), nil
   105  }
   106  
   107  type SemVerRange struct {
   108  	*versionRange
   109  }
   110  
   111  func (r *SemVerRange) Contains(ver string) (bool, error) {
   112  	c, err := semver.NewConstraints(r.String())
   113  	if err != nil {
   114  		return false, xerrors.Errorf("failed to parse version constraint: %w", err)
   115  	}
   116  
   117  	v, err := semver.Parse(ver)
   118  	if err != nil {
   119  		return false, xerrors.Errorf("failed to parse version: %w", err)
   120  	}
   121  
   122  	return c.Check(v), nil
   123  }
   124  
   125  type NpmVersionRange struct {
   126  	*versionRange
   127  }
   128  
   129  func (r *NpmVersionRange) Contains(ver string) (bool, error) {
   130  	c, err := npm.NewConstraints(r.String())
   131  	if err != nil {
   132  		return false, xerrors.Errorf("failed to parse version constraint: %w", err)
   133  	}
   134  
   135  	v, err := npm.NewVersion(ver)
   136  	if err != nil {
   137  		return false, xerrors.Errorf("failed to parse version: %w", err)
   138  	}
   139  
   140  	return c.Check(v), nil
   141  }
   142  
   143  type RubyGemsVersionRange struct {
   144  	*versionRange
   145  }
   146  
   147  func (r *RubyGemsVersionRange) Contains(ver string) (bool, error) {
   148  	c, err := gem.NewConstraints(r.String())
   149  	if err != nil {
   150  		return false, xerrors.Errorf("failed to parse version constraint: %w", err)
   151  	}
   152  
   153  	v, err := gem.NewVersion(ver)
   154  	if err != nil {
   155  		return false, xerrors.Errorf("failed to parse version: %w", err)
   156  	}
   157  
   158  	return c.Check(v), nil
   159  }
   160  
   161  type PyPIVersionRange struct {
   162  	*versionRange
   163  }
   164  
   165  func (r *PyPIVersionRange) Contains(ver string) (bool, error) {
   166  	c, err := pep440.NewSpecifiers(r.String())
   167  	if err != nil {
   168  		return false, xerrors.Errorf("failed to parse version constraint: %w", err)
   169  	}
   170  
   171  	v, err := pep440.Parse(ver)
   172  	if err != nil {
   173  		return false, xerrors.Errorf("failed to parse version: %w", err)
   174  	}
   175  
   176  	return c.Check(v), nil
   177  }
   178  
   179  type MavenVersionRange struct {
   180  	*versionRange
   181  }
   182  
   183  func (r *MavenVersionRange) Contains(ver string) (bool, error) {
   184  	c, err := mvn.NewConstraints(r.String())
   185  	if err != nil {
   186  		return false, xerrors.Errorf("failed to parse version constraint: %w", err)
   187  	}
   188  
   189  	v, err := mvn.NewVersion(ver)
   190  	if err != nil {
   191  		return false, xerrors.Errorf("failed to parse version: %w", err)
   192  	}
   193  
   194  	return c.Check(v), nil
   195  }