Package: shntool
Version: 3.0.7-1
Severity: normal
Tags: lfs upstream patch

I've submitted this upstream as well (since it also occurs with 3.0.10, the
latest version as I write), but I actually ran into it first with Debian's
package.

Having recorded an unusually long gig last night, I found after editing
it this morning that shntool had some difficulty splitting it into
tracks...

The file I'm dealing with here is 2,263,140,436 bytes -- 03:33:49.59 at
16-bit 44.1kHz -- and I'm splitting it using a CUE file produced by
Ardour, which ends with these entries:

  TRACK 89 AUDIO
    FLAGS DCP
    TITLE "Goodnight Irene and band intros"
    INDEX 01 206:20:41
  TRACK 90 AUDIO
    FLAGS DCP
    TITLE "chat"
    INDEX 01 208:21:17
  TRACK 91 AUDIO
    FLAGS DCP
    TITLE "Fields of Athenry (reprise)"
    INDEX 01 209:02:14

Note that these last few times result in byte positions greater than
2^31...

Doing:

  shnsplit -O always -o wav -t '%n %t' export.wav <export.cue

runs happily until it gets past the 2 gig point in the input file, then
blows up with an error like:

  shnsplit: warning: error while transferring -4244268632 bytes of data
  shnsplit: error: failed to split file

There are actually two causes of this:

- The time parsers in core_mode.c have casts in the wrong place, so when
  converting times like 209:02:14 into bytes, multiplications are done
  with int rather than wlong values, and the resulting position is
  nonsense. shntool-3.0.10-large-times.diff fixes this.

- When read_value_long reads the input file length from the WAV header,
  because of a missing cast, the shift for the MSB is done as an int
  rather than an unsigned long.  On machines where int and long are the
  same size, this doesn't matter -- but on x86-64 Linux, long is 64
  bits, so the two-and-a-bit-gig file size gets sign-extended during the
  conversion and becomes negative. shntool-3.0.10-large-size.diff fixes
  this.



-- System Information:
Debian Release: wheezy/sid
  APT prefers testing
  APT policy: (500, 'testing')
Architecture: amd64 (x86_64)

Kernel: Linux 3.2.0-2-amd64 (SMP w/16 CPU cores)
Locale: LANG=en_GB.UTF-8, LC_CTYPE=en_GB.UTF-8 (charmap=UTF-8)
Shell: /bin/sh linked to /bin/bash

Versions of packages shntool depends on:
ii  libc6  2.13-33

shntool recommends no packages.

Versions of packages shntool suggests:
pn  cuetools  <none>
ii  flac      1.2.1-6
ii  sox       14.4.0-3

-- no debconf information
diff -aur shntool-3.0.10-clean/src/core_mode.c shntool-3.0.10/src/core_mode.c
--- shntool-3.0.10-clean/src/core_mode.c	2009-03-30 06:55:33.000000000 +0100
+++ shntool-3.0.10/src/core_mode.c	2012-08-11 16:37:58.000000000 +0100
@@ -310,8 +310,8 @@
   if (sec >= 60)
     st_error("invalid value for seconds: [%d]",sec);
 
-  bytes = (wlong)(min * info->rate * 60) +
-          (wlong)(sec * info->rate);
+  bytes = (((wlong)min) * info->rate * 60) +
+          (((wlong)sec) * info->rate);
 
   return bytes;
 }
@@ -358,9 +358,9 @@
   if (frames >= 75)
     st_error("invalid value for frames: [%d]",frames);
 
-  bytes = (wlong)(min * CD_RATE * 60) +
-          (wlong)(sec * CD_RATE) +
-          (wlong)(frames * CD_BLOCK_SIZE);
+  bytes = (((wlong)min) * CD_RATE * 60) +
+          (((wlong)sec) * CD_RATE) +
+          (((wlong)frames) * CD_BLOCK_SIZE);
 
   return bytes;
 }
@@ -403,8 +403,8 @@
 
   nearest_byte = (int)((((double)ms * (double)info->rate) / 1000.0) + 0.5);
 
-  bytes = (wlong)(min * info->rate * 60) +
-          (wlong)(sec * info->rate);
+  bytes = (((wlong)min) * info->rate * 60) +
+          (((wlong)sec) * info->rate);
 
   if (PROB_NOT_CD(info)) {
     bytes += nearest_byte;

diff -aur shntool-3.0.10-clean/src/core_fileio.c shntool-3.0.10-size/src/core_fileio.c
--- shntool-3.0.10-clean/src/core_fileio.c	2009-03-11 17:18:01.000000000 +0000
+++ shntool-3.0.10-size/src/core_fileio.c	2012-08-11 17:20:14.000000000 +0100
@@ -110,10 +110,16 @@
   buf[4] = 0;
 
   if (be_val)
-    *be_val = (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf[3];
+    *be_val = (((unsigned long)buf[0]) << 24)
+              | (((unsigned long)buf[1]) << 16)
+              | (((unsigned long)buf[2]) << 8)
+              | ((unsigned long)buf[3]);
 
   if (le_val)
-    *le_val = (buf[3] << 24) | (buf[2] << 16) | (buf[1] << 8) | buf[0];
+    *le_val = (((unsigned long)buf[3]) << 24)
+              | (((unsigned long)buf[2]) << 16)
+              | (((unsigned long)buf[1]) << 8)
+              | ((unsigned long)buf[0]);
 
   if (tag_val)
     tagcpy(tag_val,buf);

Reply via email to