SlideShare a Scribd company logo
1 of 15
Download to read offline
Analyzing Firebird 3.0
Author: Pavel Belikov
Date: 11.05.2016
A new version of Firebird DBMS was released not so long ago. This release was one of the most significant in
the project's history, as it marked substantial revision of the architecture, addition of multithreading
support, and performance improvements. Such a significant update was a good occasion for us to scan
Firebird one more time with PVS-Studio static code analyzer.
Introduction
Firebird is a cross-platform open-source database management system written in C++ that runs on
Microsoft Windows, Linux, Mac OS X, and many Unix-like operating systems. It can be used and distributed
for free. To learn more about Firebird, welcome to the official site.
We have already scanned Firebird with our analyzer before. The previous report can be found in the article
"A Spin-off: Firebird Checked by PVS-Studio". For this analysis, we took the project code from GitHub, the
master branch. The building process is described in detail in the article at the project website. We analyzed
the source files in PVS-Studio Standalone, version 6.03, using the Compiler Monitoring mechanism, which
allows you to scan projects without integrating the tool into the build system. The log file generated by the
analyzer can be viewed both in the Standalone version and in Visual Studio.
Typos
void advance_to_start()
{
....
if (!isalpha(c) && c != '_' && c != '.' && c != '_')
syntax_error(lineno, line, cptr);
....
}
PVS-Studio diagnostic message: V501 There are identical sub-expressions 'c != '_'' to the left and to the right
of the '&&' operator. reader.c 1203
The analyzer detected a logical expression with two identical subexpressions c != '_'. The last condition
contains a typo and should actually compare the c variable with some other character. In other functions
nearby, the variable is tested for the '$' character, so it should probably be used in our example as well:
if (!isalpha(c) && c != '_' && c != '.' && c != '$')
Another mistake resulting from the programmer's inattention:
int put_message(....)
{
if (newlen <= MAX_UCHAR)
{
put(tdgbl, attribute);
put(tdgbl, (UCHAR) newlen);
}
else if (newlen <= MAX_USHORT)
{
if (!attribute2)
BURP_error(314, "");
....
}
else
BURP_error(315, "");
....
}
PVS-Studio diagnostic messages:
 V601 The string literal is implicitly cast to the bool type. Inspect the second argument. backup.cpp
6113
 V601 The string literal is implicitly cast to the bool type. Inspect the second argument. backup.cpp
6120
Here we deal with a wrong call to the BURP_error function. This is how the function is declared:
void BURP_error(USHORT errcode, bool abort,
const MsgFormat::SafeArg& arg = MsgFormat::SafeArg());
void BURP_error(USHORT errcode, bool abort, const char* str);
The second argument is a boolean value and the third one is a string. In our example, however, the string
literal is passed as the second argument and is, therefore, cast to true. The function call should be rewritten
in the following way: BURP_error(315, true, "") or BURP_error(315, false, "").
However, there are cases when only the project authors can tell if there is an error or not.
void IDX_create_index(....)
{
....
index_fast_load ifl_data;
....
if (!ifl_data.ifl_duplicates)
scb->sort(tdbb);
if (!ifl_data.ifl_duplicates)
BTR_create(tdbb, creation, selectivity);
....
}
PVS-Studio diagnostic message: V581 The conditional expressions of the 'if' operators situated alongside
each other are identical. Check lines: 506, 509. idx.cpp 509
This example deals with two blocks of code that check the same condition in succession. There might be a
typo in one of them, or this issue has to do with copying or deleting some code fragments. In any case, this
code looks strange.
In the next example we'll discuss an issue that deals with pointers.
static void string_to_datetime(....)
{
....
const char* p = NULL;
const char* const end = p + length;
....
while (p < end)
{
if (*p != ' ' && *p != 't' && p != 0)
{
CVT_conversion_error(desc, err);
return;
}
++p;
}
....
}
PVS-Studio diagnostic message: V713 The pointer p was utilized in the logical expression before it was
verified against nullptr in the same logical expression. cvt.cpp 702
In the condition, the p variable is compared with nullptr right after dereferencing. It may indicate that some
other condition should have been used instead of this check, or that this check is just not necessary.
Earlier in the code, a similar fragment can be found:
while (++p < end)
{
if (*p != ' ' && *p != 't' && *p != 0)
CVT_conversion_error(desc, err);
}
To avoid errors like this, use appropriate literals when comparing with zero: '0' for type char, 0 for
numbers, and nullptr for pointers. Sticking to this rule will help you avoid lots of silly errors like that.
Unsafe use of memcmp
SSHORT TextType::compare(ULONG len1, const UCHAR* str1,
ULONG len2, const UCHAR* str2)
{
....
SSHORT cmp = memcmp(str1, str2, MIN(len1, len2));
if (cmp == 0)
cmp = (len1 < len2 ? -1 : (len1 > len2 ? 1 : 0));
return cmp;
}
PVS-Studio diagnostic message: V642 Saving the 'memcmp' function result inside the 'short' type variable is
inappropriate. The significant bits could be lost breaking the program's logic. texttype.cpp 3
The memcmp function returns the following values:
 < 0 if str1 is less than str2
 0 if str1 equals str2
 > 0 if str1 is greater than str2
