Start here

Home
About Klocwork
What's new
Fixed issues
Release notes
Installation

Reference

C/C++ checkers
Java checkers
C# checkers
MISRA C 2004 checkers
MISRA C++ 2008 checkers
MISRA C 2012 checkers
MISRA C 2012 checkers with Amendment 1
Commands
Metrics
Troubleshooting
Reference

Product components

C/C++ Integration build analysis
Java Integration build analysis
Desktop analysis
Refactoring
Klocwork Static Code Analysis
Klocwork Code Review
Structure101
Tuning
Custom checkers

Coding environments

Visual Studio
Eclipse for C/C++
Eclipse for Java
IntelliJ IDEA
Other

Administration

Project configuration
Build configuration
Administration
Analysis performance
Server performance
Security/permissions
Licensing
Klocwork Static Code Analysis Web API
Klocwork Code Review Web API

Community

View help online
Visit RogueWave.com
Klocwork Support
Rogue Wave Videos

Legal

Legal information

PORTING.BSWAP.MACRO

Use of a custom byte-swap macro without endianness check

The PORTING checkers identify code that might rely on specific implementation details in different compilers. The PORTING.BSWAP.MACRO checker detects situations in which a custom byte-swap macro is used without checking endianness. To cause the PORTING.BSWAP.MACRO checker to flag the code as a byte-swap macro, the macro definition must include a shift operator and the bits to shift, which can be:

  • left-shift (<<) or right-shift (>>) operators
  • bitwise and (&) or bitwise or (|) operators
  • integer literals that are multiples of 8
  • byte masks, such as 0xFF or 0xFF00

If the byte-swap macro isn't protected by an endian-guarding macro, Klocwork reports the issue.

Vulnerability and risk

Typical byte-swap macros assume the layout of the integral type in which they're moving data, for example by swapping the MSB with the LSB. In an environment where the endian nature of the underlying chip is potentially different at different times, such as between builds, such operations can be unsafe, especially if the integral type being transformed is read from persistent storage or another hardware environment.

Mitigation and prevention

As with any endian-vulnerable operation, guard the macro definitions with BIG_ENDIAN or LITTLE_ENDIAN guard macros, so that you can be sure that the transformation being performed is appropriate for the environment used.

Vulnerable code example

// Pretty normal byte swapping macro, changes unsigned integers from one type of endian to another
1   #define SWAPBYTES(x) ( ((x) & 0xff) << 24 ) | ( (((x) >> 8) & 0xff) << 16 ) | ( (((x) >> 16) & 0xff) << 8 ) | ( (((x) >> 24) & 0xff) )

In this example, tthe definition of the macro is specific to a particular endian architecture, but the definition isn't guarded as such, and could be inappropriately compiled into a build intended for the opposite architecture.

Fixed code example

// Now the definition is endian-guarded
1   #if BIG_ENDIAN
2   #define SWAPBYTES(x) ( ((x) & 0xff) << 24 ) | ( (((x) >> 8) & 0xff) << 16 ) | ( (((x) >> 16) & 0xff) << 8 ) | ( (((x) >> 24) & 0xff) )
3   #else
4   #define SWAPBYTES(x) ( x )
5   #endif

In the fixed example, the macro definition is guarded with the appropriate endian guard, and an alternative can be defined for the opposite architecture.

Related checkers