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:
hillkim7
Date:
Fri Apr 10 09:04:38 2015 +0000
Revision:
2:584ce0a1a76e
Parent:
0:d18dff347122
Fix critical bug cause by accessing buffer with index of out of range.; Set reasonable stack size for server task.

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 #ifndef HTTPD_H
okini3939 0:d18dff347122 20 #define HTTPD_H
okini3939 0:d18dff347122 21
okini3939 0:d18dff347122 22 #include "mbed.h"
okini3939 0:d18dff347122 23 #include "rtos.h"
okini3939 0:d18dff347122 24 #include "EthernetInterface.h"
okini3939 0:d18dff347122 25 #include "CBuffer.h"
okini3939 0:d18dff347122 26
okini3939 0:d18dff347122 27 //#define DEBUG
okini3939 0:d18dff347122 28
okini3939 0:d18dff347122 29 #define HTTPD_PORT 80
okini3939 0:d18dff347122 30 #define HTTPD_MAX_CLIENTS 2
okini3939 0:d18dff347122 31 #define HTTPD_KEEPALIVE 10
okini3939 0:d18dff347122 32 #define HTTPD_TIMEOUT 15000
okini3939 0:d18dff347122 33 #define HTTPD_MAX_HANDLES 10
okini3939 0:d18dff347122 34
okini3939 0:d18dff347122 35 #define HTTPD_CMD_SIZE 100
okini3939 0:d18dff347122 36 #define HTTPD_BUF_SIZE 256
hillkim7 2:584ce0a1a76e 37 //#define HTTPD_STACK_SIZE (1024 * 6)
hillkim7 2:584ce0a1a76e 38 // The HTTPD_STACK_SIZE is too much for clild thread, so it is reduced.
hillkim7 2:584ce0a1a76e 39 // See following Callgraph report of Keil MDK.
hillkim7 2:584ce0a1a76e 40 #define HTTPD_STACK_SIZE (1024 * 2)
hillkim7 2:584ce0a1a76e 41 /*
hillkim7 2:584ce0a1a76e 42 HTTPD::child(const void*) (Thumb, 244 bytes, Stack size 272 bytes, httpd.o(.text))
hillkim7 2:584ce0a1a76e 43
hillkim7 2:584ce0a1a76e 44 [Stack]
hillkim7 2:584ce0a1a76e 45
hillkim7 2:584ce0a1a76e 46 Max Depth = 1288 + Unknown Stack Size
hillkim7 2:584ce0a1a76e 47 Call Chain = HTTPD::child(const void*) <-> HTTPD::recvData(int, char) <->
hillkim7 2:584ce0a1a76e 48 HTTPD::httpdFile(int, char*) <-> fopen <-> _freopen_locked <-> _sys_open <->
hillkim7 2:584ce0a1a76e 49 */
okini3939 0:d18dff347122 50 //#define HTTPD_ENABLE_CLOSER
okini3939 0:d18dff347122 51
okini3939 0:d18dff347122 52 //Debug is disabled by default
okini3939 0:d18dff347122 53 #if defined(DEBUG) and (!defined(TARGET_LPC11U24))
okini3939 0:d18dff347122 54 #define DBG(x, ...) std::printf("[DBG]" x "\r\n", ##__VA_ARGS__);
okini3939 0:d18dff347122 55 #define WARN(x, ...) std::printf("[WARN]" x "\r\n", ##__VA_ARGS__);
okini3939 0:d18dff347122 56 #define ERR(x, ...) std::printf("[ERR]" x "\r\n", ##__VA_ARGS__);
okini3939 0:d18dff347122 57 #define INFO(x, ...) std::printf("[INFO]" x "\r\n", ##__VA_ARGS__);
okini3939 0:d18dff347122 58 #else
okini3939 0:d18dff347122 59 #define DBG(x, ...)
okini3939 0:d18dff347122 60 #define WARN(x, ...)
okini3939 0:d18dff347122 61 #define ERR(x, ...)
okini3939 0:d18dff347122 62 #define INFO(x, ...)
okini3939 0:d18dff347122 63 #endif
okini3939 0:d18dff347122 64
okini3939 0:d18dff347122 65
okini3939 0:d18dff347122 66 class HTTPD {
okini3939 0:d18dff347122 67 public:
okini3939 0:d18dff347122 68
okini3939 0:d18dff347122 69 enum Request {
okini3939 0:d18dff347122 70 REQ_HTTPGET,
okini3939 0:d18dff347122 71 REQ_HTTPPOST,
okini3939 0:d18dff347122 72 REQ_PUT,
okini3939 0:d18dff347122 73 };
okini3939 0:d18dff347122 74
okini3939 0:d18dff347122 75 enum Mode {
okini3939 0:d18dff347122 76 MODE_REQUEST,
okini3939 0:d18dff347122 77 MODE_REQSTR,
okini3939 0:d18dff347122 78 MODE_HEADER,
okini3939 0:d18dff347122 79 MODE_BODY,
okini3939 0:d18dff347122 80 MODE_ENTER,
okini3939 0:d18dff347122 81 MODE_ERROR,
okini3939 0:d18dff347122 82 MODE_WEBSOCKET,
okini3939 0:d18dff347122 83 MODE_WEBSOCKET_MASK,
okini3939 0:d18dff347122 84 MODE_WEBSOCKET_BODY,
okini3939 0:d18dff347122 85 MODE_WEBSOCKET_ENTER,
okini3939 0:d18dff347122 86 };
okini3939 0:d18dff347122 87
okini3939 0:d18dff347122 88 struct STATE {
okini3939 0:d18dff347122 89 Thread *thread;
okini3939 0:d18dff347122 90 TCPSocketConnection *client;
okini3939 0:d18dff347122 91 volatile Request req;
okini3939 0:d18dff347122 92 volatile Mode mode;
okini3939 0:d18dff347122 93 CircBuffer <char>*buf;
okini3939 0:d18dff347122 94 char uri[HTTPD_CMD_SIZE];
okini3939 0:d18dff347122 95 char *filename;
okini3939 0:d18dff347122 96 char *querystring;
okini3939 0:d18dff347122 97 int enter;
okini3939 0:d18dff347122 98 int length;
okini3939 0:d18dff347122 99 int n;
okini3939 0:d18dff347122 100 int keepalive;
okini3939 0:d18dff347122 101 int websocket;
okini3939 0:d18dff347122 102 char *websocket_key;
okini3939 0:d18dff347122 103 int websocket_opcode;
okini3939 0:d18dff347122 104 int websocket_flg;
okini3939 0:d18dff347122 105 char websocket_mask[4];
okini3939 0:d18dff347122 106 int websocket_payload;
okini3939 0:d18dff347122 107 int (*sendws)(int id, const char *buf, int len, const char *mask);
okini3939 0:d18dff347122 108 };
okini3939 0:d18dff347122 109
okini3939 0:d18dff347122 110 HTTPD ();
okini3939 0:d18dff347122 111
okini3939 0:d18dff347122 112 int start (int port = HTTPD_PORT);
okini3939 0:d18dff347122 113
okini3939 0:d18dff347122 114 // --- HTTPD_req.cpp ---
okini3939 0:d18dff347122 115 void httpdError (int id, int err);
okini3939 0:d18dff347122 116
okini3939 0:d18dff347122 117 // --- HTTPD_ws.cpp ---
okini3939 0:d18dff347122 118 static int sendWebsocket (int id, const char *buf, int len, const char *mask = NULL);
okini3939 0:d18dff347122 119
okini3939 0:d18dff347122 120 // --- HTTPD_util.cpp ---
okini3939 0:d18dff347122 121 char *getUri (int id);
okini3939 0:d18dff347122 122 char *getFilename (int id);
okini3939 0:d18dff347122 123 char *getQueryString (int id);
okini3939 0:d18dff347122 124 int send (int id, const char *body, int len, const char *header = NULL);
okini3939 0:d18dff347122 125 int receive (int id, char *buf, int len);
okini3939 0:d18dff347122 126 int attach (const char *uri, const char *dir);
okini3939 0:d18dff347122 127 int attach (const char *uri, void (*funcCgi)(int id));
okini3939 0:d18dff347122 128 int base64encode (const char *input, int length, char *output, int len);
okini3939 0:d18dff347122 129 int urlencode (const char *str, char *buf, int len);
okini3939 0:d18dff347122 130 int urldecode (const char *str, char *buf, int len);
okini3939 0:d18dff347122 131
okini3939 0:d18dff347122 132 static HTTPD * getInstance() {
okini3939 0:d18dff347122 133 return _inst;
okini3939 0:d18dff347122 134 };
okini3939 0:d18dff347122 135
okini3939 0:d18dff347122 136 private :
okini3939 0:d18dff347122 137 static HTTPD *_inst;
okini3939 0:d18dff347122 138 Thread *_daemon;
okini3939 0:d18dff347122 139 TCPSocketServer _server;
okini3939 0:d18dff347122 140
okini3939 0:d18dff347122 141 #ifdef HTTPD_ENABLE_CLOSER
okini3939 0:d18dff347122 142 struct STATE _state[HTTPD_MAX_CLIENTS + 1];
okini3939 0:d18dff347122 143 #else
okini3939 0:d18dff347122 144 struct STATE _state[HTTPD_MAX_CLIENTS];
okini3939 0:d18dff347122 145 #endif
okini3939 0:d18dff347122 146
okini3939 0:d18dff347122 147 struct HANDLER {
okini3939 0:d18dff347122 148 char *uri;
okini3939 0:d18dff347122 149 char *dir;
okini3939 0:d18dff347122 150 void (*funcCgi)(int id);
okini3939 0:d18dff347122 151 } _handler[HTTPD_MAX_HANDLES];
okini3939 0:d18dff347122 152
okini3939 0:d18dff347122 153 int _handler_count;
okini3939 0:d18dff347122 154
okini3939 0:d18dff347122 155 static void daemon (void const *arg);
okini3939 0:d18dff347122 156 static void child (void const *arg);
okini3939 0:d18dff347122 157 static void closer (void const *arg);
okini3939 0:d18dff347122 158
okini3939 0:d18dff347122 159 // --- HTTPD_req.cpp ---
okini3939 0:d18dff347122 160 int httpdFile (int id, char *dir);
okini3939 0:d18dff347122 161 void recvData (int id, char c);
okini3939 0:d18dff347122 162 int parseRequest (int id);
okini3939 0:d18dff347122 163 int parseHeader (int id);
okini3939 0:d18dff347122 164 void reqContentLength (int id, const char *buf);
okini3939 0:d18dff347122 165 void reqConnection (int id, const char *buf);
okini3939 0:d18dff347122 166 void reqUpgrade (int id, const char *buf);
okini3939 0:d18dff347122 167 void reqWebSocketVersion (int id, const char *buf);
okini3939 0:d18dff347122 168 void reqWebSocketKey (int id, const char *buf);
okini3939 0:d18dff347122 169
okini3939 0:d18dff347122 170 // --- HTTPD_ws.cpp ---
okini3939 0:d18dff347122 171 void recvWS (int id, char c);
okini3939 0:d18dff347122 172 int parseWebsocket (int id);
okini3939 0:d18dff347122 173 int acceptWebsocket (int id);
okini3939 0:d18dff347122 174
okini3939 0:d18dff347122 175 // --- HTTPD_util.cpp ---
okini3939 0:d18dff347122 176 int getHandler (const char *uri);
okini3939 0:d18dff347122 177 char *mimetype (char *file);
okini3939 0:d18dff347122 178 int strnicmp (const char *p1, const char *p2, int n);
okini3939 0:d18dff347122 179 int from_hex (int ch);
okini3939 0:d18dff347122 180 int to_hex (int code);
okini3939 0:d18dff347122 181 };
okini3939 0:d18dff347122 182
okini3939 0:d18dff347122 183 #endif
hillkim7 2:584ce0a1a76e 184