SlideShare a Scribd company logo
1 of 14
Download to read offline
PVS-Studio team is about to produce a
technical breakthrough, but for now let's
recheck Blender
Author: Alexander Chibisov
Date: 21.07.2016
Static analysis is most useful when it is done on a regular basis. Especially when the project is rapidly
developing, like the Blender project, for example. Now it's time to check it once more, and see what
suspicious fragments we'll find this time.
Introduction
Blender is a free, open source professional 3D creation suite. It supports the entirety of the 3D
pipeline—modeling, rigging, animation, simulation, rendering, compositing, and motion tracking; even
video editing and game creation.
We have already checked this project before. You may find the results of the previous check of v2.62 in
the article "Analyzing the Blender project with PVS-Studio".
Since the last time we checked it, the size of the source code, including additional libraries, increased to
77 mb. Its codebase is now 2206 KLOC. At the time of the previous check the project was 68 mb (2105
KLOC).
The SourceMonitor utility was a great help to me in evaluating the codebase size. This utility is able to
analyze the code in C++, C, C #, VB.NET, Java, and Delphi, and is able to evaluate various metrics. For
example, it can determine the cyclomatic complexity of your projects, as well as generate detailed
statistics for each of the project files, and show the results as a table or diagrams.
So this article is about errors and suspicious fragments that were found in Blender, v2.77a. To do the
analysis, we used PVS-Studio 6.05
Typos
During the active usage of copying mechanism and automatic code completion, you may have errors in
the names of various variables and constants. Such errors can result in incorrect evaluation results or
unexpected program behavior. In the Blender project there were several such examples. Let's take a
closer look.
A typo in the condition
CurvePoint::CurvePoint(CurvePoint *iA, CurvePoint *iB, float t3)
{
....
if ((iA->getPoint2D() - //<=
iA->getPoint2D()).norm() < 1.0e-6) { //<=
....
}
....
}
V501 There are identical sub-expressions to the left and to the right of the '-' operator: iA->getPoint2D()
- iA->getPoint2D() curve.cpp 136
Inside the CurvePoint function the program handles two objects with similar names - iA and iB. Different
methods of these objects get intersected all the time in various operations in quite a long tree of
conditions. There is a typo in one of these conditional blocks. As a result we have a subtraction
operation between the properties of one and the same object. Without knowing the peculiarities of the
code, it's quite hard to say, in which operand we have an error. I can suggest two variants of how to fix
it:
if ((iA->getPoint2D()-iB->getPoint2D()).norm()<1.0e-6)....
or
if ((iB->getPoint2D()-iA->getPoint2D()).norm()<1.0e-6)....
The following error was also hiding inside a conditional statement.
template<typename MatrixType, int QRPreconditioner>
void JacobiSVD<MatrixType, QRPreconditioner>::allocate(....)
{
....
if(m_cols>m_rows)m_qr_precond_morecols.allocate(*this);
if(m_rows>m_cols)m_qr_precond_morerows.allocate(*this);
if(m_cols!=m_cols)m_scaledMatrix.resize(rows,cols); //<=
}
V501 There are identical sub-expressions to the left and right of the '!=' operator: m_cols != m_cols
jacobisvd.h 819
In the given fragment, you can see the equalization of the number of rows and columns inside some
matrix. If the quantity isn't the same, the program allocates memory for new elements and creates
them. Later, if new cells are added, there is an operation of altering the matrix size. Unfortunately, due
to the error in the conditional statement the operation will never be executed, because the condition
m_cols!=m_cols is always false. In this case it doesn't matter which part is changed, so I suggest the
following variant:
if(m_cols!=m_rows) m_scaledMatrix.resize(rows,cols)
Several more problem areas were detected by the V501 diagnostic:
 V501 There are identical sub-expressions to the left and to the right of the '==' operator:
left.rows() == left.rows() numeric.cc 112
 V501 There are identical sub-expressions to the left and to the right of the '>' operator:
(from[0][3]) > (from[0][3]) stereoimbuf.c 120
 V501 There are identical sub-expressions to the left and to the right of the '>' operator:
(from[0][3]) > (from[0][3]) stereoimbuf.c 157
 V501 There are identical sub-expressions to the left and to the right of the '==' operator: out->y
== out->y filter.c 209
Null pointer handling
The typo in the names had more serious consequences.
int QuantitativeInvisibilityF1D::operator()(....)
{
ViewEdge *ve = dynamic_cast<ViewEdge*>(&inter);
if (ve) {
result = ve->qi();
return 0;
}
FEdge *fe = dynamic_cast<FEdge*>(&inter);
if (fe) {
result = ve->qi(); //<=
return 0;
}
....
}
V522 Dereferencing of the null pointer 've' might take place. functions1d.cpp 107
This function is fairly short, but typos can trap us, even in simple functions. We can see in the code that
two objects get created and checked. However, after the check of the second object, an error occurred,
and even if fe was successfully created, instead of it, the result of function work from the first object is
written to the result; according to the previous conditions, this object wasn't created at all. This will
most likely lead to a crash of the program if this exception isn't caught by a handler of a higher level.
Apparently, the second code fragment was written using Copy-Paste. By accident the programmer
forgot to change the variable name ve. The correct code should probably be like this:
FEdge *fe = dynamic_cast<FEdge*>(&inter);
if (fe) {
result = fe->qi();
return 0;
}
Null pointer usage
static ImBuf *accessor_get_ibuf(....)
{
ImBuf *ibuf, *orig_ibuf, *final_ibuf;
....
/* First try to get fully processed image from the cache. */
ibuf = accesscache_get(accessor,
clip_index,
frame,
input_mode,
downscale,
transform_key);
if (ibuf != NULL) {
return ibuf;
}
/* And now we do postprocessing of the original frame. */
orig_ibuf = accessor_get_preprocessed_ibuf(accessor,
clip_index,
frame);
if (orig_ibuf == NULL) {
return NULL;
}
....
if (downscale > 0) {
if (final_ibuf == orig_ibuf) {
final_ibuf = IMB_dupImBuf(orig_ibuf);
}
IMB_scaleImBuf(final_ibuf,
ibuf->x / (1 << downscale), //<=
ibuf->y / (1 << downscale)); //<=
}
....
if (input_mode == LIBMV_IMAGE_MODE_RGBA) {
BLI_assert(ibuf->channels == 3 || //<=
ibuf->channels == 4); //<=
}
....
return final_ibuf;
}
Warnings:
 V522 Dereferencing of the null pointer 'ibuf' might take place. tracking_util.c 765
 V522 Dereferencing of the null pointer 'ibuf' might take place. tracking_util.c 766
 V522 Dereferencing of the null pointer 'ibuf' might take place. tracking_util.c 783
