xref: /openbmc/libpldm/docs/checklists/changes.md (revision 615344fc)
1# Checklist for making changes to `libpldm`
2
3## Philosophy and influences
4
5- [Good Practices in Library Design, Implementation, and Maintenance - Ulrich
6  Drepper][goodpractice]
7
8[goodpractice]: https://www.akkadia.org/drepper/goodpractice.pdf
9
10- [How Do I Make This Hard to Misuse? - Rusty Russell][rusty-api-scale-good]
11
12[rusty-api-scale-good]: https://ozlabs.org/~rusty/index.cgi/tech/2008-03-30.html
13
14- [What If I Don't Actually Like My Users? - Rusty Russell][rusty-api-scale-bad]
15
16[rusty-api-scale-bad]: https://ozlabs.org/~rusty/index.cgi/tech/2008-04-01.html
17
18- [Red flags that indicate questionable quality - Lennart
19  Poettering][poettering-library-red-flags]
20
21[poettering-library-red-flags]:
22  https://mastodon.social/@pid_eins/112517953375791453
23
24- [Not sure if this is a gcc bug or some weird corner of UB or what... - Andrew
25  Zonenberg][azonenberg-packed-struct]
26
27[azonenberg-packed-struct]: https://ioc.exchange/@azonenberg/112535511250395148
28
29- [The Good, the Bad, and the Weird - Trail of Bits
30  Blog][trail-of-bits-weird-machines]
31
32[trail-of-bits-weird-machines]:
33  https://blog.trailofbits.com/2018/10/26/the-good-the-bad-and-the-weird/
34
35- [Logic for Programmers - Hillel Wayne][logic-for-programmers]
36
37[logic-for-programmers]: https://leanpub.com/logic
38
39- [Parse, don’t validate - Alexis King][alexis-king-parse-dont-validate]
40
41[alexis-king-parse-dont-validate]:
42  https://lexi-lambda.github.io/blog/2019/11/05/parse-don-t-validate/
43
44## References
45
46- [C17 draft standard][c17-draft-standard]
47
48[c17-draft-standard]:
49  https://web.archive.org/web/20181230041359if_/http://www.open-std.org/jtc1/sc22/wg14/www/abq/c17_updated_proposed_fdis.pdf
50
51- [SEI CERT C Coding Standard][sei-cert-c-coding-standard]
52
53[sei-cert-c-coding-standard]:
54  https://wiki.sei.cmu.edu/confluence/display/c/SEI+CERT+C+Coding+Standard
55
56- [Common Weakness Enumeration (CWE) - Software
57  Development][common-weakness-enumeration-sw]
58
59[common-weakness-enumeration-sw]:
60  https://cwe.mitre.org/data/definitions/699.html
61
62## Definitions
63
64- **Error condition**: An invalid state reached at runtime, caused either by
65  resource exhaustion, or incorrect use of the library's public APIs and data
66  types.
67
68- **Invariant**: A condition in the library's implementation that must never
69  evaluate false.
70
71- **Public API**: Any definitions and declarations under `include/libpldm`.
72
73- **Wire format**: Any message structure defined in the DMTF PLDM protocol
74  specifications.
75
76## Elaborations
77
78- Resource exhaustion is always an error condition and never an invariant
79  violation.
80
81- An invariant violation is always a programming failure of the library's
82  implementation, and never the result of incorrect use of the library's public
83  APIs (see error condition).
84
85- Corollaries of the above two points:
86
87  - Incorrect use of public API functions is always an error condition, and is
88    dealt with by returning an error code.
89
90  - Incorrect use of static functions in the library's implementation is an
91    invariant violation which may be established using `assert()`.
92
93- `assert()` is the recommended way to demonstrate invariants are upheld.
94
95## Adding a new API
96
97- [ ] My new public message codec functions take a `struct` representing the
98      message as a parameter
99
100  - Function prototypes must _not_ decompose the message to individual
101    parameters. This approach is not ergonomic and is difficult to make
102    type-safe. This is especially true for message decoding functions which must
103    use pointers for out-parameters, where it has often become ambiguous whether
104    the underlying memory represents a single object or an array.
105
106- [ ] Each new `struct` I've defined is used in at least one new function I've
107      added to the public API.
108
109- [ ] My new public `struct` definitions are _not_ marked
110      `__attribute__((packed))`
111
112- [ ] My new public `struct` definitions do _not_ define a flexible array
113      member, unless:
114
115  - [ ] It's contained in an `#ifndef __cplusplus` macro guard, as flexible
116        arrays are not specified by C++, and
117
118  - [ ] I've implemented an accessor function so the array base pointer can be
119        accessed from C++, and
120
121  - [ ] It is defined as per the C17 specification by omitting the length[^1]
122
123    - Note: Any array defined with length 1 is _not_ a flexible array, and any
124      access beyond the first element invokes undefined behaviour in both C and
125      C++.
126
127  - [ ] I've annotated the flexible array member with `LIBPLDM_CC_COUNTED_BY()`
128
129[^1]:
130    [C17 draft specification][c17-draft-standard], 6.7.2.1 Structure and union
131    specifiers, paragraph 18.
132
133- [ ] If my work interacts with the PLDM wire format, then I have done so using
134      the `msgbuf` APIs found in `src/msgbuf.h` (and under `src/msgbuf/`) to
135      minimise concerns around spatial memory safety and endian-correctness.
136
137- [ ] All my error conditions are handled by returning an error code to the
138      caller.
139
140- [ ] All my invariants are tested using `assert()`.
141
142- [ ] I have not used `assert()` to evaluate any error conditions without also
143      handling the error condition by returning an error code the the caller.
144
145  - Release builds of the library are configured with `assert()` disabled
146    (`-Db_ndebug=if-release`, which provides `-DNDEBUG` in `CFLAGS`).
147
148- [ ] My new APIs return negative `errno` values on error and not PLDM
149      completion codes.
150
151  - [ ] The specific error values my function returns and their meaning in the
152        context of the function call are listed in the API documentation.
153
154- [ ] If I've added support for a new PLDM message type, then I've implemented
155      both the encoder and decoder for that message. Note this applies for both
156      request _and_ response message types.
157
158- [ ] My new function symbols are marked with `LIBPLDM_ABI_TESTING` in the
159      implementation
160
161- [ ] I've implemented test cases with reasonable branch coverage of each new
162      function I've added
163
164- [ ] I've guarded the test cases of functions marked `LIBPLDM_ABI_TESTING` so
165      that they are not compiled when the corresponding function symbols aren't
166      visible
167
168- [ ] If I've added support for a new message type, then my commit message
169      specifies all of:
170
171  - [ ] The relevant DMTF specification by its DSP number and title
172  - [ ] The relevant version of the specification
173  - [ ] The section of the specification that defines the message type
174
175- [ ] If my work impacts the public API of the library, then I've added an entry
176      to `CHANGELOG.md` describing my work
177
178## Stabilising an existing API
179
180- [ ] The API of interest is currently marked `LIBPLDM_ABI_TESTING`
181
182- [ ] My commit message links to a publicly visible patch that makes use of the
183      API
184
185- [ ] My commit updates the annotation from `LIBPLDM_ABI_TESTING` to
186      `LIBPLDM_ABI_STABLE` only for the function symbols demonstrated by the
187      patch linked in the commit message.
188
189- [ ] I've removed guards from the function's tests so they are always compiled
190
191- [ ] If I've updated the ABI dump, then I've used the OpenBMC CI container to
192      do so.
193
194## Updating an ABI dump
195
196Each of the following must succeed:
197
198- [ ] Enter the OpenBMC CI Docker container
199  - Approximately:
200    `docker run --cap-add=sys_admin --rm=true --privileged=true -u $USER -w $(pwd) -v $(pwd):$(pwd) -e MAKEFLAGS= -it openbmc/ubuntu-unit-test:2024-W21-ce361f95ff4fa669`
201- [ ] `CC=gcc CXX=g++; [ $(uname -m) = 'x86_64' ] && meson setup -Dabi=deprecated,stable build`
202- [ ] `meson compile -C build`
203- [ ] `./scripts/abi-dump-formatter < build/src/current.dump > abi/x86_64/gcc.dump`
204
205## Removing an API
206
207- [ ] If the function is marked `LIBPLDM_ABI_TESTING`, then I have removed it
208
209- [ ] If the function is marked `LIBPLDM_ABI_STABLE`, then I have changed the
210      annotation to `LIBPLDM_ABI_DEPRECATED` and left it in-place.
211
212  - [ ] I have updated the ABI dump, or will mark the change as WIP until it has
213        been.
214
215- [ ] If the function is marked `LIBPLDM_ABI_DEPRECATED`, then I have removed it
216      only after satisfying myself that each of the following is true:
217
218  - [ ] There are no known users of the function left in the community
219  - [ ] There has been at least one tagged release of `libpldm` subsequent to
220        the API being marked deprecated
221
222## Renaming an API
223
224A change to an API is a pure rename only if there are no additional behavioural
225changes. Renaming an API with no other behavioural changes is really two
226actions:
227
2281. Introducing the new API name
2292. Deprecating the old API name
230
231- [ ] Only the name of the function has changed. None of its behaviour has
232      changed.
233
234- [ ] Both the new and the old functions are declared in the public headers
235
236- [ ] I've aliased the old function name to the new function name via the
237      `libpldm_deprecated_aliases` list in `meson.build`
238
239- [ ] I've added a [semantic patch][coccinelle] to migrate users from the old
240      name to the new name
241
242[coccinelle]: https://coccinelle.gitlabpages.inria.fr/website/
243
244- [ ] I've updated the ABI dump to capture the rename, or will mark the change
245      as WIP until it has been.
246
247## Testing my changes
248
249Each of the following must succeed when executed in order. Note that to avoid
250[googletest bug #4232][googletest-issue-4232] you must avoid using GCC 12
251(shipped in Debian Bookworm).
252
253[googletest-issue-4232]: https://github.com/google/googletest/issues/4232
254
255- [ ] `meson setup -Dabi-compliance-check=disabled build`
256- [ ] `meson compile -C build && meson test -C build`
257
258- [ ] `meson configure --buildtype=release build`
259- [ ] `meson compile -C build && meson test -C build`
260
261- [ ] `meson configure --buildtype=debug build`
262- [ ] `meson configure -Dabi=deprecated,stable build`
263- [ ] `meson compile -C build && meson test -C build`
264
265This process is captured in `scripts/pre-submit` for automation.
266