To get a trial key
fill out the form below
Team License (a basic version)
Enterprise License (extended version)
* By clicking this button you agree to our Privacy Policy statement

Request our prices
New License
License Renewal
--Select currency--
USD
EUR
GBP
RUB
* By clicking this button you agree to our Privacy Policy statement

Free PVS-Studio license for Microsoft MVP specialists
* By clicking this button you agree to our Privacy Policy statement

To get the licence for your open-source project, please fill out this form
* By clicking this button you agree to our Privacy Policy statement

I am interested to try it on the platforms:
* By clicking this button you agree to our Privacy Policy statement

Message submitted.

Your message has been sent. We will email you at


If you haven't received our response, please do the following:
check your Spam/Junk folder and click the "Not Spam" button for our message.
This way, you won't miss messages from our team in the future.

>
>
>
Best Copy-Paste Algorithms for C and C+…

Best Copy-Paste Algorithms for C and C++. Haiku OS Cookbook

Jul 26 2019

Numerous typos and Copy-Paste code became the main topic of the additional article about checking the Haiku code by the PVS-Studio analyzer. Yet this article mostly tells about errors related to thoughtlessness and failed refactoring, rather than to typos. The errors found demonstrate how strong the human factor is in software development.

0645_Haiku_4/image1.png

Introduction

Haiku is a free open source operating system for personal computers. An international development team is currently working on the components of the system. Porting LibreOffice in the OS and the first R1 Beta 1 release stand out among the recent significant development improvements.

Team of developers from PVS-Studio follows this project development since 2015 and posts reviews of code defects. This is the fourth review of all time. You can read the previous articles by these links:

The feature of the last code analysis is the ability to use the official version of PVS-Studio for Linux. Neither PVS-Studio for Linux, nor a convenient report to view errors was available in 2015. This time we'll send the full report in a convenient format to Haiku developers.

Classic

V501 There are identical sub-expressions to the left and to the right of the '-' operator: (addr_t) b - (addr_t) b BitmapManager.cpp 51

int
compare_app_pointer(const ServerApp* a, const ServerApp* b)
{
  return (addr_t)b - (addr_t)b;
}

Every developer has to mix up variables a and b, x and y, i and j ... at least once in his life.

V501 There are identical sub-expressions to the left and to the right of the '||' operator: input == __null || input == __null MediaClient.cpp 182

status_t
BMediaClient::Unbind(BMediaInput* input, BMediaOutput* output)
{
  CALLED();

  if (input == NULL
    || input == NULL)
    return B_ERROR;

  if (input->fOwner != this || output->fOwner != this)
    return B_ERROR;

  input->fBind = NULL;
  output->fBind = NULL;
  return B_OK;
}

The same input pointer is checked in the condition twice. Whereas the output pointer remained unchecked, which can result in the null pointer dereference.

Fixed code:

if (input == NULL
    || output == NULL)
    return B_ERROR;

V583 The '?:' operator, regardless of its conditional expression, always returns one and the same value: 500000. usb_modeswitch.cpp 361

static status_t
my_transfer_data(....)
{
  ....
  do {
    bigtime_t timeout = directionIn ? 500000 : 500000;
    result = acquire_sem_etc(device->notify, 1, B_RELATIVE_TIMEOUT, timeout);
    ....
  } while (result == B_INTERRUPTED);
  ....
}

The ternary operator became pointless, when the code author made a mistake and wrote two identical return values - 500000.

V519 The 'm_kindex1' variable is assigned values twice successively. Perhaps this is a mistake. Check lines: 40, 41. agg_trans_double_path.cpp 41

trans_double_path::trans_double_path() :
    m_kindex1(0.0),
    m_kindex2(0.0),
    m_base_length(0.0),
    m_base_height(1.0),
    m_status1(initial),
    m_status2(initial),
    m_preserve_x_scale(true)
{
}

void trans_double_path::reset()
{
    m_src_vertices1.remove_all();
    m_src_vertices2.remove_all();
    m_kindex1 = 0.0;
    m_kindex1 = 0.0;
    m_status1 = initial;
    m_status2 = initial;
}

There is an error in the reset function: a typo in the m_kindex2 variable index. This variable won't be reset, which will probably affect the execution of other code fragments.

