Package: wavpack Severity: important wavpack currently has some unaligned memory accesses that result in SIGBUS on sparc.
> Program received signal SIGBUS, Bus error. > 0xf7edde84 in little_endian_to_native (data=0x28ce2, format=0x16411 "L") > at bits.c:143 > 143 * (int32_t *) cp = temp; > (gdb) bt > #0 0xf7edde84 in little_endian_to_native (data=0x28ce2, format=0x16411 "L") > at bits.c:143 > #1 0xf7eff284 in WavpackLittleEndianToNative (data=0x28ce2, > format=0x16410 "4L") at wputils.c:2862 > #2 0x00014504 in main (argc=<value optimized out>, argv=<value optimized > out>) > at wavpack.c:1368 Fixing little_endian_to_native() and native_to_little_endian() with the attached patch gives the following: > Program received signal SIGBUS, Bus error. > 0x00015708 in pack_file (infilename=0x2c018 "test.wav", > outfilename=0x2c030 "test.wv", out2filename=0x0, config=0xffa036f4) > at wavpack.c:1369 > 1369 riffhdr->ckSize = wrapper_size + > data_size - 8; > (gdb) bt > #0 0x00015708 in pack_file (infilename=0x2c018 "test.wav", > outfilename=0x2c030 "test.wv", out2filename=0x0, config=0xffa036f4) > at wavpack.c:1369 > #1 0x000136ac in main (argc=0, argv=0xffa038cc) at wavpack.c:772 This is then fixed by the second part of the patch. The same code is again in src/wputils.c, also fixed in the patch. So the only problem left is, that this crashes when compiled with optimizations (i.e. greater -O0).
--- wavpack-4.41.0.orig/cli/wavpack.c +++ wavpack-4.41.0/cli/wavpack.c @@ -1365,14 +1365,16 @@ uint32_t data_size = WavpackGetSampleIndex (wpc) * WavpackGetNumChannels (wpc) * WavpackGetBytesPerSample (wpc); if (!strncmp (riffhdr->ckID, "RIFF", 4)) { + uint32_t tmp = wrapper_size + data_size - 8; + WavpackLittleEndianToNative (riffhdr, ChunkHeaderFormat); - riffhdr->ckSize = wrapper_size + data_size - 8; + memcpy (&riffhdr->ckSize, &tmp, sizeof (uint32_t)); WavpackNativeToLittleEndian (riffhdr, ChunkHeaderFormat); } if (!strncmp (datahdr->ckID, "data", 4)) { WavpackLittleEndianToNative (datahdr, ChunkHeaderFormat); - datahdr->ckSize = data_size; + memcpy (&datahdr->ckSize, &data_size, sizeof (uint32_t)); WavpackNativeToLittleEndian (datahdr, ChunkHeaderFormat); } } --- wavpack-4.41.0.orig/src/bits.c +++ wavpack-4.41.0/src/bits.c @@ -135,18 +135,19 @@ { uchar *cp = (uchar *) data; int32_t temp; + short temp2; while (*format) { switch (*format) { case 'L': temp = cp [0] + ((int32_t) cp [1] << 8) + ((int32_t) cp [2] << 16) + ((int32_t) cp [3] << 24); - * (int32_t *) cp = temp; + memcpy (cp, &temp, sizeof (int32_t)); cp += 4; break; case 'S': - temp = cp [0] + (cp [1] << 8); - * (short *) cp = (short) temp; + temp2 = cp [0] + (cp [1] << 8); + memcpy (cp, &temp2, sizeof (short)); cp += 2; break; @@ -165,11 +166,12 @@ { uchar *cp = (uchar *) data; int32_t temp; + short temp2; while (*format) { switch (*format) { case 'L': - temp = * (int32_t *) cp; + memcpy (&temp, cp, sizeof (int32_t)); *cp++ = (uchar) temp; *cp++ = (uchar) (temp >> 8); *cp++ = (uchar) (temp >> 16); @@ -177,9 +179,9 @@ break; case 'S': - temp = * (short *) cp; - *cp++ = (uchar) temp; - *cp++ = (uchar) (temp >> 8); + memcpy (&temp2, cp, sizeof (short)); + *cp++ = (uchar) temp2; + *cp++ = (uchar) (temp2 >> 8); break; default: --- wavpack-4.41.0.orig/src/wputils.c +++ wavpack-4.41.0/src/wputils.c @@ -1644,9 +1644,12 @@ void WavpackUpdateNumSamples (WavpackContext *wpc, void *first_block) { uint32_t wrapper_size; + uint32_t total_samples; little_endian_to_native (first_block, WavpackHeaderFormat); - ((WavpackHeader *) first_block)->total_samples = WavpackGetSampleIndex (wpc); + + total_samples = WavpackGetSampleIndex (wpc); + memcpy (&((WavpackHeader *) first_block)->total_samples, &total_samples, sizeof (uint32_t)); if (wpc->riff_header_created) { if (WavpackGetWrapperLocation (first_block, &wrapper_size)) { @@ -1655,14 +1658,16 @@ uint32_t data_size = WavpackGetSampleIndex (wpc) * WavpackGetNumChannels (wpc) * WavpackGetBytesPerSample (wpc); if (!strncmp (riffhdr->ckID, "RIFF", 4)) { + uint32_t tmp = wrapper_size + data_size - 8; + little_endian_to_native (riffhdr, ChunkHeaderFormat); - riffhdr->ckSize = wrapper_size + data_size - 8; + memcpy (&riffhdr->ckSize, &tmp, sizeof (uint32_t)); native_to_little_endian (riffhdr, ChunkHeaderFormat); } if (!strncmp (datahdr->ckID, "data", 4)) { little_endian_to_native (datahdr, ChunkHeaderFormat); - datahdr->ckSize = data_size; + memcpy (&datahdr->ckSize, &data_size, sizeof (uint32_t)); native_to_little_endian (datahdr, ChunkHeaderFormat); } }