Forráskód Böngészése

Merge pull request #869 from civetweb/pr-rm-strdup

Improving remove_dot_segments()
bel2125 5 éve
szülő
commit
8e1f3f90ea
1 módosított fájl, 40 hozzáadás és 45 törlés
  1. 40 45
      src/civetweb.c

+ 40 - 45
src/civetweb.c

@@ -8174,14 +8174,11 @@ remove_dot_segments(char *inout)
 	/* Windows backend protection
 	 * (https://tools.ietf.org/html/rfc3986#section-7.3): Replace backslash
 	 * in URI by slash */
-	char *in_copy = inout ? mg_strdup(inout) : NULL;
-	char *out_begin = inout;
 	char *out_end = inout;
-	char *in = in_copy;
-	int replaced;
+	char *in = inout;
 
 	if (!in) {
-		/* Param error or OOM. */
+		/* Param error. */
 		return;
 	}
 
@@ -8198,11 +8195,13 @@ remove_dot_segments(char *inout)
 	 * The input buffer is initialized.
 	 * The output buffer is initialized to the empty string.
 	 */
-	in = in_copy;
+	in = inout;
 
 	/* Step 2:
 	 * While the input buffer is not empty, loop as follows:
 	 */
+	/* Less than out_end of the inout buffer is used as output, so keep
+	 * condition: out_end <= in */
 	while (*in) {
 		/* Step 2a:
 		 * If the input buffer begins with a prefix of "../" or "./",
@@ -8234,21 +8233,19 @@ remove_dot_segments(char *inout)
 		 */
 		else if (!strncmp(in, "/../", 4)) {
 			in += 3;
-			if (out_begin != out_end) {
+			if (inout != out_end) {
 				/* remove last segment */
 				do {
 					out_end--;
-				} while ((out_begin != out_end) && (*out_end != '/'));
-				*out_end = 0;
+				} while ((inout != out_end) && (*out_end != '/'));
 			}
 		} else if (!strcmp(in, "/..")) {
 			in[1] = 0;
-			if (out_begin != out_end) {
+			if (inout != out_end) {
 				/* remove last segment */
 				do {
 					out_end--;
-				} while ((out_begin != out_end) && (*out_end != '/'));
-				*out_end = 0;
+				} while ((inout != out_end) && (*out_end != '/'));
 			}
 		}
 		/* otherwise */
@@ -8287,42 +8284,40 @@ remove_dot_segments(char *inout)
 	 * the end. Also replace all "//" by "/". Repeat until there is no "./"
 	 * or "//" anymore.
 	 */
-	do {
-		replaced = 0;
-
-		/* replace ./ by / */
-		out_end = out_begin;
-		while (*out_end) {
-			if ((*out_end == '.')
-			    && ((out_end[1] == '/') || (out_end[1] == 0))) {
-				char *r = out_end;
-				do {
-					r[0] = r[1];
-					r++;
-					replaced = 1;
-				} while (r[0] != 0);
-			}
-			out_end++;
-		}
-
-		/* replace ./ by / */
-		out_end = out_begin;
-		while (*out_end) {
-			if ((out_end[0] == '/') && (out_end[1] == '/')) {
-				char *c = out_end;
-				while (*c) {
-					c[0] = c[1];
-					c++;
+	out_end = in = inout;
+	while (*in) {
+		if (*in == '.') {
+			/* remove . at the end or preceding of / */
+			char *in_ahead = in;
+			do {
+				in_ahead++;
+			} while (*in_ahead == '.');
+			if (*in_ahead == '/') {
+				in = in_ahead;
+				if ((out_end != inout) && (out_end[-1] == '/')) {
+					/* remove generated // */
+					out_end--;
 				}
-				replaced = 1;
+			} else if (*in_ahead == 0) {
+				in = in_ahead;
+			} else {
+				do {
+					*out_end++ = '.';
+					in++;
+				} while (in != in_ahead);
 			}
-			out_end++;
+		} else if (*in == '/') {
+			/* replace // by / */
+			*out_end++ = '/';
+			do {
+				in++;
+			} while (*in == '/');
+		} else {
+			*out_end++ = *in;
+			in++;
 		}
-
-	} while (replaced);
-
-	/* Free temporary copies */
-	mg_free(in_copy);
+	}
+	*out_end = 0;
 }