V501 There are identical sub-expressions to the left and to the right of the '>' operator: fg[order_type::R] > fg[order_type::R] agg_span_image_filter_rgba.h 898

typedef Source source_type;
typedef typename source_type::color_type color_type;
typedef typename source_type::order_type order_type;

void generate(color_type* span, int x, int y, unsigned len)
{
 ....
 if(fg[0] < 0) fg[0] = 0;
 if(fg[1] < 0) fg[1] = 0;
 if(fg[2] < 0) fg[2] = 0;
 if(fg[3] < 0) fg[3] = 0;

 if(fg[order_type::A] > base_mask)        fg[order_type::A] = base_mask;
 if(fg[order_type::R] > fg[order_type::R])fg[order_type::R] = fg[order_type::R];
 if(fg[order_type::G] > fg[order_type::G])fg[order_type::G] = fg[order_type::G];
 if(fg[order_type::B] > fg[order_type::B])fg[order_type::B] = fg[order_type::B];
  ....
}

In the last lines, there are two issues at once: comparison and assignment of equal variables. I even cannot suggest what the author's brainchild was. I'll just note this snippet as suspicious.

V570 The 'wPipeIndex' variable is assigned to itself. CEchoGals_transport.cpp 244

ECHOSTATUS CEchoGals::CloseAudio (....)
{
  ....
  wPipeIndex = wPipeIndex;
  m_ProcessId[ wPipeIndex ] = NULL;
  m_Pipes[ wPipeIndex ].wInterleave = 0;
  ....
}

The wPipeIndex variable is initialized by its own value. Most likely, a typo was made.

Errors with Pointers

V522 Dereferencing of the null pointer 'currentInterface' might take place. Device.cpp 258

