Re: Fix uninitialized xl_running_xacts padding
Zsolt Parragi <zsolt.parragi@percona.com>
From: Zsolt Parragi <zsolt.parragi@percona.com>
To: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Cc: Alexander Kuzmenkov <akuzmenkov@tigerdata.com>,
Heikki Linnakangas <hlinnaka@iki.fi>, Andres Freund <andres@anarazel.de>,
Anthonin Bonnefoy <anthonin.bonnefoy@datadoghq.com>, Michael Paquier <michael@paquier.xyz>, Thomas Munro <thomas.munro@gmail.com>, PostgreSQL Hackers <pgsql-hackers@postgresql.org>
Date: 2026-03-17T18:45:46Z
Lists: pgsql-hackers
Attachments
- 0004-Remove-trivial-SizeOfXXX-macros-that-are-just-sizeof.patch (application/octet-stream) patch 0004
- 0001-Integrate-pg-tidy-clang-tidy-plugin-into-the-Postgre.patch (application/octet-stream) patch 0001
- 0002-Add-PG_NO_PADDING-PG_REQUIRE_NO_PADDING-and-padding-.patch (application/octet-stream) patch 0002
- 0003-Add-explicit-padding-to-WAL-record-structs-and-annot.patch (application/octet-stream) patch 0003
Hello! I'd like to propose a different approach: instead of relying on valgrind and runtime detection of the issue, why don't we (also) add specific static analysis rules to detect the situation at compile time? There are several threads when I had the same idea: maybe I should write a postgres specific clang-tidy checker, and ask what everyone thinks about integrating that into the build process in an optional way? I attached a WIP patch that addresses this, specifically for the xlog padding problem for now. src/tools/pg-tidy contains a basic custom clang-tidy plugin that works based on two annotations (and helper macros that resolve to "" for normal compilation): * PG_NOPADDING can be used to mark that a struct doesn't have any padding. If this annotation is added to a struct, but it has padding, it will generate clang-tidy warnings. This is basically "-Wpadded", but specifically for selected types. * A separate check rule requires all PG_NOPADDING structs to be always zero-initialized, meaning we don't have to rely on memset at all * PG_REQUIRE_NOPADDING can be used to mark function arguments. If an argument is marked with this, then the underlying type of its parameter has to be either a primitive type, or a struct annotated with PG_NOPADDING Possible alternatives: * I could simplify this by removing PG_NOPADDING, and instead checking the requirement at every call site of a function with PG_REQUIRE_NOPADDING. That would also mean that it could only enforce zero-initialization when it's clearly visible in the same function. I choose the two annotation approach for increased reliability * I could simplify this to only check for end padding, enforce memset instead of zero initialization, and build upon Alexander's previous patch. 0001 implements and integrates pg-tidy (I only added it to the meson build, if there's interest I can also add it to make. clang-tidy integration works similarly to the llvm bitcode patch, so it is properly parallelized/incremental) 0002 adds basic helper macros 0003 marks the data in XLogRegisterData with PG_REQUIRE_NOPADDING, all related structs with PG_NOPADDING, and then fixes the padding issues by adding explicit padding data instead of the compiler autogenerated padding. We also cast a few arrays to char* (or alternatively we could use nolint to suppress the check), because I didn't want to everywhere zero initialize types like RelFileLocator. 0004 removes the now trivial SizeOf macros Compared to only using valgrind, clang-tidy: * works at compile time, guaranteed for every type used with xlog * in theory should work with extensions (if we want to, e.g. by integrating it into pgxs), without requiring extension developers to add proper test workflows using valgrind * valgrind should still work What do you think? I'm interested in opinions about both the specific case, and the generic idea of using custom clang-tidy checks for various postgres-specific checks. As I mentioned at the beginning of the message I think this could be useful for other things and doesn't always require custom annotations, in several cases it could work without any C code change.
Commits
-
Add test for single-page VACUUM of hash index on INSERT
- 1f7947a48d0c 19 (unreleased) landed