In the fragment given above, you can see that the check of ibuf variable interrupts the function much
sooner than this variable is used if the object was created. We could probably stop here and confirm the
fact of a pointer dereferencing. At the same time, if we do a more painstaking examination of the code
and the comments to it, we see a true reason for the error. This is a typo, again. In the fragments
indicated by the analyzer, the programmer should have used the variable orig_ibuf instead of ibuf.
Incorrect variable type
typedef enum eOutlinerIdOpTypes {
OUTLINER_IDOP_INVALID = 0,
OUTLINER_IDOP_UNLINK,
OUTLINER_IDOP_LOCAL,
....
} eOutlinerIdOpTypes;
typedef enum eOutlinerLibOpTypes {
OL_LIB_INVALID = 0,
OL_LIB_RENAME,
OL_LIB_DELETE,
} eOutlinerLibOpTypes;
static int outliner_lib_operation_exec(....)
{
....
eOutlinerIdOpTypes event; //<=
....
event = RNA_enum_get(op->ptr, "type");
switch (event) {
case OL_LIB_RENAME: //<=
{
....
}
case OL_LIB_DELETE: //<=
{
....
}
default:
/* invalid - unhandled */
break;
}
....
}
Warnings:
 V556 The values of different enum types are compared: switch(ENUM_TYPE_A) { case
ENUM_TYPE_B: ... }. outliner_tools.c 1286
 V556 The values of different enum types are compared: switch(ENUM_TYPE_A) { case
ENUM_TYPE_B: ... }. outliner_tools.c 1295
In this example you can see two types that are enumerations. It's quite an expected fact that there was
a typo in the names that are almost the same.
In fact, the code works correctly. At the same time it confuses us by the mismatch of the types. The
variable gets a value of an enumeration, and is compared with the constants of a different one. To
correct this error it's enough to change the type of the variable event to eOutlinerLibOpTypes.
Operation precedence error
static void blf_font_draw_buffer_ex(....)
{
....
cbuf[3] = (unsigned char)((alphatest = ((int)cbuf[3] +
(int)(a * 255)) < 255) ? alphatest : 255);
....
}
V593 Consider reviewing the expression of the 'A = B < C' kind. The expression is calculated as following:
'A = (B < C)'. blf_font.c 414
Failure to comply with the operation precedence is one of the most common errors when working with
complex expressions. In this case it's just a typo, but it led to a breach of the logic of the ternary
operator. Due to an incorrectly put parentheses, there was an operation precedence error. On top of
that, the value of alphatest variable also gets damaged. Instead of the value, which is evaluated by the
ternary operator, the alphatest variable is assigned with a value of bool-type that was obtained in the
result of a comparison operation. Only after that the ternary operator works with the value of the
alphatest variable, and the result doesn't get saved. To fix this bug, we should change the expression as
follows:
cbuf[3] = (unsigned char)(alphatest = (((int)cbuf[3] +
(int)(a * 255)) < 255) ? alphatest : 255);
Invalid constant
bool BKE_ffmpeg_alpha_channel_is_supported(RenderData *rd)
{
int codec = rd->ffcodecdata.codec;
if (codec == AV_CODEC_ID_QTRLE)
return true;
if (codec == AV_CODEC_ID_PNG)
return true;
if (codec == AV_CODEC_ID_PNG)
return true;
....
}
V649 There are two 'if' statements with identical conditional expressions. The first 'if' statement
contains function return. This means that the second 'if' statement is senseless. Check lines: 1672, 1675.
writeffmpeg.c 1675
We see a successive check of the variable value to match the flag with the help of single-line conditions.
Because of the typo one of the flags gets checked twice. Most likely, a different constant should have
been checked instead of a repeated check. There are a lot of variants of these constants that's why it's
hard to say how this code should be fixed.
Using one variable in an outer and inner loop
bool BM_face_exists_overlap_subset(...., const int len)
{
int i;
....
for (i = 0; i < len; i++) {
BM_ITER_ELEM (f, &viter, varr[i], BM_FACES_OF_VERT) {
if ((f->len <= len) && (....)) {
BMLoop *l_iter, *l_first;
if (is_init == false) {
is_init = true;
for (i = 0; i < len; i++) { //<=
BM_ELEM_API_FLAG_ENABLE(varr[i], _FLAG_OVERLAP);
}
}
....
}
}
}
}
V535 The variable 'i' is being used for this loop and for the outer loop. Check lines: 2204, 2212.
bmesh_queries.c 2212
Using the same variable in the outer and inner loop may lead to incorrect execution of the outer loop. In
this case this will less likely be an error, as the loop is probably looking for the necessary element and
exits, and the second loop is triggered only in this case. But still, using a single variable is a dangerous
trick and may lead to real errors if there is a necessity to optimize this code fragment.
Redundant code
Excessive code fragments can be found in any program. Sometimes this is old code that was forgotten
after refactoring. But at times those extra fragments serve as a way to keep up the project style. Such
fragments can be quite dangerous. In other words, duplicate code often indicates the presence of logical
errors.
Double check
static void knife_add_single_cut(....)
{
....
if ((lh1->v && lh2->v) && //<=
(lh1->v->v && lh2->v && lh2->v->v) && //<=
(e_base = BM_edge_exists(lh1->v->v, lh2->v->v)))
{
....
return;
}
....
}
V501 There are identical sub-expressions 'lh2->v' to the left and right of the '&&' operator.
editmesh_knife.c 781
This is one of the variants of a condition that wasn't thought out well. It's certainly not a mistake, just an
extra check, but that doesn't mean that the code does not need additional review. The condition
consists of several expressions. At the same time a part of the second expression is the same as the
check of one variable from the first expression, so it's not needed here. To fix this code we need to
remove the excessive check lh2->v from the second expression. After that the code will become much
easier to read.
Another example:
static int edbm_rip_invoke__vert(....)
{
....
if (do_fill) {
if (do_fill) {
....
}
}
....
}
V571 Recurring check. The 'if (do_fill)' condition was already verified in line 751. editmesh_rip.c 752
One more variant of a logical error. Absolutely identical expressions are checked inside an outer and
inner condition. The double check will always give the same result, which makes no sense. Of course,
this code does not affect the program work in any way. But it's not clear how this code will change over
time, and extra checks can mislead a person in the future.
Unnecessary checks can be found in several fragments of the project. Here are several more spots,
detected by the analyzer:
 V571 Recurring check. The 'but' condition was already verified in line 9587. interface_handlers.c
9590
 V571 Recurring check. The '!me->mloopcol' condition was already verified in line 252.
paint_vertex.c 253
 V571 Recurring check. The 'constinv == 0' condition was already verified in line 5256.
transform_conversions.c 5257
 V571 Recurring check. The 'vlr->v4' condition was already verified in line 4174. convertblender.c
4176
 V571 Recurring check. The 'ibuf == ((void *) 0)' condition was already verified in line 3557.
sequencer.c 3559
And the third example is obviously redundant code:
static void writedata_do_write(....)
{
if ((wd == NULL) || wd->error ||
(mem == NULL) || memlen < 1) return;
if (wd->error) return;
....
}
V649 There are two 'if' statements with identical conditional expressions. The first 'if' statement
contains function return. This means that the second 'if' statement is senseless. Check lines: 331, 332.
writefile.c 332
The string if (wd->error) return; is excessive, and the function will exit earlier than this condition will be
handled. And so, it should just be removed.
Opposite condition blocks
static int select_less_exec(....)
{
....
if ((lastsel==0)&&(bp->hide==0)&&(bp->f1 & SELECT)){
if (lastsel != 0) sel = 1;
else sel = 0;
....
}
....
}
V637 Two opposite conditions were encountered. The second condition is always false. Check lines: 938,
939. editcurve_select.c 938
In the fragment we can see that there is an extra condition inside an outer condition block. The inner
condition is opposite the main one and always gives the same result; the sel variable will never be 1.
Therefore, it is enough to simply write sel = 0 without additional check. Although this error may have
been fixed by changing one of the expressions. Since I didn't take part in the creation of this project, it's
hard for me to say for sure.
Redundant expressions
DerivedMesh *fluidsimModifier_do(....)
{
....
if (!fluidmd || (fluidmd && !fluidmd->fss))
return dm;
....
}
V728 An excessive check can be simplified. The '||' operator is surrounded by opposite expressions
'!fluidmd' and 'fluidmd'. mod_fluidsim_util.c 528
Opposite values of one and the same variable are checked under one condition. Such conditions are
often found of different kinds and variations. They don't cause any harm to the software, but they can
complicate the code. This expression can be simplified and written as follows:
if (!fluidmd || !fluidmd->fss)) ....
Similar fragments:
 V728 An excessive check can be simplified. The '||' operator is surrounded by opposite
