summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorTom Lane2022-03-04 00:03:17 +0000
committerTom Lane2022-03-04 00:03:50 +0000
commit566e1c04df5238464f0c953d9bf09682092a880f (patch)
tree1e67cd47aff240db60138cbab10b56ee77cf600c /src
parentf2087e26ebf15fe9ac59d0b485e1a5e4a8493e07 (diff)
Fix bogus casting in BlockIdGetBlockNumber().
This macro cast the result to BlockNumber after shifting, not before, which is the wrong thing. Per the C spec, the uint16 fields would promote to int not unsigned int, so that (for 32-bit int) the shift potentially shifts a nonzero bit into the sign position. I doubt there are any production systems where this would actually end with the wrong answer, but it is undefined behavior per the C spec, and clang's -fsanitize=undefined option reputedly warns about it on some platforms. (I can't reproduce that right now, but the code is undeniably wrong per spec.) It's easy to fix by casting to BlockNumber (uint32) in the proper places. It's been wrong for ages, so back-patch to all supported branches. Report and patch by Zhihong Yu (cosmetic tweaking by me) Discussion: https://postgr.es/m/CALNJ-vT9r0DSsAOw9OXVJFxLENoVS_68kJ5x0p44atoYH+H4dg@mail.gmail.com
Diffstat (limited to 'src')
-rw-r--r--src/include/storage/block.h2
1 files changed, 1 insertions, 1 deletions
diff --git a/src/include/storage/block.h b/src/include/storage/block.h
index 182aa8d4536..fd3db3575f2 100644
--- a/src/include/storage/block.h
+++ b/src/include/storage/block.h
@@ -115,7 +115,7 @@ typedef BlockIdData *BlockId; /* block identifier */
#define BlockIdGetBlockNumber(blockId) \
( \
AssertMacro(BlockIdIsValid(blockId)), \
- (BlockNumber) (((blockId)->bi_hi << 16) | ((uint16) (blockId)->bi_lo)) \
+ ((((BlockNumber) (blockId)->bi_hi) << 16) | ((BlockNumber) (blockId)->bi_lo)) \
)
#endif /* BLOCK_H */