libproxy-0.4.15-fix-pac-buffer-overflow.patch 3.0 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394
  1. From 4411b523545b22022b4be7d0cac25aa170ae1d3e Mon Sep 17 00:00:00 2001
  2. From: Fei Li <lifeibiren@gmail.com>
  3. Date: Fri, 17 Jul 2020 02:18:37 +0800
  4. Subject: [PATCH] Fix buffer overflow when PAC is enabled
  5. The bug was found on Windows 10 (MINGW64) when PAC is enabled. It turned
  6. out to be the large PAC file (more than 102400 bytes) returned by a
  7. local proxy program with no content-length present.
  8. ---
  9. libproxy/url.cpp | 44 +++++++++++++++++++++++++++++++-------------
  10. 1 file changed, 31 insertions(+), 13 deletions(-)
  11. diff --git a/libproxy/url.cpp b/libproxy/url.cpp
  12. index ee776b2..8684086 100644
  13. --- a/libproxy/url.cpp
  14. +++ b/libproxy/url.cpp
  15. @@ -54,7 +54,7 @@ using namespace std;
  16. #define PAC_MIME_TYPE_FB "text/plain"
  17. // This is the maximum pac size (to avoid memory attacks)
  18. -#define PAC_MAX_SIZE 102400
  19. +#define PAC_MAX_SIZE 0x800000
  20. // This is the default block size to use when receiving via HTTP
  21. #define PAC_HTTP_BLOCK_SIZE 512
  22. @@ -478,15 +478,13 @@ char* url::get_pac() {
  23. }
  24. // Get content
  25. - unsigned int recvd = 0;
  26. - buffer = new char[PAC_MAX_SIZE];
  27. - memset(buffer, 0, PAC_MAX_SIZE);
  28. + std::vector<char> dynamic_buffer;
  29. do {
  30. unsigned int chunk_length;
  31. if (chunked) {
  32. // Discard the empty line if we received a previous chunk
  33. - if (recvd > 0) recvline(sock);
  34. + if (!dynamic_buffer.empty()) recvline(sock);
  35. // Get the chunk-length line as an integer
  36. if (sscanf(recvline(sock).c_str(), "%x", &chunk_length) != 1 || chunk_length == 0) break;
  37. @@ -498,21 +496,41 @@ char* url::get_pac() {
  38. if (content_length >= PAC_MAX_SIZE) break;
  39. - while (content_length == 0 || recvd != content_length) {
  40. - int r = recv(sock, buffer + recvd,
  41. - content_length == 0 ? PAC_HTTP_BLOCK_SIZE
  42. - : content_length - recvd, 0);
  43. + while (content_length == 0 || dynamic_buffer.size() != content_length) {
  44. + // Calculate length to recv
  45. + unsigned int length_to_read = PAC_HTTP_BLOCK_SIZE;
  46. + if (content_length > 0)
  47. + length_to_read = content_length - dynamic_buffer.size();
  48. +
  49. + // Prepare buffer
  50. + dynamic_buffer.resize(dynamic_buffer.size() + length_to_read);
  51. +
  52. + int r = recv(sock, dynamic_buffer.data() + dynamic_buffer.size() - length_to_read, length_to_read, 0);
  53. +
  54. + // Shrink buffer to fit
  55. + if (r >= 0)
  56. + dynamic_buffer.resize(dynamic_buffer.size() - length_to_read + r);
  57. +
  58. + // PAC size too large, discard
  59. + if (dynamic_buffer.size() >= PAC_MAX_SIZE) {
  60. + chunked = false;
  61. + dynamic_buffer.clear();
  62. + break;
  63. + }
  64. +
  65. if (r <= 0) {
  66. chunked = false;
  67. break;
  68. }
  69. - recvd += r;
  70. }
  71. } while (chunked);
  72. - if (content_length != 0 && string(buffer).size() != content_length) {
  73. - delete[] buffer;
  74. - buffer = NULL;
  75. + if (content_length == 0 || content_length == dynamic_buffer.size()) {
  76. + buffer = new char[dynamic_buffer.size() + 1];
  77. + if (!dynamic_buffer.empty()) {
  78. + memcpy(buffer, dynamic_buffer.data(), dynamic_buffer.size());
  79. + }
  80. + buffer[dynamic_buffer.size()] = '\0';
  81. }
  82. }