Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix crash (infinite recursion) when changing length of measure after frame #24562

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 11 additions & 4 deletions src/engraving/dom/durationtype.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -511,17 +511,17 @@ std::vector<TDuration> toRhythmicDurationList(const Fraction& l, bool isRest, Fr
dList.reserve(8);

if (msr->isAnacrusis()) {
rtickStart = Fraction::fromTicks(nominal.ticksPerMeasure()) - rtickStart;
rtickStart += msr->anacrusisOffset();
} else if (isRest && l == msr->ticks()) {
TDuration d = TDuration(DurationType::V_MEASURE);
dList.push_back(d);
return dList;
}

if (nominal.isCompound()) {
splitCompoundBeatsForList(&dList, l, isRest, rtickStart + msr->anacrusisOffset(), nominal, maxDots);
splitCompoundBeatsForList(&dList, l, isRest, rtickStart, nominal, maxDots);
} else {
populateRhythmicList(&dList, l, isRest, rtickStart + msr->anacrusisOffset(), nominal, maxDots);
populateRhythmicList(&dList, l, isRest, rtickStart, nominal, maxDots);
}

return dList;
Expand Down Expand Up @@ -595,8 +595,15 @@ void populateRhythmicList(std::vector<TDuration>* dList, const Fraction& l, bool
// no single TDuration fits so must split anyway
}

// Prevent infinite recursion if there is no splitting point other than the start and end ticks
IF_ASSERT_FAILED(rtickStart.ticks() < rtickSplit && rtickSplit < rtickEnd.ticks()) {
std::vector<TDuration> dList2 = toDurationList(l, maxDots > 0, maxDots, false);
dList->insert(dList->end(), dList2.begin(), dList2.end());
return;
}

// Split on the strongest beat or subbeat crossed
Fraction leftSplit = Fraction::fromTicks(rtickSplit) - rtickStart;
Fraction leftSplit = Fraction::fromTicks(rtickSplit) - rtickStart;
Fraction rightSplit = l - leftSplit;

// Recurse to see if we need to split further before adding to list
Expand Down
8 changes: 6 additions & 2 deletions src/engraving/dom/measure.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1801,8 +1801,12 @@ void Measure::adjustToLen(Fraction nf, bool appendRestsIfNecessary)
rest->undoChangeProperty(Pid::DURATION_TYPE_WITH_DOTS, DurationTypeWithDots(DurationType::V_MEASURE));
} else { // if measure value did change, represent with rests actual measure value
// convert the measure duration in a list of values (no dots for rests)
std::vector<TDuration> durList = toRhythmicDurationList(nf * stretch, true, tick(),
score()->sigmap()->timesig(tick().ticks()).nominal(), this, 0);
std::vector<TDuration> durList = toRhythmicDurationList(nf * stretch,
/*isRest=*/ true,
/*rtickStart=*/ Fraction(0, 1),
/*nominal=*/ score()->sigmap()->timesig(tick().ticks()).nominal(),
/*measure=*/ this,
/*maxDots=*/ 0);

// set the existing rest to the first value of the duration list
TDuration firstDur = durList[0];
Expand Down