SlideShare a Scribd company logo
Static Code Analysis for Projects,
Built on Unreal Engine
Ilya Gainulin
PVS-Studio
gainulin@viva64.com
I Am Looking for Errors in Your Code
2
Results of Incorrect Type Casing
in the ShareX Project
3
Results of Incorrect Type Casing
in the ShareX Project
Incorrect code:
float pixelWeight = color.Alpha / 255;
Fixed code:
float pixelWeight = (float)color.Alpha / 255;
4
type Byte
Collaboration with Epic Games
5
What Is Static Analysis?
Static analysis is a way to check a program’s code without executing the
program.
6
Why Do You Need Static Analysis?
• Detect errors early in the program development process.
• Get recommendations on code formatting.
• Check your spelling.
• Calculate various software metrics
7
Cost to Fix a Bug
Fix earlier,
save money!
8
Why Do You Need Static Analysis?
• Detect errors early in the program development process.
• Get recommendations on code formatting.
• Check your spelling.
• Calculate various software metrics
9
Static Analysis Advantages?
• Detecting potential problems in code early
• Full code coverage
• Easy to use
10
Static Analysis Advantages
11
Static Analysis Advantages
12
Static Analysis Advantages
13
Mono
V3012 The '?:' operator, regardless of its conditional expression, always
returns one and the same value: Color.FromArgb (150, 179, 225).
ProfessionalColorTable.cs 258
Static Analysis Disadvantages
• Unavoidable false positives
• Static analysis is usually not as good at detecting
memory leaks and parallel errors
14
Static Analysis Disadvantages
void OutstandingIssue(const char *strCount)
{
unsigned nCount;
sscanf_s(strCount, "%u", &nCount);
int array[10];
memset(array, 0, nCount * sizeof(int));
}
15
Static Analyzers Are Not Isolated Tools and Rare
Checks – They Are a Part of DevOps
16
Написание кода Компиляция Unit тесты
Интеграционные
тесты
Развёртывание
Планирование
Commit кода
Static Analyzers Are Not Isolated Tools and Rare
Checks – They Are a Part of DevOps
17
Написание кода Компиляция
Полный статический
анализ на билд
сервере
Unit тесты
Интеграционные
тесты
Развёртывание
Планирование
Commit кода
Static Analyzers Are Not Isolated Tools and Rare
Checks – They Are a Part of DevOps
18
Static Analyzers Are Not Isolated Tools and Rare
Checks – They Are a Part of DevOps
Написание кода Компиляция
Полный статический
анализ на билд
сервере
Unit тесты
Интеграционные
тесты
Развёртывание
Планирование
Инкрементальный
статический анализ
на машине
разработчика
Commit кода
19
Incremental Analysis
• A decrease in analysis time, because only fixed or new code is
processed.
• Works well for early error detection.
20
Ways to Use Static Analysis in a UE Project
• Tracking compiler runs.
• Direct integration with the build system.
21
22
Invoking CL.exe
compiler
MSBuild
Unreal Build
Tool
Building Unreal Engine
projects
Build finished
Gathering
information
The Simplest Way to Check a UE Project: Catch All Compiler Calls
Tracking Compiler Runs from a GUI Application
23
Tracking Compiler Runs from a GUI Application
24
Tracking Compiler Runs from a GUI Application
25
Direct Integration into Build System and VS
• Run analysis directly from the Visual Studio IDE.
• Run the analysis automatically when building a UE project.
• Run incremental analysis.
26
Common assembly scenario of a C++ project in VS
27
Common assembly scenario of a C++ project in VS
28
Particularities of Building a UE Project
• Instead of Visual Studio’s standard build system, the UnrealBuildTool
(UBT) is used.
• Project files have the .uproject extension.
29
Particularities of Building a UE Project
30
What’s the Problem?
• The project file may not contain paths to source files that need to be
checked.
• Not all compilation options required for correct preprocessing are
present.
31
What’s the Solution?
• Write your own toolchain for the build system, so as to embed the
static analyzer launch into UBT.
• Pass a parameter to the UBT build system. That parameter would
demonstrate the need for analysis.
32
What’s the Solution?
33
Some of the Current toolchain’s Limitations
• Only builds a project or only analyzes the project.
• No .cpp file analysis, if an included .h file has been changed.
34
The Project Analysis After Its Build
• Modifying the Build.bat and Rebuild.bat scripts.
35
The Project Analysis After Its Build
36
The Project Analysis After Its Build
37
The .cpp File Analysis in Scenarios with the
Connected Modified .h File
• Remove and restore the cache file UBT uses.
38
The .cpp File Analysis in Scenarios with the
Connected Modified .h File
39
Errors in Unreal Engine Code
static bool PositionIsInside(....)
{
return
Position.X >= Control.Center.X - BoxSize.X * 0.5f &&
Position.X <= Control.Center.X + BoxSize.X * 0.5f &&
Position.Y >= Control.Center.Y - BoxSize.Y * 0.5f &&
Position.Y >= Control.Center.Y - BoxSize.Y * 0.5f;
}
40
Errors in Unreal Engine Code
static bool PositionIsInside(....)
{
return
Position.X >= Control.Center.X - BoxSize.X * 0.5f &&
Position.X <= Control.Center.X + BoxSize.X * 0.5f &&
Position.Y >= Control.Center.Y - BoxSize.Y * 0.5f &&
Position.Y >= Control.Center.Y - BoxSize.Y * 0.5f;
}
PVS-Studio warns: V501 There are identical sub-expressions 'Position.Y >=
Control.Center.Y — BoxSize.Y * 0.5f' to the left and to the right of the '&&'
operator. svirtualjoystick.cpp 97
41
Errors in Unreal Engine Code
static bool PositionIsInside(....)
{
return
Position.X >= Control.Center.X - BoxSize.X * 0.5f &&
Position.X <= Control.Center.X + BoxSize.X * 0.5f &&
Position.Y >= Control.Center.Y - BoxSize.Y * 0.5f &&
Position.Y >= Control.Center.Y - BoxSize.Y * 0.5f;
Position.Y <= Control.Center.Y + BoxSize.Y * 0.5f;
}
PVS-Studio warns: V501 There are identical sub-expressions 'Position.Y >=
Control.Center.Y — BoxSize.Y * 0.5f' to the left and to the right of the '&&'
operator. svirtualjoystick.cpp 97
42
enum ECubeFace;
ECubeFace CubeFace;
friend FArchive& operator<<(FArchive& Ar, FResolveParams&
ResolveParams)
{
....
if(Ar.IsLoading())
{
ResolveParams.CubeFace = (ECubeFace)ResolveParams.CubeFace;
}
....
}
43
enum ECubeFace;
ECubeFace CubeFace;
friend FArchive& operator<<(FArchive& Ar, FResolveParams&
ResolveParams)
{
....
if(Ar.IsLoading())
{
ResolveParams.CubeFace = (ECubeFace)ResolveParams.CubeFace;
}
....
}
PVS-Studio warns: V570 The 'ResolveParams.CubeFace' variable is assigned to itself.
rhi.h 1279
44
bool VertInfluencedByActiveBone(
FParticleEmitterInstance* Owner, USkeletalMeshComponent* InSkelMeshComponent,
int32 InVertexIndex, int32* OutBoneIndex = NULL);
void UParticleModuleLocationSkelVertSurface::Spawn(....)
{
int32 BoneIndex1, BoneIndex2, BoneIndex3;
BoneIndex1 = BoneIndex2 = BoneIndex3 = INDEX_NONE;
if(!VertInfluencedByActiveBone(
Owner, SourceComponent, VertIndex[0], &BoneIndex1) &&
!VertInfluencedByActiveBone(
Owner, SourceComponent, VertIndex[1], &BoneIndex2) &&
!VertInfluencedByActiveBone(
Owner, SourceComponent, VertIndex[2]) &BoneIndex3)
{
....
}
45
bool VertInfluencedByActiveBone(
FParticleEmitterInstance* Owner, USkeletalMeshComponent* InSkelMeshComponent,
int32 InVertexIndex, int32* OutBoneIndex = NULL);
void UParticleModuleLocationSkelVertSurface::Spawn(....)
{
int32 BoneIndex1, BoneIndex2, BoneIndex3;
BoneIndex1 = BoneIndex2 = BoneIndex3 = INDEX_NONE;
if(!VertInfluencedByActiveBone(
Owner, SourceComponent, VertIndex[0], &BoneIndex1) &&
!VertInfluencedByActiveBone(
Owner, SourceComponent, VertIndex[1], &BoneIndex2) &&
!VertInfluencedByActiveBone(
Owner, SourceComponent, VertIndex[2]) &BoneIndex3)
{
....
}
46
The Analyzer’s Warning About a Sneaky Error
PVS-Studio warns: V564 The '&' operator is applied to bool type value.
You've probably forgotten to include parentheses or intended to use the
'&&' operator. particlemodules_location.cpp 2120
47
void GetRenderData(....)
{
....
FT_Bitmap* Bitmap = nullptr;
if( Slot->bitmap.pixel_mode == FT_PIXEL_MODE_MONO )
{
FT_Bitmap NewBitmap;
....
Bitmap = &NewBitmap;
}
....
OutRenderData.RawPixels.AddUninitialized(
Bitmap->rows * Bitmap->width );
....
}
48
void GetRenderData(....)
{
....
FT_Bitmap* Bitmap = nullptr;
if( Slot->bitmap.pixel_mode == FT_PIXEL_MODE_MONO )
{
FT_Bitmap NewBitmap;
....
Bitmap = &NewBitmap;
}
....
OutRenderData.RawPixels.AddUninitialized(
Bitmap->rows * Bitmap->width );
....
}
49
PVS-Studio: V506 Pointer to local variable
'NewBitmap' is stored outside the scope of this
variable. Such a pointer will become invalid.
fontcache.cpp 466
void UGameplayStatics::DeactivateReverbEffect(....)
{
if (GEngine || !GEngine->UseSound())
{
return;
}
UWorld* ThisWorld = GEngine->GetWorldFromContextObject(....);
....
}
50
void UGameplayStatics::DeactivateReverbEffect(....)
{
if (GEngine || !GEngine->UseSound())
{
return;
}
UWorld* ThisWorld = GEngine->GetWorldFromContextObject(....);
....
}
PVS-Studio: V522 Dereferencing of the null pointer 'GEngine' might take place. Check the
logical condition. gameplaystatics.cpp 988
51
void UGameplayStatics::DeactivateReverbEffect(....)
{
if (GEngine || !GEngine->UseSound())
if (GEngine == nullptr || !GEngine->UseSound())
{
return;
}
UWorld* ThisWorld = GEngine->GetWorldFromContextObject(....);
....
}
PVS-Studio: V522 Dereferencing of the null pointer 'GEngine' might take place. Check the
logical condition. gameplaystatics.cpp 988
52
template< typename DefinitionType >
FORCENOINLINE void Set(....)
{
....
if ( DefinitionPtr == NULL )
{
WidgetStyleValues.Add( PropertyName,
MakeShareable( new DefinitionType( InStyleDefintion ) ) );
}
else
{
WidgetStyleValues.Add( PropertyName,
MakeShareable( new DefinitionType( InStyleDefintion ) ) );
}
}
53
template< typename DefinitionType >
FORCENOINLINE void Set(....)
{
....
if ( DefinitionPtr == NULL )
{
WidgetStyleValues.Add( PropertyName,
MakeShareable( new DefinitionType( InStyleDefintion ) ) );
}
else
{
WidgetStyleValues.Add( PropertyName,
MakeShareable( new DefinitionType( InStyleDefintion ) ) );
}
}
54
PVS-Studio: V523 The 'then' statement is
equivalent to the 'else' statement. paths.cpp
703
Conclusion
• Static analysis of UE projects is not too complicated.
• Combine static analysis with other testing methods.
55
Thank You for Your Attention
56

More Related Content

What's hot

What's hot (20)

「Press Button, Drink Coffee」 UE4における ビルドパイプラインとメンテナンスの全体像
「Press Button, Drink Coffee」 UE4における ビルドパイプラインとメンテナンスの全体像「Press Button, Drink Coffee」 UE4における ビルドパイプラインとメンテナンスの全体像
「Press Button, Drink Coffee」 UE4における ビルドパイプラインとメンテナンスの全体像
 
Nintendo Switch『OCTOPATH TRAVELER』はこうして作られた
Nintendo Switch『OCTOPATH TRAVELER』はこうして作られたNintendo Switch『OCTOPATH TRAVELER』はこうして作られた
Nintendo Switch『OCTOPATH TRAVELER』はこうして作られた
 
UE4×ADX2を使ったゼロから始めるサウンド開発
UE4×ADX2を使ったゼロから始めるサウンド開発UE4×ADX2を使ったゼロから始めるサウンド開発
UE4×ADX2を使ったゼロから始めるサウンド開発
 
Unreal Engine 4を使って地球を衛る方法
Unreal Engine 4を使って地球を衛る方法Unreal Engine 4を使って地球を衛る方法
Unreal Engine 4を使って地球を衛る方法
 
なぜなにFProperty - 対応方法と改善点 -
なぜなにFProperty - 対応方法と改善点 -なぜなにFProperty - 対応方法と改善点 -
なぜなにFProperty - 対応方法と改善点 -
 
[GTMF2019] Python / BlueprintによるUnreal Engineの自動化
[GTMF2019] Python / BlueprintによるUnreal Engineの自動化[GTMF2019] Python / BlueprintによるUnreal Engineの自動化
[GTMF2019] Python / BlueprintによるUnreal Engineの自動化
 
【Unite 2018 Tokyo】『CARAVAN STORIES』のアセットバンドル事例
【Unite 2018 Tokyo】『CARAVAN STORIES』のアセットバンドル事例【Unite 2018 Tokyo】『CARAVAN STORIES』のアセットバンドル事例
【Unite 2018 Tokyo】『CARAVAN STORIES』のアセットバンドル事例
 
UE4のモバイル向け機能や最新情報などを改めて紹介!2019
UE4のモバイル向け機能や最新情報などを改めて紹介!2019UE4のモバイル向け機能や最新情報などを改めて紹介!2019
UE4のモバイル向け機能や最新情報などを改めて紹介!2019
 
【Unite Tokyo 2019】【あら簡単】インテルのGPAを使ってあなたのUnityタイトルを高速化
【Unite Tokyo 2019】【あら簡単】インテルのGPAを使ってあなたのUnityタイトルを高速化【Unite Tokyo 2019】【あら簡単】インテルのGPAを使ってあなたのUnityタイトルを高速化
【Unite Tokyo 2019】【あら簡単】インテルのGPAを使ってあなたのUnityタイトルを高速化
 
ESP32特集の内容紹介
ESP32特集の内容紹介ESP32特集の内容紹介
ESP32特集の内容紹介
 
UE4 Performance and Profiling | Unreal Dev Day Montreal 2017 (日本語訳)
UE4 Performance and Profiling | Unreal Dev Day Montreal 2017 (日本語訳)UE4 Performance and Profiling | Unreal Dev Day Montreal 2017 (日本語訳)
UE4 Performance and Profiling | Unreal Dev Day Montreal 2017 (日本語訳)
 
Unityで始めるバーチャルプロダクション
Unityで始めるバーチャルプロダクションUnityで始めるバーチャルプロダクション
Unityで始めるバーチャルプロダクション
 
猫でも分かる Control Rig UE4.25 版
猫でも分かる Control Rig UE4.25 版猫でも分かる Control Rig UE4.25 版
猫でも分かる Control Rig UE4.25 版
 
ZeroFormatterに見るC#で最速のシリアライザを作成する100億の方法
ZeroFormatterに見るC#で最速のシリアライザを作成する100億の方法ZeroFormatterに見るC#で最速のシリアライザを作成する100億の方法
ZeroFormatterに見るC#で最速のシリアライザを作成する100億の方法
 
UE4のマテリアルを もっと楽しもう!~マテリアルでぐっと広がるリアルタイムCG表現の幅~
UE4のマテリアルを もっと楽しもう!~マテリアルでぐっと広がるリアルタイムCG表現の幅~ UE4のマテリアルを もっと楽しもう!~マテリアルでぐっと広がるリアルタイムCG表現の幅~
UE4のマテリアルを もっと楽しもう!~マテリアルでぐっと広がるリアルタイムCG表現の幅~
 
ローカライズって何?(UE4 Localization Deep Dive)
ローカライズって何?(UE4 Localization Deep Dive)ローカライズって何?(UE4 Localization Deep Dive)
ローカライズって何?(UE4 Localization Deep Dive)
 
UE4とBlenderでランニングコストを抑えるモダンなワークフロー
UE4とBlenderでランニングコストを抑えるモダンなワークフローUE4とBlenderでランニングコストを抑えるモダンなワークフロー
UE4とBlenderでランニングコストを抑えるモダンなワークフロー
 
【Unite Tokyo 2019】SRPで一から描画フローを作ってみた! ~Unity描画フローからの脱却~
【Unite Tokyo 2019】SRPで一から描画フローを作ってみた! ~Unity描画フローからの脱却~【Unite Tokyo 2019】SRPで一から描画フローを作ってみた! ~Unity描画フローからの脱却~
【Unite Tokyo 2019】SRPで一から描画フローを作ってみた! ~Unity描画フローからの脱却~
 
[CEDEC2017] 最新モバイルゲームの実例からみるUE4のモバイル向け機能・Tipsを全部まるっとご紹介!
[CEDEC2017] 最新モバイルゲームの実例からみるUE4のモバイル向け機能・Tipsを全部まるっとご紹介![CEDEC2017] 最新モバイルゲームの実例からみるUE4のモバイル向け機能・Tipsを全部まるっとご紹介!
[CEDEC2017] 最新モバイルゲームの実例からみるUE4のモバイル向け機能・Tipsを全部まるっとご紹介!
 
A frameハンズオン 20170129
A frameハンズオン 20170129A frameハンズオン 20170129
A frameハンズオン 20170129
 

Similar to Static Code Analysis for Projects, Built on Unreal Engine

Embedded c & working with avr studio
Embedded c & working with avr studioEmbedded c & working with avr studio
Embedded c & working with avr studio
Nitesh Singh
 

Similar to Static Code Analysis for Projects, Built on Unreal Engine (20)

Make Your and Other Programmer’s Life Easier with Static Analysis (Unreal Eng...
Make Your and Other Programmer’s Life Easier with Static Analysis (Unreal Eng...Make Your and Other Programmer’s Life Easier with Static Analysis (Unreal Eng...
Make Your and Other Programmer’s Life Easier with Static Analysis (Unreal Eng...
 
Cusomizing Burp Suite - Getting the Most out of Burp Extensions
Cusomizing Burp Suite - Getting the Most out of Burp ExtensionsCusomizing Burp Suite - Getting the Most out of Burp Extensions
Cusomizing Burp Suite - Getting the Most out of Burp Extensions
 
Does static analysis need machine learning?
Does static analysis need machine learning?Does static analysis need machine learning?
Does static analysis need machine learning?
 
Static code analysis: what? how? why?
Static code analysis: what? how? why?Static code analysis: what? how? why?
Static code analysis: what? how? why?
 
PVS-Studio is ready to improve the code of Tizen operating system
PVS-Studio is ready to improve the code of Tizen operating systemPVS-Studio is ready to improve the code of Tizen operating system
PVS-Studio is ready to improve the code of Tizen operating system
 
TestExec SL 7.1
TestExec SL 7.1TestExec SL 7.1
TestExec SL 7.1
 
embedded C.pptx
embedded C.pptxembedded C.pptx
embedded C.pptx
 
Dino2 - the Amazing Evolution of the VA Smalltalk Virtual Machine
Dino2 - the Amazing Evolution of the VA Smalltalk Virtual MachineDino2 - the Amazing Evolution of the VA Smalltalk Virtual Machine
Dino2 - the Amazing Evolution of the VA Smalltalk Virtual Machine
 
IoTSuite User Manual
IoTSuite User ManualIoTSuite User Manual
IoTSuite User Manual
 
Patterns of 64-bit errors in games
Patterns of 64-bit errors in gamesPatterns of 64-bit errors in games
Patterns of 64-bit errors in games
 
Vitaliy Makogon: Migration to ivy. Angular component libraries with IVY support.
Vitaliy Makogon: Migration to ivy. Angular component libraries with IVY support.Vitaliy Makogon: Migration to ivy. Angular component libraries with IVY support.
Vitaliy Makogon: Migration to ivy. Angular component libraries with IVY support.
 
Code quality
Code qualityCode quality
Code quality
 
Bypassing patchguard on Windows 8.1 and Windows 10
Bypassing patchguard on Windows 8.1 and Windows 10Bypassing patchguard on Windows 8.1 and Windows 10
Bypassing patchguard on Windows 8.1 and Windows 10
 
Embedded c & working with avr studio
Embedded c & working with avr studioEmbedded c & working with avr studio
Embedded c & working with avr studio
 
Static analysis should be used regularly
Static analysis should be used regularlyStatic analysis should be used regularly
Static analysis should be used regularly
 
685163main 2 4-a-swat_extendingbenefitsofstaticcodeanalysistools_final
685163main 2 4-a-swat_extendingbenefitsofstaticcodeanalysistools_final685163main 2 4-a-swat_extendingbenefitsofstaticcodeanalysistools_final
685163main 2 4-a-swat_extendingbenefitsofstaticcodeanalysistools_final
 
Pharo Virtual Machine: News from the Front
Pharo Virtual Machine: News from the FrontPharo Virtual Machine: News from the Front
Pharo Virtual Machine: News from the Front
 
Steelcon 2015 Reverse-Engineering Obfuscated Android Applications
Steelcon 2015 Reverse-Engineering Obfuscated Android ApplicationsSteelcon 2015 Reverse-Engineering Obfuscated Android Applications
Steelcon 2015 Reverse-Engineering Obfuscated Android Applications
 
Beachhead implements new opcode on CLR JIT
Beachhead implements new opcode on CLR JITBeachhead implements new opcode on CLR JIT
Beachhead implements new opcode on CLR JIT
 
How to create a high quality static code analyzer
How to create a high quality static code analyzerHow to create a high quality static code analyzer
How to create a high quality static code analyzer
 

More from Andrey Karpov

More from Andrey Karpov (20)

60 антипаттернов для С++ программиста
60 антипаттернов для С++ программиста60 антипаттернов для С++ программиста
60 антипаттернов для С++ программиста
 
60 terrible tips for a C++ developer
60 terrible tips for a C++ developer60 terrible tips for a C++ developer
60 terrible tips for a C++ developer
 
Ошибки, которые сложно заметить на code review, но которые находятся статичес...
Ошибки, которые сложно заметить на code review, но которые находятся статичес...Ошибки, которые сложно заметить на code review, но которые находятся статичес...
Ошибки, которые сложно заметить на code review, но которые находятся статичес...
 
PVS-Studio in 2021 - Error Examples
PVS-Studio in 2021 - Error ExamplesPVS-Studio in 2021 - Error Examples
PVS-Studio in 2021 - Error Examples
 
PVS-Studio in 2021 - Feature Overview
PVS-Studio in 2021 - Feature OverviewPVS-Studio in 2021 - Feature Overview
PVS-Studio in 2021 - Feature Overview
 
PVS-Studio в 2021 - Примеры ошибок
PVS-Studio в 2021 - Примеры ошибокPVS-Studio в 2021 - Примеры ошибок
PVS-Studio в 2021 - Примеры ошибок
 
PVS-Studio в 2021
PVS-Studio в 2021PVS-Studio в 2021
PVS-Studio в 2021
 
Best Bugs from Games: Fellow Programmers' Mistakes
Best Bugs from Games: Fellow Programmers' MistakesBest Bugs from Games: Fellow Programmers' Mistakes
Best Bugs from Games: Fellow Programmers' Mistakes
 
Typical errors in code on the example of C++, C#, and Java
Typical errors in code on the example of C++, C#, and JavaTypical errors in code on the example of C++, C#, and Java
Typical errors in code on the example of C++, C#, and Java
 
How to Fix Hundreds of Bugs in Legacy Code and Not Die (Unreal Engine 4)
How to Fix Hundreds of Bugs in Legacy Code and Not Die (Unreal Engine 4)How to Fix Hundreds of Bugs in Legacy Code and Not Die (Unreal Engine 4)
How to Fix Hundreds of Bugs in Legacy Code and Not Die (Unreal Engine 4)
 
Game Engine Code Quality: Is Everything Really That Bad?
Game Engine Code Quality: Is Everything Really That Bad?Game Engine Code Quality: Is Everything Really That Bad?
Game Engine Code Quality: Is Everything Really That Bad?
 
C++ Code as Seen by a Hypercritical Reviewer
C++ Code as Seen by a Hypercritical ReviewerC++ Code as Seen by a Hypercritical Reviewer
C++ Code as Seen by a Hypercritical Reviewer
 
The Use of Static Code Analysis When Teaching or Developing Open-Source Software
The Use of Static Code Analysis When Teaching or Developing Open-Source SoftwareThe Use of Static Code Analysis When Teaching or Developing Open-Source Software
The Use of Static Code Analysis When Teaching or Developing Open-Source Software
 
Safety on the Max: How to Write Reliable C/C++ Code for Embedded Systems
Safety on the Max: How to Write Reliable C/C++ Code for Embedded SystemsSafety on the Max: How to Write Reliable C/C++ Code for Embedded Systems
Safety on the Max: How to Write Reliable C/C++ Code for Embedded Systems
 
The Great and Mighty C++
The Great and Mighty C++The Great and Mighty C++
The Great and Mighty C++
 
Zero, one, two, Freddy's coming for you
Zero, one, two, Freddy's coming for youZero, one, two, Freddy's coming for you
Zero, one, two, Freddy's coming for you
 
PVS-Studio Is Now in Chocolatey: Checking Chocolatey under Azure DevOps
PVS-Studio Is Now in Chocolatey: Checking Chocolatey under Azure DevOpsPVS-Studio Is Now in Chocolatey: Checking Chocolatey under Azure DevOps
PVS-Studio Is Now in Chocolatey: Checking Chocolatey under Azure DevOps
 
PVS-Studio Static Analyzer as a Tool for Protection against Zero-Day Vulnerab...
PVS-Studio Static Analyzer as a Tool for Protection against Zero-Day Vulnerab...PVS-Studio Static Analyzer as a Tool for Protection against Zero-Day Vulnerab...
PVS-Studio Static Analyzer as a Tool for Protection against Zero-Day Vulnerab...
 
Analysis of commits and pull requests in Travis CI, Buddy and AppVeyor using ...
Analysis of commits and pull requests in Travis CI, Buddy and AppVeyor using ...Analysis of commits and pull requests in Travis CI, Buddy and AppVeyor using ...
Analysis of commits and pull requests in Travis CI, Buddy and AppVeyor using ...
 
PVS-Studio in the Clouds: CircleCI
PVS-Studio in the Clouds: CircleCIPVS-Studio in the Clouds: CircleCI
PVS-Studio in the Clouds: CircleCI
 

Recently uploaded

JustNaik Solution Deck (stage bus sector)
JustNaik Solution Deck (stage bus sector)JustNaik Solution Deck (stage bus sector)
JustNaik Solution Deck (stage bus sector)
Max Lee
 
AI/ML Infra Meetup | Improve Speed and GPU Utilization for Model Training & S...
AI/ML Infra Meetup | Improve Speed and GPU Utilization for Model Training & S...AI/ML Infra Meetup | Improve Speed and GPU Utilization for Model Training & S...
AI/ML Infra Meetup | Improve Speed and GPU Utilization for Model Training & S...
Alluxio, Inc.
 

Recently uploaded (20)

SOCRadar Research Team: Latest Activities of IntelBroker
SOCRadar Research Team: Latest Activities of IntelBrokerSOCRadar Research Team: Latest Activities of IntelBroker
SOCRadar Research Team: Latest Activities of IntelBroker
 
JustNaik Solution Deck (stage bus sector)
JustNaik Solution Deck (stage bus sector)JustNaik Solution Deck (stage bus sector)
JustNaik Solution Deck (stage bus sector)
 
How to install and activate eGrabber JobGrabber
How to install and activate eGrabber JobGrabberHow to install and activate eGrabber JobGrabber
How to install and activate eGrabber JobGrabber
 
AI/ML Infra Meetup | Improve Speed and GPU Utilization for Model Training & S...
AI/ML Infra Meetup | Improve Speed and GPU Utilization for Model Training & S...AI/ML Infra Meetup | Improve Speed and GPU Utilization for Model Training & S...
AI/ML Infra Meetup | Improve Speed and GPU Utilization for Model Training & S...
 
A Guideline to Zendesk to Re:amaze Data Migration
A Guideline to Zendesk to Re:amaze Data MigrationA Guideline to Zendesk to Re:amaze Data Migration
A Guideline to Zendesk to Re:amaze Data Migration
 
A Python-based approach to data loading in TM1 - Using Airflow as an ETL for TM1
A Python-based approach to data loading in TM1 - Using Airflow as an ETL for TM1A Python-based approach to data loading in TM1 - Using Airflow as an ETL for TM1
A Python-based approach to data loading in TM1 - Using Airflow as an ETL for TM1
 
AI/ML Infra Meetup | Perspective on Deep Learning Framework
AI/ML Infra Meetup | Perspective on Deep Learning FrameworkAI/ML Infra Meetup | Perspective on Deep Learning Framework
AI/ML Infra Meetup | Perspective on Deep Learning Framework
 
Abortion ^Clinic ^%[+971588192166''] Abortion Pill Al Ain (?@?) Abortion Pill...
Abortion ^Clinic ^%[+971588192166''] Abortion Pill Al Ain (?@?) Abortion Pill...Abortion ^Clinic ^%[+971588192166''] Abortion Pill Al Ain (?@?) Abortion Pill...
Abortion ^Clinic ^%[+971588192166''] Abortion Pill Al Ain (?@?) Abortion Pill...
 
AI/ML Infra Meetup | ML explainability in Michelangelo
AI/ML Infra Meetup | ML explainability in MichelangeloAI/ML Infra Meetup | ML explainability in Michelangelo
AI/ML Infra Meetup | ML explainability in Michelangelo
 
StrimziCon 2024 - Transition to Apache Kafka on Kubernetes with Strimzi
StrimziCon 2024 - Transition to Apache Kafka on Kubernetes with StrimziStrimziCon 2024 - Transition to Apache Kafka on Kubernetes with Strimzi
StrimziCon 2024 - Transition to Apache Kafka on Kubernetes with Strimzi
 
How Does XfilesPro Ensure Security While Sharing Documents in Salesforce?
How Does XfilesPro Ensure Security While Sharing Documents in Salesforce?How Does XfilesPro Ensure Security While Sharing Documents in Salesforce?
How Does XfilesPro Ensure Security While Sharing Documents in Salesforce?
 
TROUBLESHOOTING 9 TYPES OF OUTOFMEMORYERROR
TROUBLESHOOTING 9 TYPES OF OUTOFMEMORYERRORTROUBLESHOOTING 9 TYPES OF OUTOFMEMORYERROR
TROUBLESHOOTING 9 TYPES OF OUTOFMEMORYERROR
 
iGaming Platform & Lottery Solutions by Skilrock
iGaming Platform & Lottery Solutions by SkilrockiGaming Platform & Lottery Solutions by Skilrock
iGaming Platform & Lottery Solutions by Skilrock
 
How To Build a Successful SaaS Design.pdf
How To Build a Successful SaaS Design.pdfHow To Build a Successful SaaS Design.pdf
How To Build a Successful SaaS Design.pdf
 
Implementing KPIs and Right Metrics for Agile Delivery Teams.pdf
Implementing KPIs and Right Metrics for Agile Delivery Teams.pdfImplementing KPIs and Right Metrics for Agile Delivery Teams.pdf
Implementing KPIs and Right Metrics for Agile Delivery Teams.pdf
 
Secure Software Ecosystem Teqnation 2024
Secure Software Ecosystem Teqnation 2024Secure Software Ecosystem Teqnation 2024
Secure Software Ecosystem Teqnation 2024
 
Designing for Privacy in Amazon Web Services
Designing for Privacy in Amazon Web ServicesDesigning for Privacy in Amazon Web Services
Designing for Privacy in Amazon Web Services
 
top nidhi software solution freedownload
top nidhi software solution freedownloadtop nidhi software solution freedownload
top nidhi software solution freedownload
 
Agnieszka Andrzejewska - BIM School Course in Kraków
Agnieszka Andrzejewska - BIM School Course in KrakówAgnieszka Andrzejewska - BIM School Course in Kraków
Agnieszka Andrzejewska - BIM School Course in Kraków
 
Paketo Buildpacks : la meilleure façon de construire des images OCI? DevopsDa...
Paketo Buildpacks : la meilleure façon de construire des images OCI? DevopsDa...Paketo Buildpacks : la meilleure façon de construire des images OCI? DevopsDa...
Paketo Buildpacks : la meilleure façon de construire des images OCI? DevopsDa...
 

Static Code Analysis for Projects, Built on Unreal Engine

  • 1. Static Code Analysis for Projects, Built on Unreal Engine Ilya Gainulin PVS-Studio gainulin@viva64.com
  • 2. I Am Looking for Errors in Your Code 2
  • 3. Results of Incorrect Type Casing in the ShareX Project 3
  • 4. Results of Incorrect Type Casing in the ShareX Project Incorrect code: float pixelWeight = color.Alpha / 255; Fixed code: float pixelWeight = (float)color.Alpha / 255; 4 type Byte
  • 6. What Is Static Analysis? Static analysis is a way to check a program’s code without executing the program. 6
  • 7. Why Do You Need Static Analysis? • Detect errors early in the program development process. • Get recommendations on code formatting. • Check your spelling. • Calculate various software metrics 7
  • 8. Cost to Fix a Bug Fix earlier, save money! 8
  • 9. Why Do You Need Static Analysis? • Detect errors early in the program development process. • Get recommendations on code formatting. • Check your spelling. • Calculate various software metrics 9
  • 10. Static Analysis Advantages? • Detecting potential problems in code early • Full code coverage • Easy to use 10
  • 13. Static Analysis Advantages 13 Mono V3012 The '?:' operator, regardless of its conditional expression, always returns one and the same value: Color.FromArgb (150, 179, 225). ProfessionalColorTable.cs 258
  • 14. Static Analysis Disadvantages • Unavoidable false positives • Static analysis is usually not as good at detecting memory leaks and parallel errors 14
  • 15. Static Analysis Disadvantages void OutstandingIssue(const char *strCount) { unsigned nCount; sscanf_s(strCount, "%u", &nCount); int array[10]; memset(array, 0, nCount * sizeof(int)); } 15
  • 16. Static Analyzers Are Not Isolated Tools and Rare Checks – They Are a Part of DevOps 16 Написание кода Компиляция Unit тесты Интеграционные тесты Развёртывание Планирование Commit кода
  • 17. Static Analyzers Are Not Isolated Tools and Rare Checks – They Are a Part of DevOps 17 Написание кода Компиляция Полный статический анализ на билд сервере Unit тесты Интеграционные тесты Развёртывание Планирование Commit кода
  • 18. Static Analyzers Are Not Isolated Tools and Rare Checks – They Are a Part of DevOps 18
  • 19. Static Analyzers Are Not Isolated Tools and Rare Checks – They Are a Part of DevOps Написание кода Компиляция Полный статический анализ на билд сервере Unit тесты Интеграционные тесты Развёртывание Планирование Инкрементальный статический анализ на машине разработчика Commit кода 19
  • 20. Incremental Analysis • A decrease in analysis time, because only fixed or new code is processed. • Works well for early error detection. 20
  • 21. Ways to Use Static Analysis in a UE Project • Tracking compiler runs. • Direct integration with the build system. 21
  • 22. 22 Invoking CL.exe compiler MSBuild Unreal Build Tool Building Unreal Engine projects Build finished Gathering information The Simplest Way to Check a UE Project: Catch All Compiler Calls
  • 23. Tracking Compiler Runs from a GUI Application 23
  • 24. Tracking Compiler Runs from a GUI Application 24
  • 25. Tracking Compiler Runs from a GUI Application 25
  • 26. Direct Integration into Build System and VS • Run analysis directly from the Visual Studio IDE. • Run the analysis automatically when building a UE project. • Run incremental analysis. 26
  • 27. Common assembly scenario of a C++ project in VS 27
  • 28. Common assembly scenario of a C++ project in VS 28
  • 29. Particularities of Building a UE Project • Instead of Visual Studio’s standard build system, the UnrealBuildTool (UBT) is used. • Project files have the .uproject extension. 29
  • 30. Particularities of Building a UE Project 30
  • 31. What’s the Problem? • The project file may not contain paths to source files that need to be checked. • Not all compilation options required for correct preprocessing are present. 31
  • 32. What’s the Solution? • Write your own toolchain for the build system, so as to embed the static analyzer launch into UBT. • Pass a parameter to the UBT build system. That parameter would demonstrate the need for analysis. 32
  • 34. Some of the Current toolchain’s Limitations • Only builds a project or only analyzes the project. • No .cpp file analysis, if an included .h file has been changed. 34
  • 35. The Project Analysis After Its Build • Modifying the Build.bat and Rebuild.bat scripts. 35
  • 36. The Project Analysis After Its Build 36
  • 37. The Project Analysis After Its Build 37
  • 38. The .cpp File Analysis in Scenarios with the Connected Modified .h File • Remove and restore the cache file UBT uses. 38
  • 39. The .cpp File Analysis in Scenarios with the Connected Modified .h File 39
  • 40. Errors in Unreal Engine Code static bool PositionIsInside(....) { return Position.X >= Control.Center.X - BoxSize.X * 0.5f && Position.X <= Control.Center.X + BoxSize.X * 0.5f && Position.Y >= Control.Center.Y - BoxSize.Y * 0.5f && Position.Y >= Control.Center.Y - BoxSize.Y * 0.5f; } 40
  • 41. Errors in Unreal Engine Code static bool PositionIsInside(....) { return Position.X >= Control.Center.X - BoxSize.X * 0.5f && Position.X <= Control.Center.X + BoxSize.X * 0.5f && Position.Y >= Control.Center.Y - BoxSize.Y * 0.5f && Position.Y >= Control.Center.Y - BoxSize.Y * 0.5f; } PVS-Studio warns: V501 There are identical sub-expressions 'Position.Y >= Control.Center.Y — BoxSize.Y * 0.5f' to the left and to the right of the '&&' operator. svirtualjoystick.cpp 97 41
  • 42. Errors in Unreal Engine Code static bool PositionIsInside(....) { return Position.X >= Control.Center.X - BoxSize.X * 0.5f && Position.X <= Control.Center.X + BoxSize.X * 0.5f && Position.Y >= Control.Center.Y - BoxSize.Y * 0.5f && Position.Y >= Control.Center.Y - BoxSize.Y * 0.5f; Position.Y <= Control.Center.Y + BoxSize.Y * 0.5f; } PVS-Studio warns: V501 There are identical sub-expressions 'Position.Y >= Control.Center.Y — BoxSize.Y * 0.5f' to the left and to the right of the '&&' operator. svirtualjoystick.cpp 97 42
  • 43. enum ECubeFace; ECubeFace CubeFace; friend FArchive& operator<<(FArchive& Ar, FResolveParams& ResolveParams) { .... if(Ar.IsLoading()) { ResolveParams.CubeFace = (ECubeFace)ResolveParams.CubeFace; } .... } 43
  • 44. enum ECubeFace; ECubeFace CubeFace; friend FArchive& operator<<(FArchive& Ar, FResolveParams& ResolveParams) { .... if(Ar.IsLoading()) { ResolveParams.CubeFace = (ECubeFace)ResolveParams.CubeFace; } .... } PVS-Studio warns: V570 The 'ResolveParams.CubeFace' variable is assigned to itself. rhi.h 1279 44
  • 45. bool VertInfluencedByActiveBone( FParticleEmitterInstance* Owner, USkeletalMeshComponent* InSkelMeshComponent, int32 InVertexIndex, int32* OutBoneIndex = NULL); void UParticleModuleLocationSkelVertSurface::Spawn(....) { int32 BoneIndex1, BoneIndex2, BoneIndex3; BoneIndex1 = BoneIndex2 = BoneIndex3 = INDEX_NONE; if(!VertInfluencedByActiveBone( Owner, SourceComponent, VertIndex[0], &BoneIndex1) && !VertInfluencedByActiveBone( Owner, SourceComponent, VertIndex[1], &BoneIndex2) && !VertInfluencedByActiveBone( Owner, SourceComponent, VertIndex[2]) &BoneIndex3) { .... } 45
  • 46. bool VertInfluencedByActiveBone( FParticleEmitterInstance* Owner, USkeletalMeshComponent* InSkelMeshComponent, int32 InVertexIndex, int32* OutBoneIndex = NULL); void UParticleModuleLocationSkelVertSurface::Spawn(....) { int32 BoneIndex1, BoneIndex2, BoneIndex3; BoneIndex1 = BoneIndex2 = BoneIndex3 = INDEX_NONE; if(!VertInfluencedByActiveBone( Owner, SourceComponent, VertIndex[0], &BoneIndex1) && !VertInfluencedByActiveBone( Owner, SourceComponent, VertIndex[1], &BoneIndex2) && !VertInfluencedByActiveBone( Owner, SourceComponent, VertIndex[2]) &BoneIndex3) { .... } 46
  • 47. The Analyzer’s Warning About a Sneaky Error PVS-Studio warns: V564 The '&' operator is applied to bool type value. You've probably forgotten to include parentheses or intended to use the '&&' operator. particlemodules_location.cpp 2120 47
  • 48. void GetRenderData(....) { .... FT_Bitmap* Bitmap = nullptr; if( Slot->bitmap.pixel_mode == FT_PIXEL_MODE_MONO ) { FT_Bitmap NewBitmap; .... Bitmap = &NewBitmap; } .... OutRenderData.RawPixels.AddUninitialized( Bitmap->rows * Bitmap->width ); .... } 48
  • 49. void GetRenderData(....) { .... FT_Bitmap* Bitmap = nullptr; if( Slot->bitmap.pixel_mode == FT_PIXEL_MODE_MONO ) { FT_Bitmap NewBitmap; .... Bitmap = &NewBitmap; } .... OutRenderData.RawPixels.AddUninitialized( Bitmap->rows * Bitmap->width ); .... } 49 PVS-Studio: V506 Pointer to local variable 'NewBitmap' is stored outside the scope of this variable. Such a pointer will become invalid. fontcache.cpp 466
  • 50. void UGameplayStatics::DeactivateReverbEffect(....) { if (GEngine || !GEngine->UseSound()) { return; } UWorld* ThisWorld = GEngine->GetWorldFromContextObject(....); .... } 50
  • 51. void UGameplayStatics::DeactivateReverbEffect(....) { if (GEngine || !GEngine->UseSound()) { return; } UWorld* ThisWorld = GEngine->GetWorldFromContextObject(....); .... } PVS-Studio: V522 Dereferencing of the null pointer 'GEngine' might take place. Check the logical condition. gameplaystatics.cpp 988 51
  • 52. void UGameplayStatics::DeactivateReverbEffect(....) { if (GEngine || !GEngine->UseSound()) if (GEngine == nullptr || !GEngine->UseSound()) { return; } UWorld* ThisWorld = GEngine->GetWorldFromContextObject(....); .... } PVS-Studio: V522 Dereferencing of the null pointer 'GEngine' might take place. Check the logical condition. gameplaystatics.cpp 988 52
  • 53. template< typename DefinitionType > FORCENOINLINE void Set(....) { .... if ( DefinitionPtr == NULL ) { WidgetStyleValues.Add( PropertyName, MakeShareable( new DefinitionType( InStyleDefintion ) ) ); } else { WidgetStyleValues.Add( PropertyName, MakeShareable( new DefinitionType( InStyleDefintion ) ) ); } } 53
  • 54. template< typename DefinitionType > FORCENOINLINE void Set(....) { .... if ( DefinitionPtr == NULL ) { WidgetStyleValues.Add( PropertyName, MakeShareable( new DefinitionType( InStyleDefintion ) ) ); } else { WidgetStyleValues.Add( PropertyName, MakeShareable( new DefinitionType( InStyleDefintion ) ) ); } } 54 PVS-Studio: V523 The 'then' statement is equivalent to the 'else' statement. paths.cpp 703
  • 55. Conclusion • Static analysis of UE projects is not too complicated. • Combine static analysis with other testing methods. 55
  • 56. Thank You for Your Attention 56