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