SlideShare a Scribd company logo
1 of 10
Download to read offline
Python and Ruby implementations
compared by the error density
Author: Pavel Belikov
Date: 22.07.2016
Which programming language to start learning? Python or Ruby? Which one is better? Django or Ruby on
Rails? Such questions can often be found on IT forums around the world. I suggest comparing not the
languages themselves, but their reference implementations: CPython and MRI. In this article, we are going
to cover the errors that were found by PVS-Studio in these projects.
Introduction
We took the latest versions of the source code from the repositories (Ruby, Python) for the analysis. The
project was scanned with PVS-Studio v6.06 static code analyzer. Python can be easily compiled in Visual
Studio; for Ruby you can use a Standalone version in the compilation monitoring mode.
There weren't very many glaring errors: the majority of warnings are connected with the usage of macros,
which get expanded into quite a suspicious code, from the point of view of the analyzer, but rather innocent
from a developer's point of view. We could start a long discussion on whether macros bring harm or good,
but we can say for sure that the analyzer doesn't like them much. To get rid of some annoying macro, there
is an option to suppress false positives. It's enough to write:
//-V:RB_TYPE_P:501
And all the warnings by V501 diagnostic, where there is RB_TYPE_P macro will disappear.
Python
Fragment N1
#ifdef MS_WINDOWS
typedef SOCKET SOCKET_T;
#else
typedef int SOCKET_T;
#endif
typedef struct {
PyObject_HEAD
SOCKET_T sock_fd; /* Socket file descriptor */
....
} PySocketSockObject;
static int
internal_select(PySocketSockObject *s,
int writing,
_PyTime_t interval,
int connect)
{
....
if (s->sock_fd < 0) // <=
return 0;
....
}
V547 Expression 's->sock_fd < 0' is always false. Unsigned type value is never < 0. socketmodule.c 655
The SOCKET type in Windows is unsigned, so comparing it against null is meaningless. The check of the
socket() function returned a correct descriptor, it's necessary to compare its value with INVALID_SOCKET. It
is worth noting that this comparison would work correctly in Linux, because there as the socket type, we
have a signed type int used, and the value -1 indicates an error. Nevertheless, it's better to use special
macros or constants to check.
Several more similar checks that the analyzer issued warnings for.
 V547 Expression 's->sock_fd < 0' is always false. Unsigned type value is never < 0. _ssl.c 1702
 V547 Expression 'sock->sock_fd < 0' is always false. Unsigned type value is never < 0. _ssl.c 2018
