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