func RPMDefsToVulns(ctx context.Context, root *oval.Root, protoVulns ProtoVulnsFunc) ([]*claircore.Vulnerability, error) {
	log := zerolog.Ctx(ctx).With().
		Str("component", "ovalutil/RPMDefsToVulns").
		Logger()
	ctx = log.WithContext(ctx)
	vulns := make([]*claircore.Vulnerability, 0, 10000)
	cris := []*oval.Criterion{}
	for _, def := range root.Definitions.Definitions {
		// create our prototype vulnerability
		protoVulns, err := protoVulns(def)
		if err != nil {
			log.Debug().
				Err(err).
				Str("def_id", def.ID).
				Msg("could not create prototype vulnerabilities")
			continue
		}
		// recursively collect criterions for this definition
		cris := cris[:0]
		walkCriterion(ctx, &def.Criteria, &cris)
		enabledModules := getEnabledModules(cris)
		if len(enabledModules) == 0 {
			// add default empty module
			enabledModules = append(enabledModules, "")
		}
		// unpack criterions into vulnerabilities
		for _, criterion := range cris {
			// if test object is not rmpinfo_test the provided test is not
			// associated with a package. this criterion will be skipped.
			test, err := TestLookup(root, criterion.TestRef, func(kind string) bool {
				if kind != "rpminfo_test" {
					return false
				}
				return true
			})
			switch {
			case errors.Is(err, nil):
			case errors.Is(err, errTestSkip):
				continue
			default:
				log.Debug().Str("test_ref", criterion.TestRef).Msg("test ref lookup failure. moving to next criterion")
				continue
			}

			objRefs := test.ObjectRef()
			stateRefs := test.StateRef()

			// from the rpminfo_test specification found here: https://oval.mitre.org/language/version5.7/ovaldefinition/documentation/linux-definitions-schema.html
			// "The required object element references a rpminfo_object and the optional state element specifies the data to check.
			//  The evaluation of the test is guided by the check attribute that is inherited from the TestType."
			//
			// thus we *should* only need to care about a single rpminfo_object and optionally a state object providing the package's fixed-in version.

			objRef := objRefs[0].ObjectRef
			object, err := rpmObjectLookup(root, objRef)
			switch {
			case errors.Is(err, nil):
			case errors.Is(err, errObjectSkip):
				// We only handle rpminfo_objects.
				continue
			default:
				log.Debug().
					Err(err).
					Str("object_ref", objRef).
					Msg("failed object lookup. moving to next criterion")
				continue
			}

			// state refs are optional, so this is not a requirement.
			// if a state object is discovered, we can use it to find
			// the "fixed-in-version"
			var state *oval.RPMInfoState
			if len(stateRefs) > 0 {
				stateRef := stateRefs[0].StateRef
				state, err = rpmStateLookup(root, stateRef)
				if err != nil {
					log.Debug().
						Err(err).
						Str("state_ref", stateRef).
						Msg("failed state lookup. moving to next criterion")
					continue
				}
				// if we find a state, but this state does not contain an EVR,
				// we are not looking at a linux package.
				if state.EVR == nil {
					continue
				}
			}

			for _, module := range enabledModules {
				for _, protoVuln := range protoVulns {
					vuln := *protoVuln
					vuln.Package = &claircore.Package{
						Name:   object.Name,
						Module: module,
						Kind:   claircore.BINARY,
					}
					if state != nil {
						vuln.FixedInVersion = state.EVR.Body
						if state.Arch != nil {
							vuln.ArchOperation = mapArchOp(state.Arch.Operation)
							vuln.Package.Arch = state.Arch.Body
						}
					}
					vulns = append(vulns, &vuln)
				}
			}
		}
	}

	return vulns, nil
}
// RPMDefsToVulns iterates over the definitions in an oval root and assumes RPMInfo objects and states.
//
// Each Criterion encountered with an EVR string will be translated into a claircore.Vulnerability
RPMDefsToVulns iterates over the definitions in an oval root and assumes RPMInfo objects and states.