Fragment N2
int ASN1_PRINTABLE_type(const unsigned char *s, int len)
{
int c;
int ia5 = 0;
....
if (!(((c >= 'a') && (c <= 'z')) ||
((c >= 'A') && (c <= 'Z')) ||
(c == ' ') || // <=
((c >= '0') && (c <= '9')) ||
(c == ' ') || (c == ''') || // <=
(c == '(') || (c == ')') ||
(c == '+') || (c == ',') ||
(c == '-') || (c == '.') ||
(c == '/') || (c == ':') ||
(c == '=') || (c == '?')))
ia5 = 1;
....
}
V501 There are identical sub-expressions '(c == ' ')' to the left and to the right of the '||' operator. a_print.c
77
A typical example of an error that occurred as a result of Copy-Paste. Quite often, when using large amounts
of copied blocks, a programmer's attention falters and they forget to change a variable or a constant in
them. For example, in this case in a large conditional expression, the programmer confused the values that
the variable c is compared with. We cannot say for sure, but it seems that the symbol of double quotation
'"' was forgotten.
Fragment N3
static PyObject *
semlock_acquire(SemLockObject *self, PyObject *args, PyObject *kwds)
{
....
HANDLE handles[2], sigint_event;
....
/* prepare list of handles */
nhandles = 0;
handles[nhandles++] = self->handle;
if (_PyOS_IsMainThread()) {
sigint_event = _PyOS_SigintEvent();
assert(sigint_event != NULL);
handles[nhandles++] = sigint_event;
}
/* do the wait */
Py_BEGIN_ALLOW_THREADS
if (sigint_event != NULL) //<=
ResetEvent(sigint_event);
....
}
V614 Potentially uninitialized pointer 'sigint_event' used. semaphore.c 120
In case the function _PyOS_IsMainThread() returns false, the pointer sigint_event will remain uninitialized.
This will result in undefined behavior. Such an error can easily be overlooked in the debug version, where a
pointer is most likely to be initialized by a null.
Fragment N4
#define BN_MASK2 (0xffffffffffffffffLL)
int BN_mask_bits(BIGNUM *a, int n)
{
....
a->d[w] &= ~(BN_MASK2 << b); //<=
....
}
V610 Undefined behavior. Check the shift operator '<<'. The left operand '(0xffffffffffffffffLL)' is negative.
bn_lib.c 796
Despite the fact that the code works in most cases, this expression is considered to be undefined behavior
according to the standard. You can find more details about the shifts of negative numbers in the article
written by Andrey Karpov "Wade not in unknown waters. Part three". It's up to you to decide where it's
necessary to avoid constructions whose results aren't guaranteed by the standard; but it's better not to do
it at all; the analyzer agrees on that too.
static PyObject *
binascii_b2a_qp_impl(PyModuleDef *module,
Py_buffer *data,
int quotetabs,
int istext,
int header)
{
Py_ssize_t in, out;
const unsigned char *databuf;
....
if ((databuf[in] > 126) ||
(databuf[in] == '=') ||
(header && databuf[in] == '_') ||
((databuf[in] == '.') && (linelen == 0) &&
(databuf[in+1] == 'n' || databuf[in+1] == 'r' ||
databuf[in+1] == 0)) ||
(!istext && ((databuf[in] == 'r') ||
(databuf[in] == 'n'))) ||
((databuf[in] == 't' || databuf[in] == ' ') &&
(in + 1 == datalen)) ||
((databuf[in] < 33) &&
(databuf[in] != 'r') && (databuf[in] != 'n') &&
(quotetabs ||
(!quotetabs && ((databuf[in] != 't') && // <=
(databuf[in] != ' '))))))
{
....
}
....
}
V728 An excessive check can be simplified. The '||' operator is surrounded by opposite expressions
'quotetabs' and '!quotetabs'. binascii.c 1453
This fragment is not erroneous, nevertheless, we should take a closer look at it. The warning is mostly a
recommendation: the expression 'A || (!A && B)' can be simplified to 'A || B': , which will make this quite
complicated code easier to read.
Similar warnings:
 V728 An excessive check can be simplified. The '||' operator is surrounded by opposite expressions
'!type' and 'type'. digest.c 167
 V728 An excessive check can be simplified. The '||' operator is surrounded by opposite expressions
'!cipher' and 'cipher'. evp_enc.c 120
Fragment N5
static int dh_cms_set_peerkey(....)
{
....
int atype;
....
/* Only absent parameters allowed in RFC XXXX */
if (atype != V_ASN1_UNDEF && atype == V_ASN1_NULL)
goto err;
....
}
V590 Consider inspecting the 'atype != - 1 && atype == 5' expression. The expression is excessive or contains
a misprint. dh_ameth.c 670
It shouldn't seem odd, that errors in logical expressions occur even in large projects. A logical expression is
excessive here, and it can be simplified to 'atype == V_ASN1_NULL'. Judging by the context, there is no error
here, but such code looks really suspicious.
Fragment N6
static void cms_env_set_version(CMS_EnvelopedData *env)
{
....
if (env->originatorInfo || env->unprotectedAttrs)
env->version = 2;
env->version = 0;
}
V519 The 'env->version' variable is assigned values twice successively. Perhaps this is a mistake. Check lines:
907, 908. cms_env.c 908
It's hard to say what the author meant writing this code. Perhaps else is omitted here. At this point there is
no sense in if, as the value of the 'env->version' variable will be rewritten in any case.
int
_PyState_AddModule(PyObject* module, struct PyModuleDef* def)
{
PyInterpreterState *state;
if (def->m_slots) {
PyErr_SetString(PyExc_SystemError,
"PyState_AddModule called on module with slots");
return -1;
}
state = GET_INTERP_STATE();
if (!def)
return -1;
....
}
V595 The 'self->extra' pointer was utilized before it was verified against nullptr. Check lines: 917, 923.
_elementtree.c 917
This is a traditional error, related to the null pointer dereferencing, which we find almost in every project.
Firstly, in the expression 'def->m_slots' the programmer accessed by some address, and then it turned out
that this address might have been null. As a result the verification against nullptr won't work, as we'll have
the null pointer dereference, which will lead to undefined program behavior and to its crash, for instance.
Ruby
Fragment N1
static void
vm_set_main_stack(rb_thread_t *th, const rb_iseq_t *iseq)
{
VALUE toplevel_binding = rb_const_get(rb_cObject,
rb_intern("TOPLEVEL_BINDING"));
rb_binding_t *bind;
rb_env_t *env;
GetBindingPtr(toplevel_binding, bind);
GetEnvPtr(bind->env, env);
vm_set_eval_stack(th, iseq, 0, &env->block);
/* save binding */
if (bind && iseq->body->local_size > 0) {
bind->env = vm_make_env_object(th, th->cfp);
}
}
V595 The 'bind' pointer was utilized before it was verified against nullptr. Check lines: 377, 382. vm.c 377
A similar error was also encountered in the Ruby project. The check 'if (bind)' won't be of much help,
because bind was dereferenced a little earlier in the code. There were more than 30 warnings of this kind,
so there is no point in listing them all here.
Fragment N2
static int
code_page_i(....)
{
table = realloc(table, count * sizeof(*table));
if (!table) return ST_CONTINUE;
....
}
V701 realloc() possible leak: when realloc() fails in allocating memory, original pointer 'table' is lost.
Consider assigning realloc() to a temporary pointer. file.c 169
In this fragment we see that the value of realloc is saved in the same variable, which is used as an argument.
In case realloc returns nullptr, the initial pointer value will be lost, which will lead to a memory leak.
Fragment N3
static int
w32_symlink(UINT cp, const char *src, const char *link)
{
....
BOOLEAN ret;
typedef DWORD (WINAPI *create_symbolic_link_func)
(WCHAR*, WCHAR*, DWORD);
static create_symbolic_link_func create_symbolic_link =
(create_symbolic_link_func)-1;
....
ret = create_symbolic_link(wlink, wsrc, flag);
ALLOCV_END(buf);
if (!ret) {
int e = GetLastError();
errno = map_errno(e);
return -1;
}
return 0;
}
V724 Converting type 'DWORD' to type 'BOOLEAN' can lead to a loss of high-order bits. Non-zero value can
become 'FALSE'. win32.c 4974
The BOOLEAN type is used in the WinAPI as a logical type. It is declared in the following way:
typedef unsigned char BYTE;
typedef BYTE BOOLEAN;
DWORD is a 32-bit unsigned number. That's why if we cast DWORD 0xffffff00 value to BOOLEAN (or any
other, whose lowest bit is zero), then it will become 0, i.e. FALSE.
Fragment N4
static VALUE
rb_str_split_m(int argc, VALUE *argv, VALUE str)
{
....
char *ptr = RSTRING_PTR(str);
long len = RSTRING_LEN(str);
long start = beg;
....
if (ptr+start == ptr+len)
start++;
....
}
V584 The 'ptr' value is present on both sides of the '==' operator. The expression is incorrect or it can be
simplified. string.c 7211
In both parts of the comparison we have ptr addition, therefore it can be removed:
if (start == len)
But most likely, there is no error in this fragment. However, we see quite often that programmers compare
two different variables in such expressions. That's why such comparisons are always worth reviewing.
Overall results
Having analyzed all the warnings of the general analysis diagnostics, and removed all the false positives, I
have come to the following conclusion concerning the error density:
The majority of warnings in Ruby were issued by the V610 diagnostic (369 warnings!), but even if we
exclude them, the situation won't change much: Python takes the lead over Ruby in the number of
suspicious fragments.
The most frequent diagnostic turned out to be V595 - there were 17 warnings in Python, and 37 in Ruby.
Of course, it's much more interesting to look at the error density ratio. Python also leaves Ruby well behind
in this category. Here are the results of the evaluations presented as a table:
It may seem that the number of errors is quite large. But it is not so. Firstly, not all of the bugs are critical.
For example, the V610 diagnostic that we have already mentioned, detects errors from the point of view of
the C++ language. However, in practice for the set of compilers the result can always be correct. Although
these errors are still bugs, they don't affect the program in any way. Secondly, we should take into account
the size of the code. That's why we can say that the quality of these projects is rather high. At this point this
may be rather subjective, because previously we haven't evaluated the error density of these projects. We'll
try to do that in the future, so that we can later compare the result of the checks.
Conclusion
Python and Ruby are extremely popular: millions of developers use them to write code. It's hard to find a
large number of errors in a project when it is so actively used, regularly tested by another static analysis tool
(both projects get checked by Coverity) and has community support. Nonetheless, PVS-Studio managed to
find several suspicious fragments. We should understand that these are regular checks which can make the
life of programmers much easier. The ideal, is to fix the error before the edits get to repository and release -
and a static analyzer can help best of all here.
I suggest running PVS-Studio on your projects.

More Related Content

What's hot

Checking the Cross-Platform Framework Cocos2d-x
Checking the Cross-Platform Framework Cocos2d-xChecking the Cross-Platform Framework Cocos2d-x
Checking the Cross-Platform Framework Cocos2d-xAndrey Karpov
 
PVS-Studio delved into the FreeBSD kernel
PVS-Studio delved into the FreeBSD kernelPVS-Studio delved into the FreeBSD kernel
PVS-Studio delved into the FreeBSD kernelPVS-Studio
 
A Post About Analyzing PHP
A Post About Analyzing PHPA Post About Analyzing PHP
A Post About Analyzing PHPAndrey Karpov
 
A Slipshod Check of the Visual C++ 2013 Library (update 3)
A Slipshod Check of the Visual C++ 2013 Library (update 3)A Slipshod Check of the Visual C++ 2013 Library (update 3)
A Slipshod Check of the Visual C++ 2013 Library (update 3)Andrey Karpov
 
A fresh eye on Oracle VM VirtualBox
A fresh eye on Oracle VM VirtualBoxA fresh eye on Oracle VM VirtualBox
A fresh eye on Oracle VM VirtualBoxPVS-Studio
 
PVS-Studio is there to help CERN: analysis of Geant4 project
PVS-Studio is there to help CERN: analysis of Geant4 projectPVS-Studio is there to help CERN: analysis of Geant4 project
PVS-Studio is there to help CERN: analysis of Geant4 projectPVS-Studio
 
Checking Clang 11 with PVS-Studio
Checking Clang 11 with PVS-StudioChecking Clang 11 with PVS-Studio
Checking Clang 11 with PVS-StudioAndrey Karpov
 
CppCat Checks OpenMW: Not All is Fine in the Morrowind Universe
CppCat Checks OpenMW: Not All is Fine in the Morrowind UniverseCppCat Checks OpenMW: Not All is Fine in the Morrowind Universe
CppCat Checks OpenMW: Not All is Fine in the Morrowind UniverseAndrey Karpov
 
ChakraCore: analysis of JavaScript-engine for Microsoft Edge
ChakraCore: analysis of JavaScript-engine for Microsoft EdgeChakraCore: analysis of JavaScript-engine for Microsoft Edge
ChakraCore: analysis of JavaScript-engine for Microsoft EdgePVS-Studio
 
Analyzing the Blender project with PVS-Studio
Analyzing the Blender project with PVS-StudioAnalyzing the Blender project with PVS-Studio
Analyzing the Blender project with PVS-StudioPVS-Studio
 
The Unicorn's Travel to the Microcosm
The Unicorn's Travel to the MicrocosmThe Unicorn's Travel to the Microcosm
The Unicorn's Travel to the MicrocosmAndrey Karpov
 
Sony C#/.NET component set analysis
Sony C#/.NET component set analysisSony C#/.NET component set analysis
Sony C#/.NET component set analysisPVS-Studio
 
A Spin-off: CryEngine 3 SDK Checked with CppCat
A Spin-off: CryEngine 3 SDK Checked with CppCatA Spin-off: CryEngine 3 SDK Checked with CppCat
A Spin-off: CryEngine 3 SDK Checked with CppCatAndrey Karpov
 
Waiting for the Linux-version: Checking the Code of Inkscape Graphics Editor
Waiting for the Linux-version: Checking the Code of Inkscape Graphics EditorWaiting for the Linux-version: Checking the Code of Inkscape Graphics Editor
Waiting for the Linux-version: Checking the Code of Inkscape Graphics EditorPVS-Studio
 
The Unicorn Getting Interested in KDE
The Unicorn Getting Interested in KDEThe Unicorn Getting Interested in KDE
The Unicorn Getting Interested in KDEAndrey Karpov
 
Top 10 bugs in C++ open source projects, checked in 2016
Top 10 bugs in C++ open source projects, checked in 2016Top 10 bugs in C++ open source projects, checked in 2016
Top 10 bugs in C++ open source projects, checked in 2016PVS-Studio
 
Errors detected in the Visual C++ 2012 libraries
Errors detected in the Visual C++ 2012 librariesErrors detected in the Visual C++ 2012 libraries
Errors detected in the Visual C++ 2012 librariesPVS-Studio
 
Checking Wine with PVS-Studio and Clang Static Analyzer
Checking Wine with PVS-Studio and Clang Static AnalyzerChecking Wine with PVS-Studio and Clang Static Analyzer
Checking Wine with PVS-Studio and Clang Static AnalyzerAndrey Karpov
 
Checking 7-Zip with PVS-Studio analyzer
Checking 7-Zip with PVS-Studio analyzerChecking 7-Zip with PVS-Studio analyzer
Checking 7-Zip with PVS-Studio analyzerPVS-Studio
 

What's hot (20)

Checking the Cross-Platform Framework Cocos2d-x
Checking the Cross-Platform Framework Cocos2d-xChecking the Cross-Platform Framework Cocos2d-x
Checking the Cross-Platform Framework Cocos2d-x
 
PVS-Studio delved into the FreeBSD kernel
PVS-Studio delved into the FreeBSD kernelPVS-Studio delved into the FreeBSD kernel
PVS-Studio delved into the FreeBSD kernel
 
A Post About Analyzing PHP
A Post About Analyzing PHPA Post About Analyzing PHP
A Post About Analyzing PHP
 
A Slipshod Check of the Visual C++ 2013 Library (update 3)
A Slipshod Check of the Visual C++ 2013 Library (update 3)A Slipshod Check of the Visual C++ 2013 Library (update 3)
A Slipshod Check of the Visual C++ 2013 Library (update 3)
 
A fresh eye on Oracle VM VirtualBox
A fresh eye on Oracle VM VirtualBoxA fresh eye on Oracle VM VirtualBox
A fresh eye on Oracle VM VirtualBox
 
PVS-Studio is there to help CERN: analysis of Geant4 project
PVS-Studio is there to help CERN: analysis of Geant4 projectPVS-Studio is there to help CERN: analysis of Geant4 project
PVS-Studio is there to help CERN: analysis of Geant4 project
 
Checking Clang 11 with PVS-Studio
Checking Clang 11 with PVS-StudioChecking Clang 11 with PVS-Studio
Checking Clang 11 with PVS-Studio
 
CppCat Checks OpenMW: Not All is Fine in the Morrowind Universe
CppCat Checks OpenMW: Not All is Fine in the Morrowind UniverseCppCat Checks OpenMW: Not All is Fine in the Morrowind Universe
CppCat Checks OpenMW: Not All is Fine in the Morrowind Universe
 
ChakraCore: analysis of JavaScript-engine for Microsoft Edge
ChakraCore: analysis of JavaScript-engine for Microsoft EdgeChakraCore: analysis of JavaScript-engine for Microsoft Edge
ChakraCore: analysis of JavaScript-engine for Microsoft Edge
 
Analyzing the Blender project with PVS-Studio
Analyzing the Blender project with PVS-StudioAnalyzing the Blender project with PVS-Studio
Analyzing the Blender project with PVS-Studio
 
The Unicorn's Travel to the Microcosm
The Unicorn's Travel to the MicrocosmThe Unicorn's Travel to the Microcosm
The Unicorn's Travel to the Microcosm
 
Sony C#/.NET component set analysis
Sony C#/.NET component set analysisSony C#/.NET component set analysis
Sony C#/.NET component set analysis
 
C++ boot camp part 1/2
C++ boot camp part 1/2C++ boot camp part 1/2
C++ boot camp part 1/2
 
A Spin-off: CryEngine 3 SDK Checked with CppCat
A Spin-off: CryEngine 3 SDK Checked with CppCatA Spin-off: CryEngine 3 SDK Checked with CppCat
A Spin-off: CryEngine 3 SDK Checked with CppCat
 
Waiting for the Linux-version: Checking the Code of Inkscape Graphics Editor
Waiting for the Linux-version: Checking the Code of Inkscape Graphics EditorWaiting for the Linux-version: Checking the Code of Inkscape Graphics Editor
Waiting for the Linux-version: Checking the Code of Inkscape Graphics Editor
 
The Unicorn Getting Interested in KDE
The Unicorn Getting Interested in KDEThe Unicorn Getting Interested in KDE
The Unicorn Getting Interested in KDE
 
Top 10 bugs in C++ open source projects, checked in 2016
Top 10 bugs in C++ open source projects, checked in 2016Top 10 bugs in C++ open source projects, checked in 2016
Top 10 bugs in C++ open source projects, checked in 2016
 
Errors detected in the Visual C++ 2012 libraries
Errors detected in the Visual C++ 2012 librariesErrors detected in the Visual C++ 2012 libraries
Errors detected in the Visual C++ 2012 libraries
 
Checking Wine with PVS-Studio and Clang Static Analyzer
Checking Wine with PVS-Studio and Clang Static AnalyzerChecking Wine with PVS-Studio and Clang Static Analyzer
Checking Wine with PVS-Studio and Clang Static Analyzer
 
Checking 7-Zip with PVS-Studio analyzer
Checking 7-Zip with PVS-Studio analyzerChecking 7-Zip with PVS-Studio analyzer
Checking 7-Zip with PVS-Studio analyzer
 

Similar to Python and Ruby implementations compared by the error density

Checking the code of Valgrind dynamic analyzer by a static analyzer
Checking the code of Valgrind dynamic analyzer by a static analyzerChecking the code of Valgrind dynamic analyzer by a static analyzer
Checking the code of Valgrind dynamic analyzer by a static analyzerPVS-Studio
 
Analysis of Godot Engine's Source Code
Analysis of Godot Engine's Source CodeAnalysis of Godot Engine's Source Code
Analysis of Godot Engine's Source CodePVS-Studio
 
Comparing the general static analysis in Visual Studio 2010 and PVS-Studio by...
Comparing the general static analysis in Visual Studio 2010 and PVS-Studio by...Comparing the general static analysis in Visual Studio 2010 and PVS-Studio by...
Comparing the general static analysis in Visual Studio 2010 and PVS-Studio by...PVS-Studio
 
The First C# Project Analyzed
The First C# Project AnalyzedThe First C# Project Analyzed
The First C# Project AnalyzedPVS-Studio
 
Analyzing the Dolphin-emu project
Analyzing the Dolphin-emu projectAnalyzing the Dolphin-emu project
Analyzing the Dolphin-emu projectPVS-Studio
 
Tesseract. Recognizing Errors in Recognition Software
Tesseract. Recognizing Errors in Recognition SoftwareTesseract. Recognizing Errors in Recognition Software
Tesseract. Recognizing Errors in Recognition SoftwareAndrey Karpov
 
How to make fewer errors at the stage of code writing. Part N4.
How to make fewer errors at the stage of code writing. Part N4.How to make fewer errors at the stage of code writing. Part N4.
How to make fewer errors at the stage of code writing. Part N4.PVS-Studio
 
Picking Mushrooms after Cppcheck
Picking Mushrooms after CppcheckPicking Mushrooms after Cppcheck
Picking Mushrooms after CppcheckAndrey Karpov
 
The Little Unicorn That Could
The Little Unicorn That CouldThe Little Unicorn That Could
The Little Unicorn That CouldPVS-Studio
 
Checking the Code of LDAP-Server ReOpenLDAP on Our Readers' Request
Checking the Code of LDAP-Server ReOpenLDAP on Our Readers' RequestChecking the Code of LDAP-Server ReOpenLDAP on Our Readers' Request
Checking the Code of LDAP-Server ReOpenLDAP on Our Readers' RequestPVS-Studio
 
Analyzing Wine: One Year Later
Analyzing Wine: One Year LaterAnalyzing Wine: One Year Later
Analyzing Wine: One Year LaterPVS-Studio
 
Analyzing Firebird 3.0
Analyzing Firebird 3.0Analyzing Firebird 3.0
Analyzing Firebird 3.0PVS-Studio
 
Why Windows 8 drivers are buggy
Why Windows 8 drivers are buggyWhy Windows 8 drivers are buggy
Why Windows 8 drivers are buggyAndrey Karpov
 
"Why is there no artificial intelligence yet?" Or, analysis of CNTK tool kit ...
"Why is there no artificial intelligence yet?" Or, analysis of CNTK tool kit ..."Why is there no artificial intelligence yet?" Or, analysis of CNTK tool kit ...
"Why is there no artificial intelligence yet?" Or, analysis of CNTK tool kit ...PVS-Studio
 
A Unicorn Seeking Extraterrestrial Life: Analyzing SETI@home's Source Code
A Unicorn Seeking Extraterrestrial Life: Analyzing SETI@home's Source CodeA Unicorn Seeking Extraterrestrial Life: Analyzing SETI@home's Source Code
A Unicorn Seeking Extraterrestrial Life: Analyzing SETI@home's Source CodePVS-Studio
 
PVS-Studio Meets Octave
PVS-Studio Meets Octave PVS-Studio Meets Octave
PVS-Studio Meets Octave PVS-Studio
 
Rechecking TortoiseSVN with the PVS-Studio Code Analyzer
Rechecking TortoiseSVN with the PVS-Studio Code AnalyzerRechecking TortoiseSVN with the PVS-Studio Code Analyzer
Rechecking TortoiseSVN with the PVS-Studio Code AnalyzerAndrey Karpov
 

Similar to Python and Ruby implementations compared by the error density (19)

Checking the code of Valgrind dynamic analyzer by a static analyzer
Checking the code of Valgrind dynamic analyzer by a static analyzerChecking the code of Valgrind dynamic analyzer by a static analyzer
Checking the code of Valgrind dynamic analyzer by a static analyzer
 
Analysis of Godot Engine's Source Code
Analysis of Godot Engine's Source CodeAnalysis of Godot Engine's Source Code
Analysis of Godot Engine's Source Code
 
Comparing the general static analysis in Visual Studio 2010 and PVS-Studio by...
Comparing the general static analysis in Visual Studio 2010 and PVS-Studio by...Comparing the general static analysis in Visual Studio 2010 and PVS-Studio by...
Comparing the general static analysis in Visual Studio 2010 and PVS-Studio by...
 
Checking VirtualDub
Checking VirtualDubChecking VirtualDub
Checking VirtualDub
 
The First C# Project Analyzed
The First C# Project AnalyzedThe First C# Project Analyzed
The First C# Project Analyzed
 
Analyzing the Dolphin-emu project
Analyzing the Dolphin-emu projectAnalyzing the Dolphin-emu project
Analyzing the Dolphin-emu project
 
Tesseract. Recognizing Errors in Recognition Software
Tesseract. Recognizing Errors in Recognition SoftwareTesseract. Recognizing Errors in Recognition Software
Tesseract. Recognizing Errors in Recognition Software
 
How to make fewer errors at the stage of code writing. Part N4.
How to make fewer errors at the stage of code writing. Part N4.How to make fewer errors at the stage of code writing. Part N4.
How to make fewer errors at the stage of code writing. Part N4.
 
Picking Mushrooms after Cppcheck
Picking Mushrooms after CppcheckPicking Mushrooms after Cppcheck
Picking Mushrooms after Cppcheck
 
The Little Unicorn That Could
The Little Unicorn That CouldThe Little Unicorn That Could
The Little Unicorn That Could
 
Checking the Code of LDAP-Server ReOpenLDAP on Our Readers' Request
Checking the Code of LDAP-Server ReOpenLDAP on Our Readers' RequestChecking the Code of LDAP-Server ReOpenLDAP on Our Readers' Request
Checking the Code of LDAP-Server ReOpenLDAP on Our Readers' Request
 
Analyzing Wine: One Year Later
Analyzing Wine: One Year LaterAnalyzing Wine: One Year Later
Analyzing Wine: One Year Later
 
Analyzing Firebird 3.0
Analyzing Firebird 3.0Analyzing Firebird 3.0
Analyzing Firebird 3.0
 
Analyzing Firebird 3.0
Analyzing Firebird 3.0Analyzing Firebird 3.0
Analyzing Firebird 3.0
 
Why Windows 8 drivers are buggy
Why Windows 8 drivers are buggyWhy Windows 8 drivers are buggy
Why Windows 8 drivers are buggy
 
"Why is there no artificial intelligence yet?" Or, analysis of CNTK tool kit ...
"Why is there no artificial intelligence yet?" Or, analysis of CNTK tool kit ..."Why is there no artificial intelligence yet?" Or, analysis of CNTK tool kit ...
"Why is there no artificial intelligence yet?" Or, analysis of CNTK tool kit ...
 
A Unicorn Seeking Extraterrestrial Life: Analyzing SETI@home's Source Code
A Unicorn Seeking Extraterrestrial Life: Analyzing SETI@home's Source CodeA Unicorn Seeking Extraterrestrial Life: Analyzing SETI@home's Source Code
A Unicorn Seeking Extraterrestrial Life: Analyzing SETI@home's Source Code
 
PVS-Studio Meets Octave
PVS-Studio Meets Octave PVS-Studio Meets Octave
PVS-Studio Meets Octave
 
Rechecking TortoiseSVN with the PVS-Studio Code Analyzer
Rechecking TortoiseSVN with the PVS-Studio Code AnalyzerRechecking TortoiseSVN with the PVS-Studio Code Analyzer
Rechecking TortoiseSVN with the PVS-Studio Code Analyzer
 

Recently uploaded

What is Binary Language? Computer Number Systems
What is Binary Language?  Computer Number SystemsWhat is Binary Language?  Computer Number Systems
What is Binary Language? Computer Number SystemsJheuzeDellosa
 
Asset Management Software - Infographic
Asset Management Software - InfographicAsset Management Software - Infographic
Asset Management Software - InfographicHr365.us smith
 
The Ultimate Test Automation Guide_ Best Practices and Tips.pdf
The Ultimate Test Automation Guide_ Best Practices and Tips.pdfThe Ultimate Test Automation Guide_ Best Practices and Tips.pdf
The Ultimate Test Automation Guide_ Best Practices and Tips.pdfkalichargn70th171
 
The Essentials of Digital Experience Monitoring_ A Comprehensive Guide.pdf
The Essentials of Digital Experience Monitoring_ A Comprehensive Guide.pdfThe Essentials of Digital Experience Monitoring_ A Comprehensive Guide.pdf
The Essentials of Digital Experience Monitoring_ A Comprehensive Guide.pdfkalichargn70th171
 
Professional Resume Template for Software Developers
Professional Resume Template for Software DevelopersProfessional Resume Template for Software Developers
Professional Resume Template for Software DevelopersVinodh Ram
 
Hand gesture recognition PROJECT PPT.pptx
Hand gesture recognition PROJECT PPT.pptxHand gesture recognition PROJECT PPT.pptx
Hand gesture recognition PROJECT PPT.pptxbodapatigopi8531
 
Alluxio Monthly Webinar | Cloud-Native Model Training on Distributed Data
Alluxio Monthly Webinar | Cloud-Native Model Training on Distributed DataAlluxio Monthly Webinar | Cloud-Native Model Training on Distributed Data
Alluxio Monthly Webinar | Cloud-Native Model Training on Distributed DataAlluxio, Inc.
 
Optimizing AI for immediate response in Smart CCTV
Optimizing AI for immediate response in Smart CCTVOptimizing AI for immediate response in Smart CCTV
Optimizing AI for immediate response in Smart CCTVshikhaohhpro
 
TECUNIQUE: Success Stories: IT Service provider
TECUNIQUE: Success Stories: IT Service providerTECUNIQUE: Success Stories: IT Service provider
TECUNIQUE: Success Stories: IT Service providermohitmore19
 
Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...
Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...
Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...stazi3110
 
Project Based Learning (A.I).pptx detail explanation
Project Based Learning (A.I).pptx detail explanationProject Based Learning (A.I).pptx detail explanation
Project Based Learning (A.I).pptx detail explanationkaushalgiri8080
 
A Secure and Reliable Document Management System is Essential.docx
A Secure and Reliable Document Management System is Essential.docxA Secure and Reliable Document Management System is Essential.docx
A Secure and Reliable Document Management System is Essential.docxComplianceQuest1
 
Engage Usergroup 2024 - The Good The Bad_The Ugly
Engage Usergroup 2024 - The Good The Bad_The UglyEngage Usergroup 2024 - The Good The Bad_The Ugly
Engage Usergroup 2024 - The Good The Bad_The UglyFrank van der Linden
 
Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...
Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...
Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...kellynguyen01
 
HR Software Buyers Guide in 2024 - HRSoftware.com
HR Software Buyers Guide in 2024 - HRSoftware.comHR Software Buyers Guide in 2024 - HRSoftware.com
HR Software Buyers Guide in 2024 - HRSoftware.comFatema Valibhai
 
EY_Graph Database Powered Sustainability
EY_Graph Database Powered SustainabilityEY_Graph Database Powered Sustainability
EY_Graph Database Powered SustainabilityNeo4j
 
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...ICS
 
Salesforce Certified Field Service Consultant
Salesforce Certified Field Service ConsultantSalesforce Certified Field Service Consultant
Salesforce Certified Field Service ConsultantAxelRicardoTrocheRiq
 
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdfLearn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdfkalichargn70th171
 

Recently uploaded (20)

What is Binary Language? Computer Number Systems
What is Binary Language?  Computer Number SystemsWhat is Binary Language?  Computer Number Systems
What is Binary Language? Computer Number Systems
 
Asset Management Software - Infographic
Asset Management Software - InfographicAsset Management Software - Infographic
Asset Management Software - Infographic
 
The Ultimate Test Automation Guide_ Best Practices and Tips.pdf
The Ultimate Test Automation Guide_ Best Practices and Tips.pdfThe Ultimate Test Automation Guide_ Best Practices and Tips.pdf
The Ultimate Test Automation Guide_ Best Practices and Tips.pdf
 
The Essentials of Digital Experience Monitoring_ A Comprehensive Guide.pdf
The Essentials of Digital Experience Monitoring_ A Comprehensive Guide.pdfThe Essentials of Digital Experience Monitoring_ A Comprehensive Guide.pdf
The Essentials of Digital Experience Monitoring_ A Comprehensive Guide.pdf
 
Professional Resume Template for Software Developers
Professional Resume Template for Software DevelopersProfessional Resume Template for Software Developers
Professional Resume Template for Software Developers
 
Hand gesture recognition PROJECT PPT.pptx
Hand gesture recognition PROJECT PPT.pptxHand gesture recognition PROJECT PPT.pptx
Hand gesture recognition PROJECT PPT.pptx
 
Alluxio Monthly Webinar | Cloud-Native Model Training on Distributed Data
Alluxio Monthly Webinar | Cloud-Native Model Training on Distributed DataAlluxio Monthly Webinar | Cloud-Native Model Training on Distributed Data
Alluxio Monthly Webinar | Cloud-Native Model Training on Distributed Data
 
Optimizing AI for immediate response in Smart CCTV
Optimizing AI for immediate response in Smart CCTVOptimizing AI for immediate response in Smart CCTV
Optimizing AI for immediate response in Smart CCTV
 
TECUNIQUE: Success Stories: IT Service provider
TECUNIQUE: Success Stories: IT Service providerTECUNIQUE: Success Stories: IT Service provider
TECUNIQUE: Success Stories: IT Service provider
 
Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...
Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...
Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...
 
Project Based Learning (A.I).pptx detail explanation
Project Based Learning (A.I).pptx detail explanationProject Based Learning (A.I).pptx detail explanation
Project Based Learning (A.I).pptx detail explanation
 
A Secure and Reliable Document Management System is Essential.docx
A Secure and Reliable Document Management System is Essential.docxA Secure and Reliable Document Management System is Essential.docx
A Secure and Reliable Document Management System is Essential.docx
 
Engage Usergroup 2024 - The Good The Bad_The Ugly
Engage Usergroup 2024 - The Good The Bad_The UglyEngage Usergroup 2024 - The Good The Bad_The Ugly
Engage Usergroup 2024 - The Good The Bad_The Ugly
 
Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...
Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...
Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...
 
Call Girls In Mukherjee Nagar 📱 9999965857 🤩 Delhi 🫦 HOT AND SEXY VVIP 🍎 SE...
Call Girls In Mukherjee Nagar 📱  9999965857  🤩 Delhi 🫦 HOT AND SEXY VVIP 🍎 SE...Call Girls In Mukherjee Nagar 📱  9999965857  🤩 Delhi 🫦 HOT AND SEXY VVIP 🍎 SE...
Call Girls In Mukherjee Nagar 📱 9999965857 🤩 Delhi 🫦 HOT AND SEXY VVIP 🍎 SE...
 
HR Software Buyers Guide in 2024 - HRSoftware.com
HR Software Buyers Guide in 2024 - HRSoftware.comHR Software Buyers Guide in 2024 - HRSoftware.com
HR Software Buyers Guide in 2024 - HRSoftware.com
 
EY_Graph Database Powered Sustainability
EY_Graph Database Powered SustainabilityEY_Graph Database Powered Sustainability
EY_Graph Database Powered Sustainability
 
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...
 
Salesforce Certified Field Service Consultant
Salesforce Certified Field Service ConsultantSalesforce Certified Field Service Consultant
Salesforce Certified Field Service Consultant
 
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdfLearn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
 

Python and Ruby implementations compared by the error density

  • 1. Python and Ruby implementations compared by the error density Author: Pavel Belikov Date: 22.07.2016 Which programming language to start learning? Python or Ruby? Which one is better? Django or Ruby on Rails? Such questions can often be found on IT forums around the world. I suggest comparing not the languages themselves, but their reference implementations: CPython and MRI. In this article, we are going to cover the errors that were found by PVS-Studio in these projects. Introduction We took the latest versions of the source code from the repositories (Ruby, Python) for the analysis. The project was scanned with PVS-Studio v6.06 static code analyzer. Python can be easily compiled in Visual Studio; for Ruby you can use a Standalone version in the compilation monitoring mode. There weren't very many glaring errors: the majority of warnings are connected with the usage of macros, which get expanded into quite a suspicious code, from the point of view of the analyzer, but rather innocent from a developer's point of view. We could start a long discussion on whether macros bring harm or good, but we can say for sure that the analyzer doesn't like them much. To get rid of some annoying macro, there is an option to suppress false positives. It's enough to write: //-V:RB_TYPE_P:501 And all the warnings by V501 diagnostic, where there is RB_TYPE_P macro will disappear.
  • 2. Python Fragment N1 #ifdef MS_WINDOWS typedef SOCKET SOCKET_T; #else typedef int SOCKET_T; #endif typedef struct { PyObject_HEAD SOCKET_T sock_fd; /* Socket file descriptor */ .... } PySocketSockObject; static int internal_select(PySocketSockObject *s, int writing, _PyTime_t interval, int connect) { .... if (s->sock_fd < 0) // <= return 0; .... } V547 Expression 's->sock_fd < 0' is always false. Unsigned type value is never < 0. socketmodule.c 655
  • 3. The SOCKET type in Windows is unsigned, so comparing it against null is meaningless. The check of the socket() function returned a correct descriptor, it's necessary to compare its value with INVALID_SOCKET. It is worth noting that this comparison would work correctly in Linux, because there as the socket type, we have a signed type int used, and the value -1 indicates an error. Nevertheless, it's better to use special macros or constants to check. Several more similar checks that the analyzer issued warnings for.  V547 Expression 's->sock_fd < 0' is always false. Unsigned type value is never < 0. _ssl.c 1702  V547 Expression 'sock->sock_fd < 0' is always false. Unsigned type value is never < 0. _ssl.c 2018 Fragment N2 int ASN1_PRINTABLE_type(const unsigned char *s, int len) { int c; int ia5 = 0; .... if (!(((c >= 'a') && (c <= 'z')) || ((c >= 'A') && (c <= 'Z')) || (c == ' ') || // <= ((c >= '0') && (c <= '9')) || (c == ' ') || (c == ''') || // <= (c == '(') || (c == ')') || (c == '+') || (c == ',') || (c == '-') || (c == '.') || (c == '/') || (c == ':') || (c == '=') || (c == '?'))) ia5 = 1; .... } V501 There are identical sub-expressions '(c == ' ')' to the left and to the right of the '||' operator. a_print.c 77 A typical example of an error that occurred as a result of Copy-Paste. Quite often, when using large amounts of copied blocks, a programmer's attention falters and they forget to change a variable or a constant in them. For example, in this case in a large conditional expression, the programmer confused the values that the variable c is compared with. We cannot say for sure, but it seems that the symbol of double quotation '"' was forgotten. Fragment N3 static PyObject * semlock_acquire(SemLockObject *self, PyObject *args, PyObject *kwds) { .... HANDLE handles[2], sigint_event; .... /* prepare list of handles */ nhandles = 0; handles[nhandles++] = self->handle; if (_PyOS_IsMainThread()) {
  • 4. sigint_event = _PyOS_SigintEvent(); assert(sigint_event != NULL); handles[nhandles++] = sigint_event; } /* do the wait */ Py_BEGIN_ALLOW_THREADS if (sigint_event != NULL) //<= ResetEvent(sigint_event); .... } V614 Potentially uninitialized pointer 'sigint_event' used. semaphore.c 120 In case the function _PyOS_IsMainThread() returns false, the pointer sigint_event will remain uninitialized. This will result in undefined behavior. Such an error can easily be overlooked in the debug version, where a pointer is most likely to be initialized by a null. Fragment N4 #define BN_MASK2 (0xffffffffffffffffLL) int BN_mask_bits(BIGNUM *a, int n) { .... a->d[w] &= ~(BN_MASK2 << b); //<= .... } V610 Undefined behavior. Check the shift operator '<<'. The left operand '(0xffffffffffffffffLL)' is negative. bn_lib.c 796 Despite the fact that the code works in most cases, this expression is considered to be undefined behavior according to the standard. You can find more details about the shifts of negative numbers in the article written by Andrey Karpov "Wade not in unknown waters. Part three". It's up to you to decide where it's necessary to avoid constructions whose results aren't guaranteed by the standard; but it's better not to do it at all; the analyzer agrees on that too. static PyObject * binascii_b2a_qp_impl(PyModuleDef *module, Py_buffer *data, int quotetabs, int istext, int header) { Py_ssize_t in, out; const unsigned char *databuf; .... if ((databuf[in] > 126) || (databuf[in] == '=') || (header && databuf[in] == '_') || ((databuf[in] == '.') && (linelen == 0) && (databuf[in+1] == 'n' || databuf[in+1] == 'r' ||
  • 5. databuf[in+1] == 0)) || (!istext && ((databuf[in] == 'r') || (databuf[in] == 'n'))) || ((databuf[in] == 't' || databuf[in] == ' ') && (in + 1 == datalen)) || ((databuf[in] < 33) && (databuf[in] != 'r') && (databuf[in] != 'n') && (quotetabs || (!quotetabs && ((databuf[in] != 't') && // <= (databuf[in] != ' ')))))) { .... } .... } V728 An excessive check can be simplified. The '||' operator is surrounded by opposite expressions 'quotetabs' and '!quotetabs'. binascii.c 1453 This fragment is not erroneous, nevertheless, we should take a closer look at it. The warning is mostly a recommendation: the expression 'A || (!A && B)' can be simplified to 'A || B': , which will make this quite complicated code easier to read. Similar warnings:  V728 An excessive check can be simplified. The '||' operator is surrounded by opposite expressions '!type' and 'type'. digest.c 167  V728 An excessive check can be simplified. The '||' operator is surrounded by opposite expressions '!cipher' and 'cipher'. evp_enc.c 120 Fragment N5 static int dh_cms_set_peerkey(....) { .... int atype; .... /* Only absent parameters allowed in RFC XXXX */ if (atype != V_ASN1_UNDEF && atype == V_ASN1_NULL) goto err; .... } V590 Consider inspecting the 'atype != - 1 && atype == 5' expression. The expression is excessive or contains a misprint. dh_ameth.c 670 It shouldn't seem odd, that errors in logical expressions occur even in large projects. A logical expression is excessive here, and it can be simplified to 'atype == V_ASN1_NULL'. Judging by the context, there is no error here, but such code looks really suspicious. Fragment N6 static void cms_env_set_version(CMS_EnvelopedData *env)
  • 6. { .... if (env->originatorInfo || env->unprotectedAttrs) env->version = 2; env->version = 0; } V519 The 'env->version' variable is assigned values twice successively. Perhaps this is a mistake. Check lines: 907, 908. cms_env.c 908 It's hard to say what the author meant writing this code. Perhaps else is omitted here. At this point there is no sense in if, as the value of the 'env->version' variable will be rewritten in any case. int _PyState_AddModule(PyObject* module, struct PyModuleDef* def) { PyInterpreterState *state; if (def->m_slots) { PyErr_SetString(PyExc_SystemError, "PyState_AddModule called on module with slots"); return -1; } state = GET_INTERP_STATE(); if (!def) return -1; .... } V595 The 'self->extra' pointer was utilized before it was verified against nullptr. Check lines: 917, 923. _elementtree.c 917 This is a traditional error, related to the null pointer dereferencing, which we find almost in every project. Firstly, in the expression 'def->m_slots' the programmer accessed by some address, and then it turned out that this address might have been null. As a result the verification against nullptr won't work, as we'll have the null pointer dereference, which will lead to undefined program behavior and to its crash, for instance. Ruby
  • 7. Fragment N1 static void vm_set_main_stack(rb_thread_t *th, const rb_iseq_t *iseq) { VALUE toplevel_binding = rb_const_get(rb_cObject, rb_intern("TOPLEVEL_BINDING")); rb_binding_t *bind; rb_env_t *env; GetBindingPtr(toplevel_binding, bind); GetEnvPtr(bind->env, env); vm_set_eval_stack(th, iseq, 0, &env->block); /* save binding */ if (bind && iseq->body->local_size > 0) { bind->env = vm_make_env_object(th, th->cfp); } } V595 The 'bind' pointer was utilized before it was verified against nullptr. Check lines: 377, 382. vm.c 377 A similar error was also encountered in the Ruby project. The check 'if (bind)' won't be of much help, because bind was dereferenced a little earlier in the code. There were more than 30 warnings of this kind, so there is no point in listing them all here. Fragment N2 static int code_page_i(....) { table = realloc(table, count * sizeof(*table));
  • 8. if (!table) return ST_CONTINUE; .... } V701 realloc() possible leak: when realloc() fails in allocating memory, original pointer 'table' is lost. Consider assigning realloc() to a temporary pointer. file.c 169 In this fragment we see that the value of realloc is saved in the same variable, which is used as an argument. In case realloc returns nullptr, the initial pointer value will be lost, which will lead to a memory leak. Fragment N3 static int w32_symlink(UINT cp, const char *src, const char *link) { .... BOOLEAN ret; typedef DWORD (WINAPI *create_symbolic_link_func) (WCHAR*, WCHAR*, DWORD); static create_symbolic_link_func create_symbolic_link = (create_symbolic_link_func)-1; .... ret = create_symbolic_link(wlink, wsrc, flag); ALLOCV_END(buf); if (!ret) { int e = GetLastError(); errno = map_errno(e); return -1; } return 0; } V724 Converting type 'DWORD' to type 'BOOLEAN' can lead to a loss of high-order bits. Non-zero value can become 'FALSE'. win32.c 4974 The BOOLEAN type is used in the WinAPI as a logical type. It is declared in the following way: typedef unsigned char BYTE; typedef BYTE BOOLEAN; DWORD is a 32-bit unsigned number. That's why if we cast DWORD 0xffffff00 value to BOOLEAN (or any other, whose lowest bit is zero), then it will become 0, i.e. FALSE. Fragment N4 static VALUE rb_str_split_m(int argc, VALUE *argv, VALUE str) { .... char *ptr = RSTRING_PTR(str);
  • 9. long len = RSTRING_LEN(str); long start = beg; .... if (ptr+start == ptr+len) start++; .... } V584 The 'ptr' value is present on both sides of the '==' operator. The expression is incorrect or it can be simplified. string.c 7211 In both parts of the comparison we have ptr addition, therefore it can be removed: if (start == len) But most likely, there is no error in this fragment. However, we see quite often that programmers compare two different variables in such expressions. That's why such comparisons are always worth reviewing. Overall results Having analyzed all the warnings of the general analysis diagnostics, and removed all the false positives, I have come to the following conclusion concerning the error density: The majority of warnings in Ruby were issued by the V610 diagnostic (369 warnings!), but even if we exclude them, the situation won't change much: Python takes the lead over Ruby in the number of suspicious fragments. The most frequent diagnostic turned out to be V595 - there were 17 warnings in Python, and 37 in Ruby.
  • 10. Of course, it's much more interesting to look at the error density ratio. Python also leaves Ruby well behind in this category. Here are the results of the evaluations presented as a table: It may seem that the number of errors is quite large. But it is not so. Firstly, not all of the bugs are critical. For example, the V610 diagnostic that we have already mentioned, detects errors from the point of view of the C++ language. However, in practice for the set of compilers the result can always be correct. Although these errors are still bugs, they don't affect the program in any way. Secondly, we should take into account the size of the code. That's why we can say that the quality of these projects is rather high. At this point this may be rather subjective, because previously we haven't evaluated the error density of these projects. We'll try to do that in the future, so that we can later compare the result of the checks. Conclusion Python and Ruby are extremely popular: millions of developers use them to write code. It's hard to find a large number of errors in a project when it is so actively used, regularly tested by another static analysis tool (both projects get checked by Coverity) and has community support. Nonetheless, PVS-Studio managed to find several suspicious fragments. We should understand that these are regular checks which can make the life of programmers much easier. The ideal, is to fix the error before the edits get to repository and release - and a static analyzer can help best of all here. I suggest running PVS-Studio on your projects.