expressions '!render_only' and 'render_only'. drawobject.c 4663
 V728 An excessive check can be simplified. The '||' operator is surrounded by opposite
expressions '!parent' and 'parent'. kx_scene.cpp 1667
One more such a condition:
void ED_transverts_create_from_obedit(....)
{
....
if ((tipsel && rootsel) || (rootsel)) {....}
....
}
V686 A pattern was detected: (rootsel) || ((rootsel) && ...). The expression is excessive or contains a
logical error. ed_transverts.c 325
As in the example given above, the same variable is checked twice inside one expression. This
expression is not an erroneous one, but it definitely has an extra check. Let's simplify it to make it more
compact and easy-to-read.
if ((tipsel || rootsel) {....}
There were such errors in other places in the project.
 V686 A pattern was detected: (!py_b_len) || ((!py_b_len) && ...). The expression is excessive or
contains a logical error. aud_pyapi.cpp 864
 V686 A pattern was detected: (xn == 0.0f) || ((xn == 0.0f) && ...). The expression is excessive or
contains a logical error. renderdatabase.c 993
 V686 A pattern was detected: (xn == 0.0f) || ((xn == 0.0f) && ...). The expression is excessive or
contains a logical error. renderdatabase.c 1115
Iterative assignment
static bool find_prev_next_keyframes(....)
{
....
do {
aknext = (ActKeyColumn *)BLI_dlrbTree_search_next(
&keys, compare_ak_cfraPtr, &cfranext);
if (aknext) {
if (CFRA == (int)aknext->cfra) {
cfranext = aknext->cfra; //<-
}
else {
if (++nextcount == U.view_frame_keyframes)
donenext = true;
}
cfranext = aknext->cfra; //<-
}
} while ((aknext != NULL) && (donenext == false));
....
}
V519 The 'cfranext' variable is assigned values twice successively. Perhaps this is a mistake. Check lines:
447, 454. anim_draw.c 454
The assignment inside conditional blocks makes no sense, because its value is assigned again in the end
of the loop without any condition. A loop, placed in the code right after the given fragment helps us
draw the conclusion that the excessive string is placed above. It differs only in the prev variables, and
the absence of this string in the condition. Moreover, assuming that the extra string is underneath, and
the condition CFRA == (int)aknext->cfra turns out to be false, then this loop will become an infinite one.
This fragment really needs some fixing, but how to do it exactly - only the developers of the project
know.
Extra or unused variables
There were many such fragments with initialized, but unused, variables in the project. Some of them can
be considered as logical errors and excessive checks, but we have already spoken about them a lot.
There are also constants that probably should have been changed inside the functions. But as a result
they are just checks, always returning the same result. An example of such a fragment:
static int rule_avoid_collision(....)
{
....
int n, neighbors = 0, nearest = 0; //<=
....
if (ptn && nearest==0) //<=
MEM_freeN(ptn);
return ret;
}
V560 A part of conditional expression is always true: nearest == 0. boids.c 361
I'll just provide the other fragments as a list. Perhaps some of them are debatable, but they are worth
paying attention to.
 V560 A part of conditional expression is always true: edit == 0. particle.c 3781
 V560 A part of conditional expression is always true: !error. pointcache.c 154
 V560 A part of conditional expression is always true: !error. pointcache.c 2742
 V560 A part of conditional expression is always false: col. drawobject.c 7803
 V560 A part of conditional expression is always false: !canvas_verts. dynamicpaint.c 4636
 V560 A part of conditional expression is always true: (!leaf). octree.cpp 2513
 V560 A part of conditional expression is always true: (!leaf). octree.cpp 2710
 V560 A part of conditional expression is always false: (1 == i). basicstrokeshaders.cpp 67
 V560 A part of conditional expression is always true: (0 == i). basicstrokeshaders.cpp 69
 V560 A part of conditional expression is always false: (1 == i). basicstrokeshaders.cpp 84
 V560 A part of conditional expression is always true: (0 == i). basicstrokeshaders.cpp 86
 V560 A part of conditional expression is always false: (1 == i). basicstrokeshaders.cpp 155
 V560 A part of conditional expression is always true: (0 == i). basicstrokeshaders.cpp 157
 V560 A part of conditional expression is always true: (!radmod). solver_control.cpp 557
 V560 A part of conditional expression is always true: done != 1. context.c 301
 V560 A part of conditional expression is always true: is_tablet == false. ghost_systemwin32.cpp
665
 V560 A part of conditional expression is always true: mesh >= 0. kx_gameobject.cpp 976
Extra clearing of the list
int TileManager::gen_tiles(bool sliced)
{
....
state.tiles.clear(); //<=
....
int tile_index = 0;
state.tiles.clear();
state.tiles.resize(num);
....
}
V586 The 'clear' function is called twice for deallocation of the same resource. Check lines: 149, 156.
tile.cpp 156
In this case, it might just be the extra line. There probably used to be some code between the two list
clearings, but in this case it's just another useless fragment that should be removed so that the code
isn't cluttered up. This string can be a consequence of the fact that some other object should be cleared
in it, which is not seen at first glance. In this case the fragment will be a real error that may lead to
unexpected results for the program.
Very often such seemingly redundant code may lead to really serious errors, or my help avoiding them
in the future during further modifications. This is why you should pay attention to these analyzer
warnings, and not mark them as "unimportant".
Intrigue
PVS-Studio Team is now actively working on a new direction in development. And I am covering backs,
filling the information field with articles about the rechecking of some open source projects. What is the
direction that we are talking about? I cannot say. I'll just leave a picture here that you are free to
interpret as you wish.
Conclusion
The analyzer detected quite a number of troublesome spots in the project. However, at times, the
coding style in Blender is quite strange and we cannot say for sure that these are errors. In my opinion,
dangerous errors often occur because of typos. PVS-Studio is especially good at catching such bugs.
Those bugs, described in this article reflect the personal opinion of the author which is quite subjective.
To see the full range of analyzer abilities, you should download it, and try it out yourself.

More Related Content

What's hot

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
 
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
 
Python and Ruby implementations compared by the error density
Python and Ruby implementations compared by the error densityPython and Ruby implementations compared by the error density
Python and Ruby implementations compared by the error densityPVS-Studio
 
Dusting the globe: analysis of NASA World Wind project
Dusting the globe: analysis of NASA World Wind projectDusting the globe: analysis of NASA World Wind project
Dusting the globe: analysis of NASA World Wind projectPVS-Studio
 
Checking the Source Code of FlashDevelop with PVS-Studio
Checking the Source Code of FlashDevelop with PVS-StudioChecking the Source Code of FlashDevelop with PVS-Studio
Checking the Source Code of FlashDevelop with PVS-StudioPVS-Studio
 
Checking OpenCV with PVS-Studio
Checking OpenCV with PVS-StudioChecking OpenCV with PVS-Studio
Checking OpenCV with PVS-StudioPVS-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
 
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
 
Tesseract. Recognizing Errors in Recognition Software
Tesseract. Recognizing Errors in Recognition SoftwareTesseract. Recognizing Errors in Recognition Software
Tesseract. Recognizing Errors in Recognition SoftwareAndrey Karpov
 
Date Processing Attracts Bugs or 77 Defects in Qt 6
Date Processing Attracts Bugs or 77 Defects in Qt 6Date Processing Attracts Bugs or 77 Defects in Qt 6
Date Processing Attracts Bugs or 77 Defects in Qt 6Andrey Karpov
 
PVS-Studio Meets Octave
PVS-Studio Meets Octave PVS-Studio Meets Octave
PVS-Studio Meets Octave PVS-Studio
 
Linux version of PVS-Studio couldn't help checking CodeLite
Linux version of PVS-Studio couldn't help checking CodeLiteLinux version of PVS-Studio couldn't help checking CodeLite
Linux version of PVS-Studio couldn't help checking CodeLitePVS-Studio
 
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
 
Brief analysis of Media Portal 2 bugs
Brief analysis of Media Portal 2 bugsBrief analysis of Media Portal 2 bugs
Brief analysis of Media Portal 2 bugsPVS-Studio
 
2.overview of c#
2.overview of c#2.overview of c#
2.overview of c#Raghu nath
 
Checking WinMerge with PVS-Studio for the second time
Checking WinMerge with PVS-Studio for the second timeChecking WinMerge with PVS-Studio for the second time
Checking WinMerge with PVS-Studio for the second timePVS-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
 
A Post About Analyzing PHP
A Post About Analyzing PHPA Post About Analyzing PHP
A Post About Analyzing PHPAndrey Karpov
 
Intel IPP Samples for Windows - error correction
Intel IPP Samples for Windows - error correctionIntel IPP Samples for Windows - error correction
Intel IPP Samples for Windows - error correctionPVS-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
 

What's hot (20)

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 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
 
Python and Ruby implementations compared by the error density
Python and Ruby implementations compared by the error densityPython and Ruby implementations compared by the error density
Python and Ruby implementations compared by the error density
 
Dusting the globe: analysis of NASA World Wind project
Dusting the globe: analysis of NASA World Wind projectDusting the globe: analysis of NASA World Wind project
Dusting the globe: analysis of NASA World Wind project
 
Checking the Source Code of FlashDevelop with PVS-Studio
Checking the Source Code of FlashDevelop with PVS-StudioChecking the Source Code of FlashDevelop with PVS-Studio
Checking the Source Code of FlashDevelop with PVS-Studio
 
Checking OpenCV with PVS-Studio
Checking OpenCV with PVS-StudioChecking OpenCV with PVS-Studio
Checking OpenCV with PVS-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' Request
 
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
 
Tesseract. Recognizing Errors in Recognition Software
Tesseract. Recognizing Errors in Recognition SoftwareTesseract. Recognizing Errors in Recognition Software
Tesseract. Recognizing Errors in Recognition Software
 
Date Processing Attracts Bugs or 77 Defects in Qt 6
Date Processing Attracts Bugs or 77 Defects in Qt 6Date Processing Attracts Bugs or 77 Defects in Qt 6
Date Processing Attracts Bugs or 77 Defects in Qt 6
 
PVS-Studio Meets Octave
PVS-Studio Meets Octave PVS-Studio Meets Octave
PVS-Studio Meets Octave
 
Linux version of PVS-Studio couldn't help checking CodeLite
Linux version of PVS-Studio couldn't help checking CodeLiteLinux version of PVS-Studio couldn't help checking CodeLite
Linux version of PVS-Studio couldn't help checking CodeLite
 
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.
 
Brief analysis of Media Portal 2 bugs
Brief analysis of Media Portal 2 bugsBrief analysis of Media Portal 2 bugs
Brief analysis of Media Portal 2 bugs
 
2.overview of c#
2.overview of c#2.overview of c#
2.overview of c#
 
Checking WinMerge with PVS-Studio for the second time
Checking WinMerge with PVS-Studio for the second timeChecking WinMerge with PVS-Studio for the second time
Checking WinMerge with PVS-Studio for the second time
 
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
 
A Post About Analyzing PHP
A Post About Analyzing PHPA Post About Analyzing PHP
A Post About Analyzing PHP
 
Intel IPP Samples for Windows - error correction
Intel IPP Samples for Windows - error correctionIntel IPP Samples for Windows - error correction
Intel IPP Samples for Windows - error correction
 
Why Windows 8 drivers are buggy
Why Windows 8 drivers are buggyWhy Windows 8 drivers are buggy
Why Windows 8 drivers are buggy
 

Similar to PVS-Studio team is about to produce a technical breakthrough, but for now let's recheck Blender

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
 
PVS-Studio vs Chromium. 3-rd Check
PVS-Studio vs Chromium. 3-rd CheckPVS-Studio vs Chromium. 3-rd Check
PVS-Studio vs Chromium. 3-rd CheckAndrey Karpov
 
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
 
Analysis of Haiku Operating System (BeOS Family) by PVS-Studio. Part 1
Analysis of Haiku Operating System (BeOS Family) by PVS-Studio. Part 1Analysis of Haiku Operating System (BeOS Family) by PVS-Studio. Part 1
Analysis of Haiku Operating System (BeOS Family) by PVS-Studio. Part 1PVS-Studio
 
A Spin-off: Firebird Checked by PVS-Studio
A Spin-off: Firebird Checked by PVS-StudioA Spin-off: Firebird Checked by PVS-Studio
A Spin-off: Firebird Checked by PVS-StudioAndrey Karpov
 
Headache from using mathematical software
Headache from using mathematical softwareHeadache from using mathematical software
Headache from using mathematical softwarePVS-Studio
 
Analyzing ReactOS One More Time
Analyzing ReactOS One More TimeAnalyzing ReactOS One More Time
Analyzing ReactOS One More TimePVS-Studio
 
Re-checking the ReactOS project - a large report
Re-checking the ReactOS project - a large reportRe-checking the ReactOS project - a large report
Re-checking the ReactOS project - a large reportPVS-Studio
 
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
 
Picking Mushrooms after Cppcheck
Picking Mushrooms after CppcheckPicking Mushrooms after Cppcheck
Picking Mushrooms after CppcheckAndrey 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
 
Checking Clang 11 with PVS-Studio
Checking Clang 11 with PVS-StudioChecking Clang 11 with PVS-Studio
Checking Clang 11 with PVS-StudioAndrey 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
 
Looking for Bugs in MonoDevelop
Looking for Bugs in MonoDevelopLooking for Bugs in MonoDevelop
Looking for Bugs in MonoDevelopPVS-Studio
 
Errors that static code analysis does not find because it is not used
Errors that static code analysis does not find because it is not usedErrors that static code analysis does not find because it is not used
Errors that static code analysis does not find because it is not usedAndrey Karpov
 
The Little Unicorn That Could
The Little Unicorn That CouldThe Little Unicorn That Could
The Little Unicorn That CouldPVS-Studio
 
"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
 
Accord.Net: Looking for a Bug that Could Help Machines Conquer Humankind
Accord.Net: Looking for a Bug that Could Help Machines Conquer HumankindAccord.Net: Looking for a Bug that Could Help Machines Conquer Humankind
Accord.Net: Looking for a Bug that Could Help Machines Conquer HumankindPVS-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
 
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
 

Similar to PVS-Studio team is about to produce a technical breakthrough, but for now let's recheck Blender (20)

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
 
PVS-Studio vs Chromium. 3-rd Check
PVS-Studio vs Chromium. 3-rd CheckPVS-Studio vs Chromium. 3-rd Check
PVS-Studio vs Chromium. 3-rd Check
 
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
 
Analysis of Haiku Operating System (BeOS Family) by PVS-Studio. Part 1
Analysis of Haiku Operating System (BeOS Family) by PVS-Studio. Part 1Analysis of Haiku Operating System (BeOS Family) by PVS-Studio. Part 1
Analysis of Haiku Operating System (BeOS Family) by PVS-Studio. Part 1
 
A Spin-off: Firebird Checked by PVS-Studio
A Spin-off: Firebird Checked by PVS-StudioA Spin-off: Firebird Checked by PVS-Studio
A Spin-off: Firebird Checked by PVS-Studio
 
Headache from using mathematical software
Headache from using mathematical softwareHeadache from using mathematical software
Headache from using mathematical software
 
Analyzing ReactOS One More Time
Analyzing ReactOS One More TimeAnalyzing ReactOS One More Time
Analyzing ReactOS One More Time
 
Re-checking the ReactOS project - a large report
Re-checking the ReactOS project - a large reportRe-checking the ReactOS project - a large report
Re-checking the ReactOS project - a large report
 
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
 
Picking Mushrooms after Cppcheck
Picking Mushrooms after CppcheckPicking Mushrooms after Cppcheck
Picking Mushrooms after Cppcheck
 
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
 
Checking Clang 11 with PVS-Studio
Checking Clang 11 with PVS-StudioChecking Clang 11 with PVS-Studio
Checking Clang 11 with PVS-Studio
 
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)
 
