From c58a6d6115dbaaa1a1bc68839637c33007cf4f66 Mon Sep 17 00:00:00 2001 From: 94xhn <87560781+94xhn@users.noreply.github.com> Date: Fri, 17 Jul 2026 01:33:52 +0800 Subject: [PATCH] Fix off-by-one OOB table read in Sample::next() Sample::next() used a strict > comparison (phase_fractional > endpos_fractional) to decide when to wrap/finish playback, while isPlaying() already treats phase_fractional == endpos_fractional as finished (using <). When phase lands exactly on endpos_fractional (which happens deterministically for many freq/table-size ratios), next() would compute index = endpos_fractional >> SAMPLE_F_BITS == NUM_TABLE_CELLS, one past the last valid table entry, and read (and for INTERP_LINEAR, also read index+1) out of bounds before wrapping on the following call. Change the comparison to >= so next() treats phase == endpos as finished/wrap, consistent with isPlaying(), eliminating the out-of-bounds table read. --- Sample.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Sample.h b/Sample.h index 30a2d60ef..2cb9f8a47 100644 --- a/Sample.h +++ b/Sample.h @@ -164,7 +164,7 @@ class Sample inline int8_t next() { // 4us - if (phase_fractional>endpos_fractional){ + if (phase_fractional>=endpos_fractional){ if (looping) { phase_fractional = startpos_fractional + (phase_fractional - endpos_fractional); }else{