ソースを参照

Avoid const cast (see #504)

bel2125 8 年 前
コミット
25645a094e
1 ファイル変更61 行追加14 行削除
  1. 61 14
      src/handle_form.inl

+ 61 - 14
src/handle_form.inl

@@ -177,7 +177,7 @@ mg_handle_form_request(struct mg_connection *conn,
 {
 	const char *content_type;
 	char path[512];
-	char buf[1024];
+	char buf[1024]; /* Must not be smaller than ~900 - see sanity check */
 	int field_storage;
 	int buf_fill = 0;
 	int r;
@@ -517,7 +517,7 @@ mg_handle_form_request(struct mg_connection *conn,
 		/* The form data is in the request body data, encoded as multipart
 		 * content (see https://www.ietf.org/rfc/rfc1867.txt,
 		 * https://www.ietf.org/rfc/rfc2388.txt). */
-		const char *boundary;
+		char *boundary;
 		size_t bl;
 		ptrdiff_t used;
 		struct mg_request_info part_header;
@@ -540,27 +540,57 @@ mg_handle_form_request(struct mg_connection *conn,
 			return -1;
 		}
 
-		boundary = content_type + bl + 9;
-		bl = strlen(boundary);
+		/* Copy boundary string to variable "boundary" */
+		fbeg = content_type + bl + 9;
+		bl = strlen(fbeg);
+		if (*fbeg == '\"') {
+			/* RFC 2046 permits the boundary string to be quoted. */
+			/* If the boundary is quoted, trim the quotes */
+			fbeg++;
+			bl--;
+		}
+		boundary = mg_malloc(bl + 1);
+		if (!boundary) {
+			/* Out of memory */
+			mg_cry(conn,
+			       "%s: Cannot allocate memory for boundary [%lu]",
+			       __func__,
+			       (unsigned long)bl);
+			return -1;
+		}
+		memcpy(boundary, fbeg, bl);
+		boundary[bl] = 0;
+
 
+		/* Trim, if string is quoted */
 		if (boundary[0] == '"') {
 			/* RFC 2046 permits the boundary string to be quoted. */
 			hbuf = strchr(boundary + 1, '"');
-			if (!hbuf) {
-				/* Malformed request */
-				return -1;
-			}
-			if (*hbuf) {
-				*hbuf = 0;
-				boundary++;
-				bl = strlen(boundary);
-			} else {
+			if ((!hbuf) || (*hbuf != '"')) {
 				/* Malformed request */
+				mg_free(boundary);
 				return -1;
 			}
+			*hbuf = 0;
+			memmove(boundary, boundary + 1, bl);
+			bl = strlen(boundary);
 		}
 
-		if (bl + 800 > sizeof(buf)) {
+		/* Do some sanity checks for boundary lengths */
+		if (bl > 70) {
+			/* From RFC 2046:
+			 * Boundary delimiters must not appear within the
+			 * encapsulated material, and must be no longer
+			 * than 70 characters, not counting the two
+			 * leading hyphens.
+			 */
+
+			/* The initial sanity check
+			 * (bl + 800 > sizeof(buf))
+			 * is no longer required, since sizeof(buf) == 1024
+			 *
+			 * Original comment:
+			 */
 			/* Sanity check:  The algorithm can not work if bl >= sizeof(buf),
 			 * and it will not work effectively, if the buf is only a few byte
 			 * larger than bl, or if buf can not hold the multipart header
@@ -569,11 +599,13 @@ mg_handle_form_request(struct mg_connection *conn,
 			 * any reasonable request from every browser. If it is not
 			 * fulfilled, it might be a hand-made request, intended to
 			 * interfere with the algorithm. */
+			mg_free(boundary);
 			return -1;
 		}
 		if (bl < 4) {
 			/* Sanity check:  A boundary string of less than 4 bytes makes
 			 * no sense either. */
+			mg_free(boundary);
 			return -1;
 		}
 
@@ -586,12 +618,14 @@ mg_handle_form_request(struct mg_connection *conn,
 			            sizeof(buf) - 1 - (size_t)buf_fill);
 			if (r < 0) {
 				/* read error */
+				mg_free(boundary);
 				return -1;
 			}
 			buf_fill += r;
 			buf[buf_fill] = 0;
 			if (buf_fill < 1) {
 				/* No data */
+				mg_free(boundary);
 				return -1;
 			}
 
@@ -609,10 +643,12 @@ mg_handle_form_request(struct mg_connection *conn,
 
 			if (buf[0] != '-' || buf[1] != '-') {
 				/* Malformed request */
+				mg_free(boundary);
 				return -1;
 			}
 			if (strncmp(buf + 2, boundary, bl)) {
 				/* Malformed request */
+				mg_free(boundary);
 				return -1;
 			}
 			if (buf[bl + 2] != '\r' || buf[bl + 3] != '\n') {
@@ -621,6 +657,7 @@ mg_handle_form_request(struct mg_connection *conn,
 				if (((size_t)buf_fill != (size_t)(bl + 6))
 				    || (strncmp(buf + bl + 2, "--\r\n", 4))) {
 					/* Malformed request */
+					mg_free(boundary);
 					return -1;
 				}
 				/* End of the request */
@@ -632,6 +669,7 @@ mg_handle_form_request(struct mg_connection *conn,
 			hend = strstr(hbuf, "\r\n\r\n");
 			if (!hend) {
 				/* Malformed request */
+				mg_free(boundary);
 				return -1;
 			}
 
@@ -639,6 +677,7 @@ mg_handle_form_request(struct mg_connection *conn,
 			    parse_http_headers(&hbuf, part_header.http_headers);
 			if ((hend + 2) != hbuf) {
 				/* Malformed request */
+				mg_free(boundary);
 				return -1;
 			}
 
@@ -652,6 +691,7 @@ mg_handle_form_request(struct mg_connection *conn,
 			                          "Content-Disposition");
 			if (!content_disp) {
 				/* Malformed request */
+				mg_free(boundary);
 				return -1;
 			}
 
@@ -675,6 +715,7 @@ mg_handle_form_request(struct mg_connection *conn,
 				nend = strchr(nbeg, '\"');
 				if (!nend) {
 					/* Malformed request */
+					mg_free(boundary);
 					return -1;
 				}
 			} else {
@@ -686,6 +727,7 @@ mg_handle_form_request(struct mg_connection *conn,
 				}
 				if (!nbeg) {
 					/* Malformed request */
+					mg_free(boundary);
 					return -1;
 				}
 				nbeg += 5;
@@ -720,6 +762,7 @@ mg_handle_form_request(struct mg_connection *conn,
 				if (!fend) {
 					/* Malformed request (the filename field is optional, but if
 					 * it exists, it needs to be terminated correctly). */
+					mg_free(boundary);
 					return -1;
 				}
 
@@ -747,6 +790,7 @@ mg_handle_form_request(struct mg_connection *conn,
 			 * filename do not overlap. */
 			if (!(((ptrdiff_t)fbeg > (ptrdiff_t)nend)
 			      || ((ptrdiff_t)nbeg > (ptrdiff_t)fend))) {
+				mg_free(boundary);
 				return -1;
 			}
 
@@ -830,12 +874,14 @@ mg_handle_form_request(struct mg_connection *conn,
 				            sizeof(buf) - 1 - (size_t)buf_fill);
 				if (r < 0) {
 					/* read error */
+					mg_free(boundary);
 					return -1;
 				}
 				buf_fill += r;
 				buf[buf_fill] = 0;
 				if (buf_fill < 1) {
 					/* No data */
+					mg_free(boundary);
 					return -1;
 				}
 
@@ -898,6 +944,7 @@ mg_handle_form_request(struct mg_connection *conn,
 		}
 
 		/* All parts handled */
+		mg_free(boundary);
 		return field_count;
 	}