Sunteți pe pagina 1din 71

EN

I IA AS
Referenced Document

Programming guideline for C/C++


Methodenbeschreibung / Method Description

Document Attributes
Document No. A5E00785463A
File RTIL_Development_Guideline_C++_V111.doc
Status released
1
Document version 02
Type of source English (only)
Reference Key (RPH) RPH PLM-Realize
Reference to PCMB ./.
Referenced Standards ./.
Scope of validity I IA AS
Adapted for country global
Affiliated companies Sector/Division Companies: [_] Category 1 [_] Category 2 [_] Category 3
[_] Regional Companies (employees in the applicable organizations)
./.
Valid from 01.10.2012
2
Review (frequently) Implicit with corresponding regulation or process.
Responsible IOWA SW Architecture Team (SWAT)
Superseded regulation ./.
Corresponding regulation ./.
or process description

1
If released, all previous versions of this document are no longer be valid. They will be replaced by this version.
2
Review performed implicit with corresponding regulation or process, no re-release required if no need for change.

Copyright © 2012 Siemens Aktiengesellschaft – For internal use only – All rights reserved
Die Kopie oder Verteilung oder Kommunikation des Inhaltes dieses Dokumentes ist nicht gestattet ohne schriftliche Erlaubnis der Siemens AG.
Copying or distribution or communication of the content of this document is not allowed unless with express written permission from Siemens.
Vorlage/Template A5E00785494A DS12
I IA AS Copyright (C) Siemens AG 2012 All Rights Reserved.

Methodenbeschreibung / Method Description Programming guideline for C/C++ A5E00785463A

Inhalt / Contents
1 Motivation ............................................................................................................4
2 Scope of the guidelines .....................................................................................5
3 Purpose................................................................................................................6
4 Checking the Rules ............................................................................................7
5 Not compliant code ............................................................................................8
6 C/C++ Rules.........................................................................................................9
6.1 Design and implementation .............................................................................................9
6.2 Module headers and footers..........................................................................................10
6.2.1 Code for file headers ................................................................................................10
6.2.2 Code headers for functions and member functions ..................................................11
6.2.3 Code for footers ........................................................................................................11
6.3 Inclusion of header files.................................................................................................12
6.3.1 Prevent multiple including of header files .................................................................12
6.3.2 C header files with C++ compiler ..............................................................................12
6.3.3 Inclusion of OS specific headers files .......................................................................13
6.3.4 Inclusion of headers files with “<>” brackets.............................................................13
6.3.5 Namespaces in header files .....................................................................................13
6.4 Storage of header files ..................................................................................................14
6.5 Definition of constants ...................................................................................................14
6.6 Explicit type conversion .................................................................................................15
6.7 Casting on const and type casting ................................................................................16
6.8 Global variables, instances and functions .....................................................................17
6.9 Comments in code ........................................................................................................17
6.10 Naming conventions ......................................................................................................18
6.10.1 Filenames .................................................................................................................18
6.10.2 Naming conventions for code elements....................................................................18
6.11 Designing classes .........................................................................................................21
6.11.1 Class header files .....................................................................................................21
6.11.2 Virtual methods, destructors, constructors and overrides.........................................21
6.11.3 Friending classes......................................................................................................23
6.11.4 Overloading operators ..............................................................................................23
6.11.5 Private properties or members .................................................................................24
6.11.6 RTTI..........................................................................................................................24
6.11.7 Public members ........................................................................................................25
6.11.8 Initializing member variables of a class ....................................................................25
6.11.9 Init functions..............................................................................................................27
6.11.10 Freeing memory in destructors .................................................................................27
6.11.11 Copy and assignment operators...............................................................................28
6.12 Structure of decision code .............................................................................................29
6.13 Wrapping long statements.............................................................................................29
6.14 Complex boolean expressions and operator precendence ...........................................30
6.15 Switch commands .........................................................................................................31
6.15.1 Case without break statements ................................................................................31
6.15.2 Switch commands based on enums .........................................................................32
6.16 Functions.......................................................................................................................33
6.16.1 Function parameters.................................................................................................33
Version Status Valid from Page
003 released 01.10.2012 2 of 2
Copyright © 2011 Siemens Aktiengesellschaft – For internal use only – All rights reserved
I IA AS Copyright (C) Siemens AG 2012 All Rights Reserved.

Methodenbeschreibung / Method Description Programming guideline for C/C++ A5E00785463A

6.16.2 Lines of code for each function.................................................................................34


6.16.3 Number of arguments for each function ...................................................................34
6.17 Compiling options ..........................................................................................................35
6.18 Operands on logical binary............................................................................................35
6.19 “Goto” ............................................................................................................................36
6.20 Pointer handling ............................................................................................................36
6.20.1 Uninitialized pointers.................................................................................................36
6.20.2 “this”..........................................................................................................................36
6.20.3 Deleting pointers.......................................................................................................37
6.20.4 Accessing pointers and handles ...............................................................................37
6.21 Mathematical operations ...............................................................................................40
6.21.1 Division operator.......................................................................................................40
6.21.2 Overflow in mathematical operations........................................................................40
6.21.3 Algorithms.................................................................................................................41
6.21.4 Recursion..................................................................................................................41
6.22 Numerical values vs. symbolic values ...........................................................................42
6.23 Nested Loops ................................................................................................................43
6.24 Initializing variables with basic types .............................................................................43
6.25 Smartpointers and dynamic fields .................................................................................43
6.26 Memory management ...................................................................................................45
6.26.1 Allocation of memory ................................................................................................45
6.27 Exceptions.....................................................................................................................48
6.28 Scope of variables, resources and system objects .......................................................49
6.29 Complex expressions ....................................................................................................50
6.30 Inlining ...........................................................................................................................51
6.31 Forward declaration.......................................................................................................52
6.32 BOOL type.....................................................................................................................52
6.33 Printf, scanf and streams...............................................................................................53
6.34 std:: prefix......................................................................................................................53
6.35 Null terminated strings...................................................................................................55
6.36 Formatted Output ..........................................................................................................57
6.37 Checking boundaries.....................................................................................................60
6.38 Passing parameters to subsystems...............................................................................60
6.39 References, pointers with private members ..................................................................62
6.40 Utilizing std::string .........................................................................................................64
7 List of security relevant rules..........................................................................67
8 Appendix............................................................................................................70
8.1 Change Log ...................................................................................................................70
8.2 Authors ..........................................................................................................................70
8.3 Release .........................................................................................................................70
8.4 Glossary ........................................................................................................................71

Version Status Valid from Page


003 released 01.10.2012 3 of 3
Copyright © 2011 Siemens Aktiengesellschaft – For internal use only – All rights reserved
I IA AS Copyright (C) Siemens AG 2012 All Rights Reserved.

Methodenbeschreibung / Method Description Programming guideline for C/C++ A5E00785463A

1 Motivation
With the increasing possibilities of new technologies, growing security concerns and
the desire to use results further from completed projects the requirements on a new
project increase.
Aiming to develop components using results from older projects it should be possible to
realize new requests on higher standard.
Exactly the last-named point causes problems if there exist only incomplete results and
the software developers are not available after the project end any more.
For this reason, a methodical and structured procedure of the software development is
mandatorily required to be able to access acquired know-how over project phases and
out of projects.
The most important qualities of software should be:

• correctness
• reliability acceptance of user errors
• usability intuitive use of SW
• maintainability modification of SW
• portability usage of different OS-platforms
• efficiency fast execution of SW
• testability verification of correctness
• readability good structure of code
• comprehensability code functionality is easy to understand
• security resilience against malicious users and attacks

To achieve that, a systematic approach for software development is necessary.

One of the first necessary steps is the specification of programming guidelines.

The compliance with the development guidelines is demanded by all involved persons.
Besides the existence of the specifications, also the understanding of the rules and
why they apply, practical experiences, and checking the conformance to the
development guidelines lead to high-quality software.
In this guideline the rules are marked this way:
 Security  Style  common rule old/new code

These checkboxes indicate, whether the rule concerns about security and/or style
and/or is a common rule for old/new code.

