Re: [PATCH 1/2] lib/xz: Use size_t instead of uint32_t in a few places
From: Lasse Collin
Date: Mon Jun 15 2026 - 15:27:31 EST
On 2026-06-15 David Laight wrote:
> On Sun, 14 Jun 2026 19:05:17 +0300
> Lasse Collin <lasse.collin@xxxxxxxxxxx> wrote:
> > @@ -1046,25 +1048,23 @@ enum xz_ret xz_dec_lzma2_run(struct xz_dec_lzma2 *s, struct xz_buf *b)
> >
> > case SEQ_UNCOMPRESSED_1:
> > s->lzma2.uncompressed
> > - += (uint32_t)b->in[b->in_pos++] << 8;
> > + += (size_t)b->in[b->in_pos++] << 8;
>
> The type of that casts can't matter.
> Indeed all these casts can be deleted.
> (The value read from the uint8_t variable is promoted to int before
> it is used.)
It is true that the casts aren't mandatory here. There are a few more
similar casts in lib/xz.
I dislike that narrow unsigned types are promoted to signed int in C; I
would prefer unsigned staying unsigned. If the result doesn't fit into
the original unsigned type, it feels clearest to cast to the unsigned
target type, skipping the intermediate signed type and the need to
verify that the signed type indeed works correctly in the particular
expression. This results in a few seemingly useless casts, but it's
less mental load to think about two types instead of three.
uint8_t b = 0x80;
uint32_t x = b << 8; // (1)
uint32_t y = b << 24; // (2)
size_t z = b << 24; // (3)
(1) is fine, but I tend to add a cast anyway.
(2) is undefined behavior due to shifting into the sign bit of a signed
int, except with GCC it's well defined[*] but -fsanitize=undefined will
still complain.
(3) Even if the shift into the sign bit was OK, the conversion of a
negative signed int to size_t is unlikely to produce the intended
result.
Maybe many people find the extra casts weird, but at least you know my
rationale behind them now.
[*] https://gcc.gnu.org/onlinedocs/gcc-16.1.0/gcc/Integers-implementation.html
--
Lasse Collin