This document discusses static analysis for improving code quality in embedded systems. It begins by introducing the speaker and providing background on trends in IoT devices and code size growth. Examples are given of potential errors like divide by zero, use of uninitialized variables, and returning addresses of stack variables. Frameworks for finding vulnerabilities like CWE and real vulnerabilities like CVE are described. The value of code reviews and dynamic analysis are discussed but their limitations for embedded code. Finally, standards like MISRA and SEI CERT for preventing errors and examples of correctly using static analysis are provided.
1. Static analysis and writing
C/C++ of high quality code for
embedded systems
Phillip Khandeliants, PVS-Studio
2. Speaker
2
• Phillip Khandeliants, 1994
• C++/C# developer in the PVS-Studio team
• 3 years of taking part in developing the
C++ analyzer core
• Authour of articles on checking
open source projects
7. Fascinating bug
7
• A colleague made 4 robots
• They were controlled by a remote console
• They were playing football and
«catch the mice»
• One of the robots went crazy due to a
programming error
10. Code review
• Helps to find errors of high level and not to
shoot off your legs waist-high
• Allows to share experience with padawans
• Together you’ll learn a lot of new secret
things about the project
10
11. But...
• Code review is to expensive:
– Expectation: «It’ll take us 10-15 mins
to review the edit»
– Reality – we stay long for hours
• You get tired too quickly from code viewing
11
12. Why code review doesn’t always work
12
static int EatWhitespace(FILE * InFile)
{
int c;
for (c = getc(InFile); isspace(c) && ('n' != c);
c = getc(InFile));
return (c);
}
13. Why code review doesn’t always work
13
#ifdef isspace
#undef isspace
#endif
....
#define isspace(c) ((c)==' ' || (c) == 't')
....
for (c = getc(InFile); ((c)==' ' || (c) == 't') && ('n' != c);
c = getc(InFile));
V560 A part of conditional expression is always true: ('n' != c). params.c 136.
14. Dynamic code analysis
• Debuggers
• Profilers
• Sanitizers (AddressSanitizer, ThreadSanitizer, ...)
• Found a bug? Let's run for fixing it!
14
15. But again...
• It’s not always simple to test and debug
embedded code
• Sanitizers and profilers are slow
• You’ll often need some special test
dataset
15
16. Static analysis for the rescue
• Automated code review by a machine
• A machine doesn’t get tired
• You can find the most exciting error
patterns
16
17. Where has the error crept?
17
static void SHA1Final(unsigned char digest[20],
SHA1_CTX *context)
{
u32 i;
unsigned char finalcount[8];
....
memset(context->count, 0, 8);
memset(finalcount, 0, 8);
}
18. Here it is!
18
CWE-14 V597 The compiler could delete the 'memset' function call, which is used to flush
'finalcount' buffer. The memset_s() function should be used to erase the private data.
wifi_generate_pin.c 185
static void SHA1Final(unsigned char digest[20],
SHA1_CTX *context)
{
u32 i;
unsigned char finalcount[8];
....
memset(context->count, 0, 8);
memset(finalcount, 0, 8);
}
19. Static Application Security Testing (SAST)
Programming
error
Real
vulnerability
19
• «Programming errors are boring to catch!»
• «You’d better catch vulnerabilities!»
• NIST: 64% of vulnerabilities are
programming errors
• Let’s start «intimidating» managers and
team leads with potential vulnerabilities
Potential
vulnerability
20. Two kinds of SAST
• Search for known vulnerabilities in code
• Preventive measures from potential vulnerabilities
20
21. • CWE™ is a community-developed list of common software security
weaknesses.
• Set of weaknesses/potential vulnerabilities, which can become real
vulnerabilities(CVE). One just needs to describe how to exploit them .
• Website: https://cwe.mitre.org
• CWE List Version 3.1 contains 716 potential vulnerabilities.
21
Common Weakness Enumeration (CWE)
22. Examples of potential vulnerabilities
according to CWE
• CWE-20: Improper Input Validation
• CWE-369: Divide By Zero
• CWE-457: Use of Uninitialized Variable
• CWE-467: Use of sizeof() on a Pointer Type
• CWE-562: Return of Stack Variable Address
22
26. CWE-562: Return of Stack Variable Address
26
void SEMC_GetDefaultConfig(semc_config_t *config)
{
assert(config);
semc_axi_queueweight_t queueWeight; /*!< AXI queue weight. */
semc_queuea_weight_t queueaWeight;
semc_queueb_weight_t queuebWeight;
....
config->queueWeight.queueaWeight = &queueaWeight;
config->queueWeight.queuebWeight = &queuebWeight;
}
CWE-562 V506 Pointer to local variable 'queuebWeight' is stored outside the scope of
this variable. Such a pointer will become invalid. fsl_semc.c 257
27. Common Vulnerabilities and Exposures
(CVE)
• CVE — real vulnerabilities, there are confirmed
scenarios of their exploitation
• Main website: https://cve.mitre.org/
• Total CVE Entries: 114 282
27
28. CVE-2012-2122
28
typedef char my_bool;
my_bool check_scramble(const char *scramble_arg,
const char *message,
const uint8 *hash_stage2)
{
....
return memcmp(hash_stage2, hash_stage2_reassured, SHA1_HASH_SIZE);
}
V642 Saving the 'memcmp' function result inside the 'char' type variable is inappropriate.
The significant bits could be lost breaking the program's logic. password.c
29. CVE-2012-2122
29
typedef char my_bool;
my_bool check_scramble(const char *scramble_arg,
const char *message,
const uint8 *hash_stage2)
{
....
return memcmp(hash_stage2, hash_stage2_reassured, SHA1_HASH_SIZE);
}
V642 Saving the 'memcmp' function result inside the 'char' type variable is inappropriate.
The significant bits could be lost breaking the program's logic. password.c
31. CVE-2014-1266
31
static OSStatus SSLVerifySignedServerKeyExchange(....)
{
OSStatus err;
....
if ((err = SSLHashSHA1.update(&hashCtx, &serverRandom)) != 0)
goto fail;
if ((err = SSLHashSHA1.update(&hashCtx, &signedParams)) != 0)
goto fail;
goto fail;
if ((err = SSLHashSHA1.final(&hashCtx, &hashOut)) != 0)
goto fail;
....
fail:
....;
}
• V640 The code's operational logic does not correspond with its formatting. The statement is indented
to the right, but it is always executed. It is possible that curly brackets are missing.
• V779 Unreachable code detected. It is possible that an error is present
32. A path from an «ordinary» error
to a vulnerability
32
33. SEI CERT coding standard
• Developed by CERT (CERT Coordination
Center, CERT/CC)
• Meant for C, C++, Java, Perl languages
• Is quite similar to CWE
33
34. Examples of rules from SEI CERT
• MSC06-C: Beware of compiler optimizations
• INT33-C: Ensure that division and remainder operations do
not result in divide-by-zero errors
• EXP33-C, EXP53-CPP: Do not read uninitialized memory
• ARR01-C: Do not apply the sizeof operator to a pointer when
taking the size of an array
• DCL30-C: Declare objects with appropriate storage durations
34
36. EXP34-C. Do not dereference null pointers, C/C++
36
EXP34-C V701 realloc() possible leak: when realloc() fails in allocating memory, original pointer
'e->locks.lock.list' is lost. Consider assigning realloc() to a temporary pointer. evas_key.c 142
EOLIAN void _evas_canvas_key_lock_add(
...., Evas_Public_Data *e, ....)
{
....
e->locks.lock.list = realloc(e->locks.lock.list,
e->locks.lock.count * sizeof(char *));
e->locks.lock.list[e->locks.lock.count - 1] = strdup(keyname);
eina_hash_free_buckets(e->locks.masks);
}
37. MISRA С/С++ coding standards
• You’ll have to pay for it
• MISRA C 2012 contains 143 rules, MISRA C++
2008 — 228 rules
• MISRA reduces the likelihood that an error
will get into the code base
37
38. Examples of MISRA-rules
• Don’t use octal constants
• Don’t use goto
• A function has to have single exit point
• Don’t use standard library functions
(atof/…/abort/exit/getenv/system/…)
• Don’t use dynamic allocations
• Don’t use unions
• Each case has to end with break or throw
38
39. Story about Toyota not following the MISRA standard
39
• NHTSA: in 2000-2010 89 people died and 57
– sustained injuries in accidents
• NHTSA and NASA carried out investigations
• 7134 violations have been detected
• Toyota: «You’re all wrong!»
• ….
• Toyota pays off 16 billions dollars in the pre-
trial order
40. How to use MISRA and static analysis incorrectly
40
41. How to do it right?
41
• In a perfect world you run it on a developer’s
machine
• The error doesn’t get into the version control
system
• The developer won’t be afraid of
embarrassment
• Additional defence line – night runs on a CI-
server
42. But 100500 warnings are still here!
42
• You just need to supress all of them after the
first run!
• Only the newly written code is analysed
• Gradually fix old warnings
43. Shall I use static analysis instead of other
methodologies?
• Static analysis is not a silver bullet
• Static analysis is the answer to the question:
"How to make our code better?"
• What does mean " better "? It will be easier to
maintain and develop it, eliminate problems in it
43
44. Q&A
44
Check your project using PVS-Studio for programming
errors and potential vulnerabilities!
C, C++, C#, Java
www.viva64.com