Looking for Bugs in MonoDevelop
Looking for Bugs in MonoDevelopLooking for Bugs in MonoDevelop
Looking for Bugs in MonoDevelop
 
Errors that static code analysis does not find because it is not used
Errors that static code analysis does not find because it is not usedErrors that static code analysis does not find because it is not used
Errors that static code analysis does not find because it is not used
 
The Little Unicorn That Could
The Little Unicorn That CouldThe Little Unicorn That Could
The Little Unicorn That Could
 
"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 ...
 
Accord.Net: Looking for a Bug that Could Help Machines Conquer Humankind
Accord.Net: Looking for a Bug that Could Help Machines Conquer HumankindAccord.Net: Looking for a Bug that Could Help Machines Conquer Humankind
Accord.Net: Looking for a Bug that Could Help Machines Conquer Humankind
 
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
 
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
 

Recently uploaded

Hand gesture recognition PROJECT PPT.pptx
Hand gesture recognition PROJECT PPT.pptxHand gesture recognition PROJECT PPT.pptx
Hand gesture recognition PROJECT PPT.pptxbodapatigopi8531
 
Unit 1.1 Excite Part 1, class 9, cbse...
Unit 1.1 Excite Part 1, class 9, cbse...Unit 1.1 Excite Part 1, class 9, cbse...
Unit 1.1 Excite Part 1, class 9, cbse...aditisharan08
 