The function does not guarantee to return exact values when the strings are not equal, so storing the result
in a variable of size less than that of type int may lead to losing the most significant bits and distorting the
execution logic.
Extra checks
void Trigger::compile(thread_db* tdbb)
{
SET_TDBB(tdbb);
Database* dbb = tdbb->getDatabase();
Jrd::Attachment* const att = tdbb->getAttachment();
if (extTrigger)
return;
if (!statement /*&& !compile_in_progress*/)
{
if (statement)
return;
....
}
}
PVS-Studio diagnostic message: V637 Two opposite conditions were encountered. The second condition is
always false. Check lines: 778, 780. jrd.cpp 778
The analyzer detected checks of two opposite conditions. The second condition seems to be no longer
necessary since the first one was changed at some point in the past, so it can be deleted, although it is
completely up to the author to make this decision.
The following code fragment is another example of strange branching.
static void asgn_from( ref* reference, int column)
{
TEXT variable[MAX_REF_SIZE];
TEXT temp[MAX_REF_SIZE];
for (; reference; reference = reference->ref_next)
{
const gpre_fld* field = reference->ref_field;
....
if (!field || field->fld_dtype == dtype_text)
....
else if (!field || field->fld_dtype == dtype_cstring)
....
else
....
}
}
PVS-Studio diagnostic message: V560 A part of conditional expression is always false: !field. int_cxx.cpp 217
If the field pointer is non-null, the code will never reach the condition in the else if branch. Either this check
is redundant or there should be some other comparison instead of it. It's not clear, whether this condition
contradicts the execution logic.
In addition to these examples, a number of redundant checks were found in logical expressions.
bool XnetServerEndPoint::server_init(USHORT flag)
{
....
xnet_connect_mutex = CreateMutex(ISC_get_security_desc(),
FALSE, name_buffer);
if (!xnet_connect_mutex ||
(xnet_connect_mutex && ERRNO == ERROR_ALREADY_EXISTS))
{
system_error::raise(ERR_STR("CreateMutex"));
}
....
}
PVS-Studio diagnostic message: V728 An excessive check can be simplified. The '||' operator is surrounded
by opposite expressions '!xnet_connect_mutex' and 'xnet_connect_mutex'. xnet.cpp 2231
The check if (!xnet_connect_mutex || (xnet_connect_mutex && ERRNO == ERROR_ALREADY_EXISTS)) can
be simplified to if (!xnet_connect_mutex || ERRNO == ERROR_ALREADY_EXISTS). The correctness of such
transformation can be easily proved with the truth table.
Unsafe comparison of an unsigned variable
static bool write_page(thread_db* tdbb, BufferDesc* bdb, ....)
{
....
if (bdb->bdb_page.getPageNum() >= 0)
....
}
PVS-Studio diagnostic message: V547 Expression 'bdb->bdb_page.getPageNum() >= 0' is always true.
Unsigned type value is always >= 0. cch.cpp 4827
The bdb->bdb_page.getPageNum() >= 0 condition will always be true, as the function returns an unsigned
value. This error probably has to do with an incorrect check of the value. Based on other similar
comparisons in the project, I think the code should actually look like this:
if (bdb->bdb_page.getPageNum() != 0)
Null pointer dereferencing
static bool initializeFastMutex(FAST_MUTEX* lpMutex,
LPSECURITY_ATTRIBUTES lpAttributes, BOOL bInitialState,
LPCSTR lpName)
{
if (pid == 0)
pid = GetCurrentProcessId();
LPCSTR name = lpName;
if (strlen(lpName) + strlen(FAST_MUTEX_EVT_NAME) - 2
>= MAXPATHLEN)
{
SetLastError(ERROR_FILENAME_EXCED_RANGE);
return false;
}
setupMutex(lpMutex);
char sz[MAXPATHLEN];
if (lpName)
....
}
PVS-Studio diagnostic message: V595 The 'lpName' pointer was utilized before it was verified against
nullptr. Check lines: 2814, 2824. isc_sync.cpp 2814
Warning V595 is the most common among the projects scanned by PVS-Studio, and Firebird is no exception.
In total, the analyzer found 30 issues triggering this diagnostic.
In this example, the call strlen(lpName) precedes a pointer check for nullptr, thus leading to undefined
behavior when trying to pass a null pointer to the function. The pointer-dereferencing operation is hidden
inside the call to strlen, which makes it difficult to find the error without a static analyzer.
Testing for nullptr after new
rem_port* XnetServerEndPoint::get_server_port(....)
{
....
XCC xcc = FB_NEW struct xcc(this);
try {
....
}
catch (const Exception&)
{
if (port)
cleanup_port(port);
else if (xcc)
cleanup_comm(xcc);
throw;
}
return port;
}
PVS-Studio diagnostic message: V668 There is no sense in testing the 'xcc' pointer against null, as the
memory was allocated using the 'new' operator. The exception will be generated in the case of memory
allocation error. xnet.cpp 2533
The analyzer warns us that the new operator cannot return nullptr - one must use a try-catch block or new
(std::nothrow). However, this example is a bit more complicated. The programmer uses macro FB_NEW to
allocate memory. This macro is declared in the file alloc.h:
#ifdef USE_SYSTEM_NEW
#define OOM_EXCEPTION std::bad_alloc
#else
#define OOM_EXCEPTION Firebird::BadAlloc
#endif
#define FB_NEW new(__FILE__, __LINE__)
inline void* operator new(size_t s ALLOC_PARAMS)
throw (OOM_EXCEPTION)
{
return MemoryPool::globalAlloc(s ALLOC_PASS_ARGS);
}
I can't say for sure if this particular example is incorrect, as it uses a non-standard allocator; but the
presence of throw (std::bad_alloc) in the operator declaration makes this check quite suspicious.
Unsafe use of realloc
int mputchar(struct mstring *s, int ch)
{
if (!s || !s->base) return ch;
if (s->ptr == s->end) {
int len = s->end - s->base;
if ((s->base = realloc(s->base, len+len+TAIL))) {
s->ptr = s->base + len;
s->end = s->base + len+len+TAIL; }
else {
s->ptr = s->end = 0;
return ch; } }
*s->ptr++ = ch;
return ch;
}
PVS-Studio diagnostic message: V701 realloc() possible leak: when realloc() fails in allocating memory,
original pointer 's->base' is lost. Consider assigning realloc() to a temporary pointer. mstring.c 42
What is bad about expressions of the ptr = realloc(ptr, size) pattern is that the pointer to the memory block
will be lost when realloc returns nullptr. To avoid it, one needs to save the result returned by realloc in a
temporary variable and then assign this value to ptr after comparing it with nullptr.
temp_ptr = realloc(ptr, new_size);
if (temp_ptr == nullptr) {
//handle exception
} else {
ptr = temp_ptr;
}
Unused enum values in switch
template <typename CharType>
LikeEvaluator<CharType>::LikeEvaluator(....)
{
....
PatternItem *item = patternItems.begin();
....
switch (item->type)
{
case piSkipFixed:
case piSkipMore:
patternItems.grow(patternItems.getCount() + 1);
item = patternItems.end() - 1;
// Note: fall into
case piNone:
item->type = piEscapedString;
item->str.data = const_cast<CharType*>
(pattern_str + pattern_pos - 2);
item->str.length = 1;
break;
case piSearch:
item->type = piEscapedString;
// Note: fall into
case piEscapedString:
item->str.length++;
break;
}
....
}
PVS-Studio diagnostic message: V719 The switch statement does not cover all values of the
'PatternItemType' enum: piDirectMatch. evl_string.h 324
Not all enum values were used in the switch statement; the default block is absent, too. This example seems
to lack the code that handles the piDirectMatch element. Other similar issues:
 V719 The switch statement does not cover all values of the 'PatternItemType' enum: piDirectMatch,
