Browse Source

araw: fix overflows in 24-bit decoder

The high-order byte is promoted to 'int'. If the high-order bit is set,
this results in an overflow (into the sign bit) when shifted by 24 bits
to the left. This was flagged by the UB sanitiser. To fix that, promote
all bytes to 32-bit unsigned first, to perform overflow-proof unsigned
arithmetic.

Then to avoid aliasing errors, make sure the output is written as signed
32-bit values, since the decoder outputs S32N.

(cherry picked from commit 9260acab6a)
cherry-pick-c5513cf9
Rémi Denis-Courmont 4 years ago
parent
commit
50d440647b
  1. 34
      modules/codec/araw.c

34
modules/codec/araw.c

@ -436,36 +436,45 @@ static void S20BDecode( void *outp, const uint8_t *in, unsigned samples )
static void U24BDecode( void *outp, const uint8_t *in, unsigned samples )
{
uint32_t *out = outp;
int32_t *out = outp;
union { int32_t s; uint32_t u; } u;
for( size_t i = 0; i < samples; i++ )
{
uint32_t s = ((in[0] << 24) | (in[1] << 16) | (in[2] << 8)) - 0x80000000;
*(out++) = s;
uint_fast32_t hi = in[0], mid = in[1], lo = in[2];
u.u = ((hi << 24) | (mid << 16) | (lo << 8)) - UINT32_C(0x80000000);
*(out++) = u.s;
in += 3;
}
}
static void U24LDecode( void *outp, const uint8_t *in, unsigned samples )
{
uint32_t *out = outp;
int32_t *out = outp;
union { int32_t s; uint32_t u; } u;
for( size_t i = 0; i < samples; i++ )
{
uint32_t s = ((in[2] << 24) | (in[1] << 16) | (in[0] << 8)) - 0x80000000;
*(out++) = s;
uint_fast32_t hi = in[2], mid = in[1], lo = in[0];
u.u = ((hi << 24) | (mid << 16) | (lo << 8)) - UINT32_C(0x80000000);
*(out++) = u.s;
in += 3;
}
}
static void S24BDecode( void *outp, const uint8_t *in, unsigned samples )
{
uint32_t *out = outp;
int32_t *out = outp;
union { int32_t s; uint32_t u; } u;
for( size_t i = 0; i < samples; i++ )
{
uint32_t s = ((in[0] << 24) | (in[1] << 16) | (in[2] << 8));
*(out++) = s;
uint_fast32_t hi = in[0], mid = in[1], lo = in[2];
u.u = (hi << 24) | (mid << 16) | (lo << 8);
*(out++) = u.s;
in += 3;
}
}
@ -473,11 +482,14 @@ static void S24BDecode( void *outp, const uint8_t *in, unsigned samples )
static void S24LDecode( void *outp, const uint8_t *in, unsigned samples )
{
uint32_t *out = outp;
union { int32_t s; uint32_t u; } u;
for( size_t i = 0; i < samples; i++ )
{
uint32_t s = ((in[2] << 24) | (in[1] << 16) | (in[0] << 8));
*(out++) = s;
uint_fast32_t hi = in[2], mid = in[1], lo = in[0];
u.u = (hi << 24) | (mid << 16) | (lo << 8);
*(out++) = u.s;
in += 3;
}
}

Loading…
Cancel
Save