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

Three coding bugs identified by static analysis #17082

Open
shoogle opened this issue Mar 30, 2023 · 13 comments
Open

Three coding bugs identified by static analysis #17082

shoogle opened this issue Mar 30, 2023 · 13 comments
Labels
community Issues particularly suitable for community contributors to work on P2 Priority: Medium

Comments

@shoogle
Copy link
Contributor

shoogle commented Mar 30, 2023

Issue type

Other type of issue

Bug description

Coding bugs identified by this video https://www.youtube.com/watch?v=SAVbpFTj81I

The video is a year old so some of the errors don't exist anymore.

Steps to reproduce

These are the ones that are still active:

Bug at 01:11

i-i is always zero

r = &_layout[i - i].boundingRect();

Bug at 01:17

Functions are identical

//---------------------------------------------------------
// upLine
//---------------------------------------------------------
int Rest::upLine() const
{
double _spatium = spatium();
return lrint((pos().y() + bbox().top() + _spatium) * 2 / _spatium);
}
//---------------------------------------------------------
// downLine
//---------------------------------------------------------
int Rest::downLine() const
{
double _spatium = spatium();
return lrint((pos().y() + bbox().top() + _spatium) * 2 / _spatium);
}

Bug at 2m33

destinationMeasure is dereferrenced with -> in multiple places without first checking for nullptr. Same goes for a few other variables in that function.

auto destinationMeasure = currentSystem->firstMeasure();
auto firstSegment = destinationMeasure->first(SegmentType::ChordRest);
// Case: Go to next system
if (next) {
if ((destinationMeasure = currentSystem->lastMeasure()->nextMeasure())) {
// There is a next system present: get it and accommodate for MMRest
currentSystem = destinationMeasure->system() ? destinationMeasure->system() : destinationMeasure->mmRest1()->system();
if ((destinationMeasure = currentSystem->firstMeasure())) {
if ((newCR = destinationMeasure->first()->nextChordRest(trackZeroVoice(cr->track()), false))) {
cr = newCR;
}
}
} else if (currentMeasure != lastMeasure()) {
// There is no next system present: go to last measure of current system
if ((destinationMeasure = lastMeasure())) {
if ((newCR = destinationMeasure->first()->nextChordRest(trackZeroVoice(cr->track()), false))) {
if (!destinationMeasure->isMMRest()) {
cr = newCR;
}
// Last visual measure is a MMRest: go to very last measure within that MMRest
else if ((destinationMeasure = lastMeasureMM())
&& (newCR = destinationMeasure->first()->nextChordRest(trackZeroVoice(cr->track()), false))) {
cr = newCR;
}
}
}
}
}
// Case: Go to previous system
else {
auto currentSegment = cr->segment();
// Only go to previous system's beginning if user is already at the absolute beginning of current system
// and not in first measure of entire score
if ((destinationMeasure != firstMeasure() && destinationMeasure != firstMeasureMM())
&& (currentSegment == firstSegment || (currentMeasure->mmRest() && currentMeasure->mmRest()->isFirstInSystem()))) {
if (!(destinationMeasure = destinationMeasure->prevMeasure())) {
if (!(destinationMeasure = destinationMeasure->prevMeasureMM())) {
return cr;
}
}
if (!(currentSystem = destinationMeasure->system() ? destinationMeasure->system() : destinationMeasure->mmRest1()->system())) {
return cr;
}
destinationMeasure = currentSystem->firstMeasure();
}

And there are also some negated assignments within the if conditions if (!(foo = foo->bar)) which aren't exactly easy to follow. Specifically for these lines, destinationMeasure is guaranteed to be nullptr when it is dereferenced on the second line because of the condition on the line above.

if (!(destinationMeasure = destinationMeasure->prevMeasure())) {
if (!(destinationMeasure = destinationMeasure->prevMeasureMM())) {

Screenshots/Screen recordings

No response

MuseScore Version

Latest code on master

Regression

No.

Operating system

All

Additional context

No response

@muse-bot muse-bot added the needs review The issue needs review to set priority, fix version or change status etc. label Mar 30, 2023
@shoogle shoogle added P2 Priority: Medium community Issues particularly suitable for community contributors to work on and removed needs review The issue needs review to set priority, fix version or change status etc. labels Mar 30, 2023
@cbjeukendrup cbjeukendrup added this to To do in [MU4 - TECH_DEBTS] via automation Mar 31, 2023
@AntonioBL
Copy link
Contributor

AntonioBL commented Apr 3, 2023

Even if not strictly found by a static analyzer, there is also a compilation warning at line 2117 of src/engraving/libmscore/note.cpp:
warning: '?:' using integer constants in boolean context, the expression will always evaluate to 'true'
If I understood correctly, && has precedence over ?, so the condition can be basically reduced to:
if ( condition1 ? 2 : -2 ), i.e. if(numeric_const_different_form_0) always true

(Edit: already fixed in master)

@willkell

This comment was marked as outdated.

@bkunda

This comment was marked as outdated.

@BrownianNotion
Copy link
Contributor

Happy to pick this up if still relevant. I'm still quite new so I will likely return with questions.

@BrownianNotion
Copy link
Contributor

BrownianNotion commented May 15, 2024

Looks like the first bug has now been fixed, but the other two remain. Not sure that the methods Rest::upLine and Rest::downLine are actually being used anywhere though.

@Jojo-Schmitz
Copy link
Contributor

They are used, at least in

int line(bool up) const { return up ? upLine() : downLine(); }
int line() const { return ldata()->up ? upLine() : downLine(); }

@BrownianNotion
Copy link
Contributor

They are used, at least in

int line(bool up) const { return up ? upLine() : downLine(); }
int line() const { return ldata()->up ? upLine() : downLine(); }

But this is ChordRest::upLine? This method is overridden by Rest::upLine upon inheriting from the ChordRest class.

@Jojo-Schmitz
Copy link
Contributor

That's why it is used

@BrownianNotion
Copy link
Contributor

I see what you're saying now, sorry for misunderstanding :)

@wizofaus

This comment was marked as resolved.

@BrownianNotion
Copy link
Contributor

Thanks @wizofaus. Haven't had a chance to take a good look yet, aiming to start this week.

@BrownianNotion
Copy link
Contributor

@shoogle apologies, I haven't found the time to work on this, would probably better to assign someone else

@shubham-shinde-442
Copy link
Contributor

Could someone clarify what exactly we want to achieve for each bug?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
community Issues particularly suitable for community contributors to work on P2 Priority: Medium
Projects
Status: Available
Development

No branches or pull requests

10 participants