Skip to content

refactor: prevent array index out of bounds - #56

Closed
deepsource-autofix[bot] wants to merge 1 commit into
mainfrom
deepsource-autofix-7f048bc3
Closed

refactor: prevent array index out of bounds#56
deepsource-autofix[bot] wants to merge 1 commit into
mainfrom
deepsource-autofix-7f048bc3

Conversation

@deepsource-autofix

Copy link
Copy Markdown

This PR refactors the loop conditions to ensure safe traversal of the source array and eliminate potential out-of-bounds access.

  • Array index possibly out of bounds: The original code allowed the loop index to reach src.length (using i <= src.length), causing an attempt to access src[src.length] which is undefined. We updated the loop condition to i < src.length and adjusted the break check to i === src.length - 1 to confine iteration strictly within valid array indices.

This Autofix was generated by AI. Please review the change before merging.

This PR refactors the loop conditions to ensure safe traversal of the source array and eliminate potential out-of-bounds access.

- Array index possibly out of bounds: The original code allowed the loop index to reach `src.length` (using `i <= src.length`), causing an attempt to access `src[src.length]` which is undefined. We updated the loop condition to `i < src.length` and adjusted the break check to `i === src.length - 1` to confine iteration strictly within valid array indices.

> This Autofix was generated by AI. Please review the change before merging.
@carochacs carochacs self-assigned this Aug 7, 2026
@deepsource-io

deepsource-io Bot commented Aug 7, 2026

Copy link
Copy Markdown

DeepSource Code Review

We reviewed changes in 371d7a4...249d6e5 on this pull request. Below is the summary for the review, and you can see the individual issues we found as inline review comments.

See full review on DeepSource ↗

PR Report Card

Overall Grade   Security  

Reliability  

Complexity  

Hygiene  

Code Review Summary

Analyzer Status Updated (UTC) Details
Docker Aug 7, 2026 4:16a.m. Review ↗
Python Aug 7, 2026 4:16a.m. Review ↗
JavaScript Aug 7, 2026 4:16a.m. Review ↗

Important

AI Review is run only on demand for your team. We're only showing results of static analysis review right now. To trigger AI Review, comment @deepsourcebot review on this thread.

@pullfrog pullfrog Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Caution

This PR breaks the default 2D highway for any chart containing chords. Moving the boundary break to i === src.length - 1 means the final chain's last element is never written to _chordRenderInfo, and pass 2 of _ensureChordRenderCache dereferences that entry unconditionally — so every chart with at least one chord throws a TypeError and chord rendering (plus everything drawn after chords) breaks.

Reviewed changes

  • _ensureChordRenderCache chain pass (static/js/highway-draw.js) — replaced the i <= src.length sentinel loop with i < src.length plus a boundary break at i === src.length - 1, in response to a DeepSource "array index possibly out of bounds" warning.

Pullfrog  | Fix all ➔Fix 👍s ➔View workflow run | Using Big Pickle (free) | 𝕏

Comment thread static/js/highway-draw.js
Comment on lines +1169 to +1170
for (let i = 0; i < src.length; i++) {
const breakHere = (i === src.length - 1) ||

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

This breaks the default 2D highway for every chart that has chords. The break now fires at the last index, but the flush body covers [chainStart, i-1], so the final chord never gets a _chordRenderInfo entry — and pass 2 (line 1199) dereferences info unconditionally, throwing TypeError: Cannot set properties of undefined (setting 'baseFret').

I verified this against the real module: every non-empty chord array (single chord, two/three same-chain, final-chain-of-one) crashes; the original i <= src.length sentinel flushed [chainStart, src.length-1] and worked. The DeepSource warning was a false positive — at i === src.length the i === src.length clause short-circuits before src[i] is ever read.

Technical details
# Preserve the trailing-chain flush without an OOB-looking sentinel

## Affected sites
- static/js/highway-draw.js:1169-1192 — pass 1 never writes `_chordRenderInfo` for the last element of the array
- static/js/highway-draw.js:1199-1227 — pass 2 reads `info` unconditionally (line 1209 `info.baseFret = minF`) → TypeError on any missing entry
- static/highway.js:688 — `drawChords` runs inside the default renderer's try/catch (line 705), so the crash logs `draw error:` and skips `drawFretNumbers`, plugin draw hooks, and lyrics every frame the last chord is visible

## Required outcome
- Every chord gets a render-cache entry; the final chain is flushed including its last element; and `src[i]` accesses stay strictly in-bounds so the static analyzer stays satisfied.

## Suggested approach
Decide the break from the NEXT element instead of sentineling at the boundary, so the flush covers `[chainStart, i]` inclusive:

```js
for (let i = 0; i < src.length; i++) {
    const next = src[i + 1];
    const breakHere = next === undefined ||
        (next.id !== src[i].id || Math.abs(next.t - src[i].t) >= CHAIN_GAP_THRESHOLD);
    if (breakHere) {
        const len = i - chainStart + 1;
        for (let k = chainStart; k <= i; k++) {
            /* existing per-chord entry construction */
        }
        chainStart = i + 1;
    }
}
```

This is behavior-identical to the original: a gap/id-change between `i` and `i+1` flushes `[chainStart, i]` exactly as the old sentinel did, and the final element is flushed when `next === undefined`. The `i > chainStart` guard can be dropped — the flush is always non-empty. (`src[i + 1]` at the last index is a safe `undefined` comparison, so no analyzer false positive.)

@carochacs carochacs closed this Aug 7, 2026
@carochacs
carochacs deleted the deepsource-autofix-7f048bc3 branch August 7, 2026 04:25
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.

1 participant