07_Check-for-multiplication-overflow-in-sfconvert.patch 1.9 KB

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