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 #include "HTTPD.h"
okini3939 0:d18dff347122 20 #include <ctype.h>
okini3939 0:d18dff347122 21 #include <stdlib.h>
okini3939 0:d18dff347122 22 #include <string.h>
okini3939 0:d18dff347122 23
okini3939 0:d18dff347122 24 #define MIMETABLE_NUM 9
okini3939 0:d18dff347122 25 static const struct {
okini3939 0:d18dff347122 26 char ext[5];
okini3939 0:d18dff347122 27 char type[24];
okini3939 0:d18dff347122 28 } mimetable[MIMETABLE_NUM] = {
okini3939 0:d18dff347122 29 {"txt", "text/plain"}, // default
okini3939 0:d18dff347122 30 {"html", "text/html"},
okini3939 0:d18dff347122 31 {"htm", "text/html"},
okini3939 0:d18dff347122 32 {"css", "text/css"},
okini3939 0:d18dff347122 33 {"js", "application/javascript"},
okini3939 0:d18dff347122 34 {"jpg", "image/jpeg"},
okini3939 0:d18dff347122 35 {"png", "image/png"},
okini3939 0:d18dff347122 36 {"gif", "image/gif"},
okini3939 0:d18dff347122 37 {"ico", "image/x-icon"},
okini3939 0:d18dff347122 38 };
okini3939 0:d18dff347122 39
okini3939 0:d18dff347122 40 char *HTTPD::getUri (int id) {
okini3939 0:d18dff347122 41 return _state[id].uri;
okini3939 0:d18dff347122 42 }
okini3939 0:d18dff347122 43
okini3939 0:d18dff347122 44 char *HTTPD::getFilename (int id) {
okini3939 0:d18dff347122 45 return _state[id].filename;
okini3939 0:d18dff347122 46 }
okini3939 0:d18dff347122 47
okini3939 0:d18dff347122 48 char *HTTPD::getQueryString (int id) {
okini3939 0:d18dff347122 49 return _state[id].querystring;
okini3939 0:d18dff347122 50 }
okini3939 0:d18dff347122 51
okini3939 0:d18dff347122 52 int HTTPD::receive (int id, char *buf, int len) {
okini3939 0:d18dff347122 53 int i;
okini3939 0:d18dff347122 54
okini3939 0:d18dff347122 55 for (i = 0; i < len; i ++) {
okini3939 0:d18dff347122 56 if (_state[id].buf->dequeue(&buf[i]) == false) break;
okini3939 0:d18dff347122 57 }
okini3939 0:d18dff347122 58 return i;
okini3939 0:d18dff347122 59 }
okini3939 0:d18dff347122 60
okini3939 0:d18dff347122 61 int HTTPD::send (int id, const char *body, int len, const char *header) {
okini3939 0:d18dff347122 62 char buf[HTTPD_CMD_SIZE];
okini3939 0:d18dff347122 63
okini3939 0:d18dff347122 64 strcpy(buf, "HTTP/1.1 200 OK\r\n");
okini3939 0:d18dff347122 65 _state[id].client->send_all(buf, strlen(buf));
okini3939 0:d18dff347122 66 strcpy(buf, "Server: GSwifi httpd\r\n");
okini3939 0:d18dff347122 67 _state[id].client->send_all(buf, strlen(buf));
okini3939 0:d18dff347122 68 if (_state[id].keepalive) {
okini3939 0:d18dff347122 69 strcpy(buf, "Connection: Keep-Alive\r\n");
okini3939 0:d18dff347122 70 } else {
okini3939 0:d18dff347122 71 strcpy(buf, "Connection: close\r\n");
okini3939 0:d18dff347122 72 }
okini3939 0:d18dff347122 73 _state[id].client->send_all(buf, strlen(buf));
okini3939 0:d18dff347122 74 if (header) {
okini3939 0:d18dff347122 75 _state[id].client->send_all((char*)header, strlen(header));
okini3939 0:d18dff347122 76 }
okini3939 0:d18dff347122 77 sprintf(buf, "Content-Length: %d\r\n\r\n", len);
okini3939 0:d18dff347122 78 _state[id].client->send_all(buf, strlen(buf));
okini3939 0:d18dff347122 79
okini3939 0:d18dff347122 80 return _state[id].client->send_all((char*)body, len);
okini3939 0:d18dff347122 81 }
okini3939 0:d18dff347122 82
okini3939 0:d18dff347122 83 int HTTPD::getHandler (const char *uri) {
okini3939 0:d18dff347122 84 int i;
okini3939 0:d18dff347122 85
okini3939 0:d18dff347122 86 for (i = 0; i < _handler_count; i ++) {
okini3939 0:d18dff347122 87 if (strncmp(uri, _handler[i].uri, strlen(_handler[i].uri)) == NULL) {
okini3939 0:d18dff347122 88 // found
okini3939 0:d18dff347122 89 return i;
okini3939 0:d18dff347122 90 }
okini3939 0:d18dff347122 91 }
okini3939 0:d18dff347122 92 return -1;
okini3939 0:d18dff347122 93 }
okini3939 0:d18dff347122 94
okini3939 0:d18dff347122 95 int HTTPD::attach (const char *uri, const char *dir) {
okini3939 0:d18dff347122 96 if (_handler_count < HTTPD_MAX_HANDLES) {
okini3939 0:d18dff347122 97 _handler[_handler_count].uri = (char*)malloc(strlen(uri) + 1);
okini3939 0:d18dff347122 98 strcpy(_handler[_handler_count].uri, uri);
okini3939 0:d18dff347122 99 _handler[_handler_count].dir = (char*)malloc(strlen(dir) + 1);
okini3939 0:d18dff347122 100 strcpy(_handler[_handler_count].dir, dir);
okini3939 0:d18dff347122 101 _handler[_handler_count].funcCgi = NULL;
okini3939 0:d18dff347122 102 _handler_count ++;
okini3939 0:d18dff347122 103 return 0;
okini3939 0:d18dff347122 104 } else {
okini3939 0:d18dff347122 105 return -1;
okini3939 0:d18dff347122 106 }
okini3939 0:d18dff347122 107 }
okini3939 0:d18dff347122 108
okini3939 0:d18dff347122 109 int HTTPD::attach (const char *uri, void (*funcCgi)(int)) {
okini3939 0:d18dff347122 110 if (_handler_count < HTTPD_MAX_HANDLES) {
okini3939 0:d18dff347122 111 _handler[_handler_count].uri = (char*)malloc(strlen(uri) + 1);
okini3939 0:d18dff347122 112 strcpy(_handler[_handler_count].uri, uri);
okini3939 0:d18dff347122 113 _handler[_handler_count].dir = NULL;
okini3939 0:d18dff347122 114 _handler[_handler_count].funcCgi = funcCgi;
okini3939 0:d18dff347122 115 _handler_count ++;
okini3939 0:d18dff347122 116 return 0;
okini3939 0:d18dff347122 117 } else {
okini3939 0:d18dff347122 118 return -1;
okini3939 0:d18dff347122 119 }
okini3939 0:d18dff347122 120 }
okini3939 0:d18dff347122 121
okini3939 0:d18dff347122 122
okini3939 0:d18dff347122 123 char *HTTPD::mimetype (char *file) {
okini3939 0:d18dff347122 124 int i, j;
okini3939 0:d18dff347122 125
okini3939 0:d18dff347122 126 for (i = 0; i < MIMETABLE_NUM; i ++) {
okini3939 0:d18dff347122 127 j = strlen(mimetable[i].ext);
okini3939 0:d18dff347122 128 if (file[strlen(file) - j - 1] == '.' &&
okini3939 0:d18dff347122 129 strnicmp(&file[strlen(file) - j], mimetable[i].ext, j) == NULL) {
okini3939 0:d18dff347122 130 return (char*)mimetable[i].type;
okini3939 0:d18dff347122 131 }
okini3939 0:d18dff347122 132 }
okini3939 0:d18dff347122 133 return (char*)mimetable[0].type;
okini3939 0:d18dff347122 134 }
okini3939 0:d18dff347122 135
okini3939 0:d18dff347122 136 int HTTPD::strnicmp (const char *p1, const char *p2, int n) {
okini3939 0:d18dff347122 137 int i, r = -1;
okini3939 0:d18dff347122 138 char c1, c2;
okini3939 0:d18dff347122 139
okini3939 0:d18dff347122 140 for (i = 0; i < n; i ++) {
okini3939 0:d18dff347122 141 c1 = (p1[i] >= 'a' && p1[i] <= 'z') ? p1[i] - ('a' - 'A'): p1[i];
okini3939 0:d18dff347122 142 c2 = (p2[i] >= 'a' && p2[i] <= 'z') ? p2[i] - ('a' - 'A'): p2[i];
okini3939 0:d18dff347122 143 r = c1 - c2;
okini3939 0:d18dff347122 144 if (r) break;
okini3939 0:d18dff347122 145 }
okini3939 0:d18dff347122 146 return r;
okini3939 0:d18dff347122 147 }
okini3939 0:d18dff347122 148
okini3939 0:d18dff347122 149
okini3939 0:d18dff347122 150 /* base64encode code from
okini3939 0:d18dff347122 151 * Copyright (c) 2010 Donatien Garnier (donatiengar [at] gmail [dot] com)
okini3939 0:d18dff347122 152 */
okini3939 0:d18dff347122 153 int HTTPD::base64encode (const char *input, int length, char *output, int len) {
okini3939 0:d18dff347122 154 static const char base64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
okini3939 0:d18dff347122 155 unsigned int c, c1, c2, c3;
okini3939 0:d18dff347122 156
okini3939 0:d18dff347122 157 if (len < ((((length-1)/3)+1)<<2)) return -1;
okini3939 0:d18dff347122 158 for(unsigned int i = 0, j = 0; i<length; i+=3,j+=4) {
okini3939 0:d18dff347122 159 c1 = ((((unsigned char)*((unsigned char *)&input[i]))));
okini3939 0:d18dff347122 160 c2 = (length>i+1)?((((unsigned char)*((unsigned char *)&input[i+1])))):0;
okini3939 0:d18dff347122 161 c3 = (length>i+2)?((((unsigned char)*((unsigned char *)&input[i+2])))):0;
okini3939 0:d18dff347122 162
okini3939 0:d18dff347122 163 c = ((c1 & 0xFC) >> 2);
okini3939 0:d18dff347122 164 output[j+0] = base64[c];
okini3939 0:d18dff347122 165 c = ((c1 & 0x03) << 4) | ((c2 & 0xF0) >> 4);
okini3939 0:d18dff347122 166 output[j+1] = base64[c];
okini3939 0:d18dff347122 167 c = ((c2 & 0x0F) << 2) | ((c3 & 0xC0) >> 6);
okini3939 0:d18dff347122 168 output[j+2] = (length>i+1)?base64[c]:'=';
okini3939 0:d18dff347122 169 c = (c3 & 0x3F);
okini3939 0:d18dff347122 170 output[j+3] = (length>i+2)?base64[c]:'=';
okini3939 0:d18dff347122 171 }
okini3939 0:d18dff347122 172 output[(((length-1)/3)+1)<<2] = '\0';
okini3939 0:d18dff347122 173 return 0;
okini3939 0:d18dff347122 174 }
okini3939 0:d18dff347122 175
okini3939 0:d18dff347122 176
okini3939 0:d18dff347122 177 /* urlencode code from
okini3939 0:d18dff347122 178 * Copyright (c) 2010 Donatien Garnier (donatiengar [at] gmail [dot] com)
okini3939 0:d18dff347122 179 */
okini3939 0:d18dff347122 180 int HTTPD::urlencode (const char *str, char *buf, int len) {
okini3939 0:d18dff347122 181 // char *pstr = str, *buf = (char*)malloc(strlen(str) * 3 + 1), *pbuf = buf;
okini3939 0:d18dff347122 182 const char *pstr = str;
okini3939 0:d18dff347122 183 char *pbuf = buf;
okini3939 0:d18dff347122 184
okini3939 0:d18dff347122 185 if (len < (strlen(str) * 3 + 1)) return -1;
okini3939 0:d18dff347122 186 while (*pstr) {
okini3939 0:d18dff347122 187 if (isalnum(*pstr) || *pstr == '-' || *pstr == '_' || *pstr == '.' || *pstr == '~')
okini3939 0:d18dff347122 188 *pbuf++ = *pstr;
okini3939 0:d18dff347122 189 else if (*pstr == ' ')
okini3939 0:d18dff347122 190 *pbuf++ = '+';
okini3939 0:d18dff347122 191 else
okini3939 0:d18dff347122 192 *pbuf++ = '%', *pbuf++ = to_hex(*pstr >> 4), *pbuf++ = to_hex(*pstr & 15);
okini3939 0:d18dff347122 193 pstr++;
okini3939 0:d18dff347122 194 }
okini3939 0:d18dff347122 195 *pbuf = '\0';
okini3939 0:d18dff347122 196 return 0;
okini3939 0:d18dff347122 197 }
okini3939 0:d18dff347122 198
okini3939 0:d18dff347122 199 /* urldecode code from
okini3939 0:d18dff347122 200 * Copyright (c) 2010 Donatien Garnier (donatiengar [at] gmail [dot] com)
okini3939 0:d18dff347122 201 */
okini3939 0:d18dff347122 202 int HTTPD::urldecode (const char *str, char *buf, int len) {
okini3939 0:d18dff347122 203 // char *pstr = str, *buf = (char*)malloc(strlen(str) + 1), *pbuf = buf;
okini3939 0:d18dff347122 204 const char *pstr = str;
okini3939 0:d18dff347122 205 char *pbuf = buf;
okini3939 0:d18dff347122 206
okini3939 0:d18dff347122 207 if (len < (strlen(str) / 3 - 1)) return -1;
okini3939 0:d18dff347122 208 while (*pstr) {
okini3939 0:d18dff347122 209 if (*pstr == '%') {
okini3939 0:d18dff347122 210 if (pstr[1] && pstr[2]) {
okini3939 0:d18dff347122 211 *pbuf++ = from_hex(pstr[1]) << 4 | from_hex(pstr[2]);
okini3939 0:d18dff347122 212 pstr += 2;
okini3939 0:d18dff347122 213 }
okini3939 0:d18dff347122 214 } else if (*pstr == '+') {
okini3939 0:d18dff347122 215 *pbuf++ = ' ';
okini3939 0:d18dff347122 216 } else {
okini3939 0:d18dff347122 217 *pbuf++ = *pstr;
okini3939 0:d18dff347122 218 }
okini3939 0:d18dff347122 219 pstr++;
okini3939 0:d18dff347122 220 }
okini3939 0:d18dff347122 221 *pbuf = '\0';
okini3939 0:d18dff347122 222 return 0;
okini3939 0:d18dff347122 223 }
okini3939 0:d18dff347122 224
okini3939 0:d18dff347122 225 int HTTPD::from_hex (int ch) {
okini3939 0:d18dff347122 226 return isdigit(ch) ? ch - '0' : tolower(ch) - 'a' + 10;
okini3939 0:d18dff347122 227 }
okini3939 0:d18dff347122 228
okini3939 0:d18dff347122 229 int HTTPD::to_hex (int code) {
okini3939 0:d18dff347122 230 static char hex[] = "0123456789abcdef";
okini3939 0:d18dff347122 231 return hex[code & 15];
okini3939 0:d18dff347122 232 }