piSkipMore. evl_string.h 351
 V719 The switch statement does not cover all values of the 'PatternItemType' enum: piDirectMatch.
evl_string.h 368
 V719 The switch statement does not cover all values of the 'PatternItemType' enum: piDirectMatch.
evl_string.h 387
Buffer overflow
const int GDS_NAME_LEN = 32;
....
bool get_function(BurpGlobals* tdgbl)
{
....
struct isc_844_struct {
....
short isc_870; /* gds__null_flag */
....
char isc_874 [125]; /* RDB$PACKAGE_NAME */
....
} isc_844;
att_type attribute;
TEXT temp[GDS_NAME_LEN * 2];
....
SSHORT prefixLen = 0;
if (!/*X.RDB$PACKAGE_NAME.NULL*/
isc_844.isc_870)
{
prefixLen = static_cast<SSHORT>(strlen(/*X.RDB$PACKAGE_NAME*/
isc_844.isc_874));
memcpy(temp, /*X.RDB$PACKAGE_NAME*/
isc_844.isc_874, prefixLen);
temp[prefixLen++] = '.';
}
....
}
PVS-Studio diagnostic message: V557 Array overrun is possible. The value of 'prefixLen ++' index could reach
124. restore.cpp 10040
The size of the buffer isc_844.isc_874 is 125; therefore, the largest value possible of strlen(isc_844.isc_874)
is 124. The size of temp is 64, which is less than that value. Writing at this index may cause a buffer
overflow. A safer way is to allocate a larger storage for the temp variable.
Shifting negative numbers
static ISC_STATUS stuff_literal(gen_t* gen, SLONG literal)
{
....
if (literal >= -32768 && literal <= 32767)
return stuff_args(gen, 3, isc_sdl_short_integer, literal,
literal >> 8);
....
}
PVS-Studio diagnostic message: V610 Unspecified behavior. Check the shift operator '>>'. The left operand
is negative ('literal' = [-32768..32767]). array.cpp 848
The code contains a right-shift operation on a negative number. As the C++ standard states, such an
operation leads to undefined behavior, i.e. it may produce different results on different compilers and
platforms. The code should be rewritten as follows:
if (literal >= -32768 && literal <= 32767)
return stuff_args(gen, 3, isc_sdl_short_integer, literal,
(ULONG)literal >> 8);
Another fragment triggering this warning:
V610 Unspecified behavior. Check the shift operator '>>'. The left operand is negative ('i64value' = [-
2147483648..2147483647]). exprnodes.cpp 6382
Variable redefinition
THREAD_ENTRY_DECLARE Service::run(THREAD_ENTRY_PARAM arg)
{
int exit_code = -1;
try
{
Service* svc = (Service*)arg;
RefPtr<SvcMutex> ref(svc->svc_existence);
int exit_code = svc->svc_service_run->serv_thd(svc);
svc->started();
svc->svc_sem_full.release();
svc->finish(SVC_finished);
}
catch (const Exception& ex)
{
// Not much we can do here
iscLogException("Exception in Service::run():", ex);
}
return (THREAD_ENTRY_RETURN)(IPTR) exit_code;
}
PVS-Studio diagnostic message: V561 It's probably better to assign value to 'exit_code' variable than to
declare it anew. Previous declaration: svc.cpp, line 1893. svc.cpp 1898
In this example, the exit_code variable is redefined instead of being assigned a value. Variable redefinition
hides the previously declared variable from the scope and makes the function always return an incorrect
value, which is -1.
Fixed code:
THREAD_ENTRY_DECLARE Service::run(THREAD_ENTRY_PARAM arg)
{
int exit_code = -1;
try
{
Service* svc = (Service*)arg;
RefPtr<SvcMutex> ref(svc->svc_existence);
exit_code = svc->svc_service_run->serv_thd(svc);
svc->started();
svc->svc_sem_full.release();
svc->finish(SVC_finished);
}
catch (const Exception& ex)
{
// Not much we can do here
iscLogException("Exception in Service::run():", ex);
}
return (THREAD_ENTRY_RETURN)(IPTR) exit_code;
}
Conclusion
As the new analysis shows, the project developers have fixed most of the issues found during the previous
analysis, so those bugs are no longer there, which is a good sign that the compiler did a good job. However,
using the analyzer regularly could help achieve even better results because that way it allows catching bugs
at earlier stages. Incremental analysis and compatibility with any build system allow integrating the analyzer
easily into your project. Using static analysis helps save plenty of time and catch errors that are difficult to
detect by means of debugging or dynamic analysis.

