HTTPD bug fix which is caused by stack overflow.

Dependents:   mbed_controller_demo

Fork of HTTPD by Suga koubou

Original HTTPD implementation of Suga koubou is great but has some bug inside unfortunately. The most critical bug was accessing buffer with the index of out of range like following.

problematic code

char buf[256];

n = httpd->_state[id].client->receive(buf, sizeof(buf));
buf[n] =0;

With above code, it could set buf[256] = 0 when more that 255 data is received. Setting buf[256] causes some other area of memory is corrupted so that system can be predictive status since than.

bug fixed code

n = httpd->_state[id].client->receive(buf, sizeof(buf)-1);
buf[n] =0;
Committer:
okini3939
Date:
Wed Nov 13 01:58:04 2013 +0000
Revision:
0:d18dff347122
Child:
1:a4c4bd58dd3b
1st build;

Who changed what in which revision?

UserRevisionLine numberNew contents of line
okini3939 0:d18dff347122 1 /* Copyright (C) 2013 Hiroshi Suga, MIT License
okini3939 0:d18dff347122 2 *
okini3939 0:d18dff347122 3 * Permission is hereby granted, free of charge, to any person obtaining a copy of this software
okini3939 0:d18dff347122 4 * and associated documentation files (the "Software"), to deal in the Software without restriction,
okini3939 0:d18dff347122 5 * including without limitation the rights to use, copy, modify, merge, publish, distribute,
okini3939 0:d18dff347122 6 * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
okini3939 0:d18dff347122 7 * furnished to do so, subject to the following conditions:
okini3939 0:d18dff347122 8 *
okini3939 0:d18dff347122 9 * The above copyright notice and this permission notice shall be included in all copies or
okini3939 0:d18dff347122 10 * substantial portions of the Software.
okini3939 0:d18dff347122 11 *
okini3939 0:d18dff347122 12 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
okini3939 0:d18dff347122 13 * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
okini3939 0:d18dff347122 14 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
okini3939 0:d18dff347122 15 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
okini3939 0:d18dff347122 16 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
okini3939 0:d18dff347122 17 */
okini3939 0:d18dff347122 18
okini3939 0:d18dff347122 19 #include "HTTPD.h"
okini3939 0:d18dff347122 20
okini3939 0:d18dff347122 21 HTTPD * HTTPD::_inst;
okini3939 0:d18dff347122 22
okini3939 0:d18dff347122 23 HTTPD::HTTPD () {
okini3939 0:d18dff347122 24 _inst = this;
okini3939 0:d18dff347122 25 memset(_state, 0, sizeof(_state));
okini3939 0:d18dff347122 26 _handler_count = 0;
okini3939 0:d18dff347122 27 }
okini3939 0:d18dff347122 28
okini3939 0:d18dff347122 29 int HTTPD::start (int port) {
okini3939 0:d18dff347122 30 int i;
okini3939 0:d18dff347122 31
okini3939 0:d18dff347122 32 for (i = 0; i < HTTPD_MAX_CLIENTS; i ++) {
okini3939 0:d18dff347122 33 _state[i].buf = new CircBuffer<char>(HTTPD_BUF_SIZE);
okini3939 0:d18dff347122 34 _state[i].thread = new Thread(child, (void*)i, osPriorityNormal, HTTPD_STACK_SIZE);
okini3939 0:d18dff347122 35 _state[i].client = new TCPSocketConnection;
okini3939 0:d18dff347122 36 }
okini3939 0:d18dff347122 37 #ifdef HTTPD_ENABLE_CLOSER
okini3939 0:d18dff347122 38 _state[HTTPD_MAX_CLIENTS].thread = new Thread(closer, (void*)HTTPD_MAX_CLIENTS, osPriorityNormal, 128);
okini3939 0:d18dff347122 39 _state[HTTPD_MAX_CLIENTS].client = new TCPSocketConnection;
okini3939 0:d18dff347122 40 #endif
okini3939 0:d18dff347122 41
okini3939 0:d18dff347122 42 _server.bind(port);
okini3939 0:d18dff347122 43 _server.listen();
okini3939 0:d18dff347122 44 _daemon = new Thread(daemon, NULL, osPriorityNormal, 256);
okini3939 0:d18dff347122 45 return 0;
okini3939 0:d18dff347122 46 }
okini3939 0:d18dff347122 47
okini3939 0:d18dff347122 48 void HTTPD::daemon (void const *args) {
okini3939 0:d18dff347122 49 HTTPD *httpd = HTTPD::getInstance();
okini3939 0:d18dff347122 50 int i, t = 0;
okini3939 0:d18dff347122 51
okini3939 0:d18dff347122 52 INFO("Wait for new connection...\r\n");
okini3939 0:d18dff347122 53 for (;;) {
okini3939 0:d18dff347122 54 if (t >= 0) {
okini3939 0:d18dff347122 55 if (httpd->_server.accept(*httpd->_state[t].client) == 0) {
okini3939 0:d18dff347122 56 INFO("accept %d\r\n", t);
okini3939 0:d18dff347122 57 httpd->_state[t].thread->signal_set(1);
okini3939 0:d18dff347122 58 }
okini3939 0:d18dff347122 59 } else {
okini3939 0:d18dff347122 60 #ifdef HTTPD_ENABLE_CLOSER
okini3939 0:d18dff347122 61 if (httpd->_server.accept(*httpd->_state[HTTPD_MAX_CLIENTS].client) == 0) {
okini3939 0:d18dff347122 62 INFO("accept x\r\n");
okini3939 0:d18dff347122 63 httpd->_state[HTTPD_MAX_CLIENTS].thread->signal_set(1);
okini3939 0:d18dff347122 64 }
okini3939 0:d18dff347122 65 #endif
okini3939 0:d18dff347122 66 }
okini3939 0:d18dff347122 67
okini3939 0:d18dff347122 68 t = -1;
okini3939 0:d18dff347122 69 for (i = 0; i < HTTPD_MAX_CLIENTS; i ++) {
okini3939 0:d18dff347122 70 if (httpd->_state[i].thread->get_state() == Thread::WaitingAnd) {
okini3939 0:d18dff347122 71 if (t < 0) t = i; // next empty thread
okini3939 0:d18dff347122 72 }
okini3939 0:d18dff347122 73 }
okini3939 0:d18dff347122 74 }
okini3939 0:d18dff347122 75 }
okini3939 0:d18dff347122 76
okini3939 0:d18dff347122 77 void HTTPD::child (void const *arg) {
okini3939 0:d18dff347122 78 HTTPD *httpd = HTTPD::getInstance();
okini3939 0:d18dff347122 79 int id = (int)arg;
okini3939 0:d18dff347122 80 int i, n;
okini3939 0:d18dff347122 81 char buf[HTTPD_BUF_SIZE];
okini3939 0:d18dff347122 82
okini3939 0:d18dff347122 83 for (;;) {
okini3939 0:d18dff347122 84 Thread::signal_wait(1);
okini3939 0:d18dff347122 85
okini3939 0:d18dff347122 86 httpd->_state[id].mode = MODE_REQUEST;
okini3939 0:d18dff347122 87 httpd->_state[id].buf->flush();
okini3939 0:d18dff347122 88 httpd->_state[id].keepalive = 0;
okini3939 0:d18dff347122 89 INFO("Connection from %s\r\n", httpd->_state[id].client->get_address());
okini3939 0:d18dff347122 90 httpd->_state[id].client->set_blocking(false, HTTPD_TIMEOUT);
okini3939 0:d18dff347122 91 for (;;) {
okini3939 0:d18dff347122 92 if (! httpd->_state[id].client->is_connected()) break;
okini3939 0:d18dff347122 93
okini3939 0:d18dff347122 94 n = httpd->_state[id].client->receive(buf, sizeof(buf));
okini3939 0:d18dff347122 95 if (n < 0) break;
okini3939 0:d18dff347122 96 buf[n] = 0;
okini3939 0:d18dff347122 97 // DBG("Recv %d '%s'", n, buf);
okini3939 0:d18dff347122 98
okini3939 0:d18dff347122 99 for (i = 0; i < n; i ++) {
okini3939 0:d18dff347122 100 httpd->recvData(id, buf[i]);
okini3939 0:d18dff347122 101 }
okini3939 0:d18dff347122 102 }
okini3939 0:d18dff347122 103
okini3939 0:d18dff347122 104 httpd->_state[id].client->close();
okini3939 0:d18dff347122 105 INFO("Close %s\r\n", httpd->_state[id].client->get_address());
okini3939 0:d18dff347122 106 }
okini3939 0:d18dff347122 107 }
okini3939 0:d18dff347122 108
okini3939 0:d18dff347122 109 void HTTPD::closer (void const *arg) {
okini3939 0:d18dff347122 110 HTTPD *httpd = HTTPD::getInstance();
okini3939 0:d18dff347122 111 int id = (int)arg;
okini3939 0:d18dff347122 112
okini3939 0:d18dff347122 113 for (;;) {
okini3939 0:d18dff347122 114 Thread::signal_wait(1);
okini3939 0:d18dff347122 115
okini3939 0:d18dff347122 116 httpd->_state[id].client->close();
okini3939 0:d18dff347122 117 INFO("Close %s\r\n", httpd->_state[id].client->get_address());
okini3939 0:d18dff347122 118 }
okini3939 0:d18dff347122 119 }
okini3939 0:d18dff347122 120