| 1 | From: Antonio Larrosa <[email protected]>
|
| 2 | Date: Mon, 6 Mar 2017 13:54:52 +0100
|
| 3 | Subject: Check for multiplication overflow in sfconvert
|
| 4 |
|
| 5 | Checks that a multiplication doesn't overflow when
|
| 6 | calculating the buffer size, and if it overflows,
|
| 7 | reduce the buffer size instead of failing.
|
| 8 |
|
| 9 | This fixes the 00192-audiofile-signintoverflow-sfconvert case
|
| 10 | in #41
|
| 11 | ---
|
| 12 | sfcommands/sfconvert.c | 34 ++++++++++++++++++++++++++++++++--
|
| 13 | 1 file changed, 32 insertions(+), 2 deletions(-)
|
| 14 |
|
| 15 | diff --git a/sfcommands/sfconvert.c b/sfcommands/sfconvert.c
|
| 16 | index 80a1bc4..970a3e4 100644
|
| 17 | |
| 18 | |
| 19 | @@ -45,6 +45,33 @@ void printusage (void);
|
| 20 | void usageerror (void);
|
| 21 | bool copyaudiodata (AFfilehandle infile, AFfilehandle outfile, int trackid);
|
| 22 |
|
| 23 | +int firstBitSet(int x)
|
| 24 | +{
|
| 25 | + int position=0;
|
| 26 | + while (x!=0)
|
| 27 | + {
|
| 28 | + x>>=1;
|
| 29 | + ++position;
|
| 30 | + }
|
| 31 | + return position;
|
| 32 | +}
|
| 33 | +
|
| 34 | +#ifndef __has_builtin
|
| 35 | +#define __has_builtin(x) 0
|
| 36 | +#endif
|
| 37 | +
|
| 38 | +int multiplyCheckOverflow(int a, int b, int *result)
|
| 39 | +{
|
| 40 | +#if (defined __GNUC__ && __GNUC__ >= 5) || ( __clang__ && __has_builtin(__builtin_mul_overflow))
|
| 41 | + return __builtin_mul_overflow(a, b, result);
|
| 42 | +#else
|
| 43 | + if (firstBitSet(a)+firstBitSet(b)>31) // int is signed, so we can't use 32 bits
|
| 44 | + return true;
|
| 45 | + *result = a * b;
|
| 46 | + return false;
|
| 47 | +#endif
|
| 48 | +}
|
| 49 | +
|
| 50 | int main (int argc, char **argv)
|
| 51 | {
|
| 52 | if (argc == 2)
|
| 53 | @@ -323,8 +350,11 @@ bool copyaudiodata (AFfilehandle infile, AFfilehandle outfile, int trackid)
|
| 54 | {
|
| 55 | int frameSize = afGetVirtualFrameSize(infile, trackid, 1);
|
| 56 |
|
| 57 | - const int kBufferFrameCount = 65536;
|
| 58 | - void *buffer = malloc(kBufferFrameCount * frameSize);
|
| 59 | + int kBufferFrameCount = 65536;
|
| 60 | + int bufferSize;
|
| 61 | + while (multiplyCheckOverflow(kBufferFrameCount, frameSize, &bufferSize))
|
| 62 | + kBufferFrameCount /= 2;
|
| 63 | + void *buffer = malloc(bufferSize);
|
| 64 |
|
| 65 | AFframecount totalFrames = afGetFrameCount(infile, AF_DEFAULT_TRACK);
|
| 66 | AFframecount totalFramesWritten = 0;
|