Skip to content

Fix infinite loop and force-unwrap panic in scheduler cancel/remove logic#586

Open
joshuahannan wants to merge 1 commit intomasterfrom
fix/scheduler-binary-search-and-remove-id
Open

Fix infinite loop and force-unwrap panic in scheduler cancel/remove logic#586
joshuahannan wants to merge 1 commit intomasterfrom
fix/scheduler-binary-search-and-remove-id

Conversation

@joshuahannan
Copy link
Member

@joshuahannan joshuahannan commented Mar 16, 2026

Summary

Two bugs found during a security audit of the scheduler contracts:

  • FlowTransactionScheduler.cdccancelTransaction uses a binary search to maintain a sorted canceledTransactions array. When a duplicate ID is detected, a CriticalIssue event was emitted but neither low nor high was updated, making the while low < high loop infinite and exhausting all execution effort. Added a break after the event emit.

  • FlowTransactionSchedulerUtils.cdcremoveID called ids.remove(at: index!) where index is the result of firstIndex(of:), which returns nil if the element is not found. Any state inconsistency between idsByTimestamp and the tracked transactions would cause a panic. Changed to a safe if let guard.

Test plan

  • All Cadence tests pass (make test)
  • All Go tests pass (make -C lib/go test)
  • CI check-tidy passes (Go assets regenerated via make generate)

🤖 Generated with Claude Code

…ogic

FlowTransactionScheduler.cdc: The binary search in cancelTransaction had no
break when a duplicate ID was detected, leaving low/high unchanged and
creating an infinite loop that exhausted all execution effort.

FlowTransactionSchedulerUtils.cdc: removeID force-unwrapped the result of
firstIndex(of:) without a nil check. If the ID was absent from the ids
array due to any state inconsistency, the transaction would panic. Changed
to a safe if-let guard.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

if midCanceledID == id {
emit CriticalIssue(message: "Invalid ID: \(id) transaction already in canceled transactions array")
break
Copy link
Collaborator

Choose a reason for hiding this comment

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

should we just exit the function here?

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