SlideShare a Scribd company logo
1 of 133
A scrupulous code review – 15 bugs in
C++ code
Phillip Khandeliants
khandeliants@viva64.com
About Me
 Over 5 years with the PVS-Studio
team
 Team lead at the C++ analyzer
development team
 Microsoft Certified Professional, C#
 Talk on modern C++
 Live by the C++ ISO standard
2
Intro: the code review
3
 We all do code reviews
 Who doesn't admit this – does it
twice as often
1. 'Auto'matic coding
4
void foo(const std::vector<....> &vec)
{
....
for (auto i = 0; i < vec.size(); ++i)
{
// do some magic with vec[i]
....
}
....
}
5
void foo(const std::vector<....> &vec)
{
....
for (int i = 0; i < vec.size(); ++i) // 64-bit problems :)
{
// do some magic with vec[i]
....
}
....
}
6
void foo(const std::vector<....> &vec)
{
....
for (size_t i = 0; i < vec.size(); ++i) // ok
{
// do some magic with vec[i]
....
}
....
}
7
void foo(const std::vector<....> &vec)
{
....
for (std::vector<....>::size_type i = 0; i < vec.size(); ++i)
{
// do some magic with vec[i]
....
}
....
}
8
void foo(const std::vector<....> &vec)
{
....
for (auto i = 0uLL; i < vec.size(); ++i) // don't do that on
// 128-bit processors
{
// do some magic with vec[i]
....
}
....
}
9
void foo(const std::vector<....> &vec)
{
....
for (auto i = 0uLLL; i < vec.size(); ++i) // ok since C++7d
{
// do some magic with vec[i]
....
}
....
}
10
void foo(const std::vector<....> &vec)
{
....
for (auto i = 0uLLL; i < vec.size(); ++i) // ok since C++7d
{
// do some magic with vec[i]
....
}
....
}
11
2. Reference! I said reference! Perfection!
12
13
template <typename T>
int ColumnDecimal<T>::compareAt(size_t n, size_t m,
const IColumn & rhs_, int) const
{
auto other = static_cast<const Self &>(rhs_);
const T &a = data[n];
const T &b = other.data[m];
return decimalLess<T>(b, a, other.scale, scale)
? 1
: (decimalLess<T>(a, b, scale, other.scale) ? -1 : 0);
}
14
template <typename T>
int ColumnDecimal<T>::compareAt(size_t n, size_t m,
const IColumn & rhs_, int) const
{
auto other = static_cast<const Self &>(rhs_);
const T &a = data[n];
const T &b = other.data[m];
return decimalLess<T>(b, a, other.scale, scale)
? 1
: (decimalLess<T>(a, b, scale, other.scale) ? -1 : 0);
}
15
template <typename T>
int ColumnDecimal<T>::compareAt(size_t n, size_t m,
const IColumn & rhs_, int) const
{
auto &other = static_cast<const Self &>(rhs_);
const T &a = data[n];
const T &b = other.data[m];
return decimalLess<T>(b, a, other.scale, scale)
? 1
: (decimalLess<T>(a, b, scale, other.scale) ? -1 : 0);
}
16
template <typename T>
int ColumnDecimal<T>::compareAt(size_t n, size_t m,
const IColumn & rhs_, int) const
{
decltype(auto) other = static_cast<const Self &>(rhs_);
const T &a = data[n];
const T &b = other.data[m];
return decimalLess<T>(b, a, other.scale, scale)
? 1
: (decimalLess<T>(a, b, scale, other.scale) ? -1 : 0);
}
3. Vector-vector, *pChar++
17
void vector32_inc(std::vector<uint32_t> &v)
{
for (size_t i = 0; i < v.size(); i++)
{
v[i]++;
}
}
18
void vector32_inc(std::vector<uint32_t> &v)
{
for (size_t i = 0; i < v.size(); i++)
{
v[i]++;
}
}
void vector8_inc(std::vector<uint8_t> &v)
{
for (size_t i = 0; i < v.size(); i++)
{
v[i]++;
}
}
19
Let's benchmark :)
20
Compiler Element -O1 -O2 -O3
gcc 8 uint8_t 2.0 2.0 2.0
gcc 8 uint32_t 2.3 1.3 0.2
clang 8 uint8_t 9.2 2.0 2.0
clang 8 uint32_t 9.2 0.2 0.2
21
vector8_inc(std::vector<uint8_t> &):
mov rdx, QWORD PTR [rdi] ; it = begin()
cmp rdx, QWORD PTR [rdi+8] ; if (it == end())
je .L1 ; return
xor eax, eax ; i = 0
.L3: ; do {
add BYTE PTR [rdx+rax], 1 ; ++(*(it + i))
mov rdx, QWORD PTR [rdi] ; it = begin()
add rax, 1 ; ++i
mov rcx, QWORD PTR [rdi+8] ; end = end()
sub rcx, rdx ; end = end - it
cmp rax, rcx
jb .L3 ; } while (i < end)
.L1:
ret
vector32_inc(std::vector<uint32_t> &):
mov rax, QWORD PTR [rdi] ; it = begin()
mov rdx, QWORD PTR [rdi+8] ; end = end()
sub rdx, rax ; end = end - it
mov rcx, rdx ; size in bytes
shr rcx, 2 ; size in elements
je .L1 ; if (size == 0)
; return
add rdx, rax ; end = end + it
.L3: ; do {
add DWORD PTR [rax], 1 ; ++(*it)
add rax, 4 ; ++it
cmp rax, rdx
jne .L3 ; } while (it != end)
.L1:
ret
22
vector8_inc(std::vector<uint8_t> &):
mov rdx, QWORD PTR [rdi] ; it = begin()
cmp rdx, QWORD PTR [rdi+8] ; if (it == end())
je .L1 ; return
xor eax, eax ; i = 0
.L3: ; do {
add BYTE PTR [rdx+rax], 1 ; ++(*(it + i))
mov rdx, QWORD PTR [rdi] ; it = begin()
add rax, 1 ; ++i
mov rcx, QWORD PTR [rdi+8] ; end = end()
sub rcx, rdx ; end = end - it
cmp rax, rcx
jb .L3 ; } while (i < end)
.L1:
ret
vector32_inc(std::vector<uint32_t> &):
mov rax, QWORD PTR [rdi] ; it = begin()
mov rdx, QWORD PTR [rdi+8] ; end = end()
sub rdx, rax ; end = end - it
mov rcx, rdx ; size in bytes
shr rcx, 2 ; size in elements
je .L1 ; if (size == 0)
; return
add rdx, rax ; end = end + it
.L3: ; do {
add DWORD PTR [rax], 1 ; ++(*it)
add rax, 4 ; ++it
cmp rax, rdx
jne .L3 ; } while (it != end)
.L1:
ret
void vector8_inc(std::vector<uint8_t> &v)
{
for (size_t i = 0; i < v.size(); i++)
{
v[i]++;
}
}
23
void vector8_inc(std::vector<uint8_t> &v)
{
for (size_t i = 0; i < v.size(); i++)
{
v[i]++;
}
}
void vector8_inc(std::vector<uint8_t> &v)
{
auto it = v.begin();
const auto end = v.end();
for (; it != end; ++it)
{
++(*it);
}
}
24
25
vector8_inc(std::vector<uint8_t> &):
mov rax, QWORD PTR [rdi] ; it = begin()
mov rdx, QWORD PTR [rdi+8] ; end = end()
cmp rax, rdx ; if (it == end)
je .L1 ; return
.L3: ; do {
add BYTE PTR [rax], 1 ; ++(*it)
add rax, 1 ; ++it
cmp rax, rdx ; } while (it != end)
.L1:
ret
26
vector8_inc(std::vector<uint8_t> &):
mov rax, QWORD PTR [rdi] ; it = begin()
mov rdx, QWORD PTR [rdi+8] ; end = end()
cmp rax, rdx ; if (it == end)
je .L1 ; return
.L3: ; do {
add BYTE PTR [rax], 1 ; ++(*it)
add rax, 1 ; ++it
cmp rax, rdx ; } while (it != end)
.L1:
ret
Let's make benchmarks great again!
Compiler
uint8_t
-O1 -O2 -O3
gcc 8 (before) 2.0 2.0 2.0
gcc 8 (after) 1.3 1.3 0.06
gcc speedup 1.5x 1.5x 33.4x
Compiler
uint8_t
-O1 -O2 -O3
clang 8 (before) 9.2 2.0 2.0
clang 8 (after) 20.3 0.06 0.06
clang speedup 0.45x 33.4x 33.4x
void vector8_inc(std::vector<uint8_t> &v)
{
auto it = v.begin();
const auto end = v.end();
for (; it != end; ++it)
{
++(*it);
}
}
28
void vector8_inc(std::vector<uint8_t> &v)
{
auto it = v.begin();
const auto end = v.end();
for (; it != end; ++it)
{
++(*it);
}
}
void vector8_inc(std::vector<uint8_t> &v)
{
for (auto &elem : v)
{
++elem;
}
}
29
30
4. Security? Security!
31
#include <cstring>
#include <memory>
void InputPassword(char *pswd);
void ProcessPassword(const char *pswd);
#define MAX_PASSWORD_LEN ....
void Foo()
{
char password[MAX_PASSWORD_LEN];
InputPassword(password);
ProcessPassword(password);
memset(password, 0, sizeof(password));
}
32
#include <cstring>
#include <memory>
void InputPassword(char *pswd);
void ProcessPassword(const char *pswd);
#define MAX_PASSWORD_LEN ....
void Foo()
{
char password[MAX_PASSWORD_LEN];
InputPassword(password);
ProcessPassword(password);
memset(password, 0, sizeof(password));
}
33
34
#include <cstring>
#include <memory>
void InputPassword(char *pswd);
void ProcessPassword(const char *pswd);
#define MAX_PASSWORD_LEN ....
void Foo()
{
char *password = new char[MAX_PASSWORD_LEN];
InputPassword(password);
ProcessPassword(password);
memset(password, 0, MAX_PASSWORD_LEN);
delete[] password;
} 35
36
void tds_answer_challenge(....)
{
#define MAX_PW_SZ 14
....
if (ntlm_v == 1) {
....
/* with security is best be pedantic */
memset(hash, 0, sizeof(hash));
memset(passwd_buf, 0, sizeof(passwd_buf));
memset(ntlm2_challenge, 0, sizeof(ntlm2_challenge));
} else {
....
}
}
37
typedef struct tds_answer
{
unsigned char lm_resp[24];
unsigned char nt_resp[24];
} TDSANSWER;
static TDSRET tds7_send_auth(....)
{
size_t current_pos;
TDSANSWER answer;
....
/* for security reason clear structure */
memset(&answer, 0, sizeof(TDSANSWER));
return tds_flush_packet(tds);
}
38
char* crypt_md5(const char* pw, const char* salt)
{
unsigned char final[MD5_SIZE];
....
/* Don't leave anything around in vm they could use. */
memset(final, 0, sizeof final);
return passwd;
}
39
void MD4Engine::transform (UInt32 state[4],
const unsigned char block[64])
{
UInt32 a = state[0], b = state[1],
c = state[2], d = state[3], x[16];
decode(x, block, 64);
....
/* Zeroize sensitive information. */
std::memset(x, 0, sizeof(x));
}
40
char* px_crypt_md5(const char *pw, const char *salt,
char *passwd, unsigned dstlen)
{
....
unsigned char final[MD5_SIZE];
....
/* Don't leave anything around in vm they could use. */
memset(final, 0, sizeof final);
....
}
41
42
 Custom safe_memset + disabled LTO/WPO
 Access a non-volatile object through a volatile pointer
 Call memset through a volatile function pointer
 Volatile assembly code
 Memset + memory barrier
 Disable compiler optimizations (-fno-builtin-memset)
 C11: memset_s
 Windows: RtlSecureZeroMemory
 FreeBSD & OpenBSD: explicit_bzero
 Linux Kernel: memzero_explicit