DNT_Corporate presentation know about us
DNT_Corporate presentation know about usDNT_Corporate presentation know about us
DNT_Corporate presentation know about usDynamic Netsoft
 
5 Signs You Need a Fashion PLM Software.pdf
5 Signs You Need a Fashion PLM Software.pdf5 Signs You Need a Fashion PLM Software.pdf
5 Signs You Need a Fashion PLM Software.pdfWave PLM
 
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
 
Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...
Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...
Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...MyIntelliSource, Inc.
 
XpertSolvers: Your Partner in Building Innovative Software Solutions
XpertSolvers: Your Partner in Building Innovative Software SolutionsXpertSolvers: Your Partner in Building Innovative Software Solutions
XpertSolvers: Your Partner in Building Innovative Software SolutionsMehedi Hasan Shohan
 
Building Real-Time Data Pipelines: Stream & Batch Processing workshop Slide
Building Real-Time Data Pipelines: Stream & Batch Processing workshop SlideBuilding Real-Time Data Pipelines: Stream & Batch Processing workshop Slide
Building Real-Time Data Pipelines: Stream & Batch Processing workshop SlideChristina Lin
 
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
 
Advancing Engineering with AI through the Next Generation of Strategic Projec...
Advancing Engineering with AI through the Next Generation of Strategic Projec...Advancing Engineering with AI through the Next Generation of Strategic Projec...
Advancing Engineering with AI through the Next Generation of Strategic Projec...OnePlan Solutions
 
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
 
Unveiling the Tech Salsa of LAMs with Janus in Real-Time Applications
Unveiling the Tech Salsa of LAMs with Janus in Real-Time ApplicationsUnveiling the Tech Salsa of LAMs with Janus in Real-Time Applications
Unveiling the Tech Salsa of LAMs with Janus in Real-Time ApplicationsAlberto González Trastoy
 
The Evolution of Karaoke From Analog to App.pdf
The Evolution of Karaoke From Analog to App.pdfThe Evolution of Karaoke From Analog to App.pdf
The Evolution of Karaoke From Analog to App.pdfPower Karaoke
 
Professional Resume Template for Software Developers
Professional Resume Template for Software DevelopersProfessional Resume Template for Software Developers
Professional Resume Template for Software DevelopersVinodh Ram
 
EY_Graph Database Powered Sustainability
EY_Graph Database Powered SustainabilityEY_Graph Database Powered Sustainability
EY_Graph Database Powered SustainabilityNeo4j
 
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
 
Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...
Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...
Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...MyIntelliSource, Inc.
 
Cloud Management Software Platforms: OpenStack
Cloud Management Software Platforms: OpenStackCloud Management Software Platforms: OpenStack
Cloud Management Software Platforms: OpenStackVICTOR MAESTRE RAMIREZ
 
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.
 
why an Opensea Clone Script might be your perfect match.pdf
why an Opensea Clone Script might be your perfect match.pdfwhy an Opensea Clone Script might be your perfect match.pdf
why an Opensea Clone Script might be your perfect match.pdfjoe51371421
 

Recently uploaded (20)

Hand gesture recognition PROJECT PPT.pptx
Hand gesture recognition PROJECT PPT.pptxHand gesture recognition PROJECT PPT.pptx
Hand gesture recognition PROJECT PPT.pptx
 
Unit 1.1 Excite Part 1, class 9, cbse...
Unit 1.1 Excite Part 1, class 9, cbse...Unit 1.1 Excite Part 1, class 9, cbse...
Unit 1.1 Excite Part 1, class 9, cbse...
 
DNT_Corporate presentation know about us
DNT_Corporate presentation know about usDNT_Corporate presentation know about us
DNT_Corporate presentation know about us
 
5 Signs You Need a Fashion PLM Software.pdf
5 Signs You Need a Fashion PLM Software.pdf5 Signs You Need a Fashion PLM Software.pdf
5 Signs You Need a Fashion PLM Software.pdf
 
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...
 
Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...
Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...
Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...
 
XpertSolvers: Your Partner in Building Innovative Software Solutions
XpertSolvers: Your Partner in Building Innovative Software SolutionsXpertSolvers: Your Partner in Building Innovative Software Solutions
XpertSolvers: Your Partner in Building Innovative Software Solutions
 
Building Real-Time Data Pipelines: Stream & Batch Processing workshop Slide
Building Real-Time Data Pipelines: Stream & Batch Processing workshop SlideBuilding Real-Time Data Pipelines: Stream & Batch Processing workshop Slide
Building Real-Time Data Pipelines: Stream & Batch Processing workshop Slide
 
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
 
