0008-common-fix-int-overflow-in-psf_binheader_readf.patch 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181
  1. From 6be8906740cdca067f12920bb4a63f728485aff0 Mon Sep 17 00:00:00 2001
  2. From: Alex Stewart <alex.stewart@ni.com>
  3. Date: Mon, 16 Oct 2023 12:37:47 -0400
  4. Subject: [PATCH] common: fix int overflow in psf_binheader_readf()
  5. The psf_binheader_readf() function attempts to count and return the
  6. number of bytes traversed in the header. During this accumulation, it is
  7. possible to overflow the int-sized byte_count variable.
  8. Avoid this overflow by checking that the accumulated bytes do not exceed
  9. INT_MAX and throwing an error if they do. This implies that files with
  10. multi-gigabyte headers threaten to produce this error, but I imagine
  11. those files don't really exist - and this error is better than the
  12. undefined behavior which would have resulted previously.
  13. CVE: CVE-2022-33065
  14. Fixes: https://github.com/libsndfile/libsndfile/issues/833
  15. Signed-off-by: Alex Stewart <alex.stewart@ni.com>
  16. Upstream: https://github.com/libsndfile/libsndfile/commit/6be8906740cdca067f12920bb4a63f728485aff0
  17. Signed-off-by: Peter Korsgaard <peter@korsgaard.com>
  18. ---
  19. src/common.c | 36 ++++++++++++++++++++++++------------
  20. 1 file changed, 24 insertions(+), 12 deletions(-)
  21. diff --git a/src/common.c b/src/common.c
  22. index b877aa86..8982379a 100644
  23. --- a/src/common.c
  24. +++ b/src/common.c
  25. @@ -18,6 +18,7 @@
  26. #include <config.h>
  27. +#include <limits.h>
  28. #include <stdarg.h>
  29. #include <string.h>
  30. #if HAVE_UNISTD_H
  31. @@ -990,6 +991,7 @@ psf_binheader_readf (SF_PRIVATE *psf, char const *format, ...)
  32. double *doubleptr ;
  33. char c ;
  34. int byte_count = 0, count = 0 ;
  35. + int read_bytes = 0 ;
  36. if (! format)
  37. return psf_ftell (psf) ;
  38. @@ -998,6 +1000,7 @@ psf_binheader_readf (SF_PRIVATE *psf, char const *format, ...)
  39. while ((c = *format++))
  40. {
  41. + read_bytes = 0 ;
  42. if (psf->header.indx + 16 >= psf->header.len && psf_bump_header_allocation (psf, 16))
  43. break ;
  44. @@ -1014,7 +1017,7 @@ psf_binheader_readf (SF_PRIVATE *psf, char const *format, ...)
  45. intptr = va_arg (argptr, unsigned int*) ;
  46. *intptr = 0 ;
  47. ucptr = (unsigned char*) intptr ;
  48. - byte_count += header_read (psf, ucptr, sizeof (int)) ;
  49. + read_bytes = header_read (psf, ucptr, sizeof (int)) ;
  50. *intptr = GET_MARKER (ucptr) ;
  51. break ;
  52. @@ -1022,7 +1025,7 @@ psf_binheader_readf (SF_PRIVATE *psf, char const *format, ...)
  53. intptr = va_arg (argptr, unsigned int*) ;
  54. *intptr = 0 ;
  55. ucptr = (unsigned char*) intptr ;
  56. - byte_count += header_read (psf, sixteen_bytes, sizeof (sixteen_bytes)) ;
  57. + read_bytes = header_read (psf, sixteen_bytes, sizeof (sixteen_bytes)) ;
  58. { int k ;
  59. intdata = 0 ;
  60. for (k = 0 ; k < 16 ; k++)
  61. @@ -1034,14 +1037,14 @@ psf_binheader_readf (SF_PRIVATE *psf, char const *format, ...)
  62. case '1' :
  63. charptr = va_arg (argptr, char*) ;
  64. *charptr = 0 ;
  65. - byte_count += header_read (psf, charptr, sizeof (char)) ;
  66. + read_bytes = header_read (psf, charptr, sizeof (char)) ;
  67. break ;
  68. case '2' : /* 2 byte value with the current endian-ness */
  69. shortptr = va_arg (argptr, unsigned short*) ;
  70. *shortptr = 0 ;
  71. ucptr = (unsigned char*) shortptr ;
  72. - byte_count += header_read (psf, ucptr, sizeof (short)) ;
  73. + read_bytes = header_read (psf, ucptr, sizeof (short)) ;
  74. if (psf->rwf_endian == SF_ENDIAN_BIG)
  75. *shortptr = GET_BE_SHORT (ucptr) ;
  76. else
  77. @@ -1051,7 +1054,7 @@ psf_binheader_readf (SF_PRIVATE *psf, char const *format, ...)
  78. case '3' : /* 3 byte value with the current endian-ness */
  79. intptr = va_arg (argptr, unsigned int*) ;
  80. *intptr = 0 ;
  81. - byte_count += header_read (psf, sixteen_bytes, 3) ;
  82. + read_bytes = header_read (psf, sixteen_bytes, 3) ;
  83. if (psf->rwf_endian == SF_ENDIAN_BIG)
  84. *intptr = GET_BE_3BYTE (sixteen_bytes) ;
  85. else
  86. @@ -1062,7 +1065,7 @@ psf_binheader_readf (SF_PRIVATE *psf, char const *format, ...)
  87. intptr = va_arg (argptr, unsigned int*) ;
  88. *intptr = 0 ;
  89. ucptr = (unsigned char*) intptr ;
  90. - byte_count += header_read (psf, ucptr, sizeof (int)) ;
  91. + read_bytes = header_read (psf, ucptr, sizeof (int)) ;
  92. if (psf->rwf_endian == SF_ENDIAN_BIG)
  93. *intptr = psf_get_be32 (ucptr, 0) ;
  94. else
  95. @@ -1072,7 +1075,7 @@ psf_binheader_readf (SF_PRIVATE *psf, char const *format, ...)
  96. case '8' : /* 8 byte value with the current endian-ness */
  97. countptr = va_arg (argptr, sf_count_t *) ;
  98. *countptr = 0 ;
  99. - byte_count += header_read (psf, sixteen_bytes, 8) ;
  100. + read_bytes = header_read (psf, sixteen_bytes, 8) ;
  101. if (psf->rwf_endian == SF_ENDIAN_BIG)
  102. countdata = psf_get_be64 (sixteen_bytes, 0) ;
  103. else
  104. @@ -1083,7 +1086,7 @@ psf_binheader_readf (SF_PRIVATE *psf, char const *format, ...)
  105. case 'f' : /* Float conversion */
  106. floatptr = va_arg (argptr, float *) ;
  107. *floatptr = 0.0 ;
  108. - byte_count += header_read (psf, floatptr, sizeof (float)) ;
  109. + read_bytes = header_read (psf, floatptr, sizeof (float)) ;
  110. if (psf->rwf_endian == SF_ENDIAN_BIG)
  111. *floatptr = float32_be_read ((unsigned char*) floatptr) ;
  112. else
  113. @@ -1093,7 +1096,7 @@ psf_binheader_readf (SF_PRIVATE *psf, char const *format, ...)
  114. case 'd' : /* double conversion */
  115. doubleptr = va_arg (argptr, double *) ;
  116. *doubleptr = 0.0 ;
  117. - byte_count += header_read (psf, doubleptr, sizeof (double)) ;
  118. + read_bytes = header_read (psf, doubleptr, sizeof (double)) ;
  119. if (psf->rwf_endian == SF_ENDIAN_BIG)
  120. *doubleptr = double64_be_read ((unsigned char*) doubleptr) ;
  121. else
  122. @@ -1117,7 +1120,7 @@ psf_binheader_readf (SF_PRIVATE *psf, char const *format, ...)
  123. charptr = va_arg (argptr, char*) ;
  124. count = va_arg (argptr, size_t) ;
  125. memset (charptr, 0, count) ;
  126. - byte_count += header_read (psf, charptr, count) ;
  127. + read_bytes = header_read (psf, charptr, count) ;
  128. break ;
  129. case 'G' :
  130. @@ -1128,7 +1131,7 @@ psf_binheader_readf (SF_PRIVATE *psf, char const *format, ...)
  131. if (psf->header.indx + count >= psf->header.len && psf_bump_header_allocation (psf, count))
  132. break ;
  133. - byte_count += header_gets (psf, charptr, count) ;
  134. + read_bytes = header_gets (psf, charptr, count) ;
  135. break ;
  136. case 'z' :
  137. @@ -1152,7 +1155,7 @@ psf_binheader_readf (SF_PRIVATE *psf, char const *format, ...)
  138. case 'j' : /* Seek to position from current position. */
  139. count = va_arg (argptr, size_t) ;
  140. header_seek (psf, count, SEEK_CUR) ;
  141. - byte_count += count ;
  142. + read_bytes = count ;
  143. break ;
  144. case '!' : /* Clear buffer, forcing re-read. */
  145. @@ -1164,8 +1167,17 @@ psf_binheader_readf (SF_PRIVATE *psf, char const *format, ...)
  146. psf->error = SFE_INTERNAL ;
  147. break ;
  148. } ;
  149. +
  150. + if (read_bytes > 0 && byte_count > (INT_MAX - read_bytes))
  151. + { psf_log_printf (psf, "Header size exceeds INT_MAX. Aborting.", c) ;
  152. + psf->error = SFE_INTERNAL ;
  153. + break ;
  154. + } else
  155. + { byte_count += read_bytes ;
  156. } ;
  157. + } ; /*end while*/
  158. +
  159. va_end (argptr) ;
  160. return byte_count ;
  161. --
  162. 2.39.5