More Related Content

What's hot

Analysis of the Trans-Proteomic Pipeline (TPP) project
Analysis of the Trans-Proteomic Pipeline (TPP) projectAnalysis of the Trans-Proteomic Pipeline (TPP) project
Analysis of the Trans-Proteomic Pipeline (TPP) projectPVS-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
 
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
 
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
 
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 correctionAndrey Karpov
 
Analyzing the Quake III Arena GPL project
Analyzing the Quake III Arena GPL projectAnalyzing the Quake III Arena GPL project
Analyzing the Quake III Arena GPL projectPVS-Studio
 
Rechecking Apache HTTP Server
Rechecking Apache HTTP ServerRechecking Apache HTTP Server
Rechecking Apache HTTP ServerPVS-Studio
 
Analysis of Haiku Operating System (BeOS Family) by PVS-Studio. Part 2
Analysis of Haiku Operating System (BeOS Family) by PVS-Studio. Part 2Analysis of Haiku Operating System (BeOS Family) by PVS-Studio. Part 2
Analysis of Haiku Operating System (BeOS Family) by PVS-Studio. Part 2PVS-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
 
Picking Mushrooms after Cppcheck
Picking Mushrooms after CppcheckPicking Mushrooms after Cppcheck
Picking Mushrooms after CppcheckAndrey 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
 
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
 
100 bugs in Open Source C/C++ projects
100 bugs in Open Source C/C++ projects 100 bugs in Open Source C/C++ projects
100 bugs in Open Source C/C++ projects 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
 
Source code of WPF samples by Microsoft was checked
Source code of WPF samples by Microsoft was checkedSource code of WPF samples by Microsoft was checked
Source code of WPF samples by Microsoft was checkedPVS-Studio
 
An Experiment with Checking the glibc Library
An Experiment with Checking the glibc LibraryAn Experiment with Checking the glibc Library
An Experiment with Checking the glibc LibraryAndrey Karpov
 
Linux Kernel, tested by the Linux-version of PVS-Studio
Linux Kernel, tested by the Linux-version of PVS-StudioLinux Kernel, tested by the Linux-version of PVS-Studio
Linux Kernel, tested by the Linux-version of PVS-StudioPVS-Studio
 
Checking the Open-Source Multi Theft Auto Game
Checking the Open-Source Multi Theft Auto GameChecking the Open-Source Multi Theft Auto Game
Checking the Open-Source Multi Theft Auto GameAndrey Karpov
 

What's hot (19)

Analysis of the Trans-Proteomic Pipeline (TPP) project
Analysis of the Trans-Proteomic Pipeline (TPP) projectAnalysis of the Trans-Proteomic Pipeline (TPP) project
Analysis of the Trans-Proteomic Pipeline (TPP) project
 
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.
 
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
 
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
 
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
 
Analyzing the Quake III Arena GPL project
Analyzing the Quake III Arena GPL projectAnalyzing the Quake III Arena GPL project
Analyzing the Quake III Arena GPL project
 
Rechecking Apache HTTP Server
Rechecking Apache HTTP ServerRechecking Apache HTTP Server
Rechecking Apache HTTP Server
 
Analysis of Haiku Operating System (BeOS Family) by PVS-Studio. Part 2
Analysis of Haiku Operating System (BeOS Family) by PVS-Studio. Part 2Analysis of Haiku Operating System (BeOS Family) by PVS-Studio. Part 2
Analysis of Haiku Operating System (BeOS Family) by PVS-Studio. Part 2
 
Tesseract. Recognizing Errors in Recognition Software
Tesseract. Recognizing Errors in Recognition SoftwareTesseract. Recognizing Errors in Recognition Software
Tesseract. Recognizing Errors in Recognition Software
 
Picking Mushrooms after Cppcheck
Picking Mushrooms after CppcheckPicking Mushrooms after Cppcheck
Picking Mushrooms after Cppcheck
 
"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 ...
 
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
 
100 bugs in Open Source C/C++ projects
100 bugs in Open Source C/C++ projects 100 bugs in Open Source C/C++ projects
100 bugs in Open Source C/C++ projects
 
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
 
Source code of WPF samples by Microsoft was checked
Source code of WPF samples by Microsoft was checkedSource code of WPF samples by Microsoft was checked
Source code of WPF samples by Microsoft was checked
 
An Experiment with Checking the glibc Library
An Experiment with Checking the glibc LibraryAn Experiment with Checking the glibc Library
An Experiment with Checking the glibc Library
 
Linux Kernel, tested by the Linux-version of PVS-Studio
Linux Kernel, tested by the Linux-version of PVS-StudioLinux Kernel, tested by the Linux-version of PVS-Studio
Linux Kernel, tested by the Linux-version of PVS-Studio
 
Checking the Open-Source Multi Theft Auto Game
Checking the Open-Source Multi Theft Auto GameChecking the Open-Source Multi Theft Auto Game
Checking the Open-Source Multi Theft Auto Game
 

Similar to Analyzing Firebird 3.0 DBMS Release

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
 
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
 
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
 
Analysis of Microsoft Code Contracts
Analysis of Microsoft Code ContractsAnalysis of Microsoft Code Contracts
Analysis of Microsoft Code ContractsPVS-Studio
 
Static Analysis of Mozilla Thunderbird's Code by PVS-Studio
Static Analysis of Mozilla Thunderbird's Code by PVS-StudioStatic Analysis of Mozilla Thunderbird's Code by PVS-Studio
Static Analysis of Mozilla Thunderbird's Code by PVS-StudioPVS-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 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
 
Analyzing ReactOS One More Time
Analyzing ReactOS One More TimeAnalyzing ReactOS One More Time
Analyzing ReactOS One More TimePVS-Studio
 
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
 
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
 
