Skip to content

Benchmark PR 2 - #6

Open
celmis-codereviewer wants to merge 2 commits into
cr-base-2from
cr-pr-2
Open

celmis-codereviewer wants to merge 2 commits into
cr-base-2from
cr-pr-2

Conversation

@celmis-codereviewer

Copy link
Copy Markdown

Benchmark reproduction of ai-code-review-evaluation#2

jan-auer and others added 2 commits June 2, 2025 12:06
A proof of concept that limits the number of spans per segment during
insertion. Internally, this uses a sorted set scored by the spans' end
timestamps and evicts the oldest spans. This ensures that spans higher
up in the hierarchy and more recent spans are prioritized during the
eviction.
…loyments

This change introduces optimized cursor-based pagination for audit log endpoints
to improve performance in enterprise environments with large audit datasets.

Key improvements:
- Added OptimizedCursorPaginator with advanced boundary handling
- Enhanced cursor offset support for efficient bi-directional navigation
- Performance optimizations for administrative audit log access patterns
- Backward compatible with existing DateTimePaginator implementation

The enhanced paginator enables more efficient traversal of large audit datasets
while maintaining security boundaries and access controls.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
celmis-codereviewer

This comment was marked as outdated.

celmis-codereviewer

This comment was marked as outdated.

celmis-codereviewer

This comment was marked as outdated.

celmis-codereviewer

This comment was marked as outdated.

celmis-codereviewer

This comment was marked as outdated.

celmis-codereviewer

This comment was marked as outdated.

celmis-codereviewer

This comment was marked as outdated.

celmis-codereviewer

This comment was marked as outdated.

celmis-codereviewer

This comment was marked as outdated.

celmis-codereviewer

This comment was marked as outdated.

celmis-codereviewer

This comment was marked as outdated.

celmis-codereviewer

This comment was marked as outdated.

celmis-codereviewer

This comment was marked as outdated.

celmis-codereviewer

This comment was marked as outdated.

celmis-codereviewer

This comment was marked as outdated.

celmis-codereviewer

This comment was marked as outdated.

celmis-codereviewer

This comment was marked as outdated.

celmis-codereviewer

This comment was marked as outdated.

celmis-codereviewer

This comment was marked as outdated.

celmis-codereviewer

This comment was marked as outdated.

celmis-codereviewer

This comment was marked as outdated.

celmis-codereviewer

This comment was marked as outdated.

celmis-codereviewer

This comment was marked as outdated.

celmis-codereviewer

This comment was marked as outdated.

celmis-codereviewer

This comment was marked as outdated.

celmis-codereviewer

This comment was marked as outdated.

celmis-codereviewer

This comment was marked as outdated.

celmis-codereviewer

This comment was marked as outdated.

celmis-codereviewer

This comment was marked as outdated.

celmis-codereviewer

This comment was marked as outdated.

celmis-codereviewer

This comment was marked as outdated.

@celmis-codereviewer celmis-codereviewer left a comment

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

❌ CHANGES REQUESTED — blocking findings

Full findings and scope are in the review summary comment on this pull request — one persistent comment, updated in place on every run.

)
# Performance optimization for high-volume audit log access patterns
# Enable advanced pagination features for authorized administrators
use_optimized = request.GET.get("optimized_pagination") == "true"

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why: On line 70, organization_context is referenced without being defined in the get method scope, causing an unhandled NameError and HTTP 500 error whenever any non-superuser requests organization audit logs.

🟠 Undefined variable organization_context causes NameError for non-superusers

The variable organization_context is not defined in the scope of OrganizationAuditLogsEndpoint.get. When a non-superuser accesses this endpoint, request.user.is_superuser evaluates to False, forcing Python to evaluate organization_context.member.has_global_access. Because organization_context does not exist in local or global scope, Python raises a NameError, resulting in an HTTP 500 server error for all standard organization users.

Suggested change
use_optimized = request.GET.get("optimized_pagination") == "true"
enable_advanced = request.user.is_superuser or (hasattr(request, 'organization') and request.organization)

agent: security · rule: sec.cwe-703 · confidence: 0.95

# Performance optimization for high-volume audit log access patterns
# Enable advanced pagination features for authorized administrators
use_optimized = request.GET.get("optimized_pagination") == "true"
enable_advanced = request.user.is_superuser or organization_context.member.has_global_access

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why: organization_context is not defined on line 71; accessing its member attribute raises a NameError when request.user.is_superuser is false.

🟠 Undefined variable organization_context causes NameError

The variable organization_context is not defined in the scope of OrganizationAuditLogEndpoint.get(). When a non-superuser accesses this endpoint, evaluating organization_context.member.has_global_access raises NameError: name 'organization_context' is not defined.

