Преглед изворни кода

Fixed buffer overflow in put_dir()

Sergey Lyubka пре 14 година
родитељ
комит
025b11b176
2 измењених фајлова са 22 додато и 17 уклоњено
  1. 13 8
      mongoose.c
  2. 9 9
      test/test.pl

+ 13 - 8
mongoose.c

@@ -3029,26 +3029,31 @@ static int put_dir(const char *path) {
   char buf[PATH_MAX];
   const char *s, *p;
   struct mgstat st;
-  size_t len;
+  int len, res = 1;
 
-  for (s = p = path + 2; (p = strchr(s, '/')) != NULL; s = ++p) {
+  for (s = p = path + 2; (p = strchr(s, DIRSEP)) != NULL; s = ++p) {
     len = p - path;
-    assert(len < sizeof(buf));
-    (void) memcpy(buf, path, len);
+    if (len >= (int) sizeof(buf)) {
+      res = -1;
+      break;
+    }
+    memcpy(buf, path, len);
     buf[len] = '\0';
 
     // Try to create intermediate directory
+    DEBUG_TRACE(("mkdir(%s)", buf));
     if (mg_stat(buf, &st) == -1 && mg_mkdir(buf, 0755) != 0) {
-      return -1;
+      res = -1;
+      break;
     }
 
     // Is path itself a directory?
     if (p[1] == '\0') {
-      return 0;
+      res = 0;
     }
   }
 
-  return 1;
+  return res;
 }
 
 static void put_file(struct mg_connection *conn, const char *path) {
@@ -3245,7 +3250,7 @@ static void handle_request(struct mg_connection *conn) {
     * conn->request_info.query_string++ = '\0';
   }
   uri_len = strlen(ri->uri);
-  (void) url_decode(ri->uri, (size_t)uri_len, ri->uri, (size_t)(uri_len + 1), 0);
+  url_decode(ri->uri, (size_t)uri_len, ri->uri, (size_t)(uri_len + 1), 0);
   remove_double_dots_and_double_slashes(ri->uri);
   convert_uri_to_file_name(conn, ri->uri, path, sizeof(path));
 

+ 9 - 9
test/test.pl

@@ -24,8 +24,8 @@ my $embed_exe = '.' . $dir_separator . 'embed';
 my $unit_test_exe = '.' . $dir_separator . 'unit_test';
 my $exit_code = 0;
 
-my @files_to_delete = ('debug.log', 'access.log', $config, "$root/put.txt",
-  "$root/a+.txt", "$root/.htpasswd", "$root/binary_file",
+my @files_to_delete = ('debug.log', 'access.log', $config, "$root/a/put.txt",
+  "$root/a+.txt", "$root/.htpasswd", "$root/binary_file", "$root/a",
   $embed_exe, $unit_test_exe);
 
 END {
@@ -395,20 +395,20 @@ sub do_PUT_test {
   "response=896327350763836180c61d87578037d9, qop=auth, ".
   "nc=00000002, cnonce=53eddd3be4e26a98\n";
 
-  o("PUT /put.txt HTTP/1.0\nContent-Length: 7\n$auth_header\n1234567",
+  o("PUT /a/put.txt HTTP/1.0\nContent-Length: 7\n$auth_header\n1234567",
     "HTTP/1.1 201 OK", 'PUT file, status 201');
   fail("PUT content mismatch")
-  unless read_file("$root/put.txt") eq '1234567';
-  o("PUT /put.txt HTTP/1.0\nContent-Length: 4\n$auth_header\nabcd",
+  unless read_file("$root/a/put.txt") eq '1234567';
+  o("PUT /a/put.txt HTTP/1.0\nContent-Length: 4\n$auth_header\nabcd",
     "HTTP/1.1 200 OK", 'PUT file, status 200');
   fail("PUT content mismatch")
-  unless read_file("$root/put.txt") eq 'abcd';
-  o("PUT /put.txt HTTP/1.0\n$auth_header\nabcd",
+  unless read_file("$root/a/put.txt") eq 'abcd';
+  o("PUT /a/put.txt HTTP/1.0\n$auth_header\nabcd",
     "HTTP/1.1 411 Length Required", 'PUT 411 error');
-  o("PUT /put.txt HTTP/1.0\nExpect: blah\nContent-Length: 1\n".
+  o("PUT /a/put.txt HTTP/1.0\nExpect: blah\nContent-Length: 1\n".
     "$auth_header\nabcd",
     "HTTP/1.1 417 Expectation Failed", 'PUT 417 error');
-  o("PUT /put.txt HTTP/1.0\nExpect: 100-continue\nContent-Length: 4\n".
+  o("PUT /a/put.txt HTTP/1.0\nExpect: 100-continue\nContent-Length: 4\n".
     "$auth_header\nabcd",
     "HTTP/1.1 100 Continue.+HTTP/1.1 200", 'PUT 100-Continue');
 }