The Little Unicorn That Could
The Little Unicorn That CouldThe Little Unicorn That Could
The Little Unicorn That CouldPVS-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
 
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...Andrey 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
 
The CppCat Analyzer Checks TortoiseGit
The CppCat Analyzer Checks TortoiseGitThe CppCat Analyzer Checks TortoiseGit
The CppCat Analyzer Checks TortoiseGitAndrey 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
 
Headache from using mathematical software
Headache from using mathematical softwareHeadache from using mathematical software
Headache from using mathematical softwarePVS-Studio
 
Cppcheck and PVS-Studio compared
Cppcheck and PVS-Studio comparedCppcheck and PVS-Studio compared
Cppcheck and PVS-Studio comparedPVS-Studio
 

Similar to Analyzing Firebird 3.0 DBMS Release (18)

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
 
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
 
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
 
Analysis of Microsoft Code Contracts
Analysis of Microsoft Code ContractsAnalysis of Microsoft Code Contracts
Analysis of Microsoft Code Contracts
 
Static Analysis of Mozilla Thunderbird's Code by PVS-Studio
Static Analysis of Mozilla Thunderbird's Code by PVS-StudioStatic Analysis of Mozilla Thunderbird's Code by PVS-Studio
Static Analysis of Mozilla Thunderbird's Code by PVS-Studio
 
Checking Clang 11 with PVS-Studio
Checking Clang 11 with PVS-StudioChecking Clang 11 with PVS-Studio
Checking Clang 11 with PVS-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 CppCat
 
Analyzing ReactOS One More Time
Analyzing ReactOS One More TimeAnalyzing ReactOS One More Time
Analyzing ReactOS One More Time
 
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
 
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
 
The Little Unicorn That Could
The Little Unicorn That CouldThe Little Unicorn That Could
The Little Unicorn That Could
 
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...
 
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...
 
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
 
The CppCat Analyzer Checks TortoiseGit
The CppCat Analyzer Checks TortoiseGitThe CppCat Analyzer Checks TortoiseGit
The CppCat Analyzer Checks TortoiseGit
 
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
 
Headache from using mathematical software
Headache from using mathematical softwareHeadache from using mathematical software
Headache from using mathematical software
 
Cppcheck and PVS-Studio compared
Cppcheck and PVS-Studio comparedCppcheck and PVS-Studio compared
Cppcheck and PVS-Studio compared
 

Recently uploaded

Asset Management Software - Infographic
Asset Management Software - InfographicAsset Management Software - Infographic
Asset Management Software - InfographicHr365.us smith
 
Hand gesture recognition PROJECT PPT.pptx
Hand gesture recognition PROJECT PPT.pptxHand gesture recognition PROJECT PPT.pptx
Hand gesture recognition PROJECT PPT.pptxbodapatigopi8531
 
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.
 
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
 
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 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
 
Professional Resume Template for Software Developers
Professional Resume Template for Software DevelopersProfessional Resume Template for Software Developers
Professional Resume Template for Software DevelopersVinodh Ram
 
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
 
BATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASE
BATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASEBATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASE
BATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASEOrtus Solutions, Corp
 
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
 
Cloud Management Software Platforms: OpenStack
Cloud Management Software Platforms: OpenStackCloud Management Software Platforms: OpenStack
Cloud Management Software Platforms: OpenStackVICTOR MAESTRE RAMIREZ
 
