aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEvgeny Grin (Karlson2k) <k2k@narod.ru>2021-06-07 21:18:49 +0300
committerEvgeny Grin (Karlson2k) <k2k@narod.ru>2021-07-28 11:28:43 +0300
commit2cab7e09b796aa3c228b1b5e04844061a9e78812 (patch)
treeebe2ff8b84eefc4c658ad02045d54d674d812a36
parentee3f32220038303ebf1bfcf1494c9badf6d3adc4 (diff)
downloadlibmicrohttpd-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.c75
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