>
>
>
Did it have to take so long to find a b…

Sviatoslav Razmyslov
Articles: 90

Did it have to take so long to find a bug?

Have you ever wondered which type of project demonstrates higher code quality – open-source or proprietary? Our blog posts may seem to suggest that bugs tend to concentrate in open-source projects. But that's not quite true. Bugs can be found in any project, no matter the manner of storage. As for the code quality, it tends to be higher in those projects where developers care about and work on it. In this small post, you will learn about a bug that took two years to fix, although it could have been done in just five minutes.

The chronology

Minetest is an open-source cross-platform game engine about 200 thousand lines of C, C++, and Lua code long. It allows creating various game modes in voxel space, with multiplayer mode support and easy modding.

On November 10, 2018, Issue #7852 - item_image_button[]: button too small was opened in the project's bug tracker.

This is how it goes:

The button is too small resulting in the image exceeding its borders. Button should be the same size as inventory slots. See example below (using width and height of 1).

The report was accompanied by a screenshot:

In this screenshot, you can see that the images slightly exceed the borders of the buttons. The bug was reported way back in 2018, yet the cause behind it was discovered only this year, 2020.

Publication of a technical article "PVS-Studio: analyzing pull requests in Azure DevOps using self-hosted agents" in July 2020 was the next piece of this wonderful story. As an example of how the analyzer can be integrated with Azure DevOps, we chose that very game, Minetest. The article discusses a number of bugs, but here we are interested in one specific warning:

V636 The 'rect.getHeight() / 16' expression was implicitly cast from 'int' type to 'float' type. Consider utilizing an explicit type cast to avoid the loss of a fractional part. An example: double A = (double)(X) / Y;. hud.cpp 771

void drawItemStack(....)
{
  float barheight = rect.getHeight() / 16;
  float barpad_x = rect.getWidth() / 16;
  float barpad_y = rect.getHeight() / 16;

  core::rect<s32> progressrect(
    rect.UpperLeftCorner.X + barpad_x,
    rect.LowerRightCorner.Y - barpad_y - barheight,
    rect.LowerRightCorner.X - barpad_x,
    rect.LowerRightCorner.Y - barpad_y);
}

When dividing the width and height values by 16, the fractional part of the resulting value is truncated since this is an integer division.

Almost half a year since, the game's developers finally learned about the results of our check, and Issue 10726 - Fix errors found by professional static code analyzer was opened, where a link was discovered between this bug and the old Issue #7852. It was that very truncation that distorted the buttons' size.

The moral

The use of static code analyzers helps save a huge amount of time on bug detection. You can argue all you want about this bug being a minor issue, but I can tell you from our experience that its life cycle is typical of just any bug, no matter how critical it is.

Suppose it had been a serious bug indeed. The developers would have focused all their effort on finding and fixing it, which would have taken them an hour or so. But the analyzer would have found it in a couple of minutes anyway.

So, the moral of this story is that projects in development could greatly benefit from automated bug-detection methods. Such tools as PVS-Studio should be viewed as a complement to peer code review rather than a replacement of it.