(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...
(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...
(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...gurkirankumar98700
 
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
 
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.
 
What is Fashion PLM and Why Do You Need It
What is Fashion PLM and Why Do You Need ItWhat is Fashion PLM and Why Do You Need It
What is Fashion PLM and Why Do You Need ItWave PLM
 
Russian Call Girls in Karol Bagh Aasnvi ➡️ 8264348440 💋📞 Independent Escort S...
Russian Call Girls in Karol Bagh Aasnvi ➡️ 8264348440 💋📞 Independent Escort S...Russian Call Girls in Karol Bagh Aasnvi ➡️ 8264348440 💋📞 Independent Escort S...
Russian Call Girls in Karol Bagh Aasnvi ➡️ 8264348440 💋📞 Independent Escort S...soniya singh
 
DNT_Corporate presentation know about us
DNT_Corporate presentation know about usDNT_Corporate presentation know about us
DNT_Corporate presentation know about usDynamic Netsoft
 
Salesforce Certified Field Service Consultant
Salesforce Certified Field Service ConsultantSalesforce Certified Field Service Consultant
Salesforce Certified Field Service ConsultantAxelRicardoTrocheRiq
 
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
 
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.
 

Recently uploaded (20)

Asset Management Software - Infographic
Asset Management Software - InfographicAsset Management Software - Infographic
Asset Management Software - Infographic
 
Hand gesture recognition PROJECT PPT.pptx
Hand gesture recognition PROJECT PPT.pptxHand gesture recognition PROJECT PPT.pptx
Hand gesture recognition PROJECT PPT.pptx
 
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 ...
 
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
 
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 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...
 
Professional Resume Template for Software Developers
Professional Resume Template for Software DevelopersProfessional Resume Template for Software Developers
Professional Resume Template for Software Developers
 
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...
 
BATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASE
BATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASEBATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASE
BATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASE
 
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...
 
Cloud Management Software Platforms: OpenStack
Cloud Management Software Platforms: OpenStackCloud Management Software Platforms: OpenStack
Cloud Management Software Platforms: OpenStack
 
(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...
(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...
(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...
 
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
 
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
 
What is Fashion PLM and Why Do You Need It
What is Fashion PLM and Why Do You Need ItWhat is Fashion PLM and Why Do You Need It
What is Fashion PLM and Why Do You Need It
 
Russian Call Girls in Karol Bagh Aasnvi ➡️ 8264348440 💋📞 Independent Escort S...
Russian Call Girls in Karol Bagh Aasnvi ➡️ 8264348440 💋📞 Independent Escort S...Russian Call Girls in Karol Bagh Aasnvi ➡️ 8264348440 💋📞 Independent Escort S...
Russian Call Girls in Karol Bagh Aasnvi ➡️ 8264348440 💋📞 Independent Escort S...
 
DNT_Corporate presentation know about us
DNT_Corporate presentation know about usDNT_Corporate presentation know about us
DNT_Corporate presentation know about us
 
Salesforce Certified Field Service Consultant
Salesforce Certified Field Service ConsultantSalesforce Certified Field Service Consultant
Salesforce Certified Field Service Consultant
 
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
 
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...
 

Analyzing Firebird 3.0 DBMS Release

  • 1. Analyzing Firebird 3.0 Author: Pavel Belikov Date: 11.05.2016 A new version of Firebird DBMS was released not so long ago. This release was one of the most significant in the project's history, as it marked substantial revision of the architecture, addition of multithreading support, and performance improvements. Such a significant update was a good occasion for us to scan Firebird one more time with PVS-Studio static code analyzer. Introduction Firebird is a cross-platform open-source database management system written in C++ that runs on Microsoft Windows, Linux, Mac OS X, and many Unix-like operating systems. It can be used and distributed for free. To learn more about Firebird, welcome to the official site. We have already scanned Firebird with our analyzer before. The previous report can be found in the article "A Spin-off: Firebird Checked by PVS-Studio". For this analysis, we took the project code from GitHub, the master branch. The building process is described in detail in the article at the project website. We analyzed the source files in PVS-Studio Standalone, version 6.03, using the Compiler Monitoring mechanism, which allows you to scan projects without integrating the tool into the build system. The log file generated by the analyzer can be viewed both in the Standalone version and in Visual Studio.
  • 2. Typos void advance_to_start() { .... if (!isalpha(c) && c != '_' && c != '.' && c != '_') syntax_error(lineno, line, cptr); .... } PVS-Studio diagnostic message: V501 There are identical sub-expressions 'c != '_'' to the left and to the right of the '&&' operator. reader.c 1203 The analyzer detected a logical expression with two identical subexpressions c != '_'. The last condition contains a typo and should actually compare the c variable with some other character. In other functions nearby, the variable is tested for the '$' character, so it should probably be used in our example as well: if (!isalpha(c) && c != '_' && c != '.' && c != '$') Another mistake resulting from the programmer's inattention: int put_message(....) { if (newlen <= MAX_UCHAR) { put(tdgbl, attribute); put(tdgbl, (UCHAR) newlen); } else if (newlen <= MAX_USHORT) { if (!attribute2) BURP_error(314, ""); .... } else BURP_error(315, ""); .... }
  • 3. PVS-Studio diagnostic messages:  V601 The string literal is implicitly cast to the bool type. Inspect the second argument. backup.cpp 6113  V601 The string literal is implicitly cast to the bool type. Inspect the second argument. backup.cpp 6120 Here we deal with a wrong call to the BURP_error function. This is how the function is declared: void BURP_error(USHORT errcode, bool abort, const MsgFormat::SafeArg& arg = MsgFormat::SafeArg()); void BURP_error(USHORT errcode, bool abort, const char* str); The second argument is a boolean value and the third one is a string. In our example, however, the string literal is passed as the second argument and is, therefore, cast to true. The function call should be rewritten in the following way: BURP_error(315, true, "") or BURP_error(315, false, ""). However, there are cases when only the project authors can tell if there is an error or not. void IDX_create_index(....) { .... index_fast_load ifl_data; .... if (!ifl_data.ifl_duplicates) scb->sort(tdbb); if (!ifl_data.ifl_duplicates) BTR_create(tdbb, creation, selectivity); .... } PVS-Studio diagnostic message: V581 The conditional expressions of the 'if' operators situated alongside each other are identical. Check lines: 506, 509. idx.cpp 509 This example deals with two blocks of code that check the same condition in succession. There might be a typo in one of them, or this issue has to do with copying or deleting some code fragments. In any case, this code looks strange. In the next example we'll discuss an issue that deals with pointers. static void string_to_datetime(....)
  • 4. { .... const char* p = NULL; const char* const end = p + length; .... while (p < end) { if (*p != ' ' && *p != 't' && p != 0) { CVT_conversion_error(desc, err); return; } ++p; } .... } PVS-Studio diagnostic message: V713 The pointer p was utilized in the logical expression before it was verified against nullptr in the same logical expression. cvt.cpp 702 In the condition, the p variable is compared with nullptr right after dereferencing. It may indicate that some other condition should have been used instead of this check, or that this check is just not necessary. Earlier in the code, a similar fragment can be found: while (++p < end) { if (*p != ' ' && *p != 't' && *p != 0) CVT_conversion_error(desc, err); } To avoid errors like this, use appropriate literals when comparing with zero: '0' for type char, 0 for numbers, and nullptr for pointers. Sticking to this rule will help you avoid lots of silly errors like that.
  • 5. Unsafe use of memcmp SSHORT TextType::compare(ULONG len1, const UCHAR* str1, ULONG len2, const UCHAR* str2) { .... SSHORT cmp = memcmp(str1, str2, MIN(len1, len2)); if (cmp == 0) cmp = (len1 < len2 ? -1 : (len1 > len2 ? 1 : 0)); return cmp; } PVS-Studio diagnostic message: V642 Saving the 'memcmp' function result inside the 'short' type variable is inappropriate. The significant bits could be lost breaking the program's logic. texttype.cpp 3 The memcmp function returns the following values:  < 0 if str1 is less than str2  0 if str1 equals str2  > 0 if str1 is greater than str2 The function does not guarantee to return exact values when the strings are not equal, so storing the result in a variable of size less than that of type int may lead to losing the most significant bits and distorting the execution logic. Extra checks void Trigger::compile(thread_db* tdbb) { SET_TDBB(tdbb); Database* dbb = tdbb->getDatabase(); Jrd::Attachment* const att = tdbb->getAttachment(); if (extTrigger) return;
  • 6. if (!statement /*&& !compile_in_progress*/) { if (statement) return; .... } } PVS-Studio diagnostic message: V637 Two opposite conditions were encountered. The second condition is always false. Check lines: 778, 780. jrd.cpp 778 The analyzer detected checks of two opposite conditions. The second condition seems to be no longer necessary since the first one was changed at some point in the past, so it can be deleted, although it is completely up to the author to make this decision. The following code fragment is another example of strange branching. static void asgn_from( ref* reference, int column) { TEXT variable[MAX_REF_SIZE]; TEXT temp[MAX_REF_SIZE]; for (; reference; reference = reference->ref_next) { const gpre_fld* field = reference->ref_field; .... if (!field || field->fld_dtype == dtype_text) .... else if (!field || field->fld_dtype == dtype_cstring) .... else .... } }
  • 7. PVS-Studio diagnostic message: V560 A part of conditional expression is always false: !field. int_cxx.cpp 217 If the field pointer is non-null, the code will never reach the condition in the else if branch. Either this check is redundant or there should be some other comparison instead of it. It's not clear, whether this condition contradicts the execution logic. In addition to these examples, a number of redundant checks were found in logical expressions. bool XnetServerEndPoint::server_init(USHORT flag) { .... xnet_connect_mutex = CreateMutex(ISC_get_security_desc(), FALSE, name_buffer); if (!xnet_connect_mutex || (xnet_connect_mutex && ERRNO == ERROR_ALREADY_EXISTS)) { system_error::raise(ERR_STR("CreateMutex")); } .... } PVS-Studio diagnostic message: V728 An excessive check can be simplified. The '||' operator is surrounded by opposite expressions '!xnet_connect_mutex' and 'xnet_connect_mutex'. xnet.cpp 2231 The check if (!xnet_connect_mutex || (xnet_connect_mutex && ERRNO == ERROR_ALREADY_EXISTS)) can be simplified to if (!xnet_connect_mutex || ERRNO == ERROR_ALREADY_EXISTS). The correctness of such transformation can be easily proved with the truth table. Unsafe comparison of an unsigned variable static bool write_page(thread_db* tdbb, BufferDesc* bdb, ....) { .... if (bdb->bdb_page.getPageNum() >= 0) .... } PVS-Studio diagnostic message: V547 Expression 'bdb->bdb_page.getPageNum() >= 0' is always true. Unsigned type value is always >= 0. cch.cpp 4827
  • 8. The bdb->bdb_page.getPageNum() >= 0 condition will always be true, as the function returns an unsigned value. This error probably has to do with an incorrect check of the value. Based on other similar comparisons in the project, I think the code should actually look like this: if (bdb->bdb_page.getPageNum() != 0) Null pointer dereferencing static bool initializeFastMutex(FAST_MUTEX* lpMutex, LPSECURITY_ATTRIBUTES lpAttributes, BOOL bInitialState, LPCSTR lpName) { if (pid == 0) pid = GetCurrentProcessId(); LPCSTR name = lpName; if (strlen(lpName) + strlen(FAST_MUTEX_EVT_NAME) - 2 >= MAXPATHLEN) { SetLastError(ERROR_FILENAME_EXCED_RANGE); return false; } setupMutex(lpMutex); char sz[MAXPATHLEN]; if (lpName) .... } PVS-Studio diagnostic message: V595 The 'lpName' pointer was utilized before it was verified against nullptr. Check lines: 2814, 2824. isc_sync.cpp 2814 Warning V595 is the most common among the projects scanned by PVS-Studio, and Firebird is no exception. In total, the analyzer found 30 issues triggering this diagnostic.
  • 9. In this example, the call strlen(lpName) precedes a pointer check for nullptr, thus leading to undefined behavior when trying to pass a null pointer to the function. The pointer-dereferencing operation is hidden inside the call to strlen, which makes it difficult to find the error without a static analyzer. Testing for nullptr after new rem_port* XnetServerEndPoint::get_server_port(....) { .... XCC xcc = FB_NEW struct xcc(this); try { .... } catch (const Exception&) { if (port) cleanup_port(port); else if (xcc) cleanup_comm(xcc); throw; } return port; } PVS-Studio diagnostic message: V668 There is no sense in testing the 'xcc' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error. xnet.cpp 2533 The analyzer warns us that the new operator cannot return nullptr - one must use a try-catch block or new (std::nothrow). However, this example is a bit more complicated. The programmer uses macro FB_NEW to allocate memory. This macro is declared in the file alloc.h: #ifdef USE_SYSTEM_NEW #define OOM_EXCEPTION std::bad_alloc
  • 10. #else #define OOM_EXCEPTION Firebird::BadAlloc #endif #define FB_NEW new(__FILE__, __LINE__) inline void* operator new(size_t s ALLOC_PARAMS) throw (OOM_EXCEPTION) { return MemoryPool::globalAlloc(s ALLOC_PASS_ARGS); } I can't say for sure if this particular example is incorrect, as it uses a non-standard allocator; but the presence of throw (std::bad_alloc) in the operator declaration makes this check quite suspicious. Unsafe use of realloc int mputchar(struct mstring *s, int ch) { if (!s || !s->base) return ch; if (s->ptr == s->end) { int len = s->end - s->base; if ((s->base = realloc(s->base, len+len+TAIL))) { s->ptr = s->base + len; s->end = s->base + len+len+TAIL; } else { s->ptr = s->end = 0; return ch; } } *s->ptr++ = ch; return ch; } PVS-Studio diagnostic message: V701 realloc() possible leak: when realloc() fails in allocating memory, original pointer 's->base' is lost. Consider assigning realloc() to a temporary pointer. mstring.c 42 What is bad about expressions of the ptr = realloc(ptr, size) pattern is that the pointer to the memory block will be lost when realloc returns nullptr. To avoid it, one needs to save the result returned by realloc in a temporary variable and then assign this value to ptr after comparing it with nullptr.
  • 11. temp_ptr = realloc(ptr, new_size); if (temp_ptr == nullptr) { //handle exception } else { ptr = temp_ptr; } Unused enum values in switch template <typename CharType> LikeEvaluator<CharType>::LikeEvaluator(....) { .... PatternItem *item = patternItems.begin(); .... switch (item->type) { case piSkipFixed: case piSkipMore: patternItems.grow(patternItems.getCount() + 1); item = patternItems.end() - 1; // Note: fall into case piNone: item->type = piEscapedString; item->str.data = const_cast<CharType*> (pattern_str + pattern_pos - 2); item->str.length = 1; break; case piSearch: item->type = piEscapedString; // Note: fall into case piEscapedString: item->str.length++;
  • 12. break; } .... } PVS-Studio diagnostic message: V719 The switch statement does not cover all values of the 'PatternItemType' enum: piDirectMatch. evl_string.h 324 Not all enum values were used in the switch statement; the default block is absent, too. This example seems to lack the code that handles the piDirectMatch element. Other similar issues:  V719 The switch statement does not cover all values of the 'PatternItemType' enum: piDirectMatch, piSkipMore. evl_string.h 351  V719 The switch statement does not cover all values of the 'PatternItemType' enum: piDirectMatch. evl_string.h 368  V719 The switch statement does not cover all values of the 'PatternItemType' enum: piDirectMatch. evl_string.h 387 Buffer overflow const int GDS_NAME_LEN = 32; .... bool get_function(BurpGlobals* tdgbl) { .... struct isc_844_struct { .... short isc_870; /* gds__null_flag */ .... char isc_874 [125]; /* RDB$PACKAGE_NAME */ .... } isc_844; att_type attribute; TEXT temp[GDS_NAME_LEN * 2]; .... SSHORT prefixLen = 0; if (!/*X.RDB$PACKAGE_NAME.NULL*/
  • 13. isc_844.isc_870) { prefixLen = static_cast<SSHORT>(strlen(/*X.RDB$PACKAGE_NAME*/ isc_844.isc_874)); memcpy(temp, /*X.RDB$PACKAGE_NAME*/ isc_844.isc_874, prefixLen); temp[prefixLen++] = '.'; } .... } PVS-Studio diagnostic message: V557 Array overrun is possible. The value of 'prefixLen ++' index could reach 124. restore.cpp 10040 The size of the buffer isc_844.isc_874 is 125; therefore, the largest value possible of strlen(isc_844.isc_874) is 124. The size of temp is 64, which is less than that value. Writing at this index may cause a buffer overflow. A safer way is to allocate a larger storage for the temp variable. Shifting negative numbers static ISC_STATUS stuff_literal(gen_t* gen, SLONG literal) { .... if (literal >= -32768 && literal <= 32767) return stuff_args(gen, 3, isc_sdl_short_integer, literal, literal >> 8); .... } PVS-Studio diagnostic message: V610 Unspecified behavior. Check the shift operator '>>'. The left operand is negative ('literal' = [-32768..32767]). array.cpp 848
  • 14. The code contains a right-shift operation on a negative number. As the C++ standard states, such an operation leads to undefined behavior, i.e. it may produce different results on different compilers and platforms. The code should be rewritten as follows: if (literal >= -32768 && literal <= 32767) return stuff_args(gen, 3, isc_sdl_short_integer, literal, (ULONG)literal >> 8); Another fragment triggering this warning: V610 Unspecified behavior. Check the shift operator '>>'. The left operand is negative ('i64value' = [- 2147483648..2147483647]). exprnodes.cpp 6382 Variable redefinition THREAD_ENTRY_DECLARE Service::run(THREAD_ENTRY_PARAM arg) { int exit_code = -1; try { Service* svc = (Service*)arg; RefPtr<SvcMutex> ref(svc->svc_existence); int exit_code = svc->svc_service_run->serv_thd(svc); svc->started(); svc->svc_sem_full.release(); svc->finish(SVC_finished); } catch (const Exception& ex) { // Not much we can do here iscLogException("Exception in Service::run():", ex); } return (THREAD_ENTRY_RETURN)(IPTR) exit_code; }
  • 15. PVS-Studio diagnostic message: V561 It's probably better to assign value to 'exit_code' variable than to declare it anew. Previous declaration: svc.cpp, line 1893. svc.cpp 1898 In this example, the exit_code variable is redefined instead of being assigned a value. Variable redefinition hides the previously declared variable from the scope and makes the function always return an incorrect value, which is -1. Fixed code: THREAD_ENTRY_DECLARE Service::run(THREAD_ENTRY_PARAM arg) { int exit_code = -1; try { Service* svc = (Service*)arg; RefPtr<SvcMutex> ref(svc->svc_existence); exit_code = svc->svc_service_run->serv_thd(svc); svc->started(); svc->svc_sem_full.release(); svc->finish(SVC_finished); } catch (const Exception& ex) { // Not much we can do here iscLogException("Exception in Service::run():", ex); } return (THREAD_ENTRY_RETURN)(IPTR) exit_code; } Conclusion As the new analysis shows, the project developers have fixed most of the issues found during the previous analysis, so those bugs are no longer there, which is a good sign that the compiler did a good job. However, using the analyzer regularly could help achieve even better results because that way it allows catching bugs at earlier stages. Incremental analysis and compatibility with any build system allow integrating the analyzer easily into your project. Using static analysis helps save plenty of time and catch errors that are difficult to detect by means of debugging or dynamic analysis.