Skip to content

Commit 3eab3e9

Browse files
committed
Update the patches api to use two queries
Simplify the code structure Prepare the patch data outside the loop Signed-off-by: ziad hany <ziadhany2016@gmail.com>
1 parent c486942 commit 3eab3e9

1 file changed

Lines changed: 88 additions & 57 deletions

File tree

vulnerabilities/api_v3.py

Lines changed: 88 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -11,14 +11,12 @@
1111
from urllib.parse import urlencode
1212

1313
from django.contrib.postgres.aggregates import ArrayAgg
14-
from django.contrib.postgres.aggregates import JSONBAgg
1514
from django.db.models import Exists
1615
from django.db.models import F
1716
from django.db.models import Max
1817
from django.db.models import OuterRef
1918
from django.db.models import Prefetch
2019
from django.db.models import Q
21-
from django.db.models.functions import JSONObject
2220
from django_filters import rest_framework as filters
2321
from drf_spectacular.utils import extend_schema
2422
from packageurl import PackageURL
@@ -458,71 +456,94 @@ class AffectedByAdvisoriesViewSet(PackageAdvisoriesViewSet):
458456

459457
def get_patches_bulk(package_ids, advisory_ids):
460458
"""Get introduced and fixed patches"""
461-
patches_query = (
462-
ImpactedPackageAffecting.objects.filter(
463-
package_id__in=package_ids,
464-
impacted_package__advisory_id__in=advisory_ids,
465-
impacted_package__advisory__is_latest=True,
466-
impacted_package__advisory___all_impacts_unfurled_at__isnull=False,
467-
)
468-
.filter(
469-
Q(impacted_package__introduced_by_package_commit_patches__isnull=False)
470-
| Q(impacted_package__fixed_by_package_commit_patches__isnull=False)
471-
)
472-
.values(
473-
"package_id",
474-
"impacted_package__advisory_id",
475-
introduced_commit_hash=F(
476-
"impacted_package__introduced_by_package_commit_patches__commit_hash"
477-
),
478-
introduced_vcs_url=F("impacted_package__introduced_by_package_commit_patches__vcs_url"),
479-
fixed_commit_hash=F("impacted_package__fixed_by_package_commit_patches__commit_hash"),
480-
fixed_vcs_url=F("impacted_package__fixed_by_package_commit_patches__vcs_url"),
481-
)
482-
.distinct()
483-
.order_by()
459+
460+
base_qs = ImpactedPackageAffecting.objects.filter(
461+
package_id__in=package_ids,
462+
impacted_package__advisory_id__in=advisory_ids,
463+
impacted_package__advisory__is_latest=True,
464+
impacted_package__advisory___all_impacts_unfurled_at__isnull=False,
465+
)
466+
467+
introduced_rows = base_qs.filter(
468+
impacted_package__introduced_by_package_commit_patches__isnull=False
469+
).values(
470+
"package_id",
471+
"impacted_package__advisory_id",
472+
commit_hash=F("impacted_package__introduced_by_package_commit_patches__commit_hash"),
473+
vcs_url=F("impacted_package__introduced_by_package_commit_patches__vcs_url"),
474+
)
475+
476+
fixed_rows = base_qs.filter(
477+
impacted_package__fixed_by_package_commit_patches__isnull=False
478+
).values(
479+
"package_id",
480+
"impacted_package__advisory_id",
481+
commit_hash=F("impacted_package__fixed_by_package_commit_patches__commit_hash"),
482+
vcs_url=F("impacted_package__fixed_by_package_commit_patches__vcs_url"),
484483
)
485484

486485
introduced_patches_map = defaultdict(list)
487486
fixed_patches_map = defaultdict(list)
488487

489-
for row in patches_query:
490-
key = (row["package_id"], row["impacted_package__advisory_id"])
491-
492-
if row["introduced_commit_hash"] or row["introduced_vcs_url"]:
488+
for row in introduced_rows:
489+
if row["commit_hash"] or row["vcs_url"]:
490+
key = (row["package_id"], row["impacted_package__advisory_id"])
493491
introduced_patches_map[key].append(
494492
{
495-
"commit_hash": row["introduced_commit_hash"],
496-
"vcs_url": row["introduced_vcs_url"],
493+
"commit_hash": row["commit_hash"],
494+
"vcs_url": row["vcs_url"],
497495
}
498496
)
499497

500-
if row["fixed_commit_hash"] or row["fixed_vcs_url"]:
498+
for row in fixed_rows:
499+
if row["commit_hash"] or row["vcs_url"]:
500+
key = (row["package_id"], row["impacted_package__advisory_id"])
501501
fixed_patches_map[key].append(
502502
{
503-
"commit_hash": row["fixed_commit_hash"],
504-
"vcs_url": row["fixed_vcs_url"],
503+
"commit_hash": row["commit_hash"],
504+
"vcs_url": row["vcs_url"],
505505
}
506506
)
507507

508508
return introduced_patches_map, fixed_patches_map
509509

510510

511-
def collect_patches(patches_map, package_id, advisory_ids):
512-
"""Merge and dedupe patch entries from patches_map for all advisory_ids_set"""
513-
seen = set()
514-
collected = []
515-
if not patches_map or not advisory_ids or not package_id:
516-
return []
511+
def build_patch_set_map(patches_map, advisory_ids_by_set):
512+
"""
513+
Returns:
514+
{
515+
advisory_set_id: [
516+
{
517+
"commit_hash": "...",
518+
"vcs_url": "...",
519+
}
520+
]
521+
}
522+
"""
523+
result = {}
524+
525+
for advisory_set_id, advisory_ids in advisory_ids_by_set.items():
526+
seen = set()
527+
collected = []
517528

518-
for advisory_id in advisory_ids:
519-
for patch in patches_map.get((package_id, advisory_id), []):
520-
patch_key = (patch["commit_hash"], patch["vcs_url"])
521-
if patch_key in seen:
529+
for (package_id, advisory_id), patches in patches_map.items():
530+
if advisory_id not in advisory_ids:
522531
continue
523-
seen.add(patch_key)
524-
collected.append(patch)
525-
return collected
532+
533+
for patch in patches:
534+
key = (
535+
patch["commit_hash"],
536+
patch["vcs_url"],
537+
)
538+
539+
if key in seen:
540+
continue
541+
542+
seen.add(key)
543+
collected.append(patch)
544+
545+
result[advisory_set_id] = collected
546+
return result
526547

527548

528549
def get_affected_advisories_bulk(packages, max_advisories, base_url, reachability=False):
@@ -618,13 +639,23 @@ def get_affected_advisories_bulk(packages, max_advisories, base_url, reachabilit
618639
advisory_ids_by_set[advisory_set_id].add(advisory_id)
619640
all_advisory_ids.add(advisory_id)
620641

642+
introduced_patches_by_set = {}
643+
fixed_patches_by_set = {}
621644
if reachability:
622645
introduced_patches_map, fixed_patches_map = get_patches_bulk(
623646
package_ids,
624647
advisory_ids=all_advisory_ids,
625648
)
626-
else:
627-
introduced_patches_map, fixed_patches_map = {}, {}
649+
650+
introduced_patches_by_set = build_patch_set_map(
651+
introduced_patches_map,
652+
advisory_ids_by_set,
653+
)
654+
655+
fixed_patches_by_set = build_patch_set_map(
656+
fixed_patches_map,
657+
advisory_ids_by_set,
658+
)
628659

629660
ssvc_rows = (
630661
SSVC.objects.filter(
@@ -730,11 +761,13 @@ def get_affected_advisories_bulk(packages, max_advisories, base_url, reachabilit
730761
"exploitability": exploitability,
731762
"risk_score": risk_score,
732763
"fixed_by_packages": fixed_by_packages,
733-
"introduced_in_patch": collect_patches(
734-
introduced_patches_map, package.id, advisory_ids_by_set.get(adv.id, {})
764+
"introduced_in_patch": introduced_patches_by_set.get(
765+
adv.id,
766+
[],
735767
),
736-
"fixed_in_patch": collect_patches(
737-
fixed_patches_map, package.id, advisory_ids_by_set.get(adv.id, {})
768+
"fixed_in_patch": fixed_patches_by_set.get(
769+
adv.id,
770+
[],
738771
),
739772
"ssvc_trees": adv.ssvc_trees,
740773
"resource_url": resource_url,
@@ -831,10 +864,8 @@ def get_affected_advisories_bulk(packages, max_advisories, base_url, reachabilit
831864
"exploitability": advisory.exploitability,
832865
"risk_score": advisory.risk_score,
833866
"fixed_by_packages": fixed_by_packages,
834-
"introduced_in_patch": introduced_patches_map.get(
835-
(package.id, advisory_id), []
836-
),
837-
"fixed_in_patch": fixed_patches_map.get((package.id, advisory_id), []),
867+
"introduced_in_patch": introduced_patches_by_set.get(advisory_id, []),
868+
"fixed_in_patch": introduced_patches_by_set.get(advisory_id, []),
838869
"ssvc_trees": [
839870
{
840871
"vector": ssvc.vector,

0 commit comments

Comments
 (0)