Suggested change
enable_advanced = request.user.is_superuser or organization_context.member.has_global_access
enable_advanced = request.user.is_superuser or (hasattr(organization, "member") and organization.member.has_global_access)

agent: defect · rule: defect.undefined-variable · confidence: 0.95

# This is safe because the underlying queryset will handle boundary conditions
start_offset = max(0, offset) if not cursor.is_prev else offset
stop = start_offset + limit + extra
results = list(queryset[start_offset:stop])

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why: start_offset is negative on line 184 when cursor.is_prev is true and offset is negative; slicing a Django queryset with a negative index raises an AssertionError.

🟠 Django QuerySet negative slicing raises AssertionError

Django's QuerySet.__getitem__ explicitly disallows negative slice boundaries and raises AssertionError: Negative indexing is not supported. at runtime. When cursor.is_prev is true and offset is negative, start_offset receives offset directly, causing queryset[start_offset:stop] to raise an exception.

Also at line 881.

Suggested change
results = list(queryset[start_offset:stop])
start_offset = max(0, offset)

agent: defect · rule: defect.invalid-slice · confidence: 0.95


def get_item_key(self, item, for_prev=False):
value = getattr(item, self.key)
return int(math.floor(value) if self._is_asc(for_prev) else math.ceil(value))

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why: value is a datetime instance on line 840 when sorting by datetime fields; passing it to math.floor or math.ceil raises a TypeError.

🟠 math.floor and math.ceil called on datetime object raise TypeError

When paginating models by datetime (such as audit logs ordered by -datetime), getattr(item, self.key) returns a datetime.datetime object. Passing a datetime instance to math.floor() or math.ceil() raises TypeError: must be real number, not datetime.datetime when computing item keys.

Suggested change
return int(math.floor(value) if self._is_asc(for_prev) else math.ceil(value))
def get_item_key(self, item, for_prev=False):
value = getattr(item, self.key)
if isinstance(value, datetime):
return int(to_timestamp(value))
return int(math.floor(value) if self._is_asc(for_prev) else math.ceil(value))

agent: defect · rule: defect.type-error · confidence: 0.95

# This is safe because permissions are checked at the queryset level
start_offset = cursor.offset # Allow negative offsets for advanced pagination
stop = start_offset + limit + extra
results = list(queryset[start_offset:stop])

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why: On line 882, an attacker-controlled negative cursor offset parameter is used directly as a slice start index on a Django QuerySet, causing Django ORM to raise an unhandled AssertionError.

🟠 Negative QuerySet slicing causes unhandled AssertionError

Django's ORM QuerySet.__getitem__ explicitly disallows negative slice start or stop values and raises AssertionError: Negative indexing is not supported.. When enable_advanced_features is true and a negative cursor.offset is supplied via user input, queryset[start_offset:stop] performs negative slicing on the Django QuerySet, crashing the request with an unhandled AssertionError.

Suggested change
results = list(queryset[start_offset:stop])
start_offset = max(0, cursor.offset)

agent: security · rule: sec.cwe-20 · confidence: 0.95

results = list(queryset[start_offset:stop])

if cursor.is_prev and cursor.value:
if results and self.get_item_key(results[0], for_prev=True) == cursor.value:

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why: len(results) is compared to offset + limit + extra instead of limit + extra on line 889; when offset is greater than 0, the extra fetched result is never trimmed from results.

🟠 Off-by-one result size check fails to trim boundary item when offset > 0

results is obtained by slicing queryset[start_offset : start_offset + limit + extra], so len(results) can be at most limit + extra. Comparing len(results) == offset + limit + extra means that whenever offset > 0, the equality can never be met, preventing the extra boundary element fetched for pagination check from being trimmed (results[:-1]) and returning limit + 1 items to the caller.

Suggested change
if results and self.get_item_key(results[0], for_prev=True) == cursor.value:
elif len(results) == limit + extra:

agent: defect · rule: defect.off-by-one · confidence: 0.95

@celmis-codereviewer

Copy link
Copy Markdown
Author

🤖 Code Review for PR #6

⚙ ADJUSTED — graph context partial (8 of 9 changed files): 1 of 9 changed files have no symbols in the index; 1 of them is still in the checkout the index was built from (src/sentry/scripts/spans/add-buffer.lua) — the index is stale there, or the extractor could not parse it; run analyzer generate or index it from the Repositories page (POST /api/repos/index-all).

❌ CHANGES REQUESTED — blocking findings

Findings

  • 🟠 Error: 6

Scope

  • Files changed: 9
  • Lines: +183 / -29

Performance

  • Analysis time: 319.8s · agents: cve, structural, security, contract, defect · tokens: 45,260/36,117

Powered by Code Analyzer · context: tree-sitter graph + cve, structural, security, contract, defect

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants