Commit | Line | Data |
---|---|---|
a8e14943 HG |
1 | From: Antonio Larrosa <larrosa@kde.org> |
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 | --- a/sfcommands/sfconvert.c | |
18 | +++ b/sfcommands/sfconvert.c | |
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; |