aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--doc/libmicrohttpd.texi2
-rw-r--r--src/include/microhttpd.h6
-rw-r--r--src/microhttpd/connection.c13
-rw-r--r--src/microhttpd/internal.h92
-rw-r--r--src/microhttpd/response.c217
5 files changed, 169 insertions, 161 deletions
diff --git a/doc/libmicrohttpd.texi b/doc/libmicrohttpd.texi
index 2a4f09d2..bb6cab7c 100644
--- a/doc/libmicrohttpd.texi
+++ b/doc/libmicrohttpd.texi
@@ -2181,7 +2181,7 @@ The response object can be extended with header information and then be used
2181any number of times. 2181any number of times.
2182@table @var 2182@table @var
2183@item iov 2183@item iov
2184the array for response data buffers, an internal copy of this will be made; 2184the array for response data buffers, an internal copy of this will be made; however, note that the data pointed to by the @var{iov} is not copied and must be preserved unchanged at the given locations until the response is no longer in use and the @var{crfc} is called;
2185 2185
2186@item iovcnt 2186@item iovcnt
2187the number of elements in @var{iov}; 2187the number of elements in @var{iov};
diff --git a/src/include/microhttpd.h b/src/include/microhttpd.h
index b416e62a..1d44f344 100644
--- a/src/include/microhttpd.h
+++ b/src/include/microhttpd.h
@@ -1974,14 +1974,14 @@ union MHD_ConnectionInfo
1974 1974
1975 1975
1976/** 1976/**
1977 * I/O vector type. Provided for use with MHD_create_response_from_iovec. 1977 * I/O vector type. Provided for use with #MHD_create_response_from_iovec().
1978 */ 1978 */
1979struct MHD_IoVec 1979struct MHD_IoVec
1980{ 1980{
1981 /** 1981 /**
1982 * The pointer to the memory region for I/O. 1982 * The pointer to the memory region for I/O.
1983 */ 1983 */
1984 void *iov_base; 1984 const void *iov_base;
1985 1985
1986 /** 1986 /**
1987 * The size in bytes of the memory region for I/O. 1987 * The size in bytes of the memory region for I/O.
@@ -3262,7 +3262,7 @@ MHD_create_response_from_fd_at_offset64 (uint64_t size,
3262 */ 3262 */
3263_MHD_EXTERN struct MHD_Response * 3263_MHD_EXTERN struct MHD_Response *
3264MHD_create_response_from_iovec (const struct MHD_IoVec *iov, 3264MHD_create_response_from_iovec (const struct MHD_IoVec *iov,
3265 int iovcnt, 3265 unsigned int iovcnt,
3266 MHD_ContentReaderFreeCallback free_cb, 3266 MHD_ContentReaderFreeCallback free_cb,
3267 void *cls); 3267 void *cls);
3268 3268
diff --git a/src/microhttpd/connection.c b/src/microhttpd/connection.c
index 7f2dcd75..25d920e2 100644
--- a/src/microhttpd/connection.c
+++ b/src/microhttpd/connection.c
@@ -800,11 +800,12 @@ try_ready_normal_body (struct MHD_Connection *connection)
800 if (NULL != response->data_iov) 800 if (NULL != response->data_iov)
801 { 801 {
802 size_t copy_size; 802 size_t copy_size;
803
803 if (NULL != connection->resp_iov.iov) 804 if (NULL != connection->resp_iov.iov)
804 return MHD_YES; 805 return MHD_YES;
805
806 copy_size = response->data_iovcnt * sizeof(MHD_iovec_); 806 copy_size = response->data_iovcnt * sizeof(MHD_iovec_);
807 connection->resp_iov.iov = MHD_pool_allocate (connection->pool, copy_size, 807 connection->resp_iov.iov = MHD_pool_allocate (connection->pool,
808 copy_size,
808 true); 809 true);
809 if (NULL == connection->resp_iov.iov) 810 if (NULL == connection->resp_iov.iov)
810 { 811 {
@@ -814,7 +815,9 @@ try_ready_normal_body (struct MHD_Connection *connection)
814 _ ("Closing connection (out of memory).\n")); 815 _ ("Closing connection (out of memory).\n"));
815 return MHD_NO; 816 return MHD_NO;
816 } 817 }
817 memcpy (connection->resp_iov.iov, response->data_iov, copy_size); 818 memcpy (connection->resp_iov.iov,
819 response->data_iov,
820 copy_size);
818 connection->resp_iov.cnt = response->data_iovcnt; 821 connection->resp_iov.cnt = response->data_iovcnt;
819 connection->resp_iov.sent = 0; 822 connection->resp_iov.sent = 0;
820 return MHD_YES; 823 return MHD_YES;
@@ -3047,7 +3050,9 @@ MHD_connection_handle_write (struct MHD_Connection *connection)
3047#endif /* _MHD_HAVE_SENDFILE */ 3050#endif /* _MHD_HAVE_SENDFILE */
3048 if (NULL != response->data_iov) 3051 if (NULL != response->data_iov)
3049 { 3052 {
3050 ret = MHD_send_iovec_ (connection, &connection->resp_iov, true); 3053 ret = MHD_send_iovec_ (connection,
3054 &connection->resp_iov,
3055 true);
3051 } 3056 }
3052 else 3057 else
3053 { 3058 {
diff --git a/src/microhttpd/internal.h b/src/microhttpd/internal.h
index ba71d1eb..06e7e4a7 100644
--- a/src/microhttpd/internal.h
+++ b/src/microhttpd/internal.h
@@ -92,8 +92,9 @@
92 * @param fd the FD to close 92 * @param fd the FD to close
93 */ 93 */
94#define MHD_fd_close_chk_(fd) do { \ 94#define MHD_fd_close_chk_(fd) do { \
95 if ( (0 != close ((fd)) && (EBADF == errno)) ) \ 95 if ( (0 != close ((fd)) && (EBADF == errno)) ) { \
96 MHD_PANIC (_ ("Failed to close FD.\n")); \ 96 MHD_PANIC (_ ("Failed to close FD.\n")); \
97 } \
97} while (0) 98} while (0)
98 99
99/* 100/*
@@ -509,7 +510,7 @@ struct MHD_Response
509 /** 510 /**
510 * Number of elements in data_iov. 511 * Number of elements in data_iov.
511 */ 512 */
512 size_t data_iovcnt; 513 unsigned int data_iovcnt;
513}; 514};
514 515
515 516
@@ -1933,12 +1934,13 @@ struct MHD_Daemon
1933#define DLL_insert(head,tail,element) do { \ 1934#define DLL_insert(head,tail,element) do { \
1934 mhd_assert (NULL == (element)->next); \ 1935 mhd_assert (NULL == (element)->next); \
1935 mhd_assert (NULL == (element)->prev); \ 1936 mhd_assert (NULL == (element)->prev); \
1936 (element)->next = (head); \ 1937 (element)->next = (head); \
1937 (element)->prev = NULL; \ 1938 (element)->prev = NULL; \
1938 if ((tail) == NULL) \ 1939 if ((tail) == NULL) { \
1939 (tail) = element; \ 1940 (tail) = element; \
1940 else \ 1941 } else { \
1941 (head)->prev = element; \ 1942 (head)->prev = element; \
1943 } \
1942 (head) = (element); } while (0) 1944 (head) = (element); } while (0)
1943 1945
1944 1946
@@ -1954,15 +1956,17 @@ struct MHD_Daemon
1954#define DLL_remove(head,tail,element) do { \ 1956#define DLL_remove(head,tail,element) do { \
1955 mhd_assert ( (NULL != (element)->next) || ((element) == (tail))); \ 1957 mhd_assert ( (NULL != (element)->next) || ((element) == (tail))); \
1956 mhd_assert ( (NULL != (element)->prev) || ((element) == (head))); \ 1958 mhd_assert ( (NULL != (element)->prev) || ((element) == (head))); \
1957 if ((element)->prev == NULL) \ 1959 if ((element)->prev == NULL) { \
1958 (head) = (element)->next; \ 1960 (head) = (element)->next; \
1959 else \ 1961 } else { \
1960 (element)->prev->next = (element)->next; \ 1962 (element)->prev->next = (element)->next; \
1961 if ((element)->next == NULL) \ 1963 } \
1962 (tail) = (element)->prev; \ 1964 if ((element)->next == NULL) { \
1963 else \ 1965 (tail) = (element)->prev; \
1966 } else { \
1964 (element)->next->prev = (element)->prev; \ 1967 (element)->next->prev = (element)->prev; \
1965 (element)->next = NULL; \ 1968 } \
1969 (element)->next = NULL; \
1966 (element)->prev = NULL; } while (0) 1970 (element)->prev = NULL; } while (0)
1967 1971
1968 1972
@@ -1977,12 +1981,13 @@ struct MHD_Daemon
1977#define XDLL_insert(head,tail,element) do { \ 1981#define XDLL_insert(head,tail,element) do { \
1978 mhd_assert (NULL == (element)->nextX); \ 1982 mhd_assert (NULL == (element)->nextX); \
1979 mhd_assert (NULL == (element)->prevX); \ 1983 mhd_assert (NULL == (element)->prevX); \
1980 (element)->nextX = (head); \ 1984 (element)->nextX = (head); \
1981 (element)->prevX = NULL; \ 1985 (element)->prevX = NULL; \
1982 if (NULL == (tail)) \ 1986 if (NULL == (tail)) { \
1983 (tail) = element; \ 1987 (tail) = element; \
1984 else \ 1988 } else { \
1985 (head)->prevX = element; \ 1989 (head)->prevX = element; \
1990 } \
1986 (head) = (element); } while (0) 1991 (head) = (element); } while (0)
1987 1992
1988 1993
@@ -1998,15 +2003,17 @@ struct MHD_Daemon
1998#define XDLL_remove(head,tail,element) do { \ 2003#define XDLL_remove(head,tail,element) do { \
1999 mhd_assert ( (NULL != (element)->nextX) || ((element) == (tail))); \ 2004 mhd_assert ( (NULL != (element)->nextX) || ((element) == (tail))); \
2000 mhd_assert ( (NULL != (element)->prevX) || ((element) == (head))); \ 2005 mhd_assert ( (NULL != (element)->prevX) || ((element) == (head))); \
2001 if (NULL == (element)->prevX) \ 2006 if (NULL == (element)->prevX) { \
2002 (head) = (element)->nextX; \ 2007 (head) = (element)->nextX; \
2003 else \ 2008 } else { \
2004 (element)->prevX->nextX = (element)->nextX; \ 2009 (element)->prevX->nextX = (element)->nextX; \
2005 if (NULL == (element)->nextX) \ 2010 } \
2006 (tail) = (element)->prevX; \ 2011 if (NULL == (element)->nextX) { \
2007 else \ 2012 (tail) = (element)->prevX; \
2013 } else { \
2008 (element)->nextX->prevX = (element)->prevX; \ 2014 (element)->nextX->prevX = (element)->prevX; \
2009 (element)->nextX = NULL; \ 2015 } \
2016 (element)->nextX = NULL; \
2010 (element)->prevX = NULL; } while (0) 2017 (element)->prevX = NULL; } while (0)
2011 2018
2012 2019
@@ -2020,11 +2027,12 @@ struct MHD_Daemon
2020 */ 2027 */
2021#define EDLL_insert(head,tail,element) do { \ 2028#define EDLL_insert(head,tail,element) do { \
2022 (element)->nextE = (head); \ 2029 (element)->nextE = (head); \
2023 (element)->prevE = NULL; \ 2030 (element)->prevE = NULL; \
2024 if ((tail) == NULL) \ 2031 if ((tail) == NULL) { \
2025 (tail) = element; \ 2032 (tail) = element; \
2026 else \ 2033 } else { \
2027 (head)->prevE = element; \ 2034 (head)->prevE = element; \
2035 } \
2028 (head) = (element); } while (0) 2036 (head) = (element); } while (0)
2029 2037
2030 2038
@@ -2037,16 +2045,18 @@ struct MHD_Daemon
2037 * @param tail pointer to the tail of the EDLL 2045 * @param tail pointer to the tail of the EDLL
2038 * @param element element to remove 2046 * @param element element to remove
2039 */ 2047 */
2040#define EDLL_remove(head,tail,element) do { \ 2048#define EDLL_remove(head,tail,element) do { \
2041 if ((element)->prevE == NULL) \ 2049 if ((element)->prevE == NULL) { \
2042 (head) = (element)->nextE; \ 2050 (head) = (element)->nextE; \
2043 else \ 2051 } else { \
2044 (element)->prevE->nextE = (element)->nextE; \ 2052 (element)->prevE->nextE = (element)->nextE; \
2045 if ((element)->nextE == NULL) \ 2053 } \
2046 (tail) = (element)->prevE; \ 2054 if ((element)->nextE == NULL) { \
2047 else \ 2055 (tail) = (element)->prevE; \
2056 } else { \
2048 (element)->nextE->prevE = (element)->prevE; \ 2057 (element)->nextE->prevE = (element)->prevE; \
2049 (element)->nextE = NULL; \ 2058 } \
2059 (element)->nextE = NULL; \
2050 (element)->prevE = NULL; } while (0) 2060 (element)->prevE = NULL; } while (0)
2051 2061
2052 2062
diff --git a/src/microhttpd/response.c b/src/microhttpd/response.c
index 3dbcd245..14e036c8 100644
--- a/src/microhttpd/response.c
+++ b/src/microhttpd/response.c
@@ -1,6 +1,6 @@
1/* 1/*
2 This file is part of libmicrohttpd 2 This file is part of libmicrohttpd
3 Copyright (C) 2007, 2009, 2010, 2016, 2017 Daniel Pittman and Christian Grothoff 3 Copyright (C) 2007-2021 Daniel Pittman and Christian Grothoff
4 4
5 This library is free software; you can redistribute it and/or 5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public 6 modify it under the terms of the GNU Lesser General Public
@@ -861,135 +861,128 @@ MHD_create_response_from_buffer_with_free_callback (size_t size,
861 */ 861 */
862_MHD_EXTERN struct MHD_Response * 862_MHD_EXTERN struct MHD_Response *
863MHD_create_response_from_iovec (const struct MHD_IoVec *iov, 863MHD_create_response_from_iovec (const struct MHD_IoVec *iov,
864 int iovcnt, 864 unsigned int iovcnt,
865 MHD_ContentReaderFreeCallback free_cb, 865 MHD_ContentReaderFreeCallback free_cb,
866 void *cls) 866 void *cls)
867{ 867{
868 struct MHD_Response *response; 868 struct MHD_Response *response;
869 unsigned int i;
870 int i_cp = 0; /**< Index in the copy of iov */
871 uint64_t total_size = 0;
872 const void *last_valid_buffer = NULL;
869 873
870 if ((NULL == iov) && (0 < iovcnt)) 874 if ((NULL == iov) && (0 < iovcnt))
871 return NULL; 875 return NULL;
872 876
873 response = MHD_calloc_ (1, sizeof (struct MHD_Response)); 877 response = MHD_calloc_ (1, sizeof (struct MHD_Response));
874 if (NULL != response) 878 if (NULL == response)
879 return NULL;
880 if (! MHD_mutex_init_ (&response->mutex))
881 {
882 free (response);
883 return NULL;
884 }
885 /* Calculate final size, number of valid elements, and check 'iov' */
886 for (i = 0; i < iovcnt; ++i)
875 { 887 {
876 if (MHD_mutex_init_ (&response->mutex)) 888 if (0 == iov[i].iov_len)
889 continue; /* skip zero-sized elements */
890 if (NULL == iov[i].iov_base)
877 { 891 {
878 int i; 892 i_cp = -1; /* error */
879 int i_cp; /**< Index in the copy of iov */ 893 break;
880 uint64_t total_size; 894 }
881 void *last_valid_buffer; 895 if ( (total_size > (total_size + iov[i].iov_len)) ||
882 896 (INT_MAX == i_cp) ||
883 i_cp = 0; 897 (SSIZE_MAX < iov[i].iov_len) )
884 total_size = 0; 898 {
885 last_valid_buffer = NULL; 899 i_cp = -1; /* overflow */
886 /* Calculate final size, number of valid elements, and check 'iov' */ 900 break;
887 for (i = 0; iovcnt > i; ++i) 901 }
888 { 902 last_valid_buffer = iov[i].iov_base;
889#if defined(MHD_WINSOCK_SOCKETS) && defined(_WIN64) 903 total_size += iov[i].iov_len;
890 int64_t i_add;
891#endif /* ! MHD_WINSOCK_SOCKETS && _WIN64 */
892 if (0 == iov[i].iov_len)
893 continue; /* skip zero-sized elements */
894
895 if (NULL == iov[i].iov_base)
896 {
897 i_cp = -1; /* error */
898 break;
899 }
900 if ( (total_size > (total_size + iov[i].iov_len)) ||
901 (INT_MAX == i_cp) ||
902 (SSIZE_MAX < iov[i].iov_len) )
903 {
904 i_cp = -1; /* overflow */
905 break;
906 }
907 last_valid_buffer = iov[i].iov_base;
908 total_size += iov[i].iov_len;
909#if defined(MHD_POSIX_SOCKETS) || ! defined(_WIN64) 904#if defined(MHD_POSIX_SOCKETS) || ! defined(_WIN64)
910 i_cp++; 905 i_cp++;
911#else /* ! MHD_POSIX_SOCKETS && _WIN64 */ 906#else /* ! MHD_POSIX_SOCKETS && _WIN64 */
912 i_add = iov[i].iov_len / ULONG_MAX; 907 {
913 if (0 != iov[i].iov_len % ULONG_MAX) 908 int64_t i_add;
914 i_add++; 909
915 if (INT_MAX < (i_add + i_cp)) 910 i_add = iov[i].iov_len / ULONG_MAX;
916 { 911 if (0 != iov[i].iov_len % ULONG_MAX)
917 i_cp = -1; /* overflow */ 912 i_add++;
918 break; 913 if (INT_MAX < (i_add + i_cp))
919 }
920 i_cp += (int) i_add;
921#endif /* ! MHD_POSIX_SOCKETS && _WIN64 */
922 }
923 if (0 <= i_cp)
924 { 914 {
925 response->fd = -1; 915 i_cp = -1; /* overflow */
926 response->reference_count = 1; 916 break;
927 response->total_size = total_size;
928 response->crc_cls = cls;
929 response->crfc = free_cb;
930 if (1 < i_cp)
931 {
932 MHD_iovec_ *iov_copy;
933 int num_copy_elements = i_cp;
934
935 iov_copy = MHD_calloc_ (num_copy_elements, sizeof(MHD_iovec_));
936 if (NULL != iov_copy)
937 {
938 i_cp = 0;
939 for (i = 0; iovcnt > i; ++i)
940 {
941 size_t element_size;
942 uint8_t *buf;
943
944 if (0 == iov[i].iov_len)
945 continue; /* skip zero-sized elements */
946
947 buf = (uint8_t*) iov[i].iov_base;
948 element_size = iov[i].iov_len;
949#if defined(MHD_WINSOCK_SOCKETS) && defined(_WIN64)
950 while (ULONG_MAX < element_size)
951 {
952 iov_copy[i_cp].iov_base = (void*) buf;
953 iov_copy[i_cp].iov_len = ULONG_MAX;
954 buf += ULONG_MAX;
955 element_size -= ULONG_MAX;
956 i_cp++;
957 }
958#endif /* MHD_WINSOCK_SOCKETS && _WIN64 */
959 iov_copy[i_cp].iov_base = (void*) buf;
960 iov_copy[i_cp].iov_len = element_size;
961 i_cp++;
962 }
963
964 mhd_assert (num_copy_elements == i_cp);
965 response->data_iov = iov_copy;
966 response->data_iovcnt = i_cp;
967
968 return response;
969 }
970
971 }
972 else if (1 == i_cp)
973 {
974 mhd_assert (NULL != last_valid_buffer);
975 response->data = last_valid_buffer;
976 response->data_size = total_size;
977
978 return response;
979 }
980 else /* if (0 == i_nz) */
981 {
982 mhd_assert (0 == total_size);
983
984 return response;
985 }
986 } 917 }
987 /* Some error condition */ 918 i_cp += (int) i_add;
988 MHD_mutex_destroy_chk_ (&response->mutex);
989 } 919 }
920#endif /* ! MHD_POSIX_SOCKETS && _WIN64 */
921 }
922 if (-1 == i_cp)
923 {
924 /* Some error condition */
925 MHD_mutex_destroy_chk_ (&response->mutex);
990 free (response); 926 free (response);
927 return NULL;
928 }
929 response->fd = -1;
930 response->reference_count = 1;
931 response->total_size = total_size;
932 response->crc_cls = cls;
933 response->crfc = free_cb;
934 if (0 == i_cp)
935 {
936 mhd_assert (0 == total_size);
937 return response;
938 }
939 if (1 == i_cp)
940 {
941 mhd_assert (NULL != last_valid_buffer);
942 response->data = (void *) last_valid_buffer;
943 response->data_size = total_size;
944 return response;
945 }
946 mhd_assert (1 < i_cp);
947 {
948 MHD_iovec_ *iov_copy;
949 int num_copy_elements = i_cp;
950
951 iov_copy = MHD_calloc_ (num_copy_elements,
952 sizeof(MHD_iovec_));
953 if (NULL == iov_copy)
954 {
955 MHD_mutex_destroy_chk_ (&response->mutex);
956 free (response);
957 return NULL;
958 }
959 i_cp = 0;
960 for (i = 0; i < iovcnt; ++i)
961 {
962 size_t element_size = iov[i].iov_len;
963 const void *buf = iov[i].iov_base;
964
965 if (0 == element_size)
966 continue; /* skip zero-sized elements */
967#if defined(MHD_WINSOCK_SOCKETS) && defined(_WIN64)
968 while (ULONG_MAX < element_size)
969 {
970 iov_copy[i_cp].iov_base = buf;
971 iov_copy[i_cp].iov_len = ULONG_MAX;
972 buf += ULONG_MAX;
973 element_size -= ULONG_MAX;
974 i_cp++;
975 }
976#endif /* MHD_WINSOCK_SOCKETS && _WIN64 */
977 iov_copy[i_cp].iov_base = (void *) buf;
978 iov_copy[i_cp].iov_len = element_size;
979 i_cp++;
980 }
981 mhd_assert (num_copy_elements == i_cp);
982 response->data_iov = iov_copy;
983 response->data_iovcnt = i_cp;
984 return response;
991 } 985 }
992 return NULL;
993} 986}
994 987
995 988