Each Criterion encountered with an EVR string will be translated into a claircore.Vulnerability
// RPMDefsToVulns iterates over the definitions in an oval root and assumes RPMInfo objects and states . // // Each Criterion encountered with an EVR string will be translated into a claircore . Vulnerability
func RPMDefsToVulns(ctx context.Context, root *oval.Root, protoVulns ProtoVulnsFunc) ([]*claircore.Vulnerability, error) {
	log := zerolog.Ctx(ctx).With().
		Str("component", "ovalutil/RPMDefsToVulns").
		Logger()
	ctx = log.WithContext(ctx)
	vulns := make([]*claircore.Vulnerability, 0, 10000)
	cris := []*oval.Criterion{}
	for _, def := range root.Definitions.Definitions {
		protoVulns, err := protoVulns(def)
		if err != nil {
			log.Debug().
				Err(err).
				Str("def_id", def.ID).
				Msg("could not create prototype vulnerabilities")
			continue
		}
		cris := cris[:0]
		walkCriterion(ctx, &def.Criteria, &cris)
		enabledModules := getEnabledModules(cris)
		if len(enabledModules) == 0 {
			enabledModules = append(enabledModules, "")
		}
		for _, criterion := range cris {
			test, err := TestLookup(root, criterion.TestRef, func(kind string) bool {
				if kind != "rpminfo_test" {
					return false
				}
				return true
			})
			switch {
			case errors.Is(err, nil):
			case errors.Is(err, errTestSkip):
				continue
			default:
				log.Debug().Str("test_ref", criterion.TestRef).Msg("test ref lookup failure. moving to next criterion")
				continue
			}
			objRefs := test.ObjectRef()
			stateRefs := test.StateRef()
			 thus we *should* only need to care about a single rpminfo_object and optionally a state object providing the package's fixed-in version.
			objRef := objRefs[0].ObjectRef
			object, err := rpmObjectLookup(root, objRef)
			switch {
			case errors.Is(err, nil):
			case errors.Is(err, errObjectSkip):
				 We only handle rpminfo_objects.
				continue
			default:
				log.Debug().
					Err(err).
					Str("object_ref", objRef).
					Msg("failed object lookup. moving to next criterion")
				continue
			}
			 state refs are optional, so this is not a requirement.
			 if a state object is discovered, we can use it to find
			 the "fixed-in-version"
			var state *oval.RPMInfoState
			if len(stateRefs) > 0 {
				stateRef := stateRefs[0].StateRef
				state, err = rpmStateLookup(root, stateRef)
				if err != nil {
					log.Debug().
						Err(err).
						Str("state_ref", stateRef).
						Msg("failed state lookup. moving to next criterion")
					continue
				}
				 if we find a state, but this state does not contain an EVR,
				 we are not looking at a linux package.
				if state.EVR == nil {
					continue
				}
			}
			for _, module := range enabledModules {
				for _, protoVuln := range protoVulns {
					vuln := *protoVuln
					vuln.Package = &claircore.Package{
						Name:   object.Name,
						Module: module,
						Kind:   claircore.BINARY,
					}
					if state != nil {
						vuln.FixedInVersion = state.EVR.Body
						if state.Arch != nil {
							vuln.ArchOperation = mapArchOp(state.Arch.Operation)
							vuln.Package.Arch = state.Arch.Body
						}
					}
					vulns = append(vulns, &vuln)
				}
			}
		}
	}
	return vulns, nil
}
func RPMDefsToVulns ( ctx context . Context , root * oval . Root , protoVulns ProtoVulnsFunc ) ( [ ] * claircore . Vulnerability , error ) { log := zerolog . Ctx ( ctx ) . With ( ) . Str ( " " , " " ) . Logger ( ) ctx = log . WithContext ( ctx ) vulns := make ( [ ] * claircore . Vulnerability , 0 , 10000 ) cris := [ ] * oval . Criterion { } for _ , def := range root . Definitions . Definitions { protoVulns , err := protoVulns ( def ) if err != nil { log . Debug ( ) . Err ( err ) . Str ( " " , def . ID ) . Msg ( " " ) continue } cris := cris [ : 0 ] walkCriterion ( ctx , & def . Criteria , & cris ) enabledModules := getEnabledModules ( cris ) if len ( enabledModules ) == 0 { enabledModules = append ( enabledModules , " " ) } for _ , criterion := range cris { test , err := TestLookup ( root , criterion . TestRef , func ( kind string ) bool { if kind != " " { return false } return true } ) switch { case errors . Is ( err , nil ) : case errors . Is ( err , errTestSkip ) : continue default : log . Debug ( ) . Str ( " " , criterion . TestRef ) . Msg ( " " ) continue } objRefs := test . ObjectRef ( ) stateRefs := test . StateRef ( ) objRef := objRefs [ 0 ] . ObjectRef object , err := rpmObjectLookup ( root , objRef ) switch { case errors . Is ( err , nil ) : case errors . Is ( err , errObjectSkip ) : continue default : log . Debug ( ) . Err ( err ) . Str ( " " , objRef ) . Msg ( " " ) continue } var state * oval . RPMInfoState if len ( stateRefs ) > 0 { stateRef := stateRefs [ 0 ] . StateRef state , err = rpmStateLookup ( root , stateRef ) if err != nil { log . Debug ( ) . Err ( err ) . Str ( " " , stateRef ) . Msg ( " " ) continue } if state . EVR == nil { continue } } for _ , module := range enabledModules { for _ , protoVuln := range protoVulns { vuln := * protoVuln vuln . Package = & claircore . Package { Name : object . Name , Module : module , Kind : claircore . BINARY , } if state != nil { vuln . FixedInVersion = state . EVR . Body if state . Arch != nil { vuln . ArchOperation = mapArchOp ( state . Arch . Operation ) vuln . Package . Arch = state . Arch . Body } } vulns = append ( vulns , & vuln ) } } } } return vulns , nil }
RPMDefsToVulns iterates over the definitions in an oval root and assumes RPMInfo objects and states.
RPMDefsToVulns iterates over the definitions in an oval root and assumes RPMInfo objects and states .
// create our prototype vulnerability // recursively collect criterions for this definition // add default empty module // unpack criterions into vulnerabilities // if test object is not rmpinfo_test the provided test is not // associated with a package. this criterion will be skipped. // from the rpminfo_test specification found here: https://oval.mitre.org/language/version5.7/ovaldefinition/documentation/linux-definitions-schema.html // "The required object element references a rpminfo_object and the optional state element specifies the data to check. //  The evaluation of the test is guided by the check attribute that is inherited from the TestType." // // thus we *should* only need to care about a single rpminfo_object and optionally a state object providing the package's fixed-in version. // We only handle rpminfo_objects. // state refs are optional, so this is not a requirement. // if a state object is discovered, we can use it to find // the "fixed-in-version" // if we find a state, but this state does not contain an EVR, // we are not looking at a linux package.