Device::Device(....) : ....
{
  ....
  usb_interface_info* currentInterface = NULL;                     // <=
  uint32 descriptorStart = sizeof(usb_configuration_descriptor);
  while (descriptorStart < actualLength) {
    switch (configData[descriptorStart + 1]) {
    ....
    case USB_DESCRIPTOR_ENDPOINT:
    {
      ....
      if (currentInterface == NULL)                                // <=
        break;
      currentInterface->endpoint_count++;
      ....
    }
    ....
    case USB_DESCRIPTOR_ENDPOINT_COMPANION: {
      usb_endpoint_descriptor* desc = currentInterface             // <=
        ->endpoint[currentInterface->endpoint_count - 1].descr;
      ....
    }
  ....
}

The currentInterface pointer is initially initialized by null and then checked when entering in the branches of the switch operator, but not in all cases. The analyzer warns that when jumping to the USB_DESCRIPTOR_ENDPOINT_COMPANION case label, null pointer dereference might occur.

V522 Dereferencing of the null pointer 'directory' might take place. PathMonitor.cpp 1465

bool
PathHandler::_EntryCreated(....)
{
  ....
  Directory* directory = directoryNode->ToDirectory();
  if (directory == NULL) {
    // We're out of sync with reality.
    if (!dryRun) {
      if (Entry* nodeEntry = directory->FirstNodeEntry()) {
        ....
      }
    }
    return false;
  }
  ....
}

I think, there is an error in the comparison condition of the directory pointer with the null value; the condition has to be the opposite. With the current implementation, if the dryRun variable is false, the directory null pointer will be dereferenced.

V522 Dereferencing of the null pointer 'input' might take place. MediaRecorder.cpp 343

void GetInput(media_input* input);

const media_input&
BMediaRecorder::MediaInput() const
{
  CALLED();

  media_input* input = NULL;
  fNode->GetInput(input);
  return *input;
}

The input pointer is initialized by null and stays with such value, as the pointer isn't changing in the GetInput function. In other methods of the BMediaRecorder class, the implementation is different, for instance:

status_t
BMediaRecorder::_Connect(....)
{
  ....
  // Find our Node's free input
  media_input ourInput;
  fNode->GetInput(&ourInput);     // <=
  ....
}

It's all correct here, but the first fragment has to be rewritten, otherwise the function will return a reference to a local object.

V522 Dereferencing of the null pointer 'mustFree' might take place. RequestUnflattener.cpp 35

status_t
Reader::Read(int32 size, void** buffer, bool* mustFree)
{
  if (size < 0 || !buffer || mustFree)  // <=
    return B_BAD_VALUE;

  if (size == 0) {
    *buffer = NULL;
    *mustFree = false;                  // <=
    return B_OK;
  }
  ....
}

In the conditional expression where all incorrect data is checked, the author made a typo when checking the mustFree pointer. Most likely, the function should exit when having the null value of this pointer:

if (size < 0 || !buffer || !mustFree)  // <=
  return B_BAD_VALUE;

V757 It is possible that an incorrect variable is compared with nullptr after type conversion using 'dynamic_cast'. Check lines: 474, 476. recover.cpp 474

void
checkStructure(Disk &disk)
{
  ....
  Inode* missing = gMissing.Get(run);
  dir = dynamic_cast<Directory *>(missing);

  if (missing == NULL) {
    ....
  }
  ....
}

The developer should have checked the dir pointer instead of missing after type conversion. By the way, C# developers also often make a similar mistake. This proves once again that some errors don't depend on the language used.

A couple more similar places in the code:

  • V757 It is possible that an incorrect variable is compared with nullptr after type conversion using 'dynamic_cast'. Check lines: 355, 357. ExpandoMenuBar.cpp 355
  • V757 It is possible that an incorrect variable is compared with nullptr after type conversion using 'dynamic_cast'. Check lines: 600, 601. ValControl.cpp 600

Index Errors

V557 Array overrun is possible. The 'BT_SCO' index is pointing beyond array bound. h2upper.cpp 75

struct bt_usb_dev {
  ....
  struct list nbuffersTx[(1 + 1 + 0 + 0)];         // <= [0..1]
  ....
}

typedef enum {
    BT_COMMAND = 0,
    BT_EVENT,
    BT_ACL,
    BT_SCO,                                        // <= 3
    BT_ESCO,

    HCI_NUM_PACKET_TYPES
} bt_packet_t;

void
sched_tx_processing(bt_usb_dev* bdev)
{
  ....
  if (!list_is_empty(&bdev->nbuffersTx[BT_SCO])) { // <= fail
    // TODO to be implemented
  }
  ....
}

The bdev->nbuffersTx array consists only of 2 elements, but it's addressed by the BT_SCO constant, which is 3. Here comes the surefire array index out of bounds.

V557 Array overrun is possible. The 'ieee80211_send_setup' function processes value '16'. Inspect the fourth argument. Check lines: 842, 911. ieee80211_output.c 842

struct ieee80211_node {
  ....
  struct ieee80211_tx_ampdu ni_tx_ampdu[16];              // <= [0..15]
  ....
};

#define IEEE80211_NONQOS_TID 16

int
ieee80211_mgmt_output(....)
{
  ....
  ieee80211_send_setup(ni, m,
     IEEE80211_FC0_TYPE_MGT | type, IEEE80211_NONQOS_TID, // <= 16
     vap->iv_myaddr, ni->ni_macaddr, ni->ni_bssid);
  ....
}

void
ieee80211_send_setup(
  struct ieee80211_node *ni,
  struct mbuf *m,
  int type,
  int tid,                                                // <= 16
  ....)
{
  ....
  tap = &ni->ni_tx_ampdu[tid];                            // <= 16
  ....
}

Another array index out of bounds. This time, just by one element. Interprocedural analysis helped to reveal the case when the ni->ni_tx_ampdu array, consisting of 16 elements was addressed by the index 16. In C and C++ arrays are indexed from zero.

V781 The value of the 'vector' variable is checked after it was used. Perhaps there is a mistake in program logic. Check lines: 802, 805. oce_if.c 802

#define OCE_MAX_EQ 32

typedef struct oce_softc {
  ....
  OCE_INTR_INFO intrs[OCE_MAX_EQ];
  ....
} OCE_SOFTC, *POCE_SOFTC;

static int
oce_alloc_intr(POCE_SOFTC sc, int vector, void (*isr) (void *arg, int pending))
{
  POCE_INTR_INFO ii = &sc->intrs[vector];
  int rc = 0, rr;

  if (vector >= OCE_MAX_EQ)
    return (EINVAL);
  ....
}

The analyzer has detected that an element of the sc->intrs array was addressed by an invalid index, which was out of bounds. The reason is the incorrect order of operations in the code. First, the element is addressed and then comes the check if the index value is valid.

Some might say there won't be any trouble. It doesn't remove the value of the array element, it just takes the address of the cell. But no, that's not the way to do things. Read more: "Null Pointer Dereferencing Causes Undefined Behavior".

V519 The variable is assigned values twice successively. Perhaps this is a mistake. Check lines: 199, 200. nvme_ctrlr.c 200

static void nvme_ctrlr_set_intel_supported_features(struct nvme_ctrlr *ctrlr)
{
  bool *supported_feature = ctrlr->feature_supported;

  supported_feature[NVME_INTEL_FEAT_MAX_LBA] = true;
  supported_feature[NVME_INTEL_FEAT_MAX_LBA] = true;
  supported_feature[NVME_INTEL_FEAT_NATIVE_MAX_LBA] = true;
  supported_feature[NVME_INTEL_FEAT_POWER_GOVERNOR_SETTING] = true;
  supported_feature[NVME_INTEL_FEAT_SMBUS_ADDRESS] = true;
  supported_feature[NVME_INTEL_FEAT_LED_PATTERN] = true;
  supported_feature[NVME_INTEL_FEAT_RESET_TIMED_WORKLOAD_COUNTERS] = true;
  supported_feature[NVME_INTEL_FEAT_LATENCY_TRACKING] = true;
}

The array element with the NVME_INTEL_FEAT_MAX_LBA index is assigned the same value. The good news is this function presents all possible constants which makes this code just the result of the Copy-Paste programming. But chances are errors will sneak in here.

V519 The 'copiedPath[len]' variable is assigned values twice successively. Perhaps this is a mistake. Check lines: 92, 93. kernel_emu.cpp 93

int
UserlandFS::KernelEmu::new_path(const char *path, char **copy)
{
  ....
  // append a dot, if desired
  if (appendDot) {
    copiedPath[len] = '.';
    copiedPath[len] = '\0';
  }
  ....
}

Well, here the programmer got bad luck with copying. The symbol "dot" is added to a line and gets rewritten with a terminal null. It is highly likely, the author just copied the line and forgot to increment the index.

Strange Conditions

V517 The use of 'if (A) {...} else if (A) {...}' pattern was detected. There is a probability of logical error presence. Check lines: 1407, 1410. FindPanel.cpp 1407

void
FindPanel::BuildAttrQuery(BQuery* query, bool &dynamicDate) const
{
  ....
  case B_BOOL_TYPE:
  {
    uint32 value;
    if (strcasecmp(textControl->Text(),
        "true") == 0) {
      value = 1;
    } else if (strcasecmp(textControl->Text(),
        "true") == 0) {
      value = 1;
    } else
      value = (uint32)atoi(textControl->Text());

    value %= 2;
    query->PushUInt32(value);
    break;
  }
  ....
}

Copying the code led to two errors at once. The conditional expressions are identical. Most likely, a comparison with the "false" string instead of "true" has to be in one of them. Further in the branch that handles the "false" value, the value that should be changed from 1 to 0. The algorithm requires that any other values, different from true or false be converted in a number using the atoi function. But due to an error, the text "false" will get into the function.

V547 Expression 'error == ((int) 0)' is always true. Directory.cpp 688

int32
BDirectory::CountEntries()
{
  status_t error = Rewind();
  if (error != B_OK)
    return error;
  int32 count = 0;
  BPrivate::Storage::LongDirEntry entry;
  while (error == B_OK) {
    if (GetNextDirents(&entry, sizeof(entry), 1) != 1)
      break;
    if (strcmp(entry.d_name, ".") != 0 && strcmp(entry.d_name, "..") != 0)
      count++;
  }
  Rewind();
  return (error == B_OK ? count : error);
}

The analyzer detected that the error variable value will always be B_OK. Most definitely, this variable modification was missed in the while loop.

V564 The '&' operator is applied to bool type value. You've probably forgotten to include parentheses or intended to use the '&&' operator. strtod.c 545

static int
lo0bits(ULong *y)
{
  int k;
  ULong x = *y;
  ....
  if (!(x & 1)) {
    k++;
    x >>= 1;
    if (!x & 1)   // <=
      return 32;
  }
  *y = x;
  return k;
}

It's most likely that in the last conditional expression one forgot to place brackets, as in the conditions above. The complementary operator is likely to be outside the brackets:

if (!(x & 1))   // <=
      return 32;

V590 Consider inspecting this expression. The expression is excessive or contains a misprint. PoseView.cpp 5851

bool
BPoseView::AttributeChanged(const BMessage* message)
{
  ....
  result = poseModel->OpenNode();
  if (result == B_OK || result != B_BUSY)
    break;
  ....
}

This is not obvious, but the result of the condition doesn't depend on the value of B_OK value. So it can be simplified:

If (result != B_BUSY)
  break;

You can easily check it by drawing a truth table for the values of the result variable. If one wanted to specifically consider other values, different from B_OK and B_BUSY, the code should be rewritten in another way.

Two more similar fragments:

  • V590 Consider inspecting this expression. The expression is excessive or contains a misprint. Tracker.cpp 1714
  • V590 Consider inspecting this expression. The expression is excessive or contains a misprint. if_ipw.c 1871

V590 Consider inspecting the 'argc == 0 || argc != 2' expression. The expression is excessive or contains a misprint. cmds.c 2667

void
unsetoption(int argc, char *argv[])
{
  ....
  if (argc == 0 || argc != 2) {
    fprintf(ttyout, "usage: %s option\n", argv[0]);
    return;
  }
  ....
}

This is perhaps the simplest example that demonstrates the work of the V590 diagnostic. You need to display the program description in case if there are no passed arguments, or there are not two of them. Obviously, any values other than two, including zero, will not satisfy the condition. Therefore, the condition can be safely simplified to this:

if (argc != 2) {
    fprintf(ttyout, "usage: %s option\n", argv[0]);
    return;
}

V590 Consider inspecting the '* ptr == ';' && * ptr != '\0'' expression. The expression is excessive or contains a misprint. pc.c 316

ULONG
parse_expression(char *str)
{
  ....
  ptr = skipwhite(ptr);
  while (*ptr == SEMI_COLON && *ptr != '\0')
   {
     ptr++;
     if (*ptr == '\0')
       continue;

     val = assignment_expr(&ptr);
   }
  ....
}

In this example, the logical operator was changed, but the logic is still the same. Here the condition of the while loop depends only on whether the character is equal to SEMI_COLON or not.

V590 Consider inspecting this expression. The expression is excessive or contains a misprint. writembr.cpp 99

int
main(int argc, char** argv)
{
  ....
  string choice;
  getline(cin, choice, '\n');
  if (choice == "no" || choice == "" || choice != "yes") {
    cerr << "MBR was NOT written" << endl;
    fs.close();
    return B_ERROR;
  }
  ....
}

There are already three conditions in this example. It can also be simplified before checking whether the user has chosen "yes" or not:

if (choice != "yes") {
  cerr << "MBR was NOT written" << endl;
  fs.close();
  return B_ERROR;
}

Miscellaneous

V530 The return value of function 'begin' is required to be utilized. IMAPFolder.cpp 414

void
IMAPFolder::RegisterPendingBodies(...., const BMessenger* replyTo)
{
  ....
  IMAP::MessageUIDList::const_iterator iterator = uids.begin();
  for (; iterator != uids.end(); iterator++) {
    if (replyTo != NULL)
      fPendingBodies[*iterator].push_back(*replyTo);
    else
      fPendingBodies[*iterator].begin();   // <=
  }
}

The analyzer found a pointless call of the iterator begin(). I can't imagine how to fix the code. Developers should pay attention to this code.

V609 Divide by zero. Denominator range [0..64]. UiUtils.cpp 544

static int32 GetSIMDFormatByteSize(uint32 format)
{
  switch (format) {
    case SIMD_RENDER_FORMAT_INT8:
      return sizeof(char);
    case SIMD_RENDER_FORMAT_INT16:
      return sizeof(int16);
    case SIMD_RENDER_FORMAT_INT32:
      return sizeof(int32);
    case SIMD_RENDER_FORMAT_INT64:
      return sizeof(int64);
    case SIMD_RENDER_FORMAT_FLOAT:
      return sizeof(float);
    case SIMD_RENDER_FORMAT_DOUBLE:
      return sizeof(double);
  }
  return 0;
}

const BString&
UiUtils::FormatSIMDValue(const BVariant& value, uint32 bitSize,
  uint32 format, BString& _output)
{
  _output.SetTo("{");
  char* data = (char*)value.ToPointer();
  uint32 count = bitSize / (GetSIMDFormatByteSize(format) * 8);  // <=
  ....
}

The function GetSIMDFormatByteSize truly returns 0 as a default value, which might potentially lead to division by zero.

V654 The condition 'specificSequence != sequence' of loop is always false. pthread_key.cpp 55

static void*
get_key_value(pthread_thread* thread, uint32 key, int32 sequence)
{
  pthread_key_data& keyData = thread->specific[key];
  int32 specificSequence;
  void* value;

  do {
    specificSequence = keyData.sequence;
    if (specificSequence != sequence)
      return NULL;

    value = keyData.value;
  } while (specificSequence != sequence);

  keyData.value = NULL;

  return value;
}

The analyzer is right that the condition of the while operator is always false. Due to this, the loop doesn't run more than one iteration. In other words, nothing would change if you wrote while(0). All this is weird and this code contains a logic error. Developers should carefully consider this snippet.

V672 There is probably no need in creating the new 'path' variable here. One of the function's arguments possesses the same name and this argument is a reference. Check lines: 348, 429. translate.cpp 429

status_t
Translator::FindPath(...., TypeList &path, double &pathQuality)
{
  ....
  TypeList path;
  double quality;
  if (FindPath(&formats[j], stream, typesSeen, path, quality) == B_OK) {
    if (bestQuality < quality * formatQuality) {
      bestQuality = quality * formatQuality;
      bestPath.SetTo(path);
      bestPath.Add(formats[j].type);
      status = B_OK;
    }
  }
  ....
}

The path variable is passed to the FindPath function by reference. Which means, this variable can be modified in the body of the function. But there is a local variable with the same name, which is modified. In this case, all changes will remain only in the local variable. The code author might want to rename or remove the local variable.

V705 It is possible that 'else' block was forgotten or commented out, thus altering the program's operation logics. HostnameView.cpp 109

status_t
HostnameView::_LoadHostname()
{
  BString fHostnameString;
  char hostname[MAXHOSTNAMELEN];

  if (gethostname(hostname, MAXHOSTNAMELEN) == 0) {

    fHostnameString.SetTo(hostname, MAXHOSTNAMELEN);
    fHostname->SetText(fHostnameString);

    return B_OK;
  } else

  return B_ERROR;
}

The example of poor code formatting. The "hanging" keyword else doesn't change the logic yet, but once a code fragment is inserted before the return operator, the logic won't be the same.

V763 Parameter 'menu' is always rewritten in function body before being used. video.cpp 648

bool
video_mode_hook(Menu *menu, MenuItem *item)
{
  video_mode *mode = NULL;

  menu = item->Submenu();
  item = menu->FindMarked();
  ....
}

I found many cases when function arguments are rewritten when entering the function. This behavior misleads other developers who call these very functions.

The entire list of suspicious places:

  • V763 Parameter 'force_16bit' is always rewritten in function body before being used. ata_adapter.cpp 151
  • V763 Parameter 'force_16bit' is always rewritten in function body before being used. ata_adapter.cpp 179
  • V763 Parameter 'menu' is always rewritten in function body before being used. video.cpp 264
  • V763 Parameter 'length' is always rewritten in function body before being used. MailMessage.cpp 677
  • V763 Parameter 'entry' is always rewritten in function body before being used. IconCache.cpp 773
  • V763 Parameter 'entry' is always rewritten in function body before being used. IconCache.cpp 832
  • V763 Parameter 'entry' is always rewritten in function body before being used. IconCache.cpp 864
  • V763 Parameter 'rect' is always rewritten in function body before being used. ErrorLogWindow.cpp 56
  • V763 Parameter 'updateRect' is always rewritten in function body before being used. CalendarMenuWindow.cpp 49
  • V763 Parameter 'rect' is always rewritten in function body before being used. MemoryView.cpp 165
  • V763 Parameter 'rect' is always rewritten in function body before being used. TypeEditors.cpp 1124
  • V763 Parameter 'height' is always rewritten in function body before being used. Workspaces.cpp 857
  • V763 Parameter 'width' is always rewritten in function body before being used. Workspaces.cpp 856
  • V763 Parameter 'frame' is always rewritten in function body before being used. SwatchGroup.cpp 48
  • V763 Parameter 'frame' is always rewritten in function body before being used. PlaylistWindow.cpp 89
  • V763 Parameter 'rect' is always rewritten in function body before being used. ConfigView.cpp 78
  • V763 Parameter 'm' is always rewritten in function body before being used. mkntfs.c 3917
  • V763 Parameter 'rxchainmask' is always rewritten in function body before being used. ar5416_cal.c 463
  • V763 Parameter 'c' is always rewritten in function body before being used. if_iwn.c 6854

Conclusion

The Haiku project is a source of interesting and rare errors. We've added to our database some error examples and fixed a few analyzer issues that showed up when analyzing the code.

If you haven't checked your code with some code analysis tools for a long time, then some of the issues I described are probably hiding in your code. Use PVS-Studio in your project (if written in C, C++, C# or Java) to control code quality. Download the analyzer here without registration or sms.

Do you want to try Haiku and you have questions? Haiku developers invite you to the telegram-channel.

Popular related articles
PVS-Studio for Java

Date: Jan 17 2019

Author: Andrey Karpov

In the seventh version of the PVS-Studio static analyzer, we added support of the Java language. It's time for a brief story of how we've started making support of the Java language, how far we've co…
The Evil within the Comparison Functions

Date: May 19 2017

Author: Andrey Karpov

Perhaps, readers remember my article titled "Last line effect". It describes a pattern I've once noticed: in most cases programmers make an error in the last line of similar text blocks. Now I want t…
The way static analyzers fight against false positives, and why they do it

Date: Mar 20 2017

Author: Andrey Karpov

In my previous article I wrote that I don't like the approach of evaluating the efficiency of static analyzers with the help of synthetic tests. In that article, I give the example of a code fragment…
Technologies used in the PVS-Studio code analyzer for finding bugs and potential vulnerabilities

Date: Nov 21 2018

Author: Andrey Karpov

A brief description of technologies used in the PVS-Studio tool, which let us effectively detect a large number of error patterns and potential vulnerabilities. The article describes the implementati…
How PVS-Studio Proved to Be More Attentive Than Three and a Half Programmers

Date: Oct 22 2018

Author: Andrey Karpov

Just like other static analyzers, PVS-Studio often produces false positives. What you are about to read is a short story where I'll tell you how PVS-Studio proved, just one more time, to be more atte…
Appreciate Static Code Analysis!

Date: Oct 16 2017

Author: Andrey Karpov

I am really astonished by the capabilities of static code analysis even though I am one of the developers of PVS-Studio analyzer myself. The tool surprised me the other day as it turned out to be sma…
The Ultimate Question of Programming, Refactoring, and Everything

Date: Apr 14 2016

Author: Andrey Karpov

Yes, you've guessed correctly - the answer is "42". In this article you will find 42 recommendations about coding in C++ that can help a programmer avoid a lot of errors, save time and effort. The au…
PVS-Studio ROI

Date: Jan 30 2019

Author: Andrey Karpov

Occasionally, we're asked a question, what monetary value the company will receive from using PVS-Studio. We decided to draw up a response in the form of an article and provide tables, which will sho…
The Last Line Effect

Date: May 31 2014

Author: Andrey Karpov

I have studied many errors caused by the use of the Copy-Paste method, and can assure you that programmers most often tend to make mistakes in the last fragment of a homogeneous code block. I have ne…
Free PVS-Studio for those who develops open source projects

Date: Dec 22 2018

Author: Andrey Karpov

On the New 2019 year's eve, a PVS-Studio team decided to make a nice gift for all contributors of open-source projects hosted on GitHub, GitLab or Bitbucket. They are given free usage of PVS-Studio s…

Comments (0)

Next comments
This website uses cookies and other technology to provide you a more personalized experience. By continuing the view of our web-pages you accept the terms of using these files. If you don't want your personal data to be processed, please, leave this site.
Learn More →
Accept