Klaus Demo bjoern / 449f647
Haha This has to be my most embarrasing bug of all times. Embarassing because it is so stupid (assumption that HTTP header will never be larger than 1024 bytes), and because it has been in the project literally for forever. See first commit that adds HTTP support header from 2010 (!): a92d99f95bbbe7f5f009e8b35c3859f3d5707b00 It's a miracle no one EVER reported this. I guess people just switched to sane web server alternative when it first crashed on them. Well great we got this figured out now! Jonas Haag 2 years ago
1 changed file(s) with 19 addition(s) and 10 deletion(s). Raw diff Collapse all Expand all
22 #include "wsgi.h"
33 #include "py2py3.h"
44
5 static size_t wsgi_getheaders(Request*, PyObject* buf);
5 static void wsgi_getheaders(Request*, PyObject** buf, Py_ssize_t* length);
66
77 typedef struct {
88 PyObject_HEAD
138138 * At least for small responses, the complete response could be sent with
139139 * one send() call (in server.c:ev_io_on_write) which is a (tiny) performance
140140 * booster because less kernel calls means less kernel call overhead. */
141 PyObject* buf = _Bytes_FromStringAndSize(NULL, 1024);
142 Py_ssize_t length = wsgi_getheaders(request, buf);
141 Py_ssize_t length;
142 PyObject* buf;
143 wsgi_getheaders(request, &buf, &length);
143144
144145 if(first_chunk == NULL) {
145146 _Bytes_Resize(&buf, length);
153154 first_chunk = new_chunk;
154155 }
155156
156 assert(buf);
157157 _Bytes_Resize(&buf, length + _Bytes_GET_SIZE(first_chunk));
158158 memcpy((void *)(_Bytes_AS_DATA(buf)+length), _Bytes_AS_DATA(first_chunk),
159159 _Bytes_GET_SIZE(first_chunk));
160
161160 Py_DECREF(first_chunk);
162161
163162 out:
213212 }
214213
215214
216 static size_t
217 wsgi_getheaders(Request* request, PyObject* buf)
218 {
219 char* bufp = (char *)_Bytes_AS_DATA(buf);
215 static void
216 wsgi_getheaders(Request* request, PyObject** buf, Py_ssize_t *length)
217 {
218 Py_ssize_t length_upperbound = strlen("HTTP/1.1 ") + _Bytes_GET_SIZE(request->status) + strlen("\r\nTransfer-Encoding: chunked") + strlen("\r\n\rn");
219 for(Py_ssize_t i=0; i<PyList_GET_SIZE(request->headers); ++i) {
220 PyObject* tuple = PyList_GET_ITEM(request->headers, i);
221 PyObject* field = PyTuple_GET_ITEM(tuple, 0);
222 PyObject* value = PyTuple_GET_ITEM(tuple, 1);
223 length_upperbound += strlen("\r\n") + _Bytes_GET_SIZE(field) + strlen(": ") + _Bytes_GET_SIZE(value);
224 }
225
226 PyObject* bufobj = _Bytes_FromStringAndSize(NULL, length_upperbound);
227 char* bufp = (char *)_Bytes_AS_DATA(bufobj);
220228
221229 #define buf_write(src, len) \
222230 do { \
257265
258266 buf_write2("\r\n\r\n");
259267
260 return bufp - _Bytes_AS_DATA(buf);
268 *buf = bufobj;
269 *length = bufp - _Bytes_AS_DATA(bufobj);
261270 }
262271
263272 inline PyObject*