If there is an affected rule from CERT, then this rule is mentioned in brackets (e. g.
(API09-C).

The term “should not“ has the same meaning as “must not” or “is not allowed to” and is
a more legal and polite expression.

Version Status Valid from Page


003 released 01.10.2012 4 of 4
Copyright © 2011 Siemens Aktiengesellschaft – For internal use only – All rights reserved
I IA AS Copyright (C) Siemens AG 2012 All Rights Reserved.

Methodenbeschreibung / Method Description Programming guideline for C/C++ A5E00785463A

2 Scope of the guidelines


This document takes care of the different development processes that already exist.

The following guidelines and sources were taken into consideration:

Document
PCPRT guideline RTIL_DevelopmentGuidline_V0.10.doc Version 0.10 by
Hector Colado (used as template for this document)
PVSS guideline ri_ProgrammierrichtlinienC++.doc Version 6.1F by Günther
Zoffmann
WinCE PA_RT_CppProgrammierung (Version 0.9)
PC-based SIEMENS I IA AS Programming guideline for C/C++ (Version
1.0), 2009
C++ Optimizing software in C++ by Agner Fog, July 2007
CERT software Memory management
engineering
Igor Zevaka http://www.somethingorothersoft.com/2010/02/02/double-
dispatch-rtti-vs-pure-vtable/
PLM Guidance Explorer Online
Programming Conventions for C++ and Visual Basic

SCGL GL_SecureProgrammingGuideline_CPP
GL_SecureProgrammingGuideline_C

All rules in this coding guideline apply to the new modules that are developed in IOWA
platform, WinCC IL RT Comfort and WinCC IL RT Professional. New modules, are
modules that are newly developed in IOWA and WinCC IL RT (means modules which
are newly developed from scratch). This includes also modules which have its origin in
PCPRT such as VDS, VCS, RH, and Logging. Also modules which are in development
(or are allready developed) for new IOWA features (e.g. RDF modules, System
Configuration Server) need to be compliant to all rules.

Nevertheless, these coding guidelines also include rules that apply for existing WinCC
OA (PVSS legacy) modules independent if a new or existing module is targeted. These
rules are marked with “common rule old/new code”.
See example:

Version Status Valid from Page


003 released 01.10.2012 5 of 5
Copyright © 2011 Siemens Aktiengesellschaft – For internal use only – All rights reserved
I IA AS Copyright (C) Siemens AG 2012 All Rights Reserved.

Methodenbeschreibung / Method Description Programming guideline for C/C++ A5E00785463A

CPP007 Inclusion of OS specific headers files


 Security  Style  common rule old/new code
Rule Do not include OS-specific files, e.g. Windows.h.
System calls to the OS-Systems must be encoupled by OS platform
abstraction layer.

Beyond the rules that are marked with “common rule old/new code” existing modules
keep the same rules in which they have been made so far. Means that for extending or
changing these existing modules (e.g. new classes, changed methods, change of data
types, etc.) the PVSS coding guidelines apply, with the exception that rules marked
with “common rule old/new code” overrule the PVSS rules.

3 Purpose
These programming guidelines describe the rules and best practices to be used by all
developers in the project Runtime Innovation Line Platform and the IL RT Products
(Comfort and Professional).

The problems regarding existing code and different coding guidelines are taken into
consideration. If existing code conflicts with one of the coding rules, the existing code
remains unchanged..

But if existing code violates these programming guidelines in a non-acceptable manner


(memory leaks, possibility of dumping the programs, much changes in the code have to
be done, ambiguous class design etc.), SWAT and/or PL/TPL has to be informed.

Version Status Valid from Page


003 released 01.10.2012 6 of 6
Copyright © 2011 Siemens Aktiengesellschaft – For internal use only – All rights reserved
I IA AS Copyright (C) Siemens AG 2012 All Rights Reserved.

Methodenbeschreibung / Method Description Programming guideline for C/C++ A5E00785463A

4 Checking the Rules


The check of the implementation guidelines is made by tools (if possible) and additional
manual code reviews.
The functionality and the semantics for every component are checked cyclically by
standardized code reviews, unit and system tests.
These code reviews have to be planned that the code can be corrected if necessary
without pressure of time or milestone deadline.

The code checking tools are:


• Dacoda with PCLint and FxCop for static code analysis
• IBM Rational Purify and PureCoverage for runtime code analysis and coverage
• Valgrind (dynamic code analysis for Linux)
• KlocWork for static code analysis

Version Status Valid from Page


003 released 01.10.2012 7 of 7
Copyright © 2011 Siemens Aktiengesellschaft – For internal use only – All rights reserved
I IA AS Copyright (C) Siemens AG 2012 All Rights Reserved.

Methodenbeschreibung / Method Description Programming guideline for C/C++ A5E00785463A

5 Not compliant code


If source code is not compliant with these rules it has to be reworked or reasons for not
being compliant must be put into the code or checkin/checkout information. Every time
a rule is broken, this must be clearly documented and justified by the author, approved
by architect and/or PL(TPL) and by commenting the code violating the rule and check-
in comments.
Old code, that is not compliant, should not be changed and remains “as it is” (see
Chapter 3).

Assembler code in general should be avoided, if code need to be portable across


different OS/HW platforms. If assembler code is necessary (e.g. for performance
optimization) an equivalent C or C++ reference implementation must be provided
for portability reasons.
Exceptions have to be documented and approved by SWAT and TPL/PL.

Version Status Valid from Page


003 released 01.10.2012 8 of 8
Copyright © 2011 Siemens Aktiengesellschaft – For internal use only – All rights reserved
I IA AS Copyright (C) Siemens AG 2012 All Rights Reserved.

Methodenbeschreibung / Method Description Programming guideline for C/C++ A5E00785463A

6 C/C++ Rules

6.1 Design and implementation


CPP001 Design and implementation
 Security  Style  common rule old/new code

Rule No implementation without an agreed architecture/design, i. e. a released


SDS and a released SDDS.
Annotation Modifications of the design while implementing have to be discussed with
the architects and PL and agreed by them.
Implementation before design has to be aligned/discussed with PL and
SWAT.

Version Status Valid from Page


003 released 01.10.2012 9 of 9
Copyright © 2011 Siemens Aktiengesellschaft – For internal use only – All rights reserved
I IA AS Copyright (C) Siemens AG 2012 All Rights Reserved.

Methodenbeschreibung / Method Description Programming guideline for C/C++ A5E00785463A

6.2 Module headers and footers


6.2.1 Code for file headers

CPP002 Code for headers


 Security  Style  common rule old/new code

Rule //----------------------------------------------------
------------------------
// Copyright (C) Siemens AG <current year YYYY>. All
Rights Reserved. Confidential.
//----------------------------------------------------
------------------------
// Descr.: <Brief description of the code>
//----------------------------------------------------
------------------------

Example //----------------------------------------------------
------------------------
// Copyright (C) Siemens AG 2011. All Rights
Reserved. Confidential.
//----------------------------------------------------
------------------------
// Descr.: Class definition of Data Access Optimizer
//----------------------------------------------------
------------------------

Version Status Valid from Page


003 released 01.10.2012 10 of 10
Copyright © 2011 Siemens Aktiengesellschaft – For internal use only – All rights reserved
I IA AS Copyright (C) Siemens AG 2012 All Rights Reserved.

Methodenbeschreibung / Method Description Programming guideline for C/C++ A5E00785463A

6.2.2 Code headers for functions and member functions

CPP003 Code headers for functions and member functions


 Security  Style  common rule old/new code
Rule The following points of interest have to be documented in function
and member headers:
 Description of function/value
 Description of in- and out parameters
 Description of return value
 Explicit indication, which parameters are out parameters

The specific format of these headers is not defined in this


document, but is up to be specified by the respective
trams/architects. Their choice of tools will define the format.

Annotation Out parameter need to be considered as well. Consider


using Doxygen as example do.
Example /** Format the value according to a format string.
@param Format The format string.
@param pTarget This is a buffer with length len
@param Len Indicates length of the output buffer.
@return Number of bytes written into target
*/
virtual int FormatValue(const CharString &Format, char
*pTarget, size_t Len) const;

6.2.3 Code for footers

CPP004 Code for footers


 Security  Style  common rule old/new code

Rule //----------------------------------------------------
------------------------
// Copyright (C) Siemens AG <current Year YYYY> All
Rights Reserved. Confidential.
//----------------------------------------------------
------------------------
Code file footers do not have to be included necessarily as they
collide with automatic refactoring tools like Visual Assist.
Example //----------------------------------------------------
------------------------
// Copyright (C) Siemens AG 2011 All Rights Reserved.
Confidential.
//----------------------------------------------------
------------------------

Version Status Valid from Page


003 released 01.10.2012 11 of 11
Copyright © 2011 Siemens Aktiengesellschaft – For internal use only – All rights reserved
I IA AS Copyright (C) Siemens AG 2012 All Rights Reserved.

Methodenbeschreibung / Method Description Programming guideline for C/C++ A5E00785463A

6.3 Inclusion of header files

6.3.1 Prevent multiple including of header files

CPP005 Prevent multiple including of header files


 Security  Style  common rule old/new code

Rule Each header file has to start with "#ifndef <Headerflag> #define
<Headerflag> … #endif
If you expect a naming conflict, include the namespace like
_NAMESPACE_FILENAME in the flag’s name.
Example #ifndef _PERFMGR_H_
#define _PERFMGR_H_

#endif // _PERFMGR_H_
Annotation Name should be defined by class name or file name.

6.3.2 C header files with C++ compiler

CPP006 C header files with C++ compiler


 Security  Style  common rule old/new code
Rule Header files with "C" functionality must be embraced by extern "C",
when they are compiled by a C++ compiler.
Annotation This rule apply only to header files that will be used by C and C++
code. Main target are header files of c libraries that and are linked
to c++ code.
Example #ifdef __cplusplus
extern "C" {
#endif

unsigned int QueryPerfCounterIndex(const char


CounterName[32]);

void SetPerfCounter(unsigned int CounterNdx, _int64


Value);

_int64 *GetPerfCounterAddress(const char


CounterName[32]);

#ifdef __cplusplus
}
#endif

Version Status Valid from Page


003 released 01.10.2012 12 of 12
Copyright © 2011 Siemens Aktiengesellschaft – For internal use only – All rights reserved
I IA AS Copyright (C) Siemens AG 2012 All Rights Reserved.

Methodenbeschreibung / Method Description Programming guideline for C/C++ A5E00785463A

6.3.3 Inclusion of OS specific headers files

CPP007 Inclusion of OS specific headers files


 Security  Style  common rule old/new code
Rule Do not include OS-specific files, e.g. Windows.h.
System calls to the OS-Systems must be encoupled by OS platform
abstraction layer.
Annotation Apply only for projects that have platform independency as a design goal.

6.3.4 Inclusion of headers files with “<>” brackets

CPP008 Inclusion of headers files in general


 Security  Style  common rule old/new code
Rule It is recommended to include files with "" quotes (e.g. #include
"MyHeader.h") for all locally available headers. This provides the
following benefits:
 No need for development environment configuration to include
project header directories
 Reduced build time by bypassing search through preferred
system header directories
 No wrong arbitrary use of external headers with the same name
in system directories

6.3.5 Namespaces in header files

CPP009 Namespaces in header files


 Security  Style  common rule old/new code
Rule Do not import namespaces (“using namespace xxx”) in header files,
because this pollutes them.

Version Status Valid from Page


003 released 01.10.2012 13 of 13
Copyright © 2011 Siemens Aktiengesellschaft – For internal use only – All rights reserved
I IA AS Copyright (C) Siemens AG 2012 All Rights Reserved.

Methodenbeschreibung / Method Description Programming guideline for C/C++ A5E00785463A

6.4 Storage of header files


CPP010 Storage of header files
 Security  Style  common rule old/new code

Rule Header files, which are used by different systems (e. g. interface headers)
have to be stored in a global header directory.
Saving a header in a local subdirectory is allowed, when the
modules/subsystems using this header are part of a larger
module/subsystem.
The storage of header files has to be defined by CM together with
developer.

6.5 Definition of constants


CPP011 Definition of constants
 Security  Style  common rule old/new code

Rule Constants must be defined with “const” or “enum”.


Do not use #define directive, since there is no type check at compile time.

Version Status Valid from Page


003 released 01.10.2012 14 of 14
Copyright © 2011 Siemens Aktiengesellschaft – For internal use only – All rights reserved
I IA AS Copyright (C) Siemens AG 2012 All Rights Reserved.

Methodenbeschreibung / Method Description Programming guideline for C/C++ A5E00785463A

6.6 Explicit type conversion


CPP012 Use explicit type conversion (API09-C)
 Security  Style  common rule old/new code

Rule Avoid implicit type conversion, use explicit conversion.


Risk Vulnerability due to hidden string operations, missing robustness and
stability.
Annotation Due to compiler warnings on several platforms NO implicit type
conversion should be used.
Implicit conversions should only be used in exceptionally, e. g. with
reusable basic types. The implicit conversion is designed only in the
corresponding constructors.
C++ supports implicit type conversion. For example a method or function
with a parameter of type S called by a parameter with type T (if an implicit
conversion exists) causes some problems:

• A function for converting S to T can have two owners, for


example the constructor T::T(S) and the operator S::operator T().

• The following effect can happen, when using two independent


class libraries in one program: If there is a conversion from S to
T1 and a function or method f with parameter T1 will be called
with S, the compiler realizes an implicit conversion from S to T1.
When there will be a function f (in the aftermath) with an
argument of type T2 overloaded and there is a conversion from S
ot T2, so the call f(S) leads to ambiguousity and causes errors.
Additionally, constructors with only one parameter shall be marked as
explicit to prevent ambiguities. Should there be a special requirement to
do otherwise, make sure to include the reasoning in the c’tor’s header.
Example Wrong:
double DValue = 3; // implicit conversion to double
value 3.0
int NValue = 3.14156; // implicit conversion to
integer value 3
char ChValue = NValue; // implicit cast

constructors done right:


class Array
{
public:
explicit Array(size_t count);
};

Array array = 123; // now fails


Array array(123); // works and is unambigous

Version Status Valid from Page


003 released 01.10.2012 15 of 15
Copyright © 2011 Siemens Aktiengesellschaft – For internal use only – All rights reserved
I IA AS Copyright (C) Siemens AG 2012 All Rights Reserved.

Methodenbeschreibung / Method Description Programming guideline for C/C++ A5E00785463A

6.7 Casting on const and type casting


CPP013 Avoid casting on const variables (DCL00-C)
 Security  Style  common rule old/new code

Rule Do not delete "const"ness by casting, since (for example) pointers on


const remain the same, but its contents can change. Also the code
pretends, that the object remains unchanged, which might be not true.
Do not use const_cast.
Risk Broken encapsulation and vulnerability
Example Do NOT do this:

void resolve (const char* pInStr)


{

char* pStr = const_cast<char*>(pInStr);//lost const
Substitute (pStr);

};

CPP014 Type Conversion - type casting


 Security  Style  common rule old/new code
Rule If there is type conversion within the code, always the C++ specific
typecasts (<static_cast>, <reinterpret_cast>, <dynamic_cast>) should be
used. A type conversion in C-style (new type in parentheses) is not
recommended.
Annotation See RTTI regarding dynamic_cast.
C++ specific casting is easier to find in the code than old C-style casting.
Example Wrong:
int Value = 3;
char* pCh = (char*)Value;

Correct:
int Value = 3;
char* pCh;
...
pCh = reinterpret_cast<char*>(Value);

Please keep in mind, that this example is only for illustration. If you want
to convert int to char, you should use other methods, e. g. like Strings.

Version Status Valid from Page


003 released 01.10.2012 16 of 16
Copyright © 2011 Siemens Aktiengesellschaft – For internal use only – All rights reserved
I IA AS Copyright (C) Siemens AG 2012 All Rights Reserved.

Methodenbeschreibung / Method Description Programming guideline for C/C++ A5E00785463A

6.8 Global variables, instances and functions


CPP015 Global variables, instances and functions
 Security  Style  common rule old/new code

Rule Avoid global variables, instances or functions. Use member variables


instead to support the concept of capsuling (helps understanding the
code).
It has to be clarified with PL or architect if some global variables are
needed.
Annotation Globals always remain in memory, even when they are not used.
If globals cannot be avoided, these should be contained in a dedicated
module / file and should be described, why it is done in this way.

6.9 Comments in code


CPP016 Comments in code
 Security  Style  common rule old/new code

Rule Source code comments should be done in English.


The format for bugfix comments is:
// <Tracking number> <Date in YYYY-MM-DD format> <User>
<comment>
Describe the root cause, including what, why, the given context and the
idea behind the changes.
If you are making your comments in the versioning software, you must not
make the same comments in the code.
For rule exception motivation and authorization (who has authorized the
exception) should be documented.
Example // AP4815162342 2011-05-31 mrboess port changed due to
conflict with I/O processing

Version Status Valid from Page


003 released 01.10.2012 17 of 17
Copyright © 2011 Siemens Aktiengesellschaft – For internal use only – All rights reserved
I IA AS Copyright (C) Siemens AG 2012 All Rights Reserved.

Methodenbeschreibung / Method Description Programming guideline for C/C++ A5E00785463A

6.10 Naming conventions

6.10.1 Filenames

CPP017 Special characters in filenames and length of filenames


 Security  Style  common rule old/new code

Rule Filenames can have more than eight characters. In the filename no
blanks and no special characters except “_” are allowed. Choose
descriptive filenames. Upper and lower case is allowed.
Annotation See CPP020.

CPP018 Interface definition header files


 Security  Style  common rule old/new code

Rule Header files containing only the definition of an interface have a filename
starting with “I”.

CPP019 Source file naming conventions


 Security  Style  common rule old/new code
Rule C progam files have ending .c, their headers .h
C++ program files have ending .cxx or .cpp, their headers .hxx / .h

6.10.2 Naming conventions for code elements

CPP020 General naming conventions


 Security  Style  common rule old/new code

Rule Do not create names that differ only in case type (wrong example: class
WorkTest; class WorkTEST;).
Use PascalCasing, when there is no explicit naming convention (e.g.
structs).
Do not use special characters like umlauts or characters with
special meanings.
All identifiers must be named in English and should be descriptive.

CPP021 Naming conventions for enum types


 Security  Style  common rule old/new code

Rule Write enum types in PascalCasing (e.g. MsgType)

Version Status Valid from Page


003 released 01.10.2012 18 of 18
Copyright © 2011 Siemens Aktiengesellschaft – For internal use only – All rights reserved
I IA AS Copyright (C) Siemens AG 2012 All Rights Reserved.

Methodenbeschreibung / Method Description Programming guideline for C/C++ A5E00785463A

CPP021a Naming conventions for enum variables


 Security  Style  common rule old/new code

Rule Write Enum Variables in Pascal Casing;


enum Colors { RED, YELLOW, GREEN };
Colors AlarmLineColor;
Annotation Enum Values (e.g. RED) may be written in UpperCase and Pascal
Casing. This means
enum Colors { Red, Yellow, LightGreen };
is also possible.

CPP022 Naming conventions for interfaces


 Security  Style  common rule old/new code

Rule Interface elements always start with "I" and PascalCasing (e. g.
IDisposablePattern)

CPP023 Naming conventions for methods


 Security  Style  common rule old/new code

Rule PascalCasing (e.g. ToString)

CPP024 Naming conventions for properties (class members)


 Security  Style  common rule old/new code

Rule PascalCasing (e.g. BackgroundColor)

CPP026 Naming conventions for variables and parameters


 Security  Style  common rule old/new code

Rule PascalCasing (e.g.TimeVar StartTime;)


Member variables of classes start with “m_” and then PascalCasing ( e. g.
m_Value).
Static member variables of classes start with “s_” and then PascalCasing
(e. g. s_MainWnd).
Global variables start with “g_” and then PascalCasing (e .g.
g_Instance).
Pointers start with “p” and then Pascal Casing right before the name of
the Variable (e. g. pTestMessage; m_pTestContainer, if the pointer is
a member variable)

Version Status Valid from Page


003 released 01.10.2012 19 of 19
Copyright © 2011 Siemens Aktiengesellschaft – For internal use only – All rights reserved
I IA AS Copyright (C) Siemens AG 2012 All Rights Reserved.

Methodenbeschreibung / Method Description Programming guideline for C/C++ A5E00785463A

CPP027 Naming conventions for preprocessor directives


 Security  Style  common rule old/new code

Rule CAPITALCASING (e.g. #ifdef WINCE) For grouping and separating “_” is
allowed, also at the beginning of the name.

CPP028 Naming conventions for classes


 Security  Style  common rule old/new code

Rule PascalCasing starting with “C” (e.g. CTimeVar).

CPP029 Naming conventions for namespaces


 Security  Style  common rule old/new code

Rule PascalCasing is used for C++ namespaces.

Version Status Valid from Page


003 released 01.10.2012 20 of 20
Copyright © 2011 Siemens Aktiengesellschaft – For internal use only – All rights reserved
I IA AS Copyright (C) Siemens AG 2012 All Rights Reserved.

Methodenbeschreibung / Method Description Programming guideline for C/C++ A5E00785463A

6.11 Designing classes


6.11.1 Class header files

CPP030 Class header files


 Security  Style  common rule old/new code

Rule Only one class definition per header file is allowed. Inner class definitions
are allowed.

6.11.2 Virtual methods, destructors, constructors and


overrides

CPP031 Virtual destructor


 Security  Style  common rule old/new code

Rule For each class with virtual methods there must be an explicit destructor,
which is virtual, too.
Annotation This rule is only valid as long as calling delete is possible from outside –
usually as long as the destructor is public (e.g. for COM-objects lifetime
management is handled via AddRef/Release, so basic COM-Interfaces
like IUnknown don’t have virtual destructors).
There are some use cases, where it is not intended, that a class can be
derived and there a virtual destructor is producing unnecessary
performance costs. If you want, that your class should never be derived,
make the destructor non-virtual. But comment it in the header code of
your class.

Version Status Valid from Page


003 released 01.10.2012 21 of 21
Copyright © 2011 Siemens Aktiengesellschaft – For internal use only – All rights reserved
I IA AS Copyright (C) Siemens AG 2012 All Rights Reserved.

Methodenbeschreibung / Method Description Programming guideline for C/C++ A5E00785463A

CPP032 Virtual methods remain virtual


 Security  Style  common rule old/new code

Rule Each overridden virtual method remains virtual in the derived class and
must be declared as virtual.
Example class CBasicMessage
{
public:
virtual int DispatchMsg (const int DispID) {
m_MessageDispatcher = DispID; return DispID; }
private:
int m_MessageDispatcher;
int m_MessageController;
};

Wrong example:
class CControllerMessage: public CBasicMessage
{
public:
int DispatchMsg (const int DispID) {
m_MessageController = DispID; return 0; }
private:
int m_MessageDispatcher;
int m_MessageController;
};

Correct example:

class CControllerMessage: public CBasicMessage


{
public:
virtual int DispatchMsg (const int DispID) {
m_MessageController = DispID; return 0; }
private:
int m_MessageDispatcher;
int m_MessageController;
};

Annotation Think about CPP031 Annotations.


Will a non virtual method be overridden through different levels of class
hierarchy, the call via pointer decides, which method will be called (static
bind). This is often an error, which is hard to localize. Even when this
effect is intended, its behavour is often obscure.
At specification time of a method it is often not known, whether it will be
overridden or not. These decision can be easily revised. When the
function will be overriden in any derived class (vice versa the prior
decision), the base class has to be modified, too, when this method isn’t
declared as virtual.
Due to performance issues the use of virtual functions should be
considered thoroughly.

Version Status Valid from Page


003 released 01.10.2012 22 of 22
Copyright © 2011 Siemens Aktiengesellschaft – For internal use only – All rights reserved
I IA AS Copyright (C) Siemens AG 2012 All Rights Reserved.

Methodenbeschreibung / Method Description Programming guideline for C/C++ A5E00785463A

CPP033 Overridden methods


 Security  Style  common rule old/new code

Rule Each overridden method must be virtual in the base class.

6.11.3 Friending classes

CPP035 Avoid friend classes – exceptions have to be documented


 Security  Style  common rule old/new code
Rule Only classes with strong common content can be friended (class
clustering). Otherwise avoid friending classes.

6.11.4 Overloading operators

CPP036 Avoid operator overloading if semantic is not obvious.


 Security  Style  common rule old/new code

Rule Avoid operator overloading if semantic is not obvious. Use operator


overloading in cases where it is immediately obvious what the result of
the operation will be.
Example Wrong (confusing)
char &operator>>(char &To)
{
int Subst = 2;
int Subst2 = 4;
Subst2 >> To >> Subst;
return To;
}
Annotation When overloading operator=, the chaining of the operator should be
tested on consistency. When overloading an operator (e. g. operator+),
then all combinations of this operator have to be checked, too (e. g.
operator +=).
C++ allows you to overload nearly every operator for your own classes.
Using overloading excessively leads to lacks in readability and
understanding. In addition consistency problems can appear, too (e. g.
when overriding operator+ and operator=, the semantics of operator+=
doesn’t change automatically – it merely remains the same).

Version Status Valid from Page


003 released 01.10.2012 23 of 23
Copyright © 2011 Siemens Aktiengesellschaft – For internal use only – All rights reserved
I IA AS Copyright (C) Siemens AG 2012 All Rights Reserved.

Methodenbeschreibung / Method Description Programming guideline for C/C++ A5E00785463A

6.11.5 Private properties or members

CPP037 Accessing private properties or members (OOPP00-CPP)


 Security  Style  common rule old/new code

Rule Provide public Get() and Set() property accessors for private properties or
members instead of making them public. The accessors name can start
with “Get” or “Set” prefix.
Example class CTestA
{
private:
int m_ID;
...
...
public:
int ClassID()const; // this is a get()-
function
void ClassID(int SetID); // this is a set()-
function
...
...
};

void TestFunc()
{
aCTest CTest;
int ClassIDTest;
const int ClIDDefault = 10;
...
...
aCTest.ClassID(ClIDDefault);
...
...
ClassIDTest = MyClass.ClassID();
}

6.11.6 RTTI

CPP038 Do not use RTTI (OOP34-CPP)


 Security  Style  common rule old/new code

Rule Usage of RTTI is forbidden.


Risk High loss of performance, misleading function calls
Annotation Code should not use RTTI, since more memory might be needed and the
calls via RTTI (dynamic_cast) are not so fast than pure virtual table calls.
Remember, that memory and CPU speed on the panel is very limited.
There are many issues regarding RTTI problems. One problem with
virtual table calls is described here (including example).

Version Status Valid from Page


003 released 01.10.2012 24 of 24
Copyright © 2011 Siemens Aktiengesellschaft – For internal use only – All rights reserved
I IA AS Copyright (C) Siemens AG 2012 All Rights Reserved.

Methodenbeschreibung / Method Description Programming guideline for C/C++ A5E00785463A

6.11.7 Public members

CPP039 Class member variables (OOPP00-CPP)


 Security  Style  common rule old/new code

Rule Class member variables should not be “public”.

6.11.8 Initializing member variables of a class

Version Status Valid from Page


003 released 01.10.2012 25 of 25
Copyright © 2011 Siemens Aktiengesellschaft – For internal use only – All rights reserved
I IA AS Copyright (C) Siemens AG 2012 All Rights Reserved.

Methodenbeschreibung / Method Description Programming guideline for C/C++ A5E00785463A

CPP040 Initializing member variables


 Security  Style  common rule old/new code

Rule All member variables have to be initialized in a constructor of the class or


the constructor is calling an Init() function, which initializes the
members.
Since no exception handling is allowed, it is common practice to initialize
everything that can’t go wrong in the constructor and to provide a public
Init() function that does the error prone initialization steps and returns
error code if something goes wrong.
For PCLint it is better to initialize the variables in the standard constructor.
Initialization of the member variables has to be done in the same order
they are declared.
Member variables have to be initialized only in the constructor or in its
Init() function.
Instead of writing an Init() function consider using the RAII approach
(all resource acquisition should be done in the constructor).
Example
Example of RAII-approach:

class DiversityHolder {
Obj* pObj;
int number;
bool read;

public:
DiversityHolder ()
{
number = 42;
read = true;
pObj = NULL;
}

HRESULT Init ()
{
pObj = new Obj();
}

~DiversityHolder ()
{
delete pObj;
}
};

DiversityHolder div = new DiversityHolder()


div.Init();
delete div;

Version Status Valid from Page


003 released 01.10.2012 26 of 26
Copyright © 2011 Siemens Aktiengesellschaft – For internal use only – All rights reserved
I IA AS Copyright (C) Siemens AG 2012 All Rights Reserved.

Methodenbeschreibung / Method Description Programming guideline for C/C++ A5E00785463A

6.11.9 Init functions

CPP041 Init functions


 Security  Style  common rule old/new code

Rule Complex operations in the constructor of a class must be put in an


Init() function to get a chance to return initialization result.

6.11.10 Freeing memory in destructors

CPP042 Freeing memory in destructors


 Security  Style  common rule old/new code
Rule Dynamically allocated memory in the member functions of a class has to
be freed as soon as possible, at least in the destructor of the class.
Annotation Consider using the RAII approach, where resources are freed in the
destructor.

Version Status Valid from Page


003 released 01.10.2012 27 of 27
Copyright © 2011 Siemens Aktiengesellschaft – For internal use only – All rights reserved
I IA AS Copyright (C) Siemens AG 2012 All Rights Reserved.

Methodenbeschreibung / Method Description Programming guideline for C/C++ A5E00785463A

6.11.11 Copy and assignment operators

CPP043 Copy and assigment operators


 Security  Style  common rule old/new code
Rule Only create a copy constructor or assignment operator when adding
pointer/reference member variables to the class.

If no copy constructor or assignemt operator is needed, than they have to


be declared as private and no implemtation has to be done. Even more
this should be documented (to make it obvious that it is not simply
forgotten).

Writing a copy constructor/assignment operator can be error prone and


thus should be avoided when not necessary.
Example const CClass& operator = (const CClass &Rhs)
{
//protect from destroying myself in case someone
calls assignment to myself
if (this == Rhs) return this;

// free allocated memory


delete m_pSomething;
m_pSomething = 0;

//make assignment
...
return this;
}
Annotation Implement a copy and an assign operator, when you are using pointers or
handles on OS resources as class members. Implement the copy/assign
constructor, so that a full copy will be implemented, i. e. the copy/assign
operators of the base classes will be called, too. When implementing the
assign operator keep in mind that the applied memory has to be freed
again before. This is not needed, when the assignment operates on itself.

Version Status Valid from Page


003 released 01.10.2012 28 of 28
Copyright © 2011 Siemens Aktiengesellschaft – For internal use only – All rights reserved
I IA AS Copyright (C) Siemens AG 2012 All Rights Reserved.

Methodenbeschreibung / Method Description Programming guideline for C/C++ A5E00785463A

6.12 Structure of decision code


CPP044 Structure of decision code
 Security  Style  common rule old/new code

Rule
if ( .... )
{
if ( ... )
{
....
}
....
}
else if ( ... )
{
....
}
else
{
....
}

Empty decision bodies must be implemented with bracelets and


commented, why this block is empty.
while (condition)
{
// nothing to do
}

Do not use hard tabs (“\t”) for alignment.


Use four blanks (whitespaces) for alignment.
Annotation This structure is also valid for “while”, “switch … case”, “try … catch …
finally” and “for” statements.

6.13 Wrapping long statements


CPP045 Long statements over several lines
 Security  Style  common rule old/new code

Rule Use blanks instead of tabs to align your code logically, when wrapping
long statements over several lines. As a best practice limit each line to
120 characters (including whitespaces).
Annotation If this rule is violated the developer has to think about the structure of the
code. This rule is not meant to be too restrictive.

Version Status Valid from Page


003 released 01.10.2012 29 of 29
Copyright © 2011 Siemens Aktiengesellschaft – For internal use only – All rights reserved
I IA AS Copyright (C) Siemens AG 2012 All Rights Reserved.

Methodenbeschreibung / Method Description Programming guideline for C/C++ A5E00785463A

6.14 Complex boolean expressions and operator


precendence
CPP046 Complex boolean expressions and operator precendence
 Security  Style  common rule old/new code

Rule Boolean expressions within complex expressions or assignments have to


be included in brackets.
Use explicit brackets where implicit operator precedence is not obvious.
Example If ((PosStart < 0) ||
(PosEnd < 0) ||
(PosEnd < PosStart) ||
( (PosStart == 0) && (PosEnd == 0) )
)
{
return;
}

Version Status Valid from Page


003 released 01.10.2012 30 of 30
Copyright © 2011 Siemens Aktiengesellschaft – For internal use only – All rights reserved
I IA AS Copyright (C) Siemens AG 2012 All Rights Reserved.

Methodenbeschreibung / Method Description Programming guideline for C/C++ A5E00785463A

6.15 Switch commands


6.15.1 Case without break statements

CPP047 Case label


 Security  Style  common rule old/new code

Rule Each case label has to be concluded by a break-statement. Otherwise


this has to be commented.
Example DpMsg *DpMsg::Allocate(MsgType DpMsgType)
{
switch (DpMsgType)
{
case DP_MSG_CONNECT:
return new DpMsg();
break;
// same handling for two cases
case DP_MSG_DISCONNECT:
case DP_MSG_DISCONNECT_ALL:
disconnected = true;
break;
// additional handling for one case with
// similarities
case DP_MSG_ALERT_CONNECT:
retVisible = false;
case DP_MSG_ALERT_CONN_RET_VISIBLE:
return new DpMsgConnection(DpMsgType);
break;
case DP_MSG_ALERT_DISCONN:
return new DpMsgConnection(DpMsgType);
break;
default:
ASSERT_DPMSG (INVALID_MESSAGE_TYPE):
}
}
Annotation Missing break statements should be PCLint like commented. See PCLint
documentation Message #825. Also a default is needed every time. The
smallest one should be include a trace message that the default case
should be called. This maybe helps you to analyse some problems.

Version Status Valid from Page


003 released 01.10.2012 31 of 31
Copyright © 2011 Siemens Aktiengesellschaft – For internal use only – All rights reserved
I IA AS Copyright (C) Siemens AG 2012 All Rights Reserved.

Methodenbeschreibung / Method Description Programming guideline for C/C++ A5E00785463A

6.15.2 Switch commands based on enums

CPP048 Switch commands based on enums (ERR04-C)


 Security  Style  common rule old/new code

Rule Switch commands based on enum types as selector must have an assert
mechanism in the default branch.
Risk Format string attack, denial of service, information leakage, leakage of
confidential data, arbitrary code execution, abnormal program termination,
bypassing authorization mechanisms.
Annotation The issue here is, that you get a compiler warning, if an enum type is
expanded and it is not handled in the switch command in a case
statement. No default branch should be implemented, but the compiler
warning C4061 shall be turned on to indicated unhandled enum cases.
Example DpMsg *DpMsg::Allocate(MsgType DpMsgType)
{
case DP_MSG_CONNECT:
return new DpMsg();
break;
// same handling for two cases
case DP_MSG_DISCONNECT:
case DP_MSG_DISCONNECT_ALL:
disconnected = true;
break;
// additional handling for one case with
// similarities
case DP_MSG_ALERT_CONNECT:
retVisible = false;
case DP_MSG_ALERT_CONN_RET_VISIBLE:
return new DpMsgConnection(DpMsgType);
break;
case DP_MSG_ALERT_DISCONN:
return new DpMsgConnection(DpMsgType);
break;
...
// The following types are only for
completeness:
case PVSS_MSG :
case NO_MSG :
...
case DP_MSG :
case DP_MSG_CONNECTION :
case DP_MSG_VALUECHANGE :
case DP_MSG_ALERT :
return 0;
break;
}
}
Annotation Missing break statements should be PCLint like commented. See PCLint
documentation Message #825.

Version Status Valid from Page


003 released 01.10.2012 32 of 32
Copyright © 2011 Siemens Aktiengesellschaft – For internal use only – All rights reserved
I IA AS Copyright (C) Siemens AG 2012 All Rights Reserved.

Methodenbeschreibung / Method Description Programming guideline for C/C++ A5E00785463A

6.16 Functions
6.16.1 Function parameters

CPP049 Function parameter check (MSC08-CPP)


 Security  Style  common rule old/new code

Rule The function code shall start with a parameter check, if the function is a
public API function.
Risk Format string attack, denial of service, information leakage, leakage of
confidential data, arbitrary code execution, abnormal program termination,
bypassing authorization mechanisms
Example Result OnStatus(GAPStatusContext EnumContext, Result
ErrorCode)
{
if( 0 != EnumContext && S_OK != ErrorCode )
{
StopVCS();
}

CPP050 Const function parameters


 Security  Style  common rule old/new code

Rule All parameters passed to a function via pointer or reference should be


“const”, if their value will not be changed in the function.
If the object does not change inside the function, the function itself should
be declared as const, too.
Example CCharString ToString(const CClass &Rhs) const;

Version Status Valid from Page


003 released 01.10.2012 33 of 33
Copyright © 2011 Siemens Aktiengesellschaft – For internal use only – All rights reserved
I IA AS Copyright (C) Siemens AG 2012 All Rights Reserved.

Methodenbeschreibung / Method Description Programming guideline for C/C++ A5E00785463A

6.16.2 Lines of code for each function

CPP051 Limit the lines of code for each function


 Security  Style  common rule old/new code
Rule Each functions should do exactly one thing. Try limiting the lines of code
for each function to 150 lines if feasible. Lines of code contain empty lines
and comments as well.
Annotation If you exceed the number of 150 lines of code, consider creating further
subroutines.
If the function has a straightforward structure (i. e. calling another function
many times with slightly different arguments in separate blocks, e. g. in
unit tests), then this limit may be exceeded.

6.16.3 Number of arguments for each function

CPP052 Limit the number of arguments for each function


 Security  Style  common rule old/new code
Rule Limit the number of arguments for each function to 10. You need to get
your architect’s approval for more than 6 parameters.
Annotation For panel architecture with ARM processors the limit is 4
parameters, since the rest of the parameters will be stored on the
stack.

From “Clean Code”:“The ideal number of arguments for a function is zero


(niladic). Next comes one (monadic), followed closely by two (dyadic).
Three arguments (triadic) should be avoided where possible. More than
three (polyadic) requires very special justification -- and then shouldn't be
used anyway.”

Version Status Valid from Page


003 released 01.10.2012 34 of 34
Copyright © 2011 Siemens Aktiengesellschaft – For internal use only – All rights reserved
I IA AS Copyright (C) Siemens AG 2012 All Rights Reserved.

Methodenbeschreibung / Method Description Programming guideline for C/C++ A5E00785463A

6.17 Compiling options


CPP053 Errors and warnings
 Security  Style  common rule old/new code

Rule Code must be able to be built without errors or warnings. Use the highest
warning level.
If not the highest warning level is used, then this has to be
documented and approved by SWAT and PL/TPL.
Risk Some potential risky code can be in disguise, when the build produces
many warnings. Since the software must be kept always “ready for build”,
it must compile without errors.
Annotation Disabling warnings is only allowed on a global level via a global warning
header (which has to be approved by SWAT and PL).
Disabling warnings is allowed for 3rd party headers (in this case warnings
should be disabled and reenabled again e.g. pre-/post warning headers)
or 3rd party files (there it is allowed to set the warning level to 0). Also this
has to be approved by SWAT and PL..

6.18 Operands on logical binary


CPP054 Operands on logical binary
 Security  Style  common rule old/new code

Rule Operands on logical binary must not have side effects.


Example Do NOT do this:
if ((b < 20) && (b++ > 10))
{
...
}
This leads to the following behaviour: When b == 14, then b will be 11
(the operator+ will run on b), if b == 2, the operator+ will not increment b.
The behaviour of the if-clause is different – depending on b - and
confusing in both cases.

Version Status Valid from Page


003 released 01.10.2012 35 of 35
Copyright © 2011 Siemens Aktiengesellschaft – For internal use only – All rights reserved
I IA AS Copyright (C) Siemens AG 2012 All Rights Reserved.

Methodenbeschreibung / Method Description Programming guideline for C/C++ A5E00785463A

6.19 “Goto”
CPP055 Goto statements (MSC35-CPP)
 Security  Style  common rule old/new code

Rule Use “goto” statements in a decent manner, i. e. where a well placed


“goto” is better than a complex for/while construction. But try to avoid
these situations. The reason for a “goto” has to be commented in the
code.
Risk Unreadable code that prevents in-deep analysis.

6.20 Pointer handling


6.20.1 Uninitialized pointers

CPP056 Avoid uninitialized pointers


 Security  Style  common rule old/new code

Rule An empty pointer must always be assigned to "NULL".


Risk Since NULL is a keyword that is not clearly defined within all C/C++-
Compilers we have to ensure that our C/C++ compiler support NULL as 0.

6.20.2 “this”

CPP057 Deleting “this” pointer (OOP05-CPP)


 Security  Style  common rule old/new code

Rule Do not delete “this” except when working in an interface-based


environment (like COM). There, object lifetime is controlled by the object
alone.
Risk Denial of service, information leakage, abnormal program termination.
Annotation An object should generally not rely on being created on the heap (with
new).

Version Status Valid from Page


003 released 01.10.2012 36 of 36
Copyright © 2011 Siemens Aktiengesellschaft – For internal use only – All rights reserved
I IA AS Copyright (C) Siemens AG 2012 All Rights Reserved.

Methodenbeschreibung / Method Description Programming guideline for C/C++ A5E00785463A

6.20.3 Deleting pointers

CPP058 Set pointer value after deletion


 Security  Style  common rule old/new code

Rule Set a pointer to "0" after its deletion.


Risk Denial of service, information leakage, abnormal program termination,
Annotation It is possible to delete a null pointer in C++, so it is senseless to write
code like this (p being some pointer): if (p) delete p;

6.20.4 Accessing pointers and handles

Version Status Valid from Page


003 released 01.10.2012 37 of 37
Copyright © 2011 Siemens Aktiengesellschaft – For internal use only – All rights reserved
I IA AS Copyright (C) Siemens AG 2012 All Rights Reserved.

Methodenbeschreibung / Method Description Programming guideline for C/C++ A5E00785463A

CPP059 Accessing pointers and handles ( EXP34-C/CPP)


 Security  Style  common rule old/new code
Rule Access to pointers and handles without validity check is prohibited, when
this pointer comes from calling non trusted code or libraries or when
memory is allocated. If the pointer does not fulfil the check, the error
handling must be implemented there.
Risk Format string attack, denial of service, information leakage, leakage of
confidential data, arbitrary code execution, abnormal program termination,
bypassing authorization mechanisms
Example
Msg *pMainMessage = 0;
... // some pMainMessage handling by untrusted code
if (0 != pMainMessage)
{
pMainMessage->allocate(DP_MSG); // creates message
...
}
else // NULL pointer handling
{
...
}

Insecure examples

In this insecure example, the else path dereferences a null pointer:


if (NULL != requireSession && !requireSession->check(ident))
{
requireSession->Add(ident);
}
else
{
requireSession->Confirm(ident);
}

In the following insecure code example, input is copied into dynamically


allocated memory at pointer str. If malloc() fails, it returns a null
pointer that is assigned to str. If str is dereferenced in memcpy(), the
program behaves in an unpredictable manner:
size_t size = strlen(input) + 1;
str = (char *)malloc(size);
memcpy(str, input, size);
/* ... */
free(str);
str = 0;

The function get_age()behaves in an unpredictable manner if called


with a null pointer as parameter:
struct record
{

Version Status Valid from Page


003 released 01.10.2012 38 of 38
Copyright © 2011 Siemens Aktiengesellschaft – For internal use only – All rights reserved
I IA AS Copyright (C) Siemens AG 2012 All Rights Reserved.

Methodenbeschreibung / Method Description Programming guideline for C/C++ A5E00785463A

char name[20];
unsigned age;
};
unsigned get_age(struct record *my_record)
{
return my_record->age;
}

Secure Examples:

Check whether the pointer returned by malloc() is null:


size_t size = strlen(input) + 1;
str = (char *)malloc(size);
if (NULL == str)
{
/* Handle allocation error */
}
else
{
memcpy(str, input, size);
/* ... */
free(str);
str = 0;
}

Functions with pointer parameters need to check for null pointers:


struct record {
char name[20];
unsigned age;
};

unsigned get_age(struct record *my_record)


{
if (NULL != my_record)
return my_record->age;
else
/* error handling */
}

Remark: Since str is allocated by malloc(), the test against NULL (not 0) is
fine here. Non-allocated pointers have to be initialized by “0”.

Version Status Valid from Page


003 released 01.10.2012 39 of 38
Copyright © 2011 Siemens Aktiengesellschaft – For internal use only – All rights reserved
I IA AS Copyright (C) Siemens AG 2012 All Rights Reserved.

Methodenbeschreibung / Method Description Programming guideline for C/C++ A5E00785463A

6.21 Mathematical operations


6.21.1 Division operator

CPP060 Division by “0” (FLP06-C)


 Security  Style  common rule old/new code

Rule Before dividing test divisor on not being “0”.


Risk Denial of service, information leakage, arbitrary code execution, abnormal
program termination

6.21.2 Overflow in mathematical operations

CPP061 Testing possible overflows (INT08-C, INT30-C, INT32-C)


 Security  Style  common rule old/new code

Rule Test possible overflows before doing mathematical operations, that might
exceed the range.
Risk Format string attack, denial of service, information leakage, leakage of
confidential data, arbitrary code execution, abnormal program termination,
bypassing authorization mechanisms

Version Status Valid from Page


003 released 01.10.2012 40 of 40
Copyright © 2011 Siemens Aktiengesellschaft – For internal use only – All rights reserved
I IA AS Copyright (C) Siemens AG 2012 All Rights Reserved.

Methodenbeschreibung / Method Description Programming guideline for C/C++ A5E00785463A

6.21.3 Algorithms

CPP062 Writing algorithms


 Security  Style  common rule old/new code

Rule The use of common algorithms and patterns is preferred. Self made
algorithms should be avoided, when there are already known algorithms
and patterns available.
Annotation Resolving already solved problems creates unnecessary costs and can
be a source of errors.
Using algorithms it is recommended to check the runtime behaviour and
to document it in brief. This elucates any rework of the runtime behaviour.
Using commonly known algorithms you have to think about a thin
economical embedding into the system, i. e. using functions from already
existing classes, avoiding unnecessary copy operations etc.
Always consider runtime conditions in algorithms, in particular loop
conditions and memory usage.

6.21.4 Recursion

CPP063 Avoid recursion


 Security  Style  common rule old/new code

Rule Use recursion only, where it is needed, since it can lead to high memory
consumption and can be error prone.
Annotation A while/for loop is usually even more error prone, so recursions are
generally preferable to loops in most languages – but C/C++…:
C/C++ does not specify tail recursion optimization as a core feature. E.g.
MSVC does no tail recursion optimization on optimization levels < 2, so
using tail recursion instead of while can lead to a stack overflow in e.g.
debug builds…

Version Status Valid from Page


003 released 01.10.2012 41 of 41
Copyright © 2011 Siemens Aktiengesellschaft – For internal use only – All rights reserved
I IA AS Copyright (C) Siemens AG 2012 All Rights Reserved.

Methodenbeschreibung / Method Description Programming guideline for C/C++ A5E00785463A

6.22 Numerical values vs. symbolic values


CPP064 No numerical values in the code
 Security  Style  common rule old/new code

Rule Direct numerical values are not allowed in the code, only symbolic values
(use “const”) must be used. However setting pointers to “0” is allowed.
Example Wrong:
if (255 == BackgroundColor)

Correct:

const int16 WhiteBackground = 255;


...
if (WhiteBackground == BackgroundColor)

Version Status Valid from Page


003 released 01.10.2012 42 of 42
Copyright © 2011 Siemens Aktiengesellschaft – For internal use only – All rights reserved
I IA AS Copyright (C) Siemens AG 2012 All Rights Reserved.

Methodenbeschreibung / Method Description Programming guideline for C/C++ A5E00785463A

6.23 Nested Loops


CPP065 Limiting nested loops
 Security  Style  common rule old/new code

Rule Limit nesting loops to three levels.


Annotation Nested loops can be difficult to understand and error prone.

6.24 Initializing variables with basic types


CPP066 Initialize variables
 Security  Style  common rule old/new code

Rule Initialize each variable of basic type with a value.


Risk Format string attack, denial of service, information leakage, arbitrary code
execution, abnormal program termination, bypassing authorization
mechanisms

6.25 Smartpointers and dynamic fields


CPP067 Classes of smartpointers
 Security  Style  common rule old/new code

Rule The use of smart-pointers is mandatory for access to objects and


interfaces.
Example
void foo()
{
auto_ptr<CCircle> apc = new CCircle(...);

...

return;

} //auto_ptr deletes CCircle object while leaving


foo()

Version Status Valid from Page


003 released 01.10.2012 43 of 43
Copyright © 2011 Siemens Aktiengesellschaft – For internal use only – All rights reserved
I IA AS Copyright (C) Siemens AG 2012 All Rights Reserved.

Methodenbeschreibung / Method Description Programming guideline for C/C++ A5E00785463A

CPP068 Smartpointers with dynamic fields


 Security  Style  common rule old/new code

Rule Consider using smartpointers when using dynamic fields, since freeing
memory or resources is less error prone.
Example Wrong example:
class MyClass
{
protected:
Obj *pObj;
// the rest of the definition follows
MyClass~()
{
delete pObj;
}
// public methods working on pObj
};

void function()
{
MyClass ATestClass;
// Some processing involving pObj;
...
}
// when ATestClass goes out of scope, delete is
// called in the destructor

Correct example:
class MyClass
{
protected:
auto_ptr<Obj> pObj;
// public methods working on pObj
};

void function()
{
MyClass ATestClass;
// Some processing involving pObj
...
// delete in destructor not required anymore
}
With the smartpointer implementation, the pointer gets deleted when
leaving scope.

Version Status Valid from Page


003 released 01.10.2012 44 of 44
Copyright © 2011 Siemens Aktiengesellschaft – For internal use only – All rights reserved
I IA AS Copyright (C) Siemens AG 2012 All Rights Reserved.

Methodenbeschreibung / Method Description Programming guideline for C/C++ A5E00785463A

6.26 Memory management

6.26.1 Allocation of memory

CPP069 Do not perform zero length allocations (MEM04-C, MEM35-C,


INT31-C, INT32-C, INT35-C)
 Security  Style  common rule old/new code
Rule Do not perform zero length allocations.
In cases where the memory allocation functions return a non-null pointer,
using this pointer results in undefined behaviour.
Risk Format string attack, denial of service, information leakage, leakage of
confidential data, arbitrary code execution, abnormal program termination,
bypassing authorization mechanisms
Example Wrong example:
size_t Size;

// initialize size, possibly by user-controlled input

int *pList = (int *)malloc(Size);


if (NULL == pList)
{
// Handle allocation error
}
else
{
// Continue processing list
}

Correct:
size_t Size;

// initialize size, possibly by user-controlled input

if (0 == Size || len > SIZE_MAX / sizeof(long))


{
/* Handle overflow */
}
int *pList = (int *)malloc(Size);
if (NULL == pList)
{
// Handle allocation error
}
// Continue processing list
Annotation The given example is written in C. If you use C++ syntax, then use
operator new()/delete instead of malloc/calloc/realloc/free.

Version Status Valid from Page


003 released 01.10.2012 45 of 45
Copyright © 2011 Siemens Aktiengesellschaft – For internal use only – All rights reserved
I IA AS Copyright (C) Siemens AG 2012 All Rights Reserved.

Methodenbeschreibung / Method Description Programming guideline for C/C++ A5E00785463A

CPP070 Avoid excessive stack allocations


 Security  Style  common rule old/new code
Rule Avoid excessive stack allocations, particularly in situations where the
growth of the stack can be controlled or influenced by an attacker.
Risk Denial of service, information leakage, abnormal program termination
Example Wrong example:
int copy_file(FILE *pSrc, FILE *pDst, size_t Bufsize)
{
char *pBuf = (char *)malloc(Bufsize); // no
parameter checking

while (fgets(pBuf, Bufsize, pSrc))


{
if (fputs(pBuf, pDst) == EOF)
{
// Handle error
}
}

return 0;
}

Correct:
int copy_file(FILE *pSrc, FILE *pDst, size_t Bufsize)
{
if (0 == Bufsize)
{
// Handle Error
}
char *pBuf = (char *)malloc(Bufsize);
if (!pBuf)
{
return -1;
}

while (fgets(pBuf, Bufsize, pSrc))


{
if ( EOF == fputs(pBuf, pDst) )
{
// Handle error
}
}
/* ... */
free(pBuf);
return 0;
}
Annotation The given example is written in C. If you use C++ syntax, then use
operator new()/delete instead of malloc/calloc/realloc/free.

Version Status Valid from Page


003 released 01.10.2012 46 of 46
Copyright © 2011 Siemens Aktiengesellschaft – For internal use only – All rights reserved
I IA AS Copyright (C) Siemens AG 2012 All Rights Reserved.

Methodenbeschreibung / Method Description Programming guideline for C/C++ A5E00785463A

CPP071 Allocate and free memory in the same module


 Security  Style  common rule old/new code
Rule Allocate and free memory in the same module, at the same level of
abstraction.
Risk Bugs are hard to find, so the attacker might use denial of service and
abnormal program termination due to memory leaks.
Annotation Allocating and freeing memory in different modules and levels of
abstraction may make it difficult to determine when and if a block of
memory has been freed, leading to programming defects such as double-
free vulnerabilities, accessing freed memory, or writing to freed or
unallocated memory.

CPP072 Do not assume having large heap space/stack available


 Security  Style  common rule old/new code
Rule Do not assume having large heap space/stack available.
Risk Denial of service, information leakage, leakage of confidential data,
arbitrary code execution, abnormal program termination.
Annotation Excessive heap allocation causes program crashes and memory leaks.
Even when there is a garbage collector available, then the garbage
collector won’t work correctly, i.e. may not reclaim the memory as
expected or won’t control over the memory reclaim.
Never assume that a memory allocation succeeds and always free the
memory when allocation succeeded and the memory is not needed
anymore. Then your program will not crash or leak or whatever even if
memory runs low. Running low on memory has to be forseen in the
application, a strategy how to react has to be implemented (shutting
down, waiting and retrying etc.).

Version Status Valid from Page


003 released 01.10.2012 47 of 47
Copyright © 2011 Siemens Aktiengesellschaft – For internal use only – All rights reserved
I IA AS Copyright (C) Siemens AG 2012 All Rights Reserved.

Methodenbeschreibung / Method Description Programming guideline for C/C++ A5E00785463A

6.27 Exceptions
CPP074 No exceptions in general ( ERR33-C, ERR07-CPP, ERR33-CPP,
ERR30-CPP)
 Security  Style  common rule old/new code

Rule Own code should not throw exceptions, exception handling has to be
used for code that throws exceptions though (e.g. STL). Internally, these
exceptions then have to be mapped to ErrorCodes.
 Exception handling has to be implemented where exceptions can be
thrown. On interface-level ErrorCodes shall be used.
RT projects have to handle errors without exceptions, other projects may
decide differently for their own scope.
Exceptions have to be discussed with SWAT/PL, if they are really
necessary.
If an exception handling has to be implemented, it has to be documented
in the comments of the code why this exception is used (motivation) and
who has authorized it (e.g. PL, SWAT or architect).
Risk Denial of service, information leakage, abnormal program termination
Annotation Exceptions can reduce performance.

Version Status Valid from Page


003 released 01.10.2012 48 of 48
Copyright © 2011 Siemens Aktiengesellschaft – For internal use only – All rights reserved
I IA AS Copyright (C) Siemens AG 2012 All Rights Reserved.

Methodenbeschreibung / Method Description Programming guideline for C/C++ A5E00785463A

6.28 Scope of variables, resources and system


objects
CPP075 Use minimal scope for variables, resources, system objects
 Security  Style  common rule old/new code
Rule Define a variable only, where it is needed. Do not forget to initialize it
correctly. Consider auto delete/free via scoping.
Example Wrong:
// OptimizerImplTest won’t be removed automatically
tkt::COptimizerImpl OptimizerImplTest;

SIMPLE_TESTCASE_BEGIN
{
Result result;
OptimizerImplTest.OnInitialize();
}
SIMPLE_TESTCASE_END(result);

Correct:
// OptimizerImplTest will be removed automatically
SIMPLE_TESTCASE_BEGIN
{
tkt::COptimizerImpl OptimizerImplTest;
Result result;
OptimizerImplTest.OnInitialize();
}
SIMPLE_TESTCASE_END(result);

Version Status Valid from Page


003 released 01.10.2012 49 of 49
Copyright © 2011 Siemens Aktiengesellschaft – For internal use only – All rights reserved
I IA AS Copyright (C) Siemens AG 2012 All Rights Reserved.

Methodenbeschreibung / Method Description Programming guideline for C/C++ A5E00785463A

6.29 Complex expressions


CPP076 Reducing complexity of expressions
 Security  Style  common rule old/new code

Rule Use subexpressions and subvariables to lessen complexity of an


expression, if it is too complex to understand at once.
Example
Wrong:
if ((PosStart < 0) ||
(PosEnd < 0) ||
(PosEnd < PosStart) ||
( (PosStart == 0) && (PosEnd == 0) )
)
{
...
}

Correct1:
bool IsStartup = (Start < 0) ||(End < 0) || (End <
Start);

if (IsStartup ||
( (PosStart == 0) && (PosEnd == 0) )
)
{
...
}

Correct2:
bool IsStartup (const int Start, const int End)
{
if (( Start < 0 ) ||
( End < 0) ||
( End < Start)
)
{
return true;
}
else
{
return false;
}
}

if (IsStartup (PosStart, PosEnd) ||


( (PosStart == 0) && (PosEnd == 0) )
)
{
...
}

Version Status Valid from Page


003 released 01.10.2012 50 of 50
Copyright © 2011 Siemens Aktiengesellschaft – For internal use only – All rights reserved
I IA AS Copyright (C) Siemens AG 2012 All Rights Reserved.

Methodenbeschreibung / Method Description Programming guideline for C/C++ A5E00785463A

6.30 Inlining
CPP077 Inlining in header files
 Security  Style  common rule old/new code

Rule The Code of inline methods must be placed in the class header file.
Prefer inline functions to macros as far as possible.
Annotation The usage of inline functions creates some problems:
The Code of inline methods must be placed in the class header file. So
code gets larger for all developers, who are using this class.
The inline declaration of virtual functions is not sensible, since it will be
ignored by the compiler. Because many methods have to be declared as
virtual, the usage of inline methods is very small.
Get/Set member methods should be inlined as well.
Inline functions, which exceed the limits of the linesize, should be
declared outside the class definition in the same header file.
Example class CAlertTime : public CTime
{
public:
...

/**
* Checks whether the compared instances are equal.
* Time and count are compared.
*/
int operator==(const CAlertTime &rVal) const;
...
}; // end of class definition CAlertTime

inline int CAlertTime::operator==(const CAlertTime &rVal)


const
{
return CTime::operator==(rVal) && count_ == rVal.count_;
}

Version Status Valid from Page


003 released 01.10.2012 51 of 51
Copyright © 2011 Siemens Aktiengesellschaft – For internal use only – All rights reserved
I IA AS Copyright (C) Siemens AG 2012 All Rights Reserved.

Methodenbeschreibung / Method Description Programming guideline for C/C++ A5E00785463A

6.31 Forward declaration


CPP078 Forward declaration and the declaration itself
 Security  Style  common rule old/new code

Rule Forward declaration is allowed


Annotation Forward declaration can reduce build time dramatically.
Example class CBaseMsg; // forward declarations
class CCallMsg;
class CAlternateMsg
{
protected:
virtual void Init(CAlternateMsg &Alt2); //do stuff
here
virtual void Init(CBaseMsg &Base2); //delegate to
CBaseMsg
virtual void Init(CCallMsg &Call2); //delegate to
CCallMsg
...
};

6.32 BOOL type


CPP079 BOOL vs bool
 Security  Style  common rule old/new code
Rule C++-type "bool" against the C-Define "BOOL" should be preferred. The
type "bool" has defined the conditions "false" and "true”.

Version Status Valid from Page


003 released 01.10.2012 52 of 52
Copyright © 2011 Siemens Aktiengesellschaft – For internal use only – All rights reserved
I IA AS Copyright (C) Siemens AG 2012 All Rights Reserved.

Methodenbeschreibung / Method Description Programming guideline for C/C++ A5E00785463A

6.33 Printf, scanf and streams


CPP080 Use streams instead of printf and scanf
 Security  Style  common rule old/new code

Rule Use streams instead of printf and scanf.


Risk Printf and scanf are very likely producing memory overflow.
Annotation Using streams instead of stdio functions has some advantages (e. g.
compiler checking and extensibility).

6.34 std:: prefix


CPP081 Use std:: namespace prefix where applicable
 Security  Style  common rule old/new code

Rule Use everything from the standard library with its std:: namespace prefix
Annotation Do not pull the whole standard library into the global namespace.

Version Status Valid from Page


003 released 01.10.2012 53 of 53
Copyright © 2011 Siemens Aktiengesellschaft – For internal use only – All rights reserved
I IA AS Copyright (C) Siemens AG 2012 All Rights Reserved.

Methodenbeschreibung / Method Description Programming guideline for C/C++ A5E00785463A

Version Status Valid from Page


003 released 01.10.2012 54 of 54
Copyright © 2011 Siemens Aktiengesellschaft – For internal use only – All rights reserved
I IA AS Copyright (C) Siemens AG 2012 All Rights Reserved.

Methodenbeschreibung / Method Description Programming guideline for C/C++ A5E00785463A

6.35 Null terminated strings


CPP084 Guarantee that storage for character arrays has sufficient
space for character data and the null terminator (STR31-C,
STR35-C, ENV01-CPP)
 Security  Style  common rule old/new code

Rule Guarantee that storage for character arrays has sufficient space for
character data and the null terminator. Otherwise this will result in
memory leaks and crashes and is a high risk for attacks.
Prefer string classes, that take care of allocation issues.
In conclusion do not copy data from an unbounded source to a fixed-
length array and do not make assumptions about the size of an
environment variable.
The function gets() delivers character arrays of unknown length at
compile time. Prevent its usage or use it wisely.
Risk Format string attack, denial of service, information leakage, leakage of
confidential data, arbitrary code execution, abnormal program termination,
bypassing authorization mechanisms
Example Wrong example:

int main(int argc, char *argv[]) {


/* ... */
char ProgName[128];
strcpy(ProgName, argv[0]);
/* ... */
}

Correct:
int main(int argc, char *argv[]) {
/* ... */
char *pProgName = new char[strlen(argv[0])+1];
strcpy(pProgName, argv[0]);
/* ... */
}

Remember to add a byte to accommodate the null-terminated byte string


and to delete prog_name or use a string class.

Version Status Valid from Page


003 released 01.10.2012 55 of 55
Copyright © 2011 Siemens Aktiengesellschaft – For internal use only – All rights reserved
I IA AS Copyright (C) Siemens AG 2012 All Rights Reserved.

Methodenbeschreibung / Method Description Programming guideline for C/C++ A5E00785463A

CPP085 Null termination of (byte) strings (STR03-C, STR32-C)


 Security  Style  common rule old/new code

Rule Ensure correct null termination of (byte) strings. Do not


inadvertently truncate a null-terminated byte string.
Risk Leakage of confidential data, arbitrary code execution, abnormal
program termination, undefined behavior, buffer overflow, denial of
service, information leakage
Annotations A lot of string handling functions such as strcpy() or strlen()
require null-terminated byte strings (NTBS) which must contain a
null character at or before the address of the last element of the
character array. The length of a string is assumed to be the
number of characters before the first null character. String handling
functions will read characters until a null byte is found. If the
provided byte string is not null-terminated, these functions will read
beyond the allocated memory which might lead to buffer overflows,
information leakage, or undefined behavior. Printing a string which
is not correctly terminated by a null character may disclose the
content of adjacent memory.
There are several reasons for missing null terminators. For
example, the null terminator may be truncated during the
initialization of a string variable with a string literal if the string literal
is too long. The null terminator may also be removed
unintentionally when manipulating individual characters in the
array. The functions strncpy() and strncat() copy a specified
number of characters n from a source string to a destination array.
If there is no null character in the first n characters of the source
array, the result will not be null-terminated and any remaining
characters are truncated.
The incorrect usage of strlen() and sizeof() may result in
bugs, in particular off-by-one errors. strlen() does not count the
terminating null character. The value returned by strlen() has to
be incremented by 1 in order to determine the minimum array size
to store the string. On the other hand, sizeof() returns the size
of a fixed-length character array which may store null-terminated
strings with a maximum length of sizeof()-1. Note that
sizeof() does not return the array size but the size of the pointer
if applied to a pointer to a character array.
Consider using String classes where applicable and possible.
Example Wrong examples:

char a[8] = "12345678"; // One byte missing for “\0”

or:
strncpy() does not write any null terminator into the target string unless
it is contained in copied input characters. In the following example, this
may result in parts of the memory being printed out until a null byte is
found:

void my_function(char *arg)


{

Version Status Valid from Page


003 released 01.10.2012 56 of 56
Copyright © 2011 Siemens Aktiengesellschaft – For internal use only – All rights reserved
I IA AS Copyright (C) Siemens AG 2012 All Rights Reserved.

Methodenbeschreibung / Method Description Programming guideline for C/C++ A5E00785463A

char buffer[20];
strncpy(buffer, arg, sizeof(buffer));
printf("Input: %s", buffer);
}

Correct:

void my_function (char *arg)


{
char buffer[20];

strncpy(buffer, arg, sizeof(buffer) - 1);


buffer[sizeof(buffer) - 1] = ?\0?;

printf("Input: %s", buffer);


}

Here a null byte is added to the end of the byte string to ensure that it can
be handled correctly by standard C functions.

6.36 Formatted Output

Version Status Valid from Page


003 released 01.10.2012 57 of 56
Copyright © 2011 Siemens Aktiengesellschaft – For internal use only – All rights reserved
I IA AS Copyright (C) Siemens AG 2012 All Rights Reserved.

Methodenbeschreibung / Method Description Programming guideline for C/C++ A5E00785463A

CPP086 Always define format string parameters and ensure that they
do not contain user input (FIO00-C, FIO30-C)
 Security  Style  common rule old/new code

Rule Always define format string parameters and ensure that they do not
contain user input.
Risk Format string attack, denial of service, information leakage, leakage of
confidential data, arbitrary code execution, abnormal program termination,
bypassing authorization mechanisms
Annotation Format strings that are not explicit or contain user input can be abused to
read or write to arbitrary memory locations. Providing a specially crafted
format string, this can be exploited by an attacker to read sensitive
information, to make the application crash, or to run arbitrary code on the
system with the permissions of the vulnerable process. For example, the
attacker can write an integer value to a specified address using the %n
conversion specifier.
The following rules must be satisfied when using commands which
interpret format strings:
• Always supply a format string parameter if using functions that
support format strings e.g. printf(), fprintf(), sprintf(), snprintf(),
vfprintf(), vprintf(), vsprintf(), vsnprintf(), syslog(), scanf(), fscanf(),
sscanf().
• Ensure that format strings do not contain user input, e.g. by using
string literals as format strings in the functions listed above.
• Make sure that the conversion specifiers in the format string are
correct and match the arguments provided.
Note that sources of user input include configuration files which, for
example, might contain format strings for software localization.
The conversion specifier %n is disabled in the current MS libraries and
leads to a runtime error. The security-enhanced _s alternatives
printf_s() and scanf_s() validate the format string and exit with a
runtime error if the string contains unknown conversion specifiers. These
functions do not prevent vulnerabilities caused by format strings
containing user input or format strings whose conversion specifiers do not
match the arguments provided.
Current versions of the GNU C compiler perform format string checks at
compile time and issue warnings if the conversion specifiers do not match
the arguments. These checks, however, are restricted to those cases
where the format string parameter is a string literal. If the format string is
provided as a string variable, no checks are performed.
Example Wrong example:

void my_function(char *input)


{
printf(input);
}

Correct:
void my_function(char *input)
{
printf("%s", input);
}

Version Status Valid from Page


003 released 01.10.2012 58 of 58
Copyright © 2011 Siemens Aktiengesellschaft – For internal use only – All rights reserved
I IA AS Copyright (C) Siemens AG 2012 All Rights Reserved.

Methodenbeschreibung / Method Description Programming guideline for C/C++ A5E00785463A

Alternatively, printf() can be replaced by fputs() (puts() differs from printf()


as it appends a newline character):

void my_function(char *input)


{
fputs(input, stdout);
}

Version Status Valid from Page


003 released 01.10.2012 59 of 58
Copyright © 2011 Siemens Aktiengesellschaft – For internal use only – All rights reserved
I IA AS Copyright (C) Siemens AG 2012 All Rights Reserved.

Methodenbeschreibung / Method Description Programming guideline for C/C++ A5E00785463A

6.37 Checking boundaries


CPP087 Ensure that array boundaries are not exceeded (ARR00-C,
ARR30-C, ARR32-C, ARR33-C, INT30-C, INT32-C)
 Security  Style  common rule old/new code

Rule Do not form or use out of bounds pointers or array subscripts.


Ensure size arguments for variable length arrays are in a valid
range.
Guarantee that copies are made into storage of sufficient size.
Ensure that unsigned integer operations do not wrap.
Ensure that operations on signed integers do not result in overflow.
Risk Format string attack, denial of service, information leakage, leakage of
confidential data, arbitrary code execution, abnormal program termination,
bypassing authorization mechanisms
Annotation Copying data into an array that is not large enough to hold that data
results in a buffer overflow. This may give an attacker the possibility to
read data from memory or inject his own (malicious) code.
Potentially exploitable undefined behavior can result from any of the
following:
• Incorrect pointer arithmetic so that the resulting pointer does not
point into or just past the end of an object in memory.
• Using such pointers in arithmetic expressions.
• Dereferencing pointers that do not point to a valid object in the
memory.
• Using an array subscript so that the resulting reference does not
refer to an element in the array.
The above threats concern all kinds of arrays, whether they are of fixed-
length, of variable length, or dynamically allocated in the heap memory.
Integer overflows may lead to array handling errors if an inappropriate
integer type is used for an index variable. For example, negative index
values may occur when iterating over the elements in an array using an
index variable of a signed integer type.
Data copied to the destination array must be restricted based on the size
of the destination array or, preferably, the destination array must be
guaranteed to be large enough to hold the data to be copied. If available,
use the _s alternatives of memcpy() and memmove(). memcpy_s() and
memmove_s() require an additional parameter which indicates the length
of the target buffer. These alternatives are MS-specific.
Checks for the occurrence of out-of-bounds array subscripts and pointers
need to be implemented, for example when iterating over the elements of
an array in a loop.

6.38 Passing parameters to subsystems

Version Status Valid from Page


003 released 01.10.2012 60 of 60
Copyright © 2011 Siemens Aktiengesellschaft – For internal use only – All rights reserved
I IA AS Copyright (C) Siemens AG 2012 All Rights Reserved.

Methodenbeschreibung / Method Description Programming guideline for C/C++ A5E00785463A

CPP088 Sanitize data passed to complex subsystems (STR02-C,


ENV03-C, ENV04-C,CA2100)
 Security  Style  common rule old/new code

Rule Sanitize data passed to complex subsystems, i. e. check these


parameters or data thoroughly. Review SQL strings for security
vulnerabilities, especially dynamic SQL strings.
Risk Command injection, SQL injection, information leakage, arbitrary code
execution, data tampering, leakage of confidential data, access to critical
resources via SQL-integrated OS commands, bypassing authorization
mechanisms, database inconsistencies and destruction of data
Annotation String data passed to complex subsystems (e.g. external programs,
relational databases, command processor via a call to system() or
similar function) may contain special characters that can trigger
commands or actions resulting in a software vulnerability. Therefore, it
must be guaranteed that all string data passed to complex subsystems is
innocuous in the context in which it will be interpreted. If user input is
included, the string data must be sanitized. Failure to sanitize data
passed to a complex subsystem can lead to an injection attack, data
integrity issues, and leakage of sensitive data.
Command interpreters provide functionality in addition to executing a
simple command. If this functionality is not required, it is a good idea not
to use system() or any other function that invokes a command
interpreter because doing so significantly complicates the command string
sanitization. As an alternative, a function of the exec() family should be
used. These functions do not use a full shell interpreter and therefore are
not vulnerable to command injection attacks.
All programs, particularly those running with higher privileges than the
caller (such as those with setuid/setgid flags), should treat their
environment as untrusted user input. Since the environment is inherited
by processes spawned by calls to fork(), system(), or exec(), it is
important to verify that the environment does not contain any values that
can lead to unexpected behavior. Therefore, it is recommended to clear
the environment and fill it with trusted or default values. The functions
execle(), execlpe(), execve(), and execvpe() can be used for
this purpose as they allow the environment to be explicitly specified.
Programs running with higher privileges than the caller (e.g. with setuid
and setgid flags) shall drop unnecessary privileges before calling an
external program.
The functions execlp(), execlpe(), execvp(), and execvpe()
evaluate the PATH environment variable of the parent process to find the
external program. Therefore, calls to these functions are vulnerable to
attacks that change the PATH variable.
To be successful, data sanitization requires an understanding of the data
being passed and the capabilities of the underlying subsystem. String
data passed to complex subsystems can be sanitized with a filter which
removes, substitutes, or escapes special characters not included in a
white list.
When interacting with an SQL database, use prepared statements (also
known as parameterized queries) with embedded parameters to mitigate
malicious user inputs. Prepared statements allow preparing a database
operation using placeholders instead of parameter values. The parameter
values are provided later and checked by the database for validity before
being processed. This ensures that the input values are treated as literal
values and not as executable code in the database. Hence, prepared

Version Status Valid from Page


003 released 01.10.2012 61 of 61
Copyright © 2011 Siemens Aktiengesellschaft – For internal use only – All rights reserved
I IA AS Copyright (C) Siemens AG 2012 All Rights Reserved.

Methodenbeschreibung / Method Description Programming guideline for C/C++ A5E00785463A

statements effectively prevent SQL injections and shall always be used


for security as well as performance reasons. Make sure that user input is
restricted to parameters; it must not be included in the static part of the
prepared statement. Otherwise, the protection can be easily
circumvented.
If you call stored procedures with user input, make sure that your code
uses parameterized stored procedures in order to prevent SQL injection
attacks.

6.39 References, pointers with private members

Version Status Valid from Page


003 released 01.10.2012 62 of 61
Copyright © 2011 Siemens Aktiengesellschaft – For internal use only – All rights reserved
I IA AS Copyright (C) Siemens AG 2012 All Rights Reserved.

Methodenbeschreibung / Method Description Programming guideline for C/C++ A5E00785463A

CPP089 Do not return references nor pointers to private data (OOP35-


CPP)
 Security  Style  common rule old/new code

Rule Do not return references nor pointers to private data


Risk Broken encapsulation, race conditions
Annotation Class methods returning non-constant references or pointers to
private data members can lead to data tampering by untrusted
code. Hostile external code can use these references to modify the
contents of private data. If the returned reference or pointer refers
to a private object, it is even possible to invoke methods of this
object. Returning constant references or pointers to private data
members prevents modification but still provides reading access.
All in all, the private property is fully or partially removed when
returning references or pointers to private data.
The preferable solution is to return a copy of the private data,
which ensures that there is no external read and write access. Only
if external read access to the private data is acceptable, returning a
constant reference or pointer can be considered as a secondary
option.
Example Wrong example:

class Example {
public:
Example() : myString("hello") {}
~Example() {}

std::string& getString()
{
return myString;
}

private:
std::string myString;
};

int _tmain(int argc, _TCHAR* argv[])


{
Example e;
e.getS().assign("bye");
return 0;
}

Correct:
std::string getString()
{
return myString;
}

std::string const & getString()


{
return myString;
}

Version Status Valid from Page


003 released 01.10.2012 63 of 63
Copyright © 2011 Siemens Aktiengesellschaft – For internal use only – All rights reserved
I IA AS Copyright (C) Siemens AG 2012 All Rights Reserved.

Methodenbeschreibung / Method Description Programming guideline for C/C++ A5E00785463A

In this case, e.getS().assign("bye") in tmain()affects the string


copy only.
If read access to the private data is acceptable, a constant reference may
be returned, which avoids the copy operation. Calling
e.getS().assign("bye") in tmain() will result in a compiler error.

6.40 Utilizing std::string

Version Status Valid from Page


003 released 01.10.2012 64 of 63
Copyright © 2011 Siemens Aktiengesellschaft – For internal use only – All rights reserved
I IA AS Copyright (C) Siemens AG 2012 All Rights Reserved.

Methodenbeschreibung / Method Description Programming guideline for C/C++ A5E00785463A

CPP090 Use at() when accessing characters in strings and c_str() for
conversion to null-terminated C-strings (STR33-CPP, STR39-
CPP)
 Security  Style  common rule old/new code

Rule Use at() when accessing characters in strings and c_str() for
conversion to null-terminated C-strings. Do not access invalid output of
c_str() or data() and check the range of the access.
Risk Denial of service, buffer overflow, arbitrary code execution, abnormal
program termination
Annotation std::string is the standard C++ class for strings. As this class
provides boundary checking for string operations, its usage is generally
preferable over operations on C-strings based on char arrays. However,
there is one exception: if the operator[] is used to read or write
individual characters, no boundary check is performed for the provided
character position. As a result, a buffer overflow may occur.
In C++ programs, it is often necessary to convert a std::string object
into a pointer to an array of char. The std::string class offers two
methods for this purpose: data() and c_str(). data() returns a
char* pointer to the internal character array. Since this method does not
ensure that the last character is followed by a null character, the returned
pointer does not necessarily refer to a null-terminated C-string. Hence, if
the pointer is used as a pointer to a C-string (e.g. passed to C string
handling functions), buffer overflows may occur.
Remember to use always the namespace std:: to access any element
of the standard namespace.
The method at() behaves like the operator[], except that at()
performs a range check, throwing an exception of type out_of_range in
case that the given character position is not an actual position in the
string. Hence, at()must be used instead the operator[] unless there
are good reasons why a boundary check is not required. Make sure that a
proper exception handling is in place.
If a std::string object needs to be converted into a null-terminated C-
string, use the method c_str(), not data(). c_str() returns a
constant pointer to a character array which is null-terminated. Note that
the returned pointer is no longer valid after invoking any non-constant
method of the original string object.

Example Wrong example:

In this example, both insecure functions are used. If the input read by cin
has zero length, input[1] accesses an out-of-bounds array element
and possibly causes a program termination. Thereafter, strlen() is
applied to the non null-terminated character array returned by data(),
which results in an undefined program behaviour:
string input;
cin >> input;
cout << "2nd item: " << input[1] << endl;
int i = atoi(input.data());

Correct:
string input;
cin >> input;
try
{
Version Status Valid from Page
003 released 01.10.2012 65 of 65
Copyright © 2011 Siemens Aktiengesellschaft – For internal use only – All rights reserved
I IA AS Copyright (C) Siemens AG 2012 All Rights Reserved.

Methodenbeschreibung / Method Description Programming guideline for C/C++ A5E00785463A

cout << "2nd item: " << input.at(1) << endl;


}
catch (out_of_range e)
{
cerr << e.what() << endl;
}
int i = atoi(input.c_str());

Version Status Valid from Page


003 released 01.10.2012 66 of 65
Copyright © 2011 Siemens Aktiengesellschaft – For internal use only – All rights reserved
I IA AS Copyright (C) Siemens AG 2012 All Rights Reserved.

Methodenbeschreibung / Method Description Programming guideline for C/C++ A5E00785463A

7 List of security relevant rules


CPP012 Use explicit type conversion (API09-C)
 Security  Style  common rule old/new code

CPP013 Avoid casting on const variables (DCL00-C)


 Security  Style  common rule old/new code

CPP037 Accessing private properties or members (OOPP00-CPP)


 Security  Style  common rule old/new code

CPP038 Do not use RTTI (OOP34-CPP)


 Security  Style  common rule old/new code

CPP039 Class member variables (OOPP00-CPP)


 Security  Style  common rule old/new code

CPP048 Switch commands based on enums (ERR04-C)


 Security  Style  common rule old/new code

CPP049 Function parameter check (MSC08-CPP)


 Security  Style  common rule old/new code

CPP055 Goto statements (MSC35-CPP)


 Security  Style  common rule old/new code

CPP056 Avoid uninitialized pointers


 Security  Style  common rule old/new code

CPP057 Deleting “this” pointer (OOP05-CPP)


 Security  Style  common rule old/new code

CPP058 Set pointer value after deletion


 Security  Style  common rule old/new code

CPP059 Accessing pointers and handles ( EXP34-C/CPP)


 Security  Style  common rule old/new code
CPP060 Division by “0” (FLP06-C)
 Security  Style  common rule old/new code

CPP061 Testing possible overflows (INT08-C, INT30-C, INT32-C)


 Security  Style  common rule old/new code

CPP066 Initialize variables


 Security  Style  common rule old/new code

CPP068 Smartpointers with dynamic fields


 Security  Style  common rule old/new code

CPP069 Do not perform zero length allocations (MEM04-C, MEM35-C,


INT31-C, INT32-C, INT35-C)
 Security  Style  common rule old/new code
CPP070 Avoid excessive stack allocations
 Security  Style  common rule old/new code
CPP071 Allocate and free memory in the same module
 Security  Style  common rule old/new code

Version Status Valid from Page


003 released 01.10.2012 67 of 67
Copyright © 2011 Siemens Aktiengesellschaft – For internal use only – All rights reserved
I IA AS Copyright (C) Siemens AG 2012 All Rights Reserved.

Methodenbeschreibung / Method Description Programming guideline for C/C++ A5E00785463A

CPP072 Do not assume having large heap space/stack available


 Security  Style  common rule old/new code
CPP073 Return value of operator new()
 Security  Style  common rule old/new code
CPP074 No exceptions in general ( ERR33-C, ERR07-CPP, ERR33-CPP,
ERR30-CPP)
 Security  Style  common rule old/new code

CPP080 Use streams instead of printf and scanf


 Security  Style  common rule old/new code

CPP083 Do not modify the string returned by getenv() (ENV01-CPP,


ENV03-C)
 Security  Style  common rule old/new code

CPP084 Guarantee that storage for character arrays has sufficient


space for character data and the null terminator (STR31-C,
STR35-C, ENV01-CPP)
 Security  Style  common rule old/new code

CPP085 Null termination of (byte) strings (STR03-C, STR32-C)


 Security  Style  common rule old/new code

CPP086 Always define format string parameters and ensure that they
do not contain user input (FIO00-C, FIO30-C)
 Security  Style  common rule old/new code

CPP087 Ensure that array boundaries are not exceeded (ARR00-C,


ARR30-C, ARR32-C, ARR33-C, INT30-C, INT32-C)
 Security  Style  common rule old/new code

CPP088 Sanitize data passed to complex subsystems (STR02-C,


ENV03-C, ENV04-C,CA2100)
 Security  Style  common rule old/new code

CPP089 Do not return references nor pointers to private data (OOP35-


CPP)
 Security  Style  common rule old/new code

CPP090 Use at() when accessing characters in strings and c_str() for
conversion to null-terminated C-strings (STR33-CPP, STR39-
CPP)
 Security  Style  common rule old/new code

Version Status Valid from Page


003 released 01.10.2012 68 of 68
Copyright © 2011 Siemens Aktiengesellschaft – For internal use only – All rights reserved
I IA AS Copyright (C) Siemens AG 2012 All Rights Reserved.

Methodenbeschreibung / Method Description Programming guideline for C/C++ A5E00785463A

Version Status Valid from Page


003 released 01.10.2012 69 of 69
Copyright © 2011 Siemens Aktiengesellschaft – For internal use only – All rights reserved
I IA AS Copyright (C) Siemens AG 2012 All Rights Reserved.

Methodenbeschreibung / Method Description Programming guideline for C/C++ A5E00785463A

8 Appendix

8.1 Change Log


Version Date Author Status Comment
V 0.12 23.03.2011 mrboess baseline
V 0.13 02.05.2011 Mrboess Baseline
V 0.14 06.06.2011 Mrboess Baseline
V 0.15 20.07.2011 mrboess baseline Review
comments and
SWAT
decisions
V1.00 11.08.2011 Mrboess release Prepare
release
V1.01 19.08.2011 Nitzsche release Rework /
Clarification
V1.02 10.10.2011 Mrboess release Chapter PVSS
guidelines
added
V1.03 21.12.2011 Mrboess release CERT Review
Update
V1.10 20.08.2012 Nitzsche / release Prepare for I IA
Riedl AS rollout
V1.11 28.09.2012 Nitzsche release Prepare for I IA
AS rollout

8.2 Authors
Name Role Department Location Tel. Comment
mrboess Development RTIL ETM- 62681
Eisenstadt

8.3 Release
Name Role Release Department Location Tel. Comment
Date

Version Status Valid from Page


003 released 01.10.2012 70 of 70
Copyright © 2011 Siemens Aktiengesellschaft – For internal use only – All rights reserved
I IA AS Copyright (C) Siemens AG 2012 All Rights Reserved.

Methodenbeschreibung / Method Description Programming guideline for C/C++ A5E00785463A

8.4 Glossary
PascalCasing casing format
OS Operating System
RTTI Runtime Type Information
RTIL Runtime Innovation Line
SWAT Software architecture team
HMI Human-machine interface
PL Project manager (Projektleiter)
TPL Subproject manager (Teilprojektleiter)
CM Configuration management
RAII Resource Acquisition Is Initialization – a method to put functions,
which have to grab system resources, into class concepts.

Version Status Valid from Page


003 released 01.10.2012 71 of 71
Copyright © 2011 Siemens Aktiengesellschaft – For internal use only – All rights reserved

S-ar putea să vă placă și