Advancing Engineering with AI through the Next Generation of Strategic Projec...
Advancing Engineering with AI through the Next Generation of Strategic Projec...Advancing Engineering with AI through the Next Generation of Strategic Projec...
Advancing Engineering with AI through the Next Generation of Strategic Projec...
 
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
 
Unveiling the Tech Salsa of LAMs with Janus in Real-Time Applications
Unveiling the Tech Salsa of LAMs with Janus in Real-Time ApplicationsUnveiling the Tech Salsa of LAMs with Janus in Real-Time Applications
Unveiling the Tech Salsa of LAMs with Janus in Real-Time Applications
 
The Evolution of Karaoke From Analog to App.pdf
The Evolution of Karaoke From Analog to App.pdfThe Evolution of Karaoke From Analog to App.pdf
The Evolution of Karaoke From Analog to App.pdf
 
Professional Resume Template for Software Developers
Professional Resume Template for Software DevelopersProfessional Resume Template for Software Developers
Professional Resume Template for Software Developers
 
EY_Graph Database Powered Sustainability
EY_Graph Database Powered SustainabilityEY_Graph Database Powered Sustainability
EY_Graph Database Powered Sustainability
 
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
 
Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...
Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...
Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...
 
Cloud Management Software Platforms: OpenStack
Cloud Management Software Platforms: OpenStackCloud Management Software Platforms: OpenStack
Cloud Management Software Platforms: OpenStack
 
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
 
why an Opensea Clone Script might be your perfect match.pdf
why an Opensea Clone Script might be your perfect match.pdfwhy an Opensea Clone Script might be your perfect match.pdf
why an Opensea Clone Script might be your perfect match.pdf
 

