Skip to content

Commit

Permalink
Fix #331840: Crash creating 4-or-higher tuplet on a 512th
Browse files Browse the repository at this point in the history
 or an 8-or-higher tuplet on a 256th

Sort of a backport of musescore#11560 (without the `std::gcd()` part) and musescore#11561.
  • Loading branch information
Jojo-Schmitz committed Mar 5, 2023
1 parent 7a0375c commit 69c7820
Show file tree
Hide file tree
Showing 3 changed files with 25 additions and 11 deletions.
6 changes: 4 additions & 2 deletions libmscore/edit.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2765,7 +2765,10 @@ void Score::cmdCreateTuplet(ChordRest* ocr, Tuplet* tuplet)
{
int track = ocr->track();
Measure* measure = ocr->measure();
Fraction tick = ocr->tick();
Fraction tick = ocr->tick();
Fraction an = (tuplet->ticks() * tuplet->ratio()) / tuplet->baseLen().fraction();
if (!an.denominator())
return;

if (ocr->tuplet())
tuplet->setTuplet(ocr->tuplet());
Expand All @@ -2785,7 +2788,6 @@ void Score::cmdCreateTuplet(ChordRest* ocr, Tuplet* tuplet)
else
cr = new Rest(this);

Fraction an = (tuplet->ticks() * tuplet->ratio()) / tuplet->baseLen().fraction();
int actualNotes = an.numerator() / an.denominator();

tuplet->setTrack(track);
Expand Down
25 changes: 17 additions & 8 deletions libmscore/fraction.h
Original file line number Diff line number Diff line change
Expand Up @@ -99,13 +99,18 @@ class Fraction {
void reduce()
{
const int g = gcd(_numerator, _denominator);
_numerator /= g; _denominator /= g;
if (g) {
_numerator /= g;
_denominator /= g;
}
}

Fraction reduced() const
{
const int g = gcd(_numerator, _denominator);
return Fraction(_numerator / g, _denominator / g);
if (g)
return Fraction(_numerator / g, _denominator / g);
return Fraction(_numerator, _denominator);
}

// --- comparison --- //
Expand Down Expand Up @@ -148,9 +153,11 @@ class Fraction {
_numerator += val._numerator; // Common enough use case to be handled separately for efficiency
else {
const int g = gcd(_denominator, val._denominator);
const int m1 = val._denominator / g; // This saves one division over straight lcm
_numerator = _numerator * m1 + val._numerator * (_denominator / g);
_denominator = m1 * _denominator;
if (g) {
const int m1 = val._denominator / g; // This saves one division over straight lcm
_numerator = _numerator * m1 + val._numerator * (_denominator / g);
_denominator = m1 * _denominator;
}
}
return *this;
}
Expand All @@ -161,9 +168,11 @@ class Fraction {
_numerator -= val._numerator; // Common enough use case to be handled separately for efficiency
else {
const int g = gcd(_denominator, val._denominator);
const int m1 = val._denominator / g; // This saves one division over straight lcm
_numerator = _numerator * m1 - val._numerator * (_denominator / g);
_denominator = m1 * _denominator;
if (g) {
const int m1 = val._denominator / g; // This saves one division over straight lcm
_numerator = _numerator * m1 - val._numerator * (_denominator / g);
_denominator = m1 * _denominator;
}
}
return *this;
}
Expand Down
5 changes: 4 additions & 1 deletion mscore/scoreview.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4312,7 +4312,10 @@ void ScoreView::setControlCursorVisible(bool v)

void ScoreView::cmdTuplet(int n, ChordRest* cr)
{
if (cr->durationType() < TDuration(TDuration::DurationType::V_512TH) && cr->durationType() != TDuration(TDuration::DurationType::V_MEASURE)) {
if ((cr->durationType() < TDuration(TDuration::DurationType::V_512TH) && cr->durationType() != TDuration(TDuration::DurationType::V_MEASURE))
|| (cr->durationType() < TDuration(TDuration::DurationType::V_256TH) && n > 3)
|| (cr->durationType() < TDuration(TDuration::DurationType::V_128TH) && n > 7)
) {
mscore->noteTooShortForTupletDialog();
return;
}
Expand Down

0 comments on commit 69c7820

Please sign in to comment.