diff options
author | Evgeny Grin (Karlson2k) <k2k@narod.ru> | 2021-06-07 21:18:49 +0300 |
---|---|---|
committer | Evgeny Grin (Karlson2k) <k2k@narod.ru> | 2021-07-28 11:28:43 +0300 |
commit | 2cab7e09b796aa3c228b1b5e04844061a9e78812 (patch) | |
tree | ebe2ff8b84eefc4c658ad02045d54d674d812a36 | |
parent | ee3f32220038303ebf1bfcf1494c9badf6d3adc4 (diff) | |
download | libmicrohttpd-2cab7e09b796aa3c228b1b5e04844061a9e78812.tar.gz libmicrohttpd-2cab7e09b796aa3c228b1b5e04844061a9e78812.zip |
try_ready_chunked_body: use new string function, fixes.
* Used new MHD_uint32_to_strx() function
* Ensure that send buffer always has at least 128 bytes to avoid
potential overrun
* Added static const vars for readability
-rw-r--r-- | src/microhttpd/connection.c | 75 |
1 files changed, 43 insertions, 32 deletions
diff --git a/src/microhttpd/connection.c b/src/microhttpd/connection.c index 9a8209ed..d1ecd339 100644 --- a/src/microhttpd/connection.c +++ b/src/microhttpd/connection.c | |||
@@ -994,18 +994,26 @@ try_ready_chunked_body (struct MHD_Connection *connection) | |||
994 | ssize_t ret; | 994 | ssize_t ret; |
995 | struct MHD_Response *response; | 995 | struct MHD_Response *response; |
996 | static const size_t max_chunk = 0xFFFFFF; | 996 | static const size_t max_chunk = 0xFFFFFF; |
997 | char cbuf[10]; /* 10: max strlen of "FFFFFF\r\n" */ | 997 | char chunk_hdr[6]; /* 6: max strlen of "FFFFFF" */ |
998 | int cblen; | 998 | /* "FFFFFF" + "\r\n" */ |
999 | static const size_t max_chunk_hdr_len = sizeof(chunk_hdr) + 2; | ||
1000 | /* "FFFFFF" + "\r\n" + "\r\n" (chunk termination) */ | ||
1001 | static const size_t max_chunk_overhead = sizeof(chunk_hdr) + 2 + 2; | ||
1002 | size_t chunk_hdr_len; | ||
999 | 1003 | ||
1000 | response = connection->response; | 1004 | response = connection->response; |
1001 | if (NULL == response->crc) | 1005 | if (NULL == response->crc) |
1002 | return MHD_YES; | 1006 | return MHD_YES; |
1003 | if (0 == connection->write_buffer_size) | 1007 | |
1008 | mhd_assert (0 == connection->write_buffer_append_offset); | ||
1009 | |||
1010 | /* The buffer must reasonably large enough */ | ||
1011 | if (128 > connection->write_buffer_size) | ||
1004 | { | 1012 | { |
1005 | size_t size; | 1013 | size_t size; |
1006 | 1014 | ||
1007 | size = MHD_pool_get_free (connection->pool); | 1015 | size = connection->write_buffer_size + MHD_pool_get_free (connection->pool); |
1008 | if (size < 128) | 1016 | if (128 > size) |
1009 | { | 1017 | { |
1010 | #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS) | 1018 | #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS) |
1011 | MHD_mutex_unlock_chk_ (&response->mutex); | 1019 | MHD_mutex_unlock_chk_ (&response->mutex); |
@@ -1015,11 +1023,13 @@ try_ready_chunked_body (struct MHD_Connection *connection) | |||
1015 | _ ("Closing connection (out of memory).")); | 1023 | _ ("Closing connection (out of memory).")); |
1016 | return MHD_NO; | 1024 | return MHD_NO; |
1017 | } | 1025 | } |
1018 | if ( (max_chunk + sizeof(cbuf) + 2) < size) | 1026 | /* Limit the buffer size to the large usable size for chunks */ |
1019 | size = max_chunk + sizeof(cbuf) + 2; | 1027 | if ( (max_chunk + max_chunk_overhead) < size) |
1020 | connection->write_buffer = MHD_pool_allocate (connection->pool, | 1028 | size = max_chunk + max_chunk_overhead; |
1021 | size, | 1029 | connection->write_buffer = MHD_pool_reallocate (connection->pool, |
1022 | false); | 1030 | connection->write_buffer, |
1031 | connection-> | ||
1032 | write_buffer_size, size); | ||
1023 | mhd_assert (NULL != connection->write_buffer); | 1033 | mhd_assert (NULL != connection->write_buffer); |
1024 | connection->write_buffer_size = size; | 1034 | connection->write_buffer_size = size; |
1025 | } | 1035 | } |
@@ -1037,9 +1047,9 @@ try_ready_chunked_body (struct MHD_Connection *connection) | |||
1037 | = (size_t) (connection->response_write_position - response->data_start); | 1047 | = (size_t) (connection->response_write_position - response->data_start); |
1038 | /* buffer already ready, use what is there for the chunk */ | 1048 | /* buffer already ready, use what is there for the chunk */ |
1039 | ret = response->data_size - data_write_offset; | 1049 | ret = response->data_size - data_write_offset; |
1040 | if ( ((size_t) ret) > connection->write_buffer_size - sizeof (cbuf) - 2) | 1050 | if ( ((size_t) ret) > connection->write_buffer_size - max_chunk_overhead) |
1041 | ret = connection->write_buffer_size - sizeof (cbuf) - 2; | 1051 | ret = connection->write_buffer_size - max_chunk_overhead; |
1042 | memcpy (&connection->write_buffer[sizeof (cbuf)], | 1052 | memcpy (&connection->write_buffer[max_chunk_hdr_len], |
1043 | &response->data[data_write_offset], | 1053 | &response->data[data_write_offset], |
1044 | ret); | 1054 | ret); |
1045 | } | 1055 | } |
@@ -1048,12 +1058,13 @@ try_ready_chunked_body (struct MHD_Connection *connection) | |||
1048 | /* buffer not in range, try to fill it */ | 1058 | /* buffer not in range, try to fill it */ |
1049 | size_t size_to_fill; | 1059 | size_t size_to_fill; |
1050 | 1060 | ||
1051 | size_to_fill = connection->write_buffer_size - sizeof (cbuf) - 2; | 1061 | size_to_fill = connection->write_buffer_size - max_chunk_overhead; |
1062 | /* Limit size for the callback to the max usable size */ | ||
1052 | if (max_chunk < size_to_fill) | 1063 | if (max_chunk < size_to_fill) |
1053 | size_to_fill = max_chunk; | 1064 | size_to_fill = max_chunk; |
1054 | ret = response->crc (response->crc_cls, | 1065 | ret = response->crc (response->crc_cls, |
1055 | connection->response_write_position, | 1066 | connection->response_write_position, |
1056 | &connection->write_buffer[sizeof (cbuf)], | 1067 | &connection->write_buffer[max_chunk_hdr_len], |
1057 | size_to_fill); | 1068 | size_to_fill); |
1058 | } | 1069 | } |
1059 | if ( ((ssize_t) MHD_CONTENT_READER_END_WITH_ERROR) == ret) | 1070 | if ( ((ssize_t) MHD_CONTENT_READER_END_WITH_ERROR) == ret) |
@@ -1072,11 +1083,12 @@ try_ready_chunked_body (struct MHD_Connection *connection) | |||
1072 | (0 == response->total_size) ) | 1083 | (0 == response->total_size) ) |
1073 | { | 1084 | { |
1074 | /* end of message, signal other side! */ | 1085 | /* end of message, signal other side! */ |
1075 | memcpy (connection->write_buffer, | 1086 | connection->write_buffer[0] = '0'; |
1076 | "0\r\n", | 1087 | connection->write_buffer[1] = '\r'; |
1077 | 3); | 1088 | connection->write_buffer[2] = '\n'; |
1078 | connection->write_buffer_append_offset = 3; | 1089 | connection->write_buffer_append_offset = 3; |
1079 | connection->write_buffer_send_offset = 0; | 1090 | connection->write_buffer_send_offset = 0; |
1091 | /* TODO: remove update of the response size */ | ||
1080 | response->total_size = connection->response_write_position; | 1092 | response->total_size = connection->response_write_position; |
1081 | return MHD_YES; | 1093 | return MHD_YES; |
1082 | } | 1094 | } |
@@ -1088,21 +1100,20 @@ try_ready_chunked_body (struct MHD_Connection *connection) | |||
1088 | #endif | 1100 | #endif |
1089 | return MHD_NO; | 1101 | return MHD_NO; |
1090 | } | 1102 | } |
1091 | cblen = MHD_snprintf_ (cbuf, | 1103 | chunk_hdr_len = MHD_uint32_to_strx (ret, chunk_hdr, sizeof(chunk_hdr)); |
1092 | sizeof (cbuf), | 1104 | mhd_assert (chunk_hdr_len != 0); |
1093 | "%X\r\n", | 1105 | mhd_assert (chunk_hdr_len < sizeof(chunk_hdr)); |
1094 | (unsigned int) ret); | 1106 | connection->write_buffer_send_offset = |
1095 | mhd_assert (cblen > 0); | 1107 | (max_chunk_hdr_len - (chunk_hdr_len + 2)); |
1096 | mhd_assert ((size_t) cblen < sizeof(cbuf)); | 1108 | memcpy (connection->write_buffer + connection->write_buffer_send_offset, |
1097 | memcpy (&connection->write_buffer[sizeof (cbuf) - cblen], | 1109 | chunk_hdr, |
1098 | cbuf, | 1110 | chunk_hdr_len); |
1099 | cblen); | 1111 | connection->write_buffer[max_chunk_hdr_len - 2] = '\r'; |
1100 | memcpy (&connection->write_buffer[sizeof (cbuf) + ret], | 1112 | connection->write_buffer[max_chunk_hdr_len - 1] = '\n'; |
1101 | "\r\n", | 1113 | connection->write_buffer[max_chunk_hdr_len + ret] = '\r'; |
1102 | 2); | 1114 | connection->write_buffer[max_chunk_hdr_len + ret + 1] = '\n'; |
1103 | connection->response_write_position += ret; | 1115 | connection->response_write_position += ret; |
1104 | connection->write_buffer_send_offset = sizeof (cbuf) - cblen; | 1116 | connection->write_buffer_append_offset = max_chunk_hdr_len + ret + 2; |
1105 | connection->write_buffer_append_offset = sizeof (cbuf) + ret + 2; | ||
1106 | return MHD_YES; | 1117 | return MHD_YES; |
1107 | } | 1118 | } |
1108 | 1119 | ||