PVS-Studio team is about to produce a technical breakthrough, but for now let's recheck Blender

  • 1. PVS-Studio team is about to produce a technical breakthrough, but for now let's recheck Blender Author: Alexander Chibisov Date: 21.07.2016 Static analysis is most useful when it is done on a regular basis. Especially when the project is rapidly developing, like the Blender project, for example. Now it's time to check it once more, and see what suspicious fragments we'll find this time. Introduction Blender is a free, open source professional 3D creation suite. It supports the entirety of the 3D pipeline—modeling, rigging, animation, simulation, rendering, compositing, and motion tracking; even video editing and game creation. We have already checked this project before. You may find the results of the previous check of v2.62 in the article "Analyzing the Blender project with PVS-Studio". Since the last time we checked it, the size of the source code, including additional libraries, increased to 77 mb. Its codebase is now 2206 KLOC. At the time of the previous check the project was 68 mb (2105 KLOC). The SourceMonitor utility was a great help to me in evaluating the codebase size. This utility is able to analyze the code in C++, C, C #, VB.NET, Java, and Delphi, and is able to evaluate various metrics. For example, it can determine the cyclomatic complexity of your projects, as well as generate detailed statistics for each of the project files, and show the results as a table or diagrams.
  • 2. So this article is about errors and suspicious fragments that were found in Blender, v2.77a. To do the analysis, we used PVS-Studio 6.05 Typos During the active usage of copying mechanism and automatic code completion, you may have errors in the names of various variables and constants. Such errors can result in incorrect evaluation results or unexpected program behavior. In the Blender project there were several such examples. Let's take a closer look. A typo in the condition CurvePoint::CurvePoint(CurvePoint *iA, CurvePoint *iB, float t3) { .... if ((iA->getPoint2D() - //<= iA->getPoint2D()).norm() < 1.0e-6) { //<= .... } .... } V501 There are identical sub-expressions to the left and to the right of the '-' operator: iA->getPoint2D() - iA->getPoint2D() curve.cpp 136 Inside the CurvePoint function the program handles two objects with similar names - iA and iB. Different methods of these objects get intersected all the time in various operations in quite a long tree of conditions. There is a typo in one of these conditional blocks. As a result we have a subtraction operation between the properties of one and the same object. Without knowing the peculiarities of the code, it's quite hard to say, in which operand we have an error. I can suggest two variants of how to fix it: if ((iA->getPoint2D()-iB->getPoint2D()).norm()<1.0e-6).... or if ((iB->getPoint2D()-iA->getPoint2D()).norm()<1.0e-6).... The following error was also hiding inside a conditional statement. template<typename MatrixType, int QRPreconditioner> void JacobiSVD<MatrixType, QRPreconditioner>::allocate(....) { .... if(m_cols>m_rows)m_qr_precond_morecols.allocate(*this); if(m_rows>m_cols)m_qr_precond_morerows.allocate(*this); if(m_cols!=m_cols)m_scaledMatrix.resize(rows,cols); //<= }
  • 3. V501 There are identical sub-expressions to the left and right of the '!=' operator: m_cols != m_cols jacobisvd.h 819 In the given fragment, you can see the equalization of the number of rows and columns inside some matrix. If the quantity isn't the same, the program allocates memory for new elements and creates them. Later, if new cells are added, there is an operation of altering the matrix size. Unfortunately, due to the error in the conditional statement the operation will never be executed, because the condition m_cols!=m_cols is always false. In this case it doesn't matter which part is changed, so I suggest the following variant: if(m_cols!=m_rows) m_scaledMatrix.resize(rows,cols) Several more problem areas were detected by the V501 diagnostic:  V501 There are identical sub-expressions to the left and to the right of the '==' operator: left.rows() == left.rows() numeric.cc 112  V501 There are identical sub-expressions to the left and to the right of the '>' operator: (from[0][3]) > (from[0][3]) stereoimbuf.c 120  V501 There are identical sub-expressions to the left and to the right of the '>' operator: (from[0][3]) > (from[0][3]) stereoimbuf.c 157  V501 There are identical sub-expressions to the left and to the right of the '==' operator: out->y == out->y filter.c 209 Null pointer handling The typo in the names had more serious consequences. int QuantitativeInvisibilityF1D::operator()(....) { ViewEdge *ve = dynamic_cast<ViewEdge*>(&inter); if (ve) { result = ve->qi(); return 0; } FEdge *fe = dynamic_cast<FEdge*>(&inter); if (fe) { result = ve->qi(); //<= return 0; } .... } V522 Dereferencing of the null pointer 've' might take place. functions1d.cpp 107 This function is fairly short, but typos can trap us, even in simple functions. We can see in the code that two objects get created and checked. However, after the check of the second object, an error occurred, and even if fe was successfully created, instead of it, the result of function work from the first object is
  • 4. written to the result; according to the previous conditions, this object wasn't created at all. This will most likely lead to a crash of the program if this exception isn't caught by a handler of a higher level. Apparently, the second code fragment was written using Copy-Paste. By accident the programmer forgot to change the variable name ve. The correct code should probably be like this: FEdge *fe = dynamic_cast<FEdge*>(&inter); if (fe) { result = fe->qi(); return 0; } Null pointer usage static ImBuf *accessor_get_ibuf(....) { ImBuf *ibuf, *orig_ibuf, *final_ibuf; .... /* First try to get fully processed image from the cache. */ ibuf = accesscache_get(accessor, clip_index, frame, input_mode, downscale, transform_key); if (ibuf != NULL) { return ibuf; } /* And now we do postprocessing of the original frame. */ orig_ibuf = accessor_get_preprocessed_ibuf(accessor, clip_index, frame); if (orig_ibuf == NULL) { return NULL; } .... if (downscale > 0) { if (final_ibuf == orig_ibuf) { final_ibuf = IMB_dupImBuf(orig_ibuf);
  • 5. } IMB_scaleImBuf(final_ibuf, ibuf->x / (1 << downscale), //<= ibuf->y / (1 << downscale)); //<= } .... if (input_mode == LIBMV_IMAGE_MODE_RGBA) { BLI_assert(ibuf->channels == 3 || //<= ibuf->channels == 4); //<= } .... return final_ibuf; } Warnings:  V522 Dereferencing of the null pointer 'ibuf' might take place. tracking_util.c 765  V522 Dereferencing of the null pointer 'ibuf' might take place. tracking_util.c 766  V522 Dereferencing of the null pointer 'ibuf' might take place. tracking_util.c 783 In the fragment given above, you can see that the check of ibuf variable interrupts the function much sooner than this variable is used if the object was created. We could probably stop here and confirm the fact of a pointer dereferencing. At the same time, if we do a more painstaking examination of the code and the comments to it, we see a true reason for the error. This is a typo, again. In the fragments indicated by the analyzer, the programmer should have used the variable orig_ibuf instead of ibuf. Incorrect variable type typedef enum eOutlinerIdOpTypes { OUTLINER_IDOP_INVALID = 0, OUTLINER_IDOP_UNLINK, OUTLINER_IDOP_LOCAL, .... } eOutlinerIdOpTypes; typedef enum eOutlinerLibOpTypes { OL_LIB_INVALID = 0, OL_LIB_RENAME, OL_LIB_DELETE, } eOutlinerLibOpTypes;
  • 6. static int outliner_lib_operation_exec(....) { .... eOutlinerIdOpTypes event; //<= .... event = RNA_enum_get(op->ptr, "type"); switch (event) { case OL_LIB_RENAME: //<= { .... } case OL_LIB_DELETE: //<= { .... } default: /* invalid - unhandled */ break; } .... } Warnings:  V556 The values of different enum types are compared: switch(ENUM_TYPE_A) { case ENUM_TYPE_B: ... }. outliner_tools.c 1286  V556 The values of different enum types are compared: switch(ENUM_TYPE_A) { case ENUM_TYPE_B: ... }. outliner_tools.c 1295 In this example you can see two types that are enumerations. It's quite an expected fact that there was a typo in the names that are almost the same. In fact, the code works correctly. At the same time it confuses us by the mismatch of the types. The variable gets a value of an enumeration, and is compared with the constants of a different one. To correct this error it's enough to change the type of the variable event to eOutlinerLibOpTypes. Operation precedence error static void blf_font_draw_buffer_ex(....) { .... cbuf[3] = (unsigned char)((alphatest = ((int)cbuf[3] +
  • 7. (int)(a * 255)) < 255) ? alphatest : 255); .... } V593 Consider reviewing the expression of the 'A = B < C' kind. The expression is calculated as following: 'A = (B < C)'. blf_font.c 414 Failure to comply with the operation precedence is one of the most common errors when working with complex expressions. In this case it's just a typo, but it led to a breach of the logic of the ternary operator. Due to an incorrectly put parentheses, there was an operation precedence error. On top of that, the value of alphatest variable also gets damaged. Instead of the value, which is evaluated by the ternary operator, the alphatest variable is assigned with a value of bool-type that was obtained in the result of a comparison operation. Only after that the ternary operator works with the value of the alphatest variable, and the result doesn't get saved. To fix this bug, we should change the expression as follows: cbuf[3] = (unsigned char)(alphatest = (((int)cbuf[3] + (int)(a * 255)) < 255) ? alphatest : 255); Invalid constant bool BKE_ffmpeg_alpha_channel_is_supported(RenderData *rd) { int codec = rd->ffcodecdata.codec; if (codec == AV_CODEC_ID_QTRLE) return true; if (codec == AV_CODEC_ID_PNG) return true; if (codec == AV_CODEC_ID_PNG) return true; .... } V649 There are two 'if' statements with identical conditional expressions. The first 'if' statement contains function return. This means that the second 'if' statement is senseless. Check lines: 1672, 1675. writeffmpeg.c 1675 We see a successive check of the variable value to match the flag with the help of single-line conditions. Because of the typo one of the flags gets checked twice. Most likely, a different constant should have been checked instead of a repeated check. There are a lot of variants of these constants that's why it's hard to say how this code should be fixed. Using one variable in an outer and inner loop bool BM_face_exists_overlap_subset(...., const int len) { int i;
  • 8. .... for (i = 0; i < len; i++) { BM_ITER_ELEM (f, &viter, varr[i], BM_FACES_OF_VERT) { if ((f->len <= len) && (....)) { BMLoop *l_iter, *l_first; if (is_init == false) { is_init = true; for (i = 0; i < len; i++) { //<= BM_ELEM_API_FLAG_ENABLE(varr[i], _FLAG_OVERLAP); } } .... } } } } V535 The variable 'i' is being used for this loop and for the outer loop. Check lines: 2204, 2212. bmesh_queries.c 2212 Using the same variable in the outer and inner loop may lead to incorrect execution of the outer loop. In this case this will less likely be an error, as the loop is probably looking for the necessary element and exits, and the second loop is triggered only in this case. But still, using a single variable is a dangerous trick and may lead to real errors if there is a necessity to optimize this code fragment. Redundant code Excessive code fragments can be found in any program. Sometimes this is old code that was forgotten after refactoring. But at times those extra fragments serve as a way to keep up the project style. Such fragments can be quite dangerous. In other words, duplicate code often indicates the presence of logical errors. Double check static void knife_add_single_cut(....) { .... if ((lh1->v && lh2->v) && //<= (lh1->v->v && lh2->v && lh2->v->v) && //<= (e_base = BM_edge_exists(lh1->v->v, lh2->v->v))) {
  • 9. .... return; } .... } V501 There are identical sub-expressions 'lh2->v' to the left and right of the '&&' operator. editmesh_knife.c 781 This is one of the variants of a condition that wasn't thought out well. It's certainly not a mistake, just an extra check, but that doesn't mean that the code does not need additional review. The condition consists of several expressions. At the same time a part of the second expression is the same as the check of one variable from the first expression, so it's not needed here. To fix this code we need to remove the excessive check lh2->v from the second expression. After that the code will become much easier to read. Another example: static int edbm_rip_invoke__vert(....) { .... if (do_fill) { if (do_fill) { .... } } .... } V571 Recurring check. The 'if (do_fill)' condition was already verified in line 751. editmesh_rip.c 752 One more variant of a logical error. Absolutely identical expressions are checked inside an outer and inner condition. The double check will always give the same result, which makes no sense. Of course, this code does not affect the program work in any way. But it's not clear how this code will change over time, and extra checks can mislead a person in the future. Unnecessary checks can be found in several fragments of the project. Here are several more spots, detected by the analyzer:  V571 Recurring check. The 'but' condition was already verified in line 9587. interface_handlers.c 9590  V571 Recurring check. The '!me->mloopcol' condition was already verified in line 252. paint_vertex.c 253  V571 Recurring check. The 'constinv == 0' condition was already verified in line 5256. transform_conversions.c 5257  V571 Recurring check. The 'vlr->v4' condition was already verified in line 4174. convertblender.c 4176
  • 10.  V571 Recurring check. The 'ibuf == ((void *) 0)' condition was already verified in line 3557. sequencer.c 3559 And the third example is obviously redundant code: static void writedata_do_write(....) { if ((wd == NULL) || wd->error || (mem == NULL) || memlen < 1) return; if (wd->error) return; .... } V649 There are two 'if' statements with identical conditional expressions. The first 'if' statement contains function return. This means that the second 'if' statement is senseless. Check lines: 331, 332. writefile.c 332 The string if (wd->error) return; is excessive, and the function will exit earlier than this condition will be handled. And so, it should just be removed. Opposite condition blocks static int select_less_exec(....) { .... if ((lastsel==0)&&(bp->hide==0)&&(bp->f1 & SELECT)){ if (lastsel != 0) sel = 1; else sel = 0; .... } .... } V637 Two opposite conditions were encountered. The second condition is always false. Check lines: 938, 939. editcurve_select.c 938 In the fragment we can see that there is an extra condition inside an outer condition block. The inner condition is opposite the main one and always gives the same result; the sel variable will never be 1. Therefore, it is enough to simply write sel = 0 without additional check. Although this error may have been fixed by changing one of the expressions. Since I didn't take part in the creation of this project, it's hard for me to say for sure. Redundant expressions DerivedMesh *fluidsimModifier_do(....) { ....
  • 11. if (!fluidmd || (fluidmd && !fluidmd->fss)) return dm; .... } V728 An excessive check can be simplified. The '||' operator is surrounded by opposite expressions '!fluidmd' and 'fluidmd'. mod_fluidsim_util.c 528 Opposite values of one and the same variable are checked under one condition. Such conditions are often found of different kinds and variations. They don't cause any harm to the software, but they can complicate the code. This expression can be simplified and written as follows: if (!fluidmd || !fluidmd->fss)) .... Similar fragments:  V728 An excessive check can be simplified. The '||' operator is surrounded by opposite expressions '!render_only' and 'render_only'. drawobject.c 4663  V728 An excessive check can be simplified. The '||' operator is surrounded by opposite expressions '!parent' and 'parent'. kx_scene.cpp 1667 One more such a condition: void ED_transverts_create_from_obedit(....) { .... if ((tipsel && rootsel) || (rootsel)) {....} .... } V686 A pattern was detected: (rootsel) || ((rootsel) && ...). The expression is excessive or contains a logical error. ed_transverts.c 325 As in the example given above, the same variable is checked twice inside one expression. This expression is not an erroneous one, but it definitely has an extra check. Let's simplify it to make it more compact and easy-to-read. if ((tipsel || rootsel) {....} There were such errors in other places in the project.  V686 A pattern was detected: (!py_b_len) || ((!py_b_len) && ...). The expression is excessive or contains a logical error. aud_pyapi.cpp 864  V686 A pattern was detected: (xn == 0.0f) || ((xn == 0.0f) && ...). The expression is excessive or contains a logical error. renderdatabase.c 993  V686 A pattern was detected: (xn == 0.0f) || ((xn == 0.0f) && ...). The expression is excessive or contains a logical error. renderdatabase.c 1115 Iterative assignment static bool find_prev_next_keyframes(....) {
  • 12. .... do { aknext = (ActKeyColumn *)BLI_dlrbTree_search_next( &keys, compare_ak_cfraPtr, &cfranext); if (aknext) { if (CFRA == (int)aknext->cfra) { cfranext = aknext->cfra; //<- } else { if (++nextcount == U.view_frame_keyframes) donenext = true; } cfranext = aknext->cfra; //<- } } while ((aknext != NULL) && (donenext == false)); .... } V519 The 'cfranext' variable is assigned values twice successively. Perhaps this is a mistake. Check lines: 447, 454. anim_draw.c 454 The assignment inside conditional blocks makes no sense, because its value is assigned again in the end of the loop without any condition. A loop, placed in the code right after the given fragment helps us draw the conclusion that the excessive string is placed above. It differs only in the prev variables, and the absence of this string in the condition. Moreover, assuming that the extra string is underneath, and the condition CFRA == (int)aknext->cfra turns out to be false, then this loop will become an infinite one. This fragment really needs some fixing, but how to do it exactly - only the developers of the project know. Extra or unused variables There were many such fragments with initialized, but unused, variables in the project. Some of them can be considered as logical errors and excessive checks, but we have already spoken about them a lot. There are also constants that probably should have been changed inside the functions. But as a result they are just checks, always returning the same result. An example of such a fragment: static int rule_avoid_collision(....) { .... int n, neighbors = 0, nearest = 0; //<= .... if (ptn && nearest==0) //<=
  • 13. MEM_freeN(ptn); return ret; } V560 A part of conditional expression is always true: nearest == 0. boids.c 361 I'll just provide the other fragments as a list. Perhaps some of them are debatable, but they are worth paying attention to.  V560 A part of conditional expression is always true: edit == 0. particle.c 3781  V560 A part of conditional expression is always true: !error. pointcache.c 154  V560 A part of conditional expression is always true: !error. pointcache.c 2742  V560 A part of conditional expression is always false: col. drawobject.c 7803  V560 A part of conditional expression is always false: !canvas_verts. dynamicpaint.c 4636  V560 A part of conditional expression is always true: (!leaf). octree.cpp 2513  V560 A part of conditional expression is always true: (!leaf). octree.cpp 2710  V560 A part of conditional expression is always false: (1 == i). basicstrokeshaders.cpp 67  V560 A part of conditional expression is always true: (0 == i). basicstrokeshaders.cpp 69  V560 A part of conditional expression is always false: (1 == i). basicstrokeshaders.cpp 84  V560 A part of conditional expression is always true: (0 == i). basicstrokeshaders.cpp 86  V560 A part of conditional expression is always false: (1 == i). basicstrokeshaders.cpp 155  V560 A part of conditional expression is always true: (0 == i). basicstrokeshaders.cpp 157  V560 A part of conditional expression is always true: (!radmod). solver_control.cpp 557  V560 A part of conditional expression is always true: done != 1. context.c 301  V560 A part of conditional expression is always true: is_tablet == false. ghost_systemwin32.cpp 665  V560 A part of conditional expression is always true: mesh >= 0. kx_gameobject.cpp 976 Extra clearing of the list int TileManager::gen_tiles(bool sliced) { .... state.tiles.clear(); //<= .... int tile_index = 0; state.tiles.clear(); state.tiles.resize(num); .... } V586 The 'clear' function is called twice for deallocation of the same resource. Check lines: 149, 156. tile.cpp 156
  • 14. In this case, it might just be the extra line. There probably used to be some code between the two list clearings, but in this case it's just another useless fragment that should be removed so that the code isn't cluttered up. This string can be a consequence of the fact that some other object should be cleared in it, which is not seen at first glance. In this case the fragment will be a real error that may lead to unexpected results for the program. Very often such seemingly redundant code may lead to really serious errors, or my help avoiding them in the future during further modifications. This is why you should pay attention to these analyzer warnings, and not mark them as "unimportant". Intrigue PVS-Studio Team is now actively working on a new direction in development. And I am covering backs, filling the information field with articles about the rechecking of some open source projects. What is the direction that we are talking about? I cannot say. I'll just leave a picture here that you are free to interpret as you wish. Conclusion The analyzer detected quite a number of troublesome spots in the project. However, at times, the coding style in Blender is quite strange and we cannot say for sure that these are errors. In my opinion, dangerous errors often occur because of typos. PVS-Studio is especially good at catching such bugs. Those bugs, described in this article reflect the personal opinion of the author which is quite subjective. To see the full range of analyzer abilities, you should download it, and try it out yourself.