Ways to fix
43
5. Dirty thoughts data
44
static const char* basic_gets(int *cnt)
{
....
int c = getchar();
if (c < 0)
{
if ( fgets(command_buf, sizeof(command_buf) - 1, stdin)
!= command_buf)
{
break;
}
/* remove endline */
command_buf[strlen(command_buf)-1] = '0';
break;
}
....
}
45
static const char* basic_gets(int *cnt)
{
....
int c = getchar();
if (c < 0)
{
if ( fgets(command_buf, sizeof(command_buf) - 1, stdin)
!= command_buf)
{
break;
}
/* remove endline */
command_buf[strlen(command_buf)-1] = '0';
break;
}
....
}
46
int main (int argc, char *argv[])
{
....
else if (fgets(readbuf, BUFSIZ, stdin) == NULL)
{
if (feof (stdin))
break;
error (EXIT_FAILURE, errno, _("input error"));
}
if (readbuf[strlen(readbuf) - 1] == 'n')
readbuf[strlen(readbuf) - 1] = '0';
....
}
47
int main (int argc, char *argv[])
{
....
else if (fgets(readbuf, BUFSIZ, stdin) == NULL)
{
if (feof (stdin))
break;
error (EXIT_FAILURE, errno, _("input error"));
}
if (readbuf[strlen(readbuf) - 1] == 'n')
readbuf[strlen(readbuf) - 1] = '0';
....
}
48
CVE-2015-8948
int main (int argc, char *argv[])
{
....
else if (getline(&line, &linelen, stdin) == -1)
{
if (feof (stdin))
break;
error (EXIT_FAILURE, errno, _("input error"));
}
if (line[strlen(line) - 1] == 'n')
line[strlen(line) - 1] = '0';
....
}
49
int main (int argc, char *argv[])
{
....
else if (getline(&line, &linelen, stdin) == -1)
{
if (feof (stdin))
break;
error (EXIT_FAILURE, errno, _("input error"));
}
if (line[strlen(line) - 1] == 'n')
line[strlen(line) - 1] = '0';
....
}
50
CVE-2016-6262
6. Last effort
51
inline void Init( float ix=0, float iy=0,
float iz=0, float iw = 0 )
{
SetX( ix );
SetY( iy );
SetZ( iz );
SetZ( iw );
}
52
inline void Init( float ix=0, float iy=0,
float iz=0, float iw = 0 )
{
SetX( ix );
SetY( iy );
SetZ( iz );
SetZ( iw );
}
53
54
inline void Init( float ix=0, float iy=0,
float iz=0, float iw = 0 )
{
SetX( ix );
SetY( iy );
SetZ( iz );
SetW( iw );
}
if (access & FILE_WRITE_ATTRIBUTES)
output.append(ASCIIToUTF16("tFILE_WRITE_ATTRIBUTESn"));
if (access & FILE_WRITE_DATA)
output.append(ASCIIToUTF16("tFILE_WRITE_DATAn"));
if (access & FILE_WRITE_EA)
output.append(ASCIIToUTF16("tFILE_WRITE_EAn"));
if (access & FILE_WRITE_EA)
output.append(ASCIIToUTF16("tFILE_WRITE_EAn"));
break;
55
if (access & FILE_WRITE_ATTRIBUTES)
output.append(ASCIIToUTF16("tFILE_WRITE_ATTRIBUTESn"));
if (access & FILE_WRITE_DATA)
output.append(ASCIIToUTF16("tFILE_WRITE_DATAn"));
if (access & FILE_WRITE_EA)
output.append(ASCIIToUTF16("tFILE_WRITE_EAn"));
if (access & FILE_WRITE_EA)
output.append(ASCIIToUTF16("tFILE_WRITE_EAn"));
break;
56
if (protocol.EqualsIgnoreCase("http") ||
protocol.EqualsIgnoreCase("https") ||
protocol.EqualsIgnoreCase("news") ||
protocol.EqualsIgnoreCase("ftp") ||
protocol.EqualsIgnoreCase("file") ||
protocol.EqualsIgnoreCase("javascript") ||
protocol.EqualsIgnoreCase("ftp")) {
57
if (protocol.EqualsIgnoreCase("http") ||
protocol.EqualsIgnoreCase("https") ||
protocol.EqualsIgnoreCase("news") ||
protocol.EqualsIgnoreCase("ftp") ||
protocol.EqualsIgnoreCase("file") ||
protocol.EqualsIgnoreCase("javascript") ||
protocol.EqualsIgnoreCase("ftp")) {
58
7. Zero, one, two,
Freddy's coming for you!
59
Sequence< OUString > FirebirdDriver::
getSupportedServiceNames_Static() throw (RuntimeException)
{
Sequence< OUString > aSNS( 2 );
aSNS[0] = "com.sun.star.sdbc.Driver";
aSNS[0] = "com.sun.star.sdbcx.Driver";
return aSNS;
}
60
Sequence< OUString > FirebirdDriver::
getSupportedServiceNames_Static() throw (RuntimeException)
{
Sequence< OUString > aSNS( 2 );
aSNS[0] = "com.sun.star.sdbc.Driver";
aSNS[0] = "com.sun.star.sdbcx.Driver";
return aSNS;
}
61
struct short2
{
short values[2];
short2(short s1, short s2)
{
values[0] = s1;
values[2] = s2;
}
....
};
62
struct short2
{
short values[2];
short2(short s1, short s2)
{
values[0] = s1;
values[2] = s2;
}
....
};
63
8. Evil within comparisons!
64
string _server;
....
bool operator<( const ServerAndQuery& other ) const {
if ( ! _orderObject.isEmpty() )
return _orderObject.woCompare( other._orderObject ) < 0;
if ( _server < other._server )
return true;
if ( other._server > _server )
return false;
return _extra.woCompare( other._extra ) < 0;
}
Pattern: A < B, B > A
65
string _server;
....
bool operator<( const ServerAndQuery& other ) const {
if ( ! _orderObject.isEmpty() )
return _orderObject.woCompare( other._orderObject ) < 0;
if ( _server < other._server )
return true;
if ( other._server > _server )
return false;
return _extra.woCompare( other._extra ) < 0;
}
Pattern: A < B, B > A
66
bool
operator==(const SComputePipelineStateDescription &other) const
{
return 0 == memcmp(this, &other, sizeof(this));
}
Pattern: evaluating the size of a pointer instead of
the size of the structure/class
67
bool
operator==(const SComputePipelineStateDescription &other) const
{
return 0 == memcmp(this, &other, sizeof(this));
}
Pattern: evaluating the size of a pointer instead of
the size of the structure/class
68
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;
}
Pattern: incorrect use of the memcmp result
69
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;
}
Pattern: incorrect use of the memcmp result
70
if (cmp == 0)
cmp = (len1 < len2 ? -1 : (len1 > len2 ? 1 : 0));
Pattern: incorrect use of the memcmp result
71
bool Peptide::operator==(Peptide& p) {
....
for (i = 0, j = 0;
i < this->stripped.length(), j < p.stripped.length();
i++, j++) {
....
}
Pattern: incorrect loops
72
bool Peptide::operator==(Peptide& p) {
....
for (i = 0, j = 0;
i < this->stripped.length(), j < p.stripped.length();
i++, j++) {
....
}
Pattern: incorrect loops
73
bool equals( class1* val1, class2* val2 ) const
{
...
size_t size = val1->size();
...
while ( --size >= 0 )
{
if ( !comp(*itr1,*itr2) )
return false;
itr1++;
itr2++;
}
...
}
Pattern: incorrect loops
74
bool equals( class1* val1, class2* val2 ) const
{
...
size_t size = val1->size();
...
while ( --size >= 0 )
{
if ( !comp(*itr1,*itr2) )
return false;
itr1++;
itr2++;
}
...
}
Pattern: Incorrect Loops
75
9. Use <=>, Luke!
76
Base equality comparison
77
struct Foo
{
int a, b;
};
Base equality comparison
78
struct Foo
{
int a, b;
};
bool operator==(Foo lhs, Foo rhs)
{
return lhs.a == rhs.a && lhs.b == rhs.b;
}
Base equality comparison
79
struct Foo
{
int a, b;
};
bool operator==(Foo lhs, Foo rhs)
{
return lhs.a == rhs.a && lhs.b == rhs.b;
}
bool operator!=(Foo lhs, Foo rhs)
{
return !(lhs == rhs);
}
Base 'less' comparison
80
struct Foo
{
int a, b;
};
bool operator<(Foo lhs, Foo rhs)
{
return lhs.a < rhs.a && lhs.b < rhs.b;
}
Base 'less' comparison
81
struct Foo
{
int a, b;
};
bool operator<(Foo lhs, Foo rhs)
{
return lhs.a < rhs.a && lhs.b < rhs.b;
}
Foo { 1, 2 } < Foo { 2, 1 }; // <= false
Foo { 2, 1 } < Foo { 1, 2 }; // <= false
Base 'less' comparison
82
struct Foo
{
int a, b;
};
bool operator<(Foo lhs, Foo rhs)
{
if (lhs.a < rhs.a) return true;
if (rhs.a < lhs.a) return false;
return lhs.b < rhs.b;
}
Foo { 1, 2 } < Foo { 2, 1 }; // <= true
Foo { 2, 1 } < Foo { 1, 2 }; // <= false
Base 'less' comparison
83
struct Foo
{
double a;
};
bool operator<(Foo lhs, Foo rhs)
{
return lhs.a < rhs.a;
}
Base 'less' comparison
84
struct Foo
{
double a;
};
bool operator<(Foo lhs, Foo rhs)
{
return lhs.a < rhs.a;
}
bool operator>=(Foo lhs, Foo rhs)
{
return !(lhs < rhs);
}
Base 'less' comparison
85
struct Foo
{
double a;
};
bool operator<(Foo lhs, Foo rhs)
{
return lhs.a < rhs.a;
}
bool operator>=(Foo lhs, Foo rhs)
{
return !(lhs < rhs);
}
Foo { 1.0 } < Foo { 2.0 }; // <= true
Foo { 1.0 } < Foo { NaN }; // <= false
Foo { 1.0 } >= Foo { NaN }; // <= true
Comparisons in C++20
86
#include <compare>
struct Foo
{
double a;
auto operator<=>(const Foo &rhs) const = default;
};
Foo { 1.0 } < Foo { 2.0 }; // <= true
Foo { 1.0 } < Foo { NaN }; // <= false
Foo { 1.0 } >= Foo { NaN }; // <= false
10. Payne, I can't feel my legs pointer
87
void Item_Paint(itemDef_t *item) {
vec4_t red;
menuDef_t *parent = (menuDef_t*)item->parent;
red[0] = red[3] = 1;
red[1] = red[2] = 0;
if (item == NULL) {
return;
}
....
}
88
void Item_Paint(itemDef_t *item) {
vec4_t red;
menuDef_t *parent = (menuDef_t*)item->parent;
red[0] = red[3] = 1;
red[1] = red[2] = 0;
if (item == NULL) {
return;
}
....
}
89
void Item_Paint(std::unique_ptr<itemDef_t> &item) {
vec4_t red;
menuDef_t *parent = (menuDef_t*)item->parent;
red[0] = red[3] = 1;
red[1] = red[2] = 0;
if (item == NULL) {
return;
}
....
}
90
void Item_Paint(std::shared_ptr<itemDef_t> &item) {
vec4_t red;
menuDef_t *parent = (menuDef_t*)item->parent;
red[0] = red[3] = 1;
red[1] = red[2] = 0;
if (item == NULL) {
return;
}
....
}
91
void Item_Paint(std::optional<itemDef_t> &item) {
vec4_t red;
menuDef_t *parent = (menuDef_t*)item->parent;
red[0] = red[3] = 1;
red[1] = red[2] = 0;
if (!item) {
return;
}
....
}
92
static struct DerivedMesh *dynamicPaint_Modifier_apply(....)
{
....
for (; surface; surface = surface->next) {
PaintSurfaceData *sData = surface->data;
if (surface &&
surface->format !=
MOD_DPAINT_SURFACE_F_IMAGESEQ &&
sData)
{
....
}
93
static struct DerivedMesh *dynamicPaint_Modifier_apply(....)
{
....
for (; surface; surface = surface->next) {
PaintSurfaceData *sData = surface->data;
if (surface &&
surface->format !=
MOD_DPAINT_SURFACE_F_IMAGESEQ &&
sData)
{
....
}
94
11. Push me and then emplace me!
95
struct G584_Info
{
G584_Info(const Ptree *p, bool add, bool mul, bool sub, bool div)
{
....
}
....
const Ptree *m_p;
bool m_add;
bool m_mul;
bool m_sub;
bool m_div;
};
96
static void G584_CollectExprInfo(const Ptree *p,
vector<G584_Info> &infs)
{
....
auto what = p->What();
if (what == ntParenExpr)
{
// Remember the expression in parentheses and continue
infs.push_back(G584_Info(p, true, true, false, false));
p = SafeSkipParentesis(p);
}
....
}
97
static void G584_CollectExprInfo(const Ptree *p,
vector<G584_Info> &infs)
{
....
auto what = p->What();
if (what == ntParenExpr)
{
// Remember the expression in parentheses and continue
infs.push_back(G584_Info(p, true, true, false, false));
p = SafeSkipParentesis(p);
}
....
}
98
static void G584_CollectExprInfo(const Ptree *p,
vector<G584_Info> &infs)
{
....
auto what = p->What();
if (what == ntParenExpr)
{
// Remember the expression in parentheses and continue
infs.emplace_back(p, true, true, false, false);
p = SafeSkipParentesis(p);
}
....
}
99
struct G584_Info
{
G584_Info(const Ptree *p, bool add, bool mul, bool sub, bool div)
{
....
}
....
const Ptree *m_p;
bool m_add;
bool m_mul;
bool m_sub;
bool m_div;
};
100
struct G584_Info
{
G584_Info(const Ptree *p, bool add, bool mul, bool sub, bool div)
{
....
}
....
const Ptree *m_p;
bool m_add;
bool m_mul;
bool m_sub;
bool m_div;
};
101
static void G584_CollectExprInfo(const Ptree *p,
vector<G584_Info> &infs)
{
....
auto what = p->What();
if (what == ntParenExpr)
{
// Remember the expression in parentheses and continue
infs.emplace_back(p, true, true, false, false); // ok since C++20
p = SafeSkipParentesis(p);
}
....
}
102
103
12. I will find you and insert you!
104
void AddFunctionDangerousInfo(const vstring &strFunctionInfo,
const FunctionDangerousInfo &info)
{
FunctionDangerousInfoMap &infoMap = GetFunctionDangerousInfoMap();
DangerousInfoIterator it = infoMap.find(strFunctionInfo);
if (it == infoMap.end())
{
infoMap.insert(make_pair(strFunctionInfo, dangerousInfo));
}
else
{
FunctionDangerousInfo &a = it->second;
// some works with 'a'
}
}
105
void AddFunctionDangerousInfo(const vstring &strFunctionInfo,
const FunctionDangerousInfo &info)
{
FunctionDangerousInfoMap &infoMap = GetFunctionDangerousInfoMap();
DangerousInfoIterator it = infoMap.find(strFunctionInfo);
if (it == infoMap.end())
{
infoMap.insert(make_pair(strFunctionInfo, dangerousInfo));
}
else
{
FunctionDangerousInfo &a = it->second;
// some works with 'a'
}
}
106
void AddFunctionDangerousInfo(....)
{
auto &infoMap = GetFunctionDangerousInfoMap();
if (auto it = infoMap.find(strFunctionInfo); it == infoMap.end())
{
infoMap.emplace(strFunctionInfo, dangerousInfo);
}
else
{
FunctionDangerousInfo &a = it->second;
// some works with 'a'
}
}
107
void AddFunctionDangerousInfo(....)
{
auto &infoMap = GetFunctionDangerousInfoMap();
if (auto it = infoMap.find(strFunctionInfo); it == infoMap.end())
{
infoMap.emplace(strFunctionInfo, dangerousInfo);
}
else
{
FunctionDangerousInfo &a = it->second;
// some works with 'a'
}
}
108
void AddFunctionDangerousInfo(....)
{
auto &infoMap = GetFunctionDangerousInfoMap();
if (auto it = infoMap.lower_bound(strFunctionInfo);
it != infoMap.end())
{
auto &a = it->second;
// some works with 'a'
}
else
{
infoMap.emplace_hint(it,
strFunctionInfo,
dangerousInfo);
}
}
109
void AddFunctionDangerousInfo(....)
{
auto &infoMap = GetFunctionDangerousInfoMap();
if (auto it = infoMap.lower_bound(strFunctionInfo);
it != infoMap.end() && it->first == strFunctionInfo)
{
auto &a = it->second;
// some works with 'a'
}
else
{
infoMap.emplace_hint(it,
strFunctionInfo,
dangerousInfo);
}
}
110
13. Is it alive?
111
struct Foo
{
int i;
double d;
};
Foo* bar()
{
Foo *ptr = (Foo *) malloc(sizeof(Foo));
if (ptr == NULL)
return NULL;
ptr->i = 0;
ptr->d = 0.0;
return ptr;
}
112
struct Foo
{
int i;
double d;
};
Foo* bar()
{
Foo *ptr = (Foo *) malloc(sizeof(Foo));
if (ptr == NULL)
return NULL;
ptr->i = 0; // ok in C, UB in C++
ptr->d = 0.0; // ok in C, UB in C++
return ptr;
}
113
struct Foo
{
int i;
double d;
};
Foo* bar()
{
Foo *ptr = (Foo *) malloc(sizeof(Foo));
if (ptr == NULL)
return NULL;
new (ptr) Foo;
ptr->i = 0; // ok in C++
ptr->d = 0.0; // ok in C++
return ptr;
}
114
struct Foo
{
int i;
double d;
};
Foo* bar()
{
Foo *ptr = (Foo *) malloc(sizeof(Foo));
if (ptr == NULL)
return NULL;
ptr->i = 0; // ok in C, UB in C++ until C++20
ptr->d = 0.0; // ok in C, UB in C++ until C++20
return ptr;
}
115
14. Mind the sign
116
int foo(const char *s)
{
int r = 0;
while (*s)
{
r += ((r * 20891 + *s * 200) | *s ^ 4 | *s ^ 3 ) ^ (r >> 1);
s++;
}
return r & 0x7fffffff;
}
117
int foo(const char *s)
{
int r = 0;
while (*s)
{
r += ((r * 20891 + *s * 200) | *s ^ 4 | *s ^ 3 ) ^ (r >> 1);
s++;
}
return r & 0x7fffffff;
}
gcc-8 -O2 -std=c++17 -funsigned-char source.cpp
118
int foo(const char *s)
{
int r = 0;
while (*s)
{
r += ((r * 20891 + *s * 200) | *s ^ 4 | *s ^ 3 ) ^ (r >> 1);
s++;
}
return r & 0x7fffffff;
}
gcc-8 -O2 -std=c++17 -funsigned-char source.cpp
119
15. No exceptions, except...
122
BOOL WINAPI DllMain(HANDLE hModule, ULONG nReason, LPVOID /*pSituation*/)
{
BOOL br = TRUE;
if (nReason == DLL_PROCESS_ATTACH)
{
// Remember our hModule.
g_hModule = hModule;
g_hInstance = (HINSTANCE)g_hModule;
// Make sure we're properly registered.
if (FAILED(DllRegisterServer()))
br = FALSE;
}
else if (nReason == DLL_PROCESS_DETACH)
{
// Nothing to do.
}
return br;
}
123
BOOL WINAPI DllMain(HANDLE hModule, ULONG nReason, LPVOID /*pSituation*/)
{
BOOL br = TRUE;
if (nReason == DLL_PROCESS_ATTACH)
{
// Remember our hModule.
g_hModule = hModule;
g_hInstance = (HINSTANCE)g_hModule;
// Make sure we're properly registered.
if (FAILED(DllRegisterServer()))
br = FALSE;
}
else if (nReason == DLL_PROCESS_DETACH)
{
// Nothing to do.
}
return br;
}
124
HRESULT WINAPI DllRegisterServer(VOID)
{
....
hr = ::RegOpenKeyEx(HKEY_CURRENT_USER, "SoftwaregeOgeOShellPlugins",
NULL, KEY_WRITE, &hk);
if ( SUCCEEDED(hr = HRESULT_FROM_WIN32(hr)) )
{
strcpy(szValue, "geOCommandTime.dll,0");
DllGetObjectInfo(0, GI_Name, szName, MAX_PATH);
hr = ::RegSetValueEx(hk, szName, 0, REG_SZ, (LPBYTE)szValue, strlen(szValue));
hr = HRESULT_FROM_WIN32(hr);
RegCloseKey(hk);
}
....
return hr;
}
125
HRESULT WINAPI DllGetObjectInfo(DWORD dwPluginId, DWORD dwInfo,
VOID *pBuffer, DWORD dwBuffer)
{
....
// Get the specified plugin:
hr = DllGetObject(dwPluginId, &pPlugin);
if (SUCCEEDED(hr))
{
// We got it, so get some info:
hr = pPlugin->GetInfo(dwInfo, pBuffer, dwBuffer);
// And delete the plugin:
delete pPlugin;
}
....
return hr;
}
126
HRESULT WINAPI DllGetObjectInfo(DWORD dwPluginId, DWORD dwInfo,
VOID *pBuffer, DWORD dwBuffer)
{
....
// Get the specified plugin:
hr = DllGetObject(dwPluginId, &pPlugin);
if (SUCCEEDED(hr))
{
// We got it, so get some info:
hr = pPlugin->GetInfo(dwInfo, pBuffer, dwBuffer);
// And delete the plugin:
delete pPlugin;
}
....
return hr;
}
127
HRESULT WINAPI DllGetObject(DWORD dwPluginId, IShellPlugin **ppPlugin)
{
....
{
// We need to create a new command plugin:
switch (dwPluginId)
{
case 0:
*ppPlugin = new CCommandPlugin;
break;
default:
*ppPlugin = NULL;
};
....
}
....
return hr;
}
128
HRESULT WINAPI DllGetObject(DWORD dwPluginId, IShellPlugin **ppPlugin)
{
....
{
// We need to create a new command plugin:
switch (dwPluginId)
{
case 0:
*ppPlugin = new CCommandPlugin;
break;
default:
*ppPlugin = NULL;
};
....
}
....
return hr;
}
129
10 commandments
130
 Thou shalt not auto, unless thy faith is strong and pure
 Thou shalt not write indexed loops for they are abominations before the Code
 Thou shalt wash thy data thoroughly before releasing it
 Thou shalt not accept data from strangers for they might be sinful
 Thou shalt not copy-paste thy code blocks
131
 Thy comparison routines shall be correct or else the Wrath of Code will get thee
 Thou shalt check thy nullables for they are sinful
 Thou shalt not push that which can be emplaced
 Thou shalt not cook signed values with overflow semantics
 He who is without noexcept shall throw, and none other
132
END
Q&A133
Brought to you by:
pvs-studio.com

More Related Content

What's hot

Influencer marketing strategy - module 6 lesson 3
Influencer marketing strategy - module 6 lesson 3Influencer marketing strategy - module 6 lesson 3
Influencer marketing strategy - module 6 lesson 3Greg Jarboe
 
The Journey to a data driven organization
The Journey to a data driven organizationThe Journey to a data driven organization
The Journey to a data driven organizationEinat Shimoni
 
Influencer marketing strategy - module 4 lesson 1
Influencer marketing strategy - module 4 lesson 1Influencer marketing strategy - module 4 lesson 1
Influencer marketing strategy - module 4 lesson 1Greg Jarboe
 
Schmooze optimization: How it increases views, improves engagement, and boost...
Schmooze optimization: How it increases views, improves engagement, and boost...Schmooze optimization: How it increases views, improves engagement, and boost...
Schmooze optimization: How it increases views, improves engagement, and boost...Greg Jarboe
 
The CMO Survey - Highlights and Insights Report - March 2023
The CMO Survey - Highlights and Insights Report - March 2023The CMO Survey - Highlights and Insights Report - March 2023
The CMO Survey - Highlights and Insights Report - March 2023christinemoorman
 
Influencer marketing strategy - module 5 lesson 3
Influencer marketing strategy - module 5 lesson 3Influencer marketing strategy - module 5 lesson 3
Influencer marketing strategy - module 5 lesson 3Greg Jarboe
 
Influencer marketing strategy - module 3 lesson 2
Influencer marketing strategy - module 3 lesson 2Influencer marketing strategy - module 3 lesson 2
Influencer marketing strategy - module 3 lesson 2Greg Jarboe
 
Your Go-To-Market is Killing Your Business, and You Don't Even Know It
Your Go-To-Market is Killing Your Business, and You Don't Even Know ItYour Go-To-Market is Killing Your Business, and You Don't Even Know It
Your Go-To-Market is Killing Your Business, and You Don't Even Know ItHubSpot
 
YouTube Growth Results
YouTube Growth ResultsYouTube Growth Results
YouTube Growth ResultsOffrBox
 
Influencer marketing strategy - module 4 lesson 2
Influencer marketing strategy - module 4 lesson 2Influencer marketing strategy - module 4 lesson 2
Influencer marketing strategy - module 4 lesson 2Greg Jarboe
 
b2b-2023-CMI research report.pdf
b2b-2023-CMI research report.pdfb2b-2023-CMI research report.pdf
b2b-2023-CMI research report.pdfAnnefleur6
 
Influencer marketing
Influencer marketingInfluencer marketing
Influencer marketingBizProspex
 
Influencer marketing strategy - module 3 lesson 3
Influencer marketing strategy - module 3 lesson 3Influencer marketing strategy - module 3 lesson 3
Influencer marketing strategy - module 3 lesson 3Greg Jarboe
 
6-Step Guide to B2B Content Marketing that Works
6-Step Guide to B2B Content Marketing that Works6-Step Guide to B2B Content Marketing that Works
6-Step Guide to B2B Content Marketing that WorksLinkedIn
 
Augment Content Marketing with Influencer Strategy
Augment Content Marketing with Influencer StrategyAugment Content Marketing with Influencer Strategy
Augment Content Marketing with Influencer StrategyTraackr
 
8 Free Types of Marketing Strategies
8 Free Types of Marketing Strategies8 Free Types of Marketing Strategies
8 Free Types of Marketing StrategiesBrian Downard
 

What's hot (20)

Influencer marketing strategy - module 6 lesson 3
Influencer marketing strategy - module 6 lesson 3Influencer marketing strategy - module 6 lesson 3
Influencer marketing strategy - module 6 lesson 3
 
Displaying Data
Displaying DataDisplaying Data
Displaying Data
 
The Journey to a data driven organization
The Journey to a data driven organizationThe Journey to a data driven organization
The Journey to a data driven organization
 
Influencer marketing strategy - module 4 lesson 1
Influencer marketing strategy - module 4 lesson 1Influencer marketing strategy - module 4 lesson 1
Influencer marketing strategy - module 4 lesson 1
 
Schmooze optimization: How it increases views, improves engagement, and boost...
Schmooze optimization: How it increases views, improves engagement, and boost...Schmooze optimization: How it increases views, improves engagement, and boost...
Schmooze optimization: How it increases views, improves engagement, and boost...
 
The CMO Survey - Highlights and Insights Report - March 2023
The CMO Survey - Highlights and Insights Report - March 2023The CMO Survey - Highlights and Insights Report - March 2023
The CMO Survey - Highlights and Insights Report - March 2023
 
Influencer marketing strategy - module 5 lesson 3
Influencer marketing strategy - module 5 lesson 3Influencer marketing strategy - module 5 lesson 3
Influencer marketing strategy - module 5 lesson 3
 
Influencer marketing strategy - module 3 lesson 2
Influencer marketing strategy - module 3 lesson 2Influencer marketing strategy - module 3 lesson 2
Influencer marketing strategy - module 3 lesson 2
 
Your Go-To-Market is Killing Your Business, and You Don't Even Know It
Your Go-To-Market is Killing Your Business, and You Don't Even Know ItYour Go-To-Market is Killing Your Business, and You Don't Even Know It
Your Go-To-Market is Killing Your Business, and You Don't Even Know It
 
YouTube Growth Results
YouTube Growth ResultsYouTube Growth Results
YouTube Growth Results
 
Influencer marketing strategy - module 4 lesson 2
Influencer marketing strategy - module 4 lesson 2Influencer marketing strategy - module 4 lesson 2
Influencer marketing strategy - module 4 lesson 2
 
b2b-2023-CMI research report.pdf
b2b-2023-CMI research report.pdfb2b-2023-CMI research report.pdf
b2b-2023-CMI research report.pdf
 
Influencer marketing
Influencer marketingInfluencer marketing
Influencer marketing
 
Influencer marketing strategy - module 3 lesson 3
Influencer marketing strategy - module 3 lesson 3Influencer marketing strategy - module 3 lesson 3
Influencer marketing strategy - module 3 lesson 3
 
6-Step Guide to B2B Content Marketing that Works
6-Step Guide to B2B Content Marketing that Works6-Step Guide to B2B Content Marketing that Works
6-Step Guide to B2B Content Marketing that Works
 
Steps to influencer marketing
Steps to influencer marketingSteps to influencer marketing
Steps to influencer marketing
 
Augment Content Marketing with Influencer Strategy
Augment Content Marketing with Influencer StrategyAugment Content Marketing with Influencer Strategy
Augment Content Marketing with Influencer Strategy
 
Infuencer Marketing Pitch Deck
Infuencer Marketing Pitch DeckInfuencer Marketing Pitch Deck
Infuencer Marketing Pitch Deck
 
Influencer Marketing 101
Influencer Marketing 101Influencer Marketing 101
Influencer Marketing 101
 
8 Free Types of Marketing Strategies
8 Free Types of Marketing Strategies8 Free Types of Marketing Strategies
8 Free Types of Marketing Strategies
 

Similar to A scrupulous code review - 15 bugs in C++ code

C++ Code as Seen by a Hypercritical Reviewer
C++ Code as Seen by a Hypercritical ReviewerC++ Code as Seen by a Hypercritical Reviewer
C++ Code as Seen by a Hypercritical ReviewerAndrey Karpov
 
Write Python for Speed
Write Python for SpeedWrite Python for Speed
Write Python for SpeedYung-Yu Chen
 
Some examples of the 64-bit code errors
Some examples of the 64-bit code errorsSome examples of the 64-bit code errors
Some examples of the 64-bit code errorsPVS-Studio
 
Egor Bogatov - .NET Core intrinsics and other micro-optimizations
Egor Bogatov - .NET Core intrinsics and other micro-optimizationsEgor Bogatov - .NET Core intrinsics and other micro-optimizations
Egor Bogatov - .NET Core intrinsics and other micro-optimizationsEgor Bogatov
 
Sparse Matrix and Polynomial
Sparse Matrix and PolynomialSparse Matrix and Polynomial
Sparse Matrix and PolynomialAroosa Rajput
 
Whats new in_csharp4
Whats new in_csharp4Whats new in_csharp4
Whats new in_csharp4Abed Bukhari
 
C++11 - A Change in Style - v2.0
C++11 - A Change in Style - v2.0C++11 - A Change in Style - v2.0
C++11 - A Change in Style - v2.0Yaser Zhian
 
Look Ma, “update DB to HTML5 using C++”, no hands! 
Look Ma, “update DB to HTML5 using C++”, no hands! Look Ma, “update DB to HTML5 using C++”, no hands! 
Look Ma, “update DB to HTML5 using C++”, no hands! aleks-f
 
Translate the following CC++ code into MIPS Assembly Codevoid ch.pdf
Translate the following CC++ code into MIPS Assembly Codevoid ch.pdfTranslate the following CC++ code into MIPS Assembly Codevoid ch.pdf
Translate the following CC++ code into MIPS Assembly Codevoid ch.pdffcsondhiindia
 
Frsa
FrsaFrsa
Frsa_111
 
C++17 introduction - Meetup @EtixLabs
C++17 introduction - Meetup @EtixLabsC++17 introduction - Meetup @EtixLabs
C++17 introduction - Meetup @EtixLabsStephane Gleizes
 
Implement an MPI program to perform matrix-matrix multiplication AB .pdf
Implement an MPI program to perform matrix-matrix multiplication AB .pdfImplement an MPI program to perform matrix-matrix multiplication AB .pdf
Implement an MPI program to perform matrix-matrix multiplication AB .pdfmeerobertsonheyde608
 
Getting started cpp full
Getting started cpp   fullGetting started cpp   full
Getting started cpp fullVõ Hòa
 
Story of static code analyzer development
Story of static code analyzer developmentStory of static code analyzer development
Story of static code analyzer developmentAndrey Karpov
 
Gentle Introduction to Functional Programming
Gentle Introduction to Functional ProgrammingGentle Introduction to Functional Programming
Gentle Introduction to Functional ProgrammingSaurabh Singh
 
Templates in C++
Templates in C++Templates in C++
Templates in C++Tech_MX
 
Chainer-Compiler 動かしてみた
Chainer-Compiler 動かしてみたChainer-Compiler 動かしてみた
Chainer-Compiler 動かしてみたAkira Maruoka
 
C Programming Language
C Programming LanguageC Programming Language
C Programming LanguageRTS Tech
 

Similar to A scrupulous code review - 15 bugs in C++ code (20)

C++ Code as Seen by a Hypercritical Reviewer
C++ Code as Seen by a Hypercritical ReviewerC++ Code as Seen by a Hypercritical Reviewer
C++ Code as Seen by a Hypercritical Reviewer
 
Write Python for Speed
Write Python for SpeedWrite Python for Speed
Write Python for Speed
 
Some examples of the 64-bit code errors
Some examples of the 64-bit code errorsSome examples of the 64-bit code errors
Some examples of the 64-bit code errors
 
Egor Bogatov - .NET Core intrinsics and other micro-optimizations
Egor Bogatov - .NET Core intrinsics and other micro-optimizationsEgor Bogatov - .NET Core intrinsics and other micro-optimizations
Egor Bogatov - .NET Core intrinsics and other micro-optimizations
 
Sparse Matrix and Polynomial
Sparse Matrix and PolynomialSparse Matrix and Polynomial
Sparse Matrix and Polynomial
 
Whats new in_csharp4
Whats new in_csharp4Whats new in_csharp4
Whats new in_csharp4
 
C++11 - A Change in Style - v2.0
C++11 - A Change in Style - v2.0C++11 - A Change in Style - v2.0
C++11 - A Change in Style - v2.0
 
Look Ma, “update DB to HTML5 using C++”, no hands! 
Look Ma, “update DB to HTML5 using C++”, no hands! Look Ma, “update DB to HTML5 using C++”, no hands! 
Look Ma, “update DB to HTML5 using C++”, no hands! 
 
Translate the following CC++ code into MIPS Assembly Codevoid ch.pdf
Translate the following CC++ code into MIPS Assembly Codevoid ch.pdfTranslate the following CC++ code into MIPS Assembly Codevoid ch.pdf
Translate the following CC++ code into MIPS Assembly Codevoid ch.pdf
 
Frsa
FrsaFrsa
Frsa
 
C++17 introduction - Meetup @EtixLabs
C++17 introduction - Meetup @EtixLabsC++17 introduction - Meetup @EtixLabs
C++17 introduction - Meetup @EtixLabs
 
Implement an MPI program to perform matrix-matrix multiplication AB .pdf
Implement an MPI program to perform matrix-matrix multiplication AB .pdfImplement an MPI program to perform matrix-matrix multiplication AB .pdf
Implement an MPI program to perform matrix-matrix multiplication AB .pdf
 
Rcpp11 genentech
Rcpp11 genentechRcpp11 genentech
Rcpp11 genentech
 
Getting started cpp full
Getting started cpp   fullGetting started cpp   full
Getting started cpp full
 
Story of static code analyzer development
Story of static code analyzer developmentStory of static code analyzer development
Story of static code analyzer development
 
Ac2
Ac2Ac2
Ac2
 
Gentle Introduction to Functional Programming
Gentle Introduction to Functional ProgrammingGentle Introduction to Functional Programming
Gentle Introduction to Functional Programming
 
Templates in C++
Templates in C++Templates in C++
Templates in C++
 
Chainer-Compiler 動かしてみた
Chainer-Compiler 動かしてみたChainer-Compiler 動かしてみた
Chainer-Compiler 動かしてみた
 
C Programming Language
C Programming LanguageC Programming Language
C Programming Language
 

Recently uploaded

TECUNIQUE: Success Stories: IT Service provider
TECUNIQUE: Success Stories: IT Service providerTECUNIQUE: Success Stories: IT Service provider
TECUNIQUE: Success Stories: IT Service providermohitmore19
 
Optimizing AI for immediate response in Smart CCTV
Optimizing AI for immediate response in Smart CCTVOptimizing AI for immediate response in Smart CCTV
Optimizing AI for immediate response in Smart CCTVshikhaohhpro
 
The Ultimate Test Automation Guide_ Best Practices and Tips.pdf
The Ultimate Test Automation Guide_ Best Practices and Tips.pdfThe Ultimate Test Automation Guide_ Best Practices and Tips.pdf
The Ultimate Test Automation Guide_ Best Practices and Tips.pdfkalichargn70th171
 
Right Money Management App For Your Financial Goals
Right Money Management App For Your Financial GoalsRight Money Management App For Your Financial Goals
Right Money Management App For Your Financial GoalsJhone kinadey
 
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
 
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
 
Unlocking the Future of AI Agents with Large Language Models
Unlocking the Future of AI Agents with Large Language ModelsUnlocking the Future of AI Agents with Large Language Models
Unlocking the Future of AI Agents with Large Language Modelsaagamshah0812
 
How To Troubleshoot Collaboration Apps for the Modern Connected Worker
How To Troubleshoot Collaboration Apps for the Modern Connected WorkerHow To Troubleshoot Collaboration Apps for the Modern Connected Worker
How To Troubleshoot Collaboration Apps for the Modern Connected WorkerThousandEyes
 
CALL ON ➥8923113531 🔝Call Girls Badshah Nagar Lucknow best Female service
CALL ON ➥8923113531 🔝Call Girls Badshah Nagar Lucknow best Female serviceCALL ON ➥8923113531 🔝Call Girls Badshah Nagar Lucknow best Female service
CALL ON ➥8923113531 🔝Call Girls Badshah Nagar Lucknow best Female serviceanilsa9823
 
Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...
Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...
Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...Steffen Staab
 
How To Use Server-Side Rendering with Nuxt.js
How To Use Server-Side Rendering with Nuxt.jsHow To Use Server-Side Rendering with Nuxt.js
How To Use Server-Side Rendering with Nuxt.jsAndolasoft Inc
 
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...panagenda
 
A Secure and Reliable Document Management System is Essential.docx
A Secure and Reliable Document Management System is Essential.docxA Secure and Reliable Document Management System is Essential.docx
A Secure and Reliable Document Management System is Essential.docxComplianceQuest1
 
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...Health
 
Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...
Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...
Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...harshavardhanraghave
 
HR Software Buyers Guide in 2024 - HRSoftware.com
HR Software Buyers Guide in 2024 - HRSoftware.comHR Software Buyers Guide in 2024 - HRSoftware.com
HR Software Buyers Guide in 2024 - HRSoftware.comFatema Valibhai
 
CALL ON ➥8923113531 🔝Call Girls Kakori Lucknow best sexual service Online ☂️
CALL ON ➥8923113531 🔝Call Girls Kakori Lucknow best sexual service Online  ☂️CALL ON ➥8923113531 🔝Call Girls Kakori Lucknow best sexual service Online  ☂️
CALL ON ➥8923113531 🔝Call Girls Kakori Lucknow best sexual service Online ☂️anilsa9823
 

Recently uploaded (20)

TECUNIQUE: Success Stories: IT Service provider
TECUNIQUE: Success Stories: IT Service providerTECUNIQUE: Success Stories: IT Service provider
TECUNIQUE: Success Stories: IT Service provider
 
Microsoft AI Transformation Partner Playbook.pdf
Microsoft AI Transformation Partner Playbook.pdfMicrosoft AI Transformation Partner Playbook.pdf
Microsoft AI Transformation Partner Playbook.pdf
 
Optimizing AI for immediate response in Smart CCTV
Optimizing AI for immediate response in Smart CCTVOptimizing AI for immediate response in Smart CCTV
Optimizing AI for immediate response in Smart CCTV
 
The Ultimate Test Automation Guide_ Best Practices and Tips.pdf
The Ultimate Test Automation Guide_ Best Practices and Tips.pdfThe Ultimate Test Automation Guide_ Best Practices and Tips.pdf
The Ultimate Test Automation Guide_ Best Practices and Tips.pdf
 
Right Money Management App For Your Financial Goals
Right Money Management App For Your Financial GoalsRight Money Management App For Your Financial Goals
Right Money Management App For Your Financial Goals
 
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
 
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
 
Unlocking the Future of AI Agents with Large Language Models
Unlocking the Future of AI Agents with Large Language ModelsUnlocking the Future of AI Agents with Large Language Models
Unlocking the Future of AI Agents with Large Language Models
 
How To Troubleshoot Collaboration Apps for the Modern Connected Worker
How To Troubleshoot Collaboration Apps for the Modern Connected WorkerHow To Troubleshoot Collaboration Apps for the Modern Connected Worker
How To Troubleshoot Collaboration Apps for the Modern Connected Worker
 
CHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICE
CHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICECHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICE
CHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICE
 
CALL ON ➥8923113531 🔝Call Girls Badshah Nagar Lucknow best Female service
CALL ON ➥8923113531 🔝Call Girls Badshah Nagar Lucknow best Female serviceCALL ON ➥8923113531 🔝Call Girls Badshah Nagar Lucknow best Female service
CALL ON ➥8923113531 🔝Call Girls Badshah Nagar Lucknow best Female service
 
Vip Call Girls Noida ➡️ Delhi ➡️ 9999965857 No Advance 24HRS Live
Vip Call Girls Noida ➡️ Delhi ➡️ 9999965857 No Advance 24HRS LiveVip Call Girls Noida ➡️ Delhi ➡️ 9999965857 No Advance 24HRS Live
Vip Call Girls Noida ➡️ Delhi ➡️ 9999965857 No Advance 24HRS Live
 
Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...
Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...
Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...
 
How To Use Server-Side Rendering with Nuxt.js
How To Use Server-Side Rendering with Nuxt.jsHow To Use Server-Side Rendering with Nuxt.js
How To Use Server-Side Rendering with Nuxt.js
 
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...
 
A Secure and Reliable Document Management System is Essential.docx
A Secure and Reliable Document Management System is Essential.docxA Secure and Reliable Document Management System is Essential.docx
A Secure and Reliable Document Management System is Essential.docx
 
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
 
Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...
Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...
Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...
 
HR Software Buyers Guide in 2024 - HRSoftware.com
HR Software Buyers Guide in 2024 - HRSoftware.comHR Software Buyers Guide in 2024 - HRSoftware.com
HR Software Buyers Guide in 2024 - HRSoftware.com
 
CALL ON ➥8923113531 🔝Call Girls Kakori Lucknow best sexual service Online ☂️
CALL ON ➥8923113531 🔝Call Girls Kakori Lucknow best sexual service Online  ☂️CALL ON ➥8923113531 🔝Call Girls Kakori Lucknow best sexual service Online  ☂️
CALL ON ➥8923113531 🔝Call Girls Kakori Lucknow best sexual service Online ☂️
 

A scrupulous code review - 15 bugs in C++ code

  • 1. A scrupulous code review – 15 bugs in C++ code Phillip Khandeliants khandeliants@viva64.com
  • 2. About Me  Over 5 years with the PVS-Studio team  Team lead at the C++ analyzer development team  Microsoft Certified Professional, C#  Talk on modern C++  Live by the C++ ISO standard 2
  • 3. Intro: the code review 3  We all do code reviews  Who doesn't admit this – does it twice as often
  • 5. void foo(const std::vector<....> &vec) { .... for (auto i = 0; i < vec.size(); ++i) { // do some magic with vec[i] .... } .... } 5
  • 6. void foo(const std::vector<....> &vec) { .... for (int i = 0; i < vec.size(); ++i) // 64-bit problems :) { // do some magic with vec[i] .... } .... } 6
  • 7. void foo(const std::vector<....> &vec) { .... for (size_t i = 0; i < vec.size(); ++i) // ok { // do some magic with vec[i] .... } .... } 7
  • 8. void foo(const std::vector<....> &vec) { .... for (std::vector<....>::size_type i = 0; i < vec.size(); ++i) { // do some magic with vec[i] .... } .... } 8
  • 9. void foo(const std::vector<....> &vec) { .... for (auto i = 0uLL; i < vec.size(); ++i) // don't do that on // 128-bit processors { // do some magic with vec[i] .... } .... } 9
  • 10. void foo(const std::vector<....> &vec) { .... for (auto i = 0uLLL; i < vec.size(); ++i) // ok since C++7d { // do some magic with vec[i] .... } .... } 10
  • 11. void foo(const std::vector<....> &vec) { .... for (auto i = 0uLLL; i < vec.size(); ++i) // ok since C++7d { // do some magic with vec[i] .... } .... } 11
  • 12. 2. Reference! I said reference! Perfection! 12
  • 13. 13 template <typename T> int ColumnDecimal<T>::compareAt(size_t n, size_t m, const IColumn & rhs_, int) const { auto other = static_cast<const Self &>(rhs_); const T &a = data[n]; const T &b = other.data[m]; return decimalLess<T>(b, a, other.scale, scale) ? 1 : (decimalLess<T>(a, b, scale, other.scale) ? -1 : 0); }
  • 14. 14 template <typename T> int ColumnDecimal<T>::compareAt(size_t n, size_t m, const IColumn & rhs_, int) const { auto other = static_cast<const Self &>(rhs_); const T &a = data[n]; const T &b = other.data[m]; return decimalLess<T>(b, a, other.scale, scale) ? 1 : (decimalLess<T>(a, b, scale, other.scale) ? -1 : 0); }
  • 15. 15 template <typename T> int ColumnDecimal<T>::compareAt(size_t n, size_t m, const IColumn & rhs_, int) const { auto &other = static_cast<const Self &>(rhs_); const T &a = data[n]; const T &b = other.data[m]; return decimalLess<T>(b, a, other.scale, scale) ? 1 : (decimalLess<T>(a, b, scale, other.scale) ? -1 : 0); }
  • 16. 16 template <typename T> int ColumnDecimal<T>::compareAt(size_t n, size_t m, const IColumn & rhs_, int) const { decltype(auto) other = static_cast<const Self &>(rhs_); const T &a = data[n]; const T &b = other.data[m]; return decimalLess<T>(b, a, other.scale, scale) ? 1 : (decimalLess<T>(a, b, scale, other.scale) ? -1 : 0); }
  • 18. void vector32_inc(std::vector<uint32_t> &v) { for (size_t i = 0; i < v.size(); i++) { v[i]++; } } 18
  • 19. void vector32_inc(std::vector<uint32_t> &v) { for (size_t i = 0; i < v.size(); i++) { v[i]++; } } void vector8_inc(std::vector<uint8_t> &v) { for (size_t i = 0; i < v.size(); i++) { v[i]++; } } 19
  • 20. Let's benchmark :) 20 Compiler Element -O1 -O2 -O3 gcc 8 uint8_t 2.0 2.0 2.0 gcc 8 uint32_t 2.3 1.3 0.2 clang 8 uint8_t 9.2 2.0 2.0 clang 8 uint32_t 9.2 0.2 0.2
  • 21. 21 vector8_inc(std::vector<uint8_t> &): mov rdx, QWORD PTR [rdi] ; it = begin() cmp rdx, QWORD PTR [rdi+8] ; if (it == end()) je .L1 ; return xor eax, eax ; i = 0 .L3: ; do { add BYTE PTR [rdx+rax], 1 ; ++(*(it + i)) mov rdx, QWORD PTR [rdi] ; it = begin() add rax, 1 ; ++i mov rcx, QWORD PTR [rdi+8] ; end = end() sub rcx, rdx ; end = end - it cmp rax, rcx jb .L3 ; } while (i < end) .L1: ret vector32_inc(std::vector<uint32_t> &): mov rax, QWORD PTR [rdi] ; it = begin() mov rdx, QWORD PTR [rdi+8] ; end = end() sub rdx, rax ; end = end - it mov rcx, rdx ; size in bytes shr rcx, 2 ; size in elements je .L1 ; if (size == 0) ; return add rdx, rax ; end = end + it .L3: ; do { add DWORD PTR [rax], 1 ; ++(*it) add rax, 4 ; ++it cmp rax, rdx jne .L3 ; } while (it != end) .L1: ret
  • 22. 22 vector8_inc(std::vector<uint8_t> &): mov rdx, QWORD PTR [rdi] ; it = begin() cmp rdx, QWORD PTR [rdi+8] ; if (it == end()) je .L1 ; return xor eax, eax ; i = 0 .L3: ; do { add BYTE PTR [rdx+rax], 1 ; ++(*(it + i)) mov rdx, QWORD PTR [rdi] ; it = begin() add rax, 1 ; ++i mov rcx, QWORD PTR [rdi+8] ; end = end() sub rcx, rdx ; end = end - it cmp rax, rcx jb .L3 ; } while (i < end) .L1: ret vector32_inc(std::vector<uint32_t> &): mov rax, QWORD PTR [rdi] ; it = begin() mov rdx, QWORD PTR [rdi+8] ; end = end() sub rdx, rax ; end = end - it mov rcx, rdx ; size in bytes shr rcx, 2 ; size in elements je .L1 ; if (size == 0) ; return add rdx, rax ; end = end + it .L3: ; do { add DWORD PTR [rax], 1 ; ++(*it) add rax, 4 ; ++it cmp rax, rdx jne .L3 ; } while (it != end) .L1: ret
  • 23. void vector8_inc(std::vector<uint8_t> &v) { for (size_t i = 0; i < v.size(); i++) { v[i]++; } } 23
  • 24. void vector8_inc(std::vector<uint8_t> &v) { for (size_t i = 0; i < v.size(); i++) { v[i]++; } } void vector8_inc(std::vector<uint8_t> &v) { auto it = v.begin(); const auto end = v.end(); for (; it != end; ++it) { ++(*it); } } 24
  • 25. 25 vector8_inc(std::vector<uint8_t> &): mov rax, QWORD PTR [rdi] ; it = begin() mov rdx, QWORD PTR [rdi+8] ; end = end() cmp rax, rdx ; if (it == end) je .L1 ; return .L3: ; do { add BYTE PTR [rax], 1 ; ++(*it) add rax, 1 ; ++it cmp rax, rdx ; } while (it != end) .L1: ret
  • 26. 26 vector8_inc(std::vector<uint8_t> &): mov rax, QWORD PTR [rdi] ; it = begin() mov rdx, QWORD PTR [rdi+8] ; end = end() cmp rax, rdx ; if (it == end) je .L1 ; return .L3: ; do { add BYTE PTR [rax], 1 ; ++(*it) add rax, 1 ; ++it cmp rax, rdx ; } while (it != end) .L1: ret
  • 27. Let's make benchmarks great again! Compiler uint8_t -O1 -O2 -O3 gcc 8 (before) 2.0 2.0 2.0 gcc 8 (after) 1.3 1.3 0.06 gcc speedup 1.5x 1.5x 33.4x Compiler uint8_t -O1 -O2 -O3 clang 8 (before) 9.2 2.0 2.0 clang 8 (after) 20.3 0.06 0.06 clang speedup 0.45x 33.4x 33.4x
  • 28. void vector8_inc(std::vector<uint8_t> &v) { auto it = v.begin(); const auto end = v.end(); for (; it != end; ++it) { ++(*it); } } 28
  • 29. void vector8_inc(std::vector<uint8_t> &v) { auto it = v.begin(); const auto end = v.end(); for (; it != end; ++it) { ++(*it); } } void vector8_inc(std::vector<uint8_t> &v) { for (auto &elem : v) { ++elem; } } 29
  • 30. 30
  • 32. #include <cstring> #include <memory> void InputPassword(char *pswd); void ProcessPassword(const char *pswd); #define MAX_PASSWORD_LEN .... void Foo() { char password[MAX_PASSWORD_LEN]; InputPassword(password); ProcessPassword(password); memset(password, 0, sizeof(password)); } 32
  • 33. #include <cstring> #include <memory> void InputPassword(char *pswd); void ProcessPassword(const char *pswd); #define MAX_PASSWORD_LEN .... void Foo() { char password[MAX_PASSWORD_LEN]; InputPassword(password); ProcessPassword(password); memset(password, 0, sizeof(password)); } 33
  • 34. 34
  • 35. #include <cstring> #include <memory> void InputPassword(char *pswd); void ProcessPassword(const char *pswd); #define MAX_PASSWORD_LEN .... void Foo() { char *password = new char[MAX_PASSWORD_LEN]; InputPassword(password); ProcessPassword(password); memset(password, 0, MAX_PASSWORD_LEN); delete[] password; } 35
  • 36. 36
  • 37. void tds_answer_challenge(....) { #define MAX_PW_SZ 14 .... if (ntlm_v == 1) { .... /* with security is best be pedantic */ memset(hash, 0, sizeof(hash)); memset(passwd_buf, 0, sizeof(passwd_buf)); memset(ntlm2_challenge, 0, sizeof(ntlm2_challenge)); } else { .... } } 37
  • 38. typedef struct tds_answer { unsigned char lm_resp[24]; unsigned char nt_resp[24]; } TDSANSWER; static TDSRET tds7_send_auth(....) { size_t current_pos; TDSANSWER answer; .... /* for security reason clear structure */ memset(&answer, 0, sizeof(TDSANSWER)); return tds_flush_packet(tds); } 38
  • 39. char* crypt_md5(const char* pw, const char* salt) { unsigned char final[MD5_SIZE]; .... /* Don't leave anything around in vm they could use. */ memset(final, 0, sizeof final); return passwd; } 39
  • 40. void MD4Engine::transform (UInt32 state[4], const unsigned char block[64]) { UInt32 a = state[0], b = state[1], c = state[2], d = state[3], x[16]; decode(x, block, 64); .... /* Zeroize sensitive information. */ std::memset(x, 0, sizeof(x)); } 40
  • 41. char* px_crypt_md5(const char *pw, const char *salt, char *passwd, unsigned dstlen) { .... unsigned char final[MD5_SIZE]; .... /* Don't leave anything around in vm they could use. */ memset(final, 0, sizeof final); .... } 41
  • 42. 42
  • 43.  Custom safe_memset + disabled LTO/WPO  Access a non-volatile object through a volatile pointer  Call memset through a volatile function pointer  Volatile assembly code  Memset + memory barrier  Disable compiler optimizations (-fno-builtin-memset)  C11: memset_s  Windows: RtlSecureZeroMemory  FreeBSD & OpenBSD: explicit_bzero  Linux Kernel: memzero_explicit Ways to fix 43
  • 44. 5. Dirty thoughts data 44
  • 45. static const char* basic_gets(int *cnt) { .... int c = getchar(); if (c < 0) { if ( fgets(command_buf, sizeof(command_buf) - 1, stdin) != command_buf) { break; } /* remove endline */ command_buf[strlen(command_buf)-1] = '0'; break; } .... } 45
  • 46. static const char* basic_gets(int *cnt) { .... int c = getchar(); if (c < 0) { if ( fgets(command_buf, sizeof(command_buf) - 1, stdin) != command_buf) { break; } /* remove endline */ command_buf[strlen(command_buf)-1] = '0'; break; } .... } 46
  • 47. int main (int argc, char *argv[]) { .... else if (fgets(readbuf, BUFSIZ, stdin) == NULL) { if (feof (stdin)) break; error (EXIT_FAILURE, errno, _("input error")); } if (readbuf[strlen(readbuf) - 1] == 'n') readbuf[strlen(readbuf) - 1] = '0'; .... } 47
  • 48. int main (int argc, char *argv[]) { .... else if (fgets(readbuf, BUFSIZ, stdin) == NULL) { if (feof (stdin)) break; error (EXIT_FAILURE, errno, _("input error")); } if (readbuf[strlen(readbuf) - 1] == 'n') readbuf[strlen(readbuf) - 1] = '0'; .... } 48 CVE-2015-8948
  • 49. int main (int argc, char *argv[]) { .... else if (getline(&line, &linelen, stdin) == -1) { if (feof (stdin)) break; error (EXIT_FAILURE, errno, _("input error")); } if (line[strlen(line) - 1] == 'n') line[strlen(line) - 1] = '0'; .... } 49
  • 50. int main (int argc, char *argv[]) { .... else if (getline(&line, &linelen, stdin) == -1) { if (feof (stdin)) break; error (EXIT_FAILURE, errno, _("input error")); } if (line[strlen(line) - 1] == 'n') line[strlen(line) - 1] = '0'; .... } 50 CVE-2016-6262
  • 52. inline void Init( float ix=0, float iy=0, float iz=0, float iw = 0 ) { SetX( ix ); SetY( iy ); SetZ( iz ); SetZ( iw ); } 52
  • 53. inline void Init( float ix=0, float iy=0, float iz=0, float iw = 0 ) { SetX( ix ); SetY( iy ); SetZ( iz ); SetZ( iw ); } 53
  • 54. 54 inline void Init( float ix=0, float iy=0, float iz=0, float iw = 0 ) { SetX( ix ); SetY( iy ); SetZ( iz ); SetW( iw ); }
  • 55. if (access & FILE_WRITE_ATTRIBUTES) output.append(ASCIIToUTF16("tFILE_WRITE_ATTRIBUTESn")); if (access & FILE_WRITE_DATA) output.append(ASCIIToUTF16("tFILE_WRITE_DATAn")); if (access & FILE_WRITE_EA) output.append(ASCIIToUTF16("tFILE_WRITE_EAn")); if (access & FILE_WRITE_EA) output.append(ASCIIToUTF16("tFILE_WRITE_EAn")); break; 55
  • 56. if (access & FILE_WRITE_ATTRIBUTES) output.append(ASCIIToUTF16("tFILE_WRITE_ATTRIBUTESn")); if (access & FILE_WRITE_DATA) output.append(ASCIIToUTF16("tFILE_WRITE_DATAn")); if (access & FILE_WRITE_EA) output.append(ASCIIToUTF16("tFILE_WRITE_EAn")); if (access & FILE_WRITE_EA) output.append(ASCIIToUTF16("tFILE_WRITE_EAn")); break; 56
  • 57. if (protocol.EqualsIgnoreCase("http") || protocol.EqualsIgnoreCase("https") || protocol.EqualsIgnoreCase("news") || protocol.EqualsIgnoreCase("ftp") || protocol.EqualsIgnoreCase("file") || protocol.EqualsIgnoreCase("javascript") || protocol.EqualsIgnoreCase("ftp")) { 57
  • 58. if (protocol.EqualsIgnoreCase("http") || protocol.EqualsIgnoreCase("https") || protocol.EqualsIgnoreCase("news") || protocol.EqualsIgnoreCase("ftp") || protocol.EqualsIgnoreCase("file") || protocol.EqualsIgnoreCase("javascript") || protocol.EqualsIgnoreCase("ftp")) { 58
  • 59. 7. Zero, one, two, Freddy's coming for you! 59
  • 60. Sequence< OUString > FirebirdDriver:: getSupportedServiceNames_Static() throw (RuntimeException) { Sequence< OUString > aSNS( 2 ); aSNS[0] = "com.sun.star.sdbc.Driver"; aSNS[0] = "com.sun.star.sdbcx.Driver"; return aSNS; } 60
  • 61. Sequence< OUString > FirebirdDriver:: getSupportedServiceNames_Static() throw (RuntimeException) { Sequence< OUString > aSNS( 2 ); aSNS[0] = "com.sun.star.sdbc.Driver"; aSNS[0] = "com.sun.star.sdbcx.Driver"; return aSNS; } 61
  • 62. struct short2 { short values[2]; short2(short s1, short s2) { values[0] = s1; values[2] = s2; } .... }; 62
  • 63. struct short2 { short values[2]; short2(short s1, short s2) { values[0] = s1; values[2] = s2; } .... }; 63
  • 64. 8. Evil within comparisons! 64
  • 65. string _server; .... bool operator<( const ServerAndQuery& other ) const { if ( ! _orderObject.isEmpty() ) return _orderObject.woCompare( other._orderObject ) < 0; if ( _server < other._server ) return true; if ( other._server > _server ) return false; return _extra.woCompare( other._extra ) < 0; } Pattern: A < B, B > A 65
  • 66. string _server; .... bool operator<( const ServerAndQuery& other ) const { if ( ! _orderObject.isEmpty() ) return _orderObject.woCompare( other._orderObject ) < 0; if ( _server < other._server ) return true; if ( other._server > _server ) return false; return _extra.woCompare( other._extra ) < 0; } Pattern: A < B, B > A 66
  • 67. bool operator==(const SComputePipelineStateDescription &other) const { return 0 == memcmp(this, &other, sizeof(this)); } Pattern: evaluating the size of a pointer instead of the size of the structure/class 67
  • 68. bool operator==(const SComputePipelineStateDescription &other) const { return 0 == memcmp(this, &other, sizeof(this)); } Pattern: evaluating the size of a pointer instead of the size of the structure/class 68
  • 69. 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; } Pattern: incorrect use of the memcmp result 69
  • 70. 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; } Pattern: incorrect use of the memcmp result 70
  • 71. if (cmp == 0) cmp = (len1 < len2 ? -1 : (len1 > len2 ? 1 : 0)); Pattern: incorrect use of the memcmp result 71
  • 72. bool Peptide::operator==(Peptide& p) { .... for (i = 0, j = 0; i < this->stripped.length(), j < p.stripped.length(); i++, j++) { .... } Pattern: incorrect loops 72
  • 73. bool Peptide::operator==(Peptide& p) { .... for (i = 0, j = 0; i < this->stripped.length(), j < p.stripped.length(); i++, j++) { .... } Pattern: incorrect loops 73
  • 74. bool equals( class1* val1, class2* val2 ) const { ... size_t size = val1->size(); ... while ( --size >= 0 ) { if ( !comp(*itr1,*itr2) ) return false; itr1++; itr2++; } ... } Pattern: incorrect loops 74
  • 75. bool equals( class1* val1, class2* val2 ) const { ... size_t size = val1->size(); ... while ( --size >= 0 ) { if ( !comp(*itr1,*itr2) ) return false; itr1++; itr2++; } ... } Pattern: Incorrect Loops 75
  • 76. 9. Use <=>, Luke! 76
  • 78. Base equality comparison 78 struct Foo { int a, b; }; bool operator==(Foo lhs, Foo rhs) { return lhs.a == rhs.a && lhs.b == rhs.b; }
  • 79. Base equality comparison 79 struct Foo { int a, b; }; bool operator==(Foo lhs, Foo rhs) { return lhs.a == rhs.a && lhs.b == rhs.b; } bool operator!=(Foo lhs, Foo rhs) { return !(lhs == rhs); }
  • 80. Base 'less' comparison 80 struct Foo { int a, b; }; bool operator<(Foo lhs, Foo rhs) { return lhs.a < rhs.a && lhs.b < rhs.b; }
  • 81. Base 'less' comparison 81 struct Foo { int a, b; }; bool operator<(Foo lhs, Foo rhs) { return lhs.a < rhs.a && lhs.b < rhs.b; } Foo { 1, 2 } < Foo { 2, 1 }; // <= false Foo { 2, 1 } < Foo { 1, 2 }; // <= false
  • 82. Base 'less' comparison 82 struct Foo { int a, b; }; bool operator<(Foo lhs, Foo rhs) { if (lhs.a < rhs.a) return true; if (rhs.a < lhs.a) return false; return lhs.b < rhs.b; } Foo { 1, 2 } < Foo { 2, 1 }; // <= true Foo { 2, 1 } < Foo { 1, 2 }; // <= false
  • 83. Base 'less' comparison 83 struct Foo { double a; }; bool operator<(Foo lhs, Foo rhs) { return lhs.a < rhs.a; }
  • 84. Base 'less' comparison 84 struct Foo { double a; }; bool operator<(Foo lhs, Foo rhs) { return lhs.a < rhs.a; } bool operator>=(Foo lhs, Foo rhs) { return !(lhs < rhs); }
  • 85. Base 'less' comparison 85 struct Foo { double a; }; bool operator<(Foo lhs, Foo rhs) { return lhs.a < rhs.a; } bool operator>=(Foo lhs, Foo rhs) { return !(lhs < rhs); } Foo { 1.0 } < Foo { 2.0 }; // <= true Foo { 1.0 } < Foo { NaN }; // <= false Foo { 1.0 } >= Foo { NaN }; // <= true
  • 86. Comparisons in C++20 86 #include <compare> struct Foo { double a; auto operator<=>(const Foo &rhs) const = default; }; Foo { 1.0 } < Foo { 2.0 }; // <= true Foo { 1.0 } < Foo { NaN }; // <= false Foo { 1.0 } >= Foo { NaN }; // <= false
  • 87. 10. Payne, I can't feel my legs pointer 87
  • 88. void Item_Paint(itemDef_t *item) { vec4_t red; menuDef_t *parent = (menuDef_t*)item->parent; red[0] = red[3] = 1; red[1] = red[2] = 0; if (item == NULL) { return; } .... } 88
  • 89. void Item_Paint(itemDef_t *item) { vec4_t red; menuDef_t *parent = (menuDef_t*)item->parent; red[0] = red[3] = 1; red[1] = red[2] = 0; if (item == NULL) { return; } .... } 89
  • 90. void Item_Paint(std::unique_ptr<itemDef_t> &item) { vec4_t red; menuDef_t *parent = (menuDef_t*)item->parent; red[0] = red[3] = 1; red[1] = red[2] = 0; if (item == NULL) { return; } .... } 90
  • 91. void Item_Paint(std::shared_ptr<itemDef_t> &item) { vec4_t red; menuDef_t *parent = (menuDef_t*)item->parent; red[0] = red[3] = 1; red[1] = red[2] = 0; if (item == NULL) { return; } .... } 91
  • 92. void Item_Paint(std::optional<itemDef_t> &item) { vec4_t red; menuDef_t *parent = (menuDef_t*)item->parent; red[0] = red[3] = 1; red[1] = red[2] = 0; if (!item) { return; } .... } 92
  • 93. static struct DerivedMesh *dynamicPaint_Modifier_apply(....) { .... for (; surface; surface = surface->next) { PaintSurfaceData *sData = surface->data; if (surface && surface->format != MOD_DPAINT_SURFACE_F_IMAGESEQ && sData) { .... } 93
  • 94. static struct DerivedMesh *dynamicPaint_Modifier_apply(....) { .... for (; surface; surface = surface->next) { PaintSurfaceData *sData = surface->data; if (surface && surface->format != MOD_DPAINT_SURFACE_F_IMAGESEQ && sData) { .... } 94
  • 95. 11. Push me and then emplace me! 95
  • 96. struct G584_Info { G584_Info(const Ptree *p, bool add, bool mul, bool sub, bool div) { .... } .... const Ptree *m_p; bool m_add; bool m_mul; bool m_sub; bool m_div; }; 96
  • 97. static void G584_CollectExprInfo(const Ptree *p, vector<G584_Info> &infs) { .... auto what = p->What(); if (what == ntParenExpr) { // Remember the expression in parentheses and continue infs.push_back(G584_Info(p, true, true, false, false)); p = SafeSkipParentesis(p); } .... } 97
  • 98. static void G584_CollectExprInfo(const Ptree *p, vector<G584_Info> &infs) { .... auto what = p->What(); if (what == ntParenExpr) { // Remember the expression in parentheses and continue infs.push_back(G584_Info(p, true, true, false, false)); p = SafeSkipParentesis(p); } .... } 98
  • 99. static void G584_CollectExprInfo(const Ptree *p, vector<G584_Info> &infs) { .... auto what = p->What(); if (what == ntParenExpr) { // Remember the expression in parentheses and continue infs.emplace_back(p, true, true, false, false); p = SafeSkipParentesis(p); } .... } 99
  • 100. struct G584_Info { G584_Info(const Ptree *p, bool add, bool mul, bool sub, bool div) { .... } .... const Ptree *m_p; bool m_add; bool m_mul; bool m_sub; bool m_div; }; 100
  • 101. struct G584_Info { G584_Info(const Ptree *p, bool add, bool mul, bool sub, bool div) { .... } .... const Ptree *m_p; bool m_add; bool m_mul; bool m_sub; bool m_div; }; 101
  • 102. static void G584_CollectExprInfo(const Ptree *p, vector<G584_Info> &infs) { .... auto what = p->What(); if (what == ntParenExpr) { // Remember the expression in parentheses and continue infs.emplace_back(p, true, true, false, false); // ok since C++20 p = SafeSkipParentesis(p); } .... } 102
  • 103. 103
  • 104. 12. I will find you and insert you! 104
  • 105. void AddFunctionDangerousInfo(const vstring &strFunctionInfo, const FunctionDangerousInfo &info) { FunctionDangerousInfoMap &infoMap = GetFunctionDangerousInfoMap(); DangerousInfoIterator it = infoMap.find(strFunctionInfo); if (it == infoMap.end()) { infoMap.insert(make_pair(strFunctionInfo, dangerousInfo)); } else { FunctionDangerousInfo &a = it->second; // some works with 'a' } } 105
  • 106. void AddFunctionDangerousInfo(const vstring &strFunctionInfo, const FunctionDangerousInfo &info) { FunctionDangerousInfoMap &infoMap = GetFunctionDangerousInfoMap(); DangerousInfoIterator it = infoMap.find(strFunctionInfo); if (it == infoMap.end()) { infoMap.insert(make_pair(strFunctionInfo, dangerousInfo)); } else { FunctionDangerousInfo &a = it->second; // some works with 'a' } } 106
  • 107. void AddFunctionDangerousInfo(....) { auto &infoMap = GetFunctionDangerousInfoMap(); if (auto it = infoMap.find(strFunctionInfo); it == infoMap.end()) { infoMap.emplace(strFunctionInfo, dangerousInfo); } else { FunctionDangerousInfo &a = it->second; // some works with 'a' } } 107
  • 108. void AddFunctionDangerousInfo(....) { auto &infoMap = GetFunctionDangerousInfoMap(); if (auto it = infoMap.find(strFunctionInfo); it == infoMap.end()) { infoMap.emplace(strFunctionInfo, dangerousInfo); } else { FunctionDangerousInfo &a = it->second; // some works with 'a' } } 108
  • 109. void AddFunctionDangerousInfo(....) { auto &infoMap = GetFunctionDangerousInfoMap(); if (auto it = infoMap.lower_bound(strFunctionInfo); it != infoMap.end()) { auto &a = it->second; // some works with 'a' } else { infoMap.emplace_hint(it, strFunctionInfo, dangerousInfo); } } 109
  • 110. void AddFunctionDangerousInfo(....) { auto &infoMap = GetFunctionDangerousInfoMap(); if (auto it = infoMap.lower_bound(strFunctionInfo); it != infoMap.end() && it->first == strFunctionInfo) { auto &a = it->second; // some works with 'a' } else { infoMap.emplace_hint(it, strFunctionInfo, dangerousInfo); } } 110
  • 111. 13. Is it alive? 111
  • 112. struct Foo { int i; double d; }; Foo* bar() { Foo *ptr = (Foo *) malloc(sizeof(Foo)); if (ptr == NULL) return NULL; ptr->i = 0; ptr->d = 0.0; return ptr; } 112
  • 113. struct Foo { int i; double d; }; Foo* bar() { Foo *ptr = (Foo *) malloc(sizeof(Foo)); if (ptr == NULL) return NULL; ptr->i = 0; // ok in C, UB in C++ ptr->d = 0.0; // ok in C, UB in C++ return ptr; } 113
  • 114. struct Foo { int i; double d; }; Foo* bar() { Foo *ptr = (Foo *) malloc(sizeof(Foo)); if (ptr == NULL) return NULL; new (ptr) Foo; ptr->i = 0; // ok in C++ ptr->d = 0.0; // ok in C++ return ptr; } 114
  • 115. struct Foo { int i; double d; }; Foo* bar() { Foo *ptr = (Foo *) malloc(sizeof(Foo)); if (ptr == NULL) return NULL; ptr->i = 0; // ok in C, UB in C++ until C++20 ptr->d = 0.0; // ok in C, UB in C++ until C++20 return ptr; } 115
  • 116. 14. Mind the sign 116
  • 117. int foo(const char *s) { int r = 0; while (*s) { r += ((r * 20891 + *s * 200) | *s ^ 4 | *s ^ 3 ) ^ (r >> 1); s++; } return r & 0x7fffffff; } 117
  • 118. int foo(const char *s) { int r = 0; while (*s) { r += ((r * 20891 + *s * 200) | *s ^ 4 | *s ^ 3 ) ^ (r >> 1); s++; } return r & 0x7fffffff; } gcc-8 -O2 -std=c++17 -funsigned-char source.cpp 118
  • 119. int foo(const char *s) { int r = 0; while (*s) { r += ((r * 20891 + *s * 200) | *s ^ 4 | *s ^ 3 ) ^ (r >> 1); s++; } return r & 0x7fffffff; } gcc-8 -O2 -std=c++17 -funsigned-char source.cpp 119
  • 120.
  • 121.
  • 122. 15. No exceptions, except... 122
  • 123. BOOL WINAPI DllMain(HANDLE hModule, ULONG nReason, LPVOID /*pSituation*/) { BOOL br = TRUE; if (nReason == DLL_PROCESS_ATTACH) { // Remember our hModule. g_hModule = hModule; g_hInstance = (HINSTANCE)g_hModule; // Make sure we're properly registered. if (FAILED(DllRegisterServer())) br = FALSE; } else if (nReason == DLL_PROCESS_DETACH) { // Nothing to do. } return br; } 123
  • 124. BOOL WINAPI DllMain(HANDLE hModule, ULONG nReason, LPVOID /*pSituation*/) { BOOL br = TRUE; if (nReason == DLL_PROCESS_ATTACH) { // Remember our hModule. g_hModule = hModule; g_hInstance = (HINSTANCE)g_hModule; // Make sure we're properly registered. if (FAILED(DllRegisterServer())) br = FALSE; } else if (nReason == DLL_PROCESS_DETACH) { // Nothing to do. } return br; } 124
  • 125. HRESULT WINAPI DllRegisterServer(VOID) { .... hr = ::RegOpenKeyEx(HKEY_CURRENT_USER, "SoftwaregeOgeOShellPlugins", NULL, KEY_WRITE, &hk); if ( SUCCEEDED(hr = HRESULT_FROM_WIN32(hr)) ) { strcpy(szValue, "geOCommandTime.dll,0"); DllGetObjectInfo(0, GI_Name, szName, MAX_PATH); hr = ::RegSetValueEx(hk, szName, 0, REG_SZ, (LPBYTE)szValue, strlen(szValue)); hr = HRESULT_FROM_WIN32(hr); RegCloseKey(hk); } .... return hr; } 125
  • 126. HRESULT WINAPI DllGetObjectInfo(DWORD dwPluginId, DWORD dwInfo, VOID *pBuffer, DWORD dwBuffer) { .... // Get the specified plugin: hr = DllGetObject(dwPluginId, &pPlugin); if (SUCCEEDED(hr)) { // We got it, so get some info: hr = pPlugin->GetInfo(dwInfo, pBuffer, dwBuffer); // And delete the plugin: delete pPlugin; } .... return hr; } 126
  • 127. HRESULT WINAPI DllGetObjectInfo(DWORD dwPluginId, DWORD dwInfo, VOID *pBuffer, DWORD dwBuffer) { .... // Get the specified plugin: hr = DllGetObject(dwPluginId, &pPlugin); if (SUCCEEDED(hr)) { // We got it, so get some info: hr = pPlugin->GetInfo(dwInfo, pBuffer, dwBuffer); // And delete the plugin: delete pPlugin; } .... return hr; } 127
  • 128. HRESULT WINAPI DllGetObject(DWORD dwPluginId, IShellPlugin **ppPlugin) { .... { // We need to create a new command plugin: switch (dwPluginId) { case 0: *ppPlugin = new CCommandPlugin; break; default: *ppPlugin = NULL; }; .... } .... return hr; } 128
  • 129. HRESULT WINAPI DllGetObject(DWORD dwPluginId, IShellPlugin **ppPlugin) { .... { // We need to create a new command plugin: switch (dwPluginId) { case 0: *ppPlugin = new CCommandPlugin; break; default: *ppPlugin = NULL; }; .... } .... return hr; } 129
  • 131.  Thou shalt not auto, unless thy faith is strong and pure  Thou shalt not write indexed loops for they are abominations before the Code  Thou shalt wash thy data thoroughly before releasing it  Thou shalt not accept data from strangers for they might be sinful  Thou shalt not copy-paste thy code blocks 131
  • 132.  Thy comparison routines shall be correct or else the Wrath of Code will get thee  Thou shalt check thy nullables for they are sinful  Thou shalt not push that which can be emplaced  Thou shalt not cook signed values with overflow semantics  He who is without noexcept shall throw, and none other 132
  • 133. END Q&A133 Brought to you by: pvs-studio.com