Languages

Visao reads nineteen languages, and one set of rules holds for all of them. A defect class that Visao reports in C, it also reports in Python, in Go or in C#.

How Visao picks the language

Visao reads the extension of each input file. Give it the files, and it selects the language for each one:

visao -- src/app.py tests/test_app.py
visao -- cmd/server.go

The --language option sets the language for the whole run. Use it for a file whose extension does not state the language:

visao --language c -- src/main.inc

A tree with more than one language needs no option. Visao groups the files by language and analyses each group with the front-end of that language:

visao -- src/core.c src/ui.cpp scripts/build.py

For C and C++, a compile database gives Visao the flags of each file. Pass the database as the only input:

visao compile_commands.json

A RAD Studio project gives the same data: a Delphi .dproj file or a C++Builder .cbproj file. Visao reads the sources of the project and, for each source, the defines, the search paths and the unit scope names of the project:

visao -- MyApp.dproj
visao -- MyApp.cbproj

Visao uses the default configuration of the project. The VISAO_MSBUILD_CONFIG environment variable selects another one, for example Release. The platform is a Windows platform of the project: the default platform when it is Win32 or Win64, else Win64 or Win32. The VISAO_MSBUILD_PLATFORM environment variable selects another one. Visao ignores a path that starts with a RAD Studio property without a value, such as $(BDS). To give $(BDS) a value, set the BDS environment variable to the RAD Studio directory.

Extensions

Language

--language value

File names

C

c

.c, .h

C++

cpp

.cpp, .cxx, .cc, .hpp, .hxx, .hh

Go

go

.go

Python

python

.py, .pyi

Rust

rust

.rs

C#

csharp

.cs

Java

java

.java

Kotlin

kotlin

.kt, .kts

JavaScript

javascript

.js, .mjs, .cjs, .jsx

TypeScript

typescript

.ts, .tsx

PHP

php

.php

Ruby

ruby

.rb

Swift

swift

.swift

Lua

lua

.lua

Delphi

delphi

.pas, .dpr, .dpk, .pp, .lpr

Assembly

asm

.s, .S, .asm

Bash

bash

.sh, .bash

CMake

cmake

.cmake, CMakeLists.txt

YAML

yaml

.yaml, .yml

What the package carries

Visao takes the types of a program from the best authority for the language. For eight languages that authority is a helper program, and the package carries the helper beside the visao binary. You install nothing more for Python, TypeScript, JavaScript, C#, Java, Kotlin, Rust and Go.

C and C++ use a compiler of the host. Install gcc or clang. Visao probes the compiler for the target triple, the predefined macros and the header search paths. Refer to Running the analyzer.

A Go toolchain on the host is also useful: Visao asks it for the list of the Go targets.

Delphi and Free Pascal

Visao reads Delphi units, programs and packages. It also reads Free Pascal sources. A .pp or .lpr file selects the Free Pascal dialect. The other extensions select the Delphi dialect.

Visao evaluates the conditional compilation directives before it reads the source: {$IFDEF}, {$IFNDEF}, {$IF}, {$ELSEIF}, {$ELSE}, {$ENDIF}, {$IFEND}, {$DEFINE} and {$UNDEF}. The directives of an {$I} file also apply. Visao defines the symbols of the compiler and of the platform, for example MSWINDOWS and UNICODE. To add symbols, set the VISAO_DELPHI_DEFINES environment variable to a list that commas separate:

VISAO_DELPHI_DEFINES="DEBUG,USE_SSL" visao -- src/*.pas

Visao reads the interface section of each unit in the uses clause of a file. It looks for the unit in the directory of the file and at the path of a uses Name in 'path' clause. To add directories, set the VISAO_DELPHI_UNIT_PATH environment variable to a list that semicolons separate:

VISAO_DELPHI_UNIT_PATH="lib/common;lib/ui" visao -- src/*.pas

The units that a used unit uses give their types too. Thus a class of the file knows the fields of an ancestor in another unit.

The units of the run-time library come from their sources. Visao finds the sources of RAD Studio:

  • in the directories of the VISAO_DELPHI_RTL_PATH environment variable, a list that semicolons separate;

  • in $(BDS)\source, when the BDS environment variable is set. The RAD Studio command prompt sets it;

  • on Windows, in the source directory of each RAD Studio installation in the registry. The newest version comes first.

A unit name without a unit scope also finds the scoped unit, as the compiler does: SysUtils finds System.SysUtils and Forms finds Vcl.Forms.

VISAO_DELPHI_RTL_PATH="C:\RAD\source\rtl;C:\RAD\source\vcl" visao -- src\*.pas

Contracts describe the units of the run-time library: System, SysUtils, Classes, IOUtils and the Windows API. They apply also when the sources are not available. Refer to Function contracts and roles.

What each language receives

Each front-end supplies the types, the control flow and the vocabulary of its ecosystem. The analysis above the front-ends is shared. Therefore each language receives:

  • The value analysis: an overflow, an index past the end of a container, a division by zero, and a condition that is always true or always false.

  • The resource analysis: a value that can be absent, a use after a release, a double release, and a handle that stays open.

  • The taint analysis: untrusted data that reaches a shell, an interpreter or a query.

  • The contract analysis: the specifications that the source states.

  • The suspicious places of a change. Refer to Suspicious places.

The rules are the same for every language. The catalogue at https://defectdb.org holds one page for each rule.

Examples

Analyse a Python package and print the findings of medium severity and higher:

visao --severity Medium -- src/*.py

Analyse a C project through its compile database and write SARIF for the CI system:

visao --report-format sarif --report-output visao.sarif \
      compile_commands.json

Identify the language of each file without a deeper analysis:

visao --identify -- src/*