diff --git a/mongoose.c b/mongoose.c index a1c48b20..159c6b40 100644 --- a/mongoose.c +++ b/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)); diff --git a/test/test.pl b/test/test.pl index 040b161a..36aad115 100644 --- a/test/test.pl +++ b/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'); }