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);
             }
         }

Reply via email to