Skip to content

Commit e07ab6c

Browse files
author
Luca Toniolo
committed
Fix uninitialized read in bezier9MaxCurvature when called via bezier9InitFast
bezier9MaxCurvature iterated the dκ/ds and 9D dκ/ds loops up to BEZIER9_ARC_LENGTH_SAMPLES (1024) regardless of how many samples were actually populated. bezier9InitFast fills only SAMPLES_FAST (32) entries of t_table[]/s_table[], leaving slots [33..1024] holding uninitialized stack memory from the caller. Reading those slots produced garbage max_dkappa_ds values that depended on prior call-stack contents. Since max_dkappa_ds feeds the centripetal jerk cap v_jerk = cbrt(j_max * dt / max_dkappa_ds) inside the blend optimizer, the resulting blend v_plan was history-dependent: the same gcode produced different execution times depending on what tolerance the previous program used (different prior runs left different stack patterns, creating multiple stable timing fixed points). Fix: clamp the loop bound to b->arc_samples for both the 3D and 9D curvature-rate scans, with a safety fallback to the full size if the field is out of range. Introduced by 43516ac "Fast bezier init for blend optimizer".
1 parent 806a593 commit e07ab6c

File tree

1 file changed

+11
-2
lines changed

1 file changed

+11
-2
lines changed

src/emc/motion_planning/bezier9.cc

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -768,9 +768,17 @@ int bezier9MaxCurvature(Bezier9 * const b)
768768
// Compute max |dκ/ds| using arc-length table nodes.
769769
// The curvature rate determines the centripetal jerk = v³ · dκ/ds,
770770
// which must be bounded for smooth motion at blend entry/exit.
771+
//
772+
// Loop bound MUST be b->arc_samples, not BEZIER9_ARC_LENGTH_SAMPLES.
773+
// bezier9InitFast populates only SAMPLES_FAST entries; reading past that
774+
// returns uninitialized stack memory and produces non-deterministic
775+
// max_dkappa_ds values that depend on prior call-stack contents.
776+
int n_samples = b->arc_samples;
777+
if (n_samples <= 0 || n_samples > BEZIER9_ARC_LENGTH_SAMPLES)
778+
n_samples = BEZIER9_ARC_LENGTH_SAMPLES;
771779
double max_dkds = 0.0;
772780
double prev_kappa = bezier9Curvature(b, 0.0);
773-
for (int i = 1; i <= BEZIER9_ARC_LENGTH_SAMPLES; i++) {
781+
for (int i = 1; i <= n_samples; i++) {
774782
double kappa_i = bezier9Curvature(b, b->t_table[i]);
775783
double ds = b->s_table[i] - b->s_table[i - 1];
776784
if (ds > BEZIER9_MIN_LENGTH) {
@@ -788,9 +796,10 @@ int bezier9MaxCurvature(Bezier9 * const b)
788796
// axes change rapidly through the blend, max_dkappa_ds (xyz-only) is
789797
// near zero while the actual joint-space jerk from the Jacobian-
790798
// amplified rotary curvature is large. max_dkappa_ds_9d captures this.
799+
// Same loop-bound rule as above.
791800
double max_dkds_9d = 0.0;
792801
double prev_kappa_9d = bezier9Curvature9D(b, 0.0);
793-
for (int i = 1; i <= BEZIER9_ARC_LENGTH_SAMPLES; i++) {
802+
for (int i = 1; i <= n_samples; i++) {
794803
double kappa_9d_i = bezier9Curvature9D(b, b->t_table[i]);
795804
double ds_i = b->s_table[i] - b->s_table[i - 1];
796805
if (ds_i > BEZIER9_MIN_LENGTH) {

0 commit comments

Comments
 (0)