| From 7d65f89defb092b63bcbc5d98349fb222ca73b3c Mon Sep 17 00:00:00 2001 |
| From: Antonio Larrosa <larrosa@kde.org> |
| Date: Mon, 6 Mar 2017 13:54:52 +0100 |
| Subject: [PATCH] Check for multiplication overflow in sfconvert |
| |
| Checks that a multiplication doesn't overflow when |
| calculating the buffer size, and if it overflows, |
| reduce the buffer size instead of failing. |
| |
| This fixes the 00192-audiofile-signintoverflow-sfconvert case |
| in #41 |
| |
| Signed-off-by: Peter Korsgaard <peter@korsgaard.com> |
| --- |
| sfcommands/sfconvert.c | 34 ++++++++++++++++++++++++++++++++-- |
| 1 file changed, 32 insertions(+), 2 deletions(-) |
| |
| diff --git a/sfcommands/sfconvert.c b/sfcommands/sfconvert.c |
| index 80a1bc4..970a3e4 100644 |
| --- a/sfcommands/sfconvert.c |
| +++ b/sfcommands/sfconvert.c |
| @@ -45,6 +45,33 @@ void printusage (void); |
| void usageerror (void); |
| bool copyaudiodata (AFfilehandle infile, AFfilehandle outfile, int trackid); |
| |
| +int firstBitSet(int x) |
| +{ |
| + int position=0; |
| + while (x!=0) |
| + { |
| + x>>=1; |
| + ++position; |
| + } |
| + return position; |
| +} |
| + |
| +#ifndef __has_builtin |
| +#define __has_builtin(x) 0 |
| +#endif |
| + |
| +int multiplyCheckOverflow(int a, int b, int *result) |
| +{ |
| +#if (defined __GNUC__ && __GNUC__ >= 5) || ( __clang__ && __has_builtin(__builtin_mul_overflow)) |
| + return __builtin_mul_overflow(a, b, result); |
| +#else |
| + if (firstBitSet(a)+firstBitSet(b)>31) // int is signed, so we can't use 32 bits |
| + return true; |
| + *result = a * b; |
| + return false; |
| +#endif |
| +} |
| + |
| int main (int argc, char **argv) |
| { |
| if (argc == 2) |
| @@ -323,8 +350,11 @@ bool copyaudiodata (AFfilehandle infile, AFfilehandle outfile, int trackid) |
| { |
| int frameSize = afGetVirtualFrameSize(infile, trackid, 1); |
| |
| - const int kBufferFrameCount = 65536; |
| - void *buffer = malloc(kBufferFrameCount * frameSize); |
| + int kBufferFrameCount = 65536; |
| + int bufferSize; |
| + while (multiplyCheckOverflow(kBufferFrameCount, frameSize, &bufferSize)) |
| + kBufferFrameCount /= 2; |
| + void *buffer = malloc(bufferSize); |
| |
| AFframecount totalFrames = afGetFrameCount(infile, AF_DEFAULT_TRACK); |
| AFframecount totalFramesWritten = 0; |
| -- |
| 2.11.0 |
| |