Blame

ab8e2d flichtenheld 2025-10-13 13:37:16 1
# CodeStyle
2
3
## Introduction
4
5
The OpenVPN 2.4+ coding style is based on the Allman style, e.g.:
6
7
```c
8
void
9
myfunction(int a, int b)
10
{
11
const char *dummy = "Hello world!";
12
if (a == b)
13
{
14
something_equals(dummy);
15
}
16
else
17
{
18
does_not_equal(dummy);
19
}
20
}
21
```
22
23
Summarizing:
24
25
* Indentation is 4 spaces, no tabs ever.
26
* Opening and closing brackets get their own line, and must match indentation.
27
* Line length is 80 characters (soft limit) but may be extended up to 120 if wrapping makes the result less readable / more ugly
28
* C99 is allowed. E.g. `for (int i = 0; i < max; i++)`.
29
* Only use `/* */`-style comments
30
31
## Line wrapping
32
33
The maximum line length is 80 characters. When statements exceed this length, wrap them by aligning with the appropriate (, or otherwise using a single indent (i.e. 4 spaces) on the new line. For example:
34
35
```c
36
void
37
my_function(void)
38
{
39
if (variable_with_artificially_long_name_1 != 0
40
&& variable_with_artificially_long_name_2 != 0)
41
{
42
return variable_with_artificially_long_name_1
43
+ variable_with_artificially_long_name_2
44
+ variable_with_artificially_long_name_3;
45
}
46
}
47
```
48
49
If you find yourself continuously exceeding the line limit, you might want to consider breaking up your function into smaller functions to reduce nesting.
50
51
Single lines may use up to 120 characters if the resulting code is more readable than if wrapped. But this should be an exception, no whole code blocks should be written with "more than 80 as a general norm".
52
53
## Some additional secure coding style rules
54
55
This are style rules, not general secure coding guide lines. See e.g. https://www.securecoding.cert.org/confluence/display/c/SEI+CERT+C+Coding+Standard for useful guidelines on writing secure C.
56
57
### All branches must use braces
58
59
For example:
60
61
```c
62
if (a)
63
{
64
return true;
65
}
66
```
67
68
We wouldn't be the first to not spot missing braces in an if statement, like what happened in Apple's [goto fail](https://web.archive.org/web/20240615172304/https://www.imperialviolet.org/2014/02/22/applebug.html) bug. Always using braces prevents this kind of mistake.
69
70
### Cases in a switch statement should break or explicitly fall through
71
72
The only exception to this rule are empty case statements, to not overly clutter the code with comments.
73
74
For example:
75
76
```c
77
switch (a)
78
{
79
case ONE:
80
case TWO:
81
one_or_two = true;
82
/* Intentional [[fallthrough]]; */
83
case THREE:
84
now_do_something();
85
break;
86
default:
87
ASSERT(0);
88
}
89
```
90
91
This makes the intent immediately clear to the reader / reviewer.
92
Note that we do not use the `[[fallthrough]]` attribute yet, since this is only officially introduced by C23.
93
cac9bc flichtenheld 2025-10-28 12:02:02 94
### Use `ASSERT()` to verify assumptions, but never use `assert()`
95
96
If there are assumptions in your code about the state of parameters/variables and you assume these conditions to be always fulfilled then you can use `ASSERT()` to verify them. We define our own version of `ASSERT()` which is not affected by `-DNDEBUG`. It will exit the program with an error code but log an informational message first. For this reason it is preferred over the default `assert()` provided by the standard library. Never use `assert()` in our code.
97
98
`ASSERT()` can be used if you want to make sure that certain conditions are fulfilled which are necessary to avoid e.g. overflows or unsafe casts. This should only be used if a violation of the condition signifies a programming error or an otherwise unexpected program state (think hardware error). Do not use it to handle expectable errors. E.g. if the condition is violated due to external input then it is probably required to handle it gracefully instead of allowing the external entity to DOS us.
99
100
It is acceptable to use `ASSERT()` to react to OOM conditions in most cases, since we do expect our code to recover in those situations.
101
ab8e2d flichtenheld 2025-10-13 13:37:16 102
## Portability concerns
103
104
### Printing time_t and suseconds_t values
105
106
POSIX specifies that `time_t` is an integer type but does not specify its size. The underlying type might be `int`, `long` or `long long`, some systems might make it unsigned too. This makes it hard to portably print `time_t` values using printf-like APIs, as a mismatch between the format string and the actual `time_t` size can lead to crashes or bogus representations.
107
108
The safest way is to print `time_t` values after casting to `int64_t` and using `PRIi64` as format specifier. Casting to a 64 bits wide int avoids y2038 problems and `PRIi64` is preferred over `%lld` as the latter is not supported in the windows runtime targeted by mingw.
109
110
Similarly, POSIX specifies `suseconds_t` as a signed integer, but does not specify its size. Casting it as a long is enough.
111
112
```c
113
struct timeval now;
114
gettimeofday(&now, NULL);
115
printf("%"PRIi64".%06ld\n", (int64_t)now.tv_sec, (long)now.tv_usec);
116
```
117
118
### Windows specific
119
120
OpenVPN core uses UTF-8 encoding for strings. These may be converted to and from UTF-16 used in Windows as required. Declare all strings explicitly as `char *` or `wchar_t *`. **Use of `TCHAR` is not allowed**. Call Windows API functions using their explicit ANSI or wide character variants: e.g., `CreateFileW` or `CreateFileA` instead of `CreateFile`. The core executable for Windows is built without `-DUNICODE` and `-D_UNICODE`.
121
122
## Automatic formatting
123
124
OpenVPN master is formatted with [clang-format](https://clang.llvm.org/docs/ClangFormat.html). A pre-commit hook is available for use by developers. See [`dev-tools/git-pre-commit-format.sh`](https://github.com/OpenVPN/openvpn/blob/master/dev-tools/git-pre-commit-format.sh).
6fe51a flichtenheld 2025-10-13 13:52:30 125
126
Since we do not want to enforce a hard limit on line length but instead want to allow developers to use a sensible line length depending on what is most readable, clang-format can not be used to enforce the line length. You will need to take care of this
127
yourself.