summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGlenn Strauss <gstrauss@gluelogic.com>2018-11-28 02:12:41 -0500
committerGlenn Strauss <gstrauss@gluelogic.com>2018-11-28 02:12:41 -0500
commit77c01f981725512653c01cde5ca74c11633dfec4 (patch)
treeba511202897b50f59e4ad81fd1df2cee73d35210
parent608026e5aaed1b1c510814d3020aa8241d78f905 (diff)
downloadlighttpd1.4-77c01f981725512653c01cde5ca74c11633dfec4.tar.gz
lighttpd1.4-77c01f981725512653c01cde5ca74c11633dfec4.zip
[core] buffer_append_path_len()
concatenate paths, placing single '/' between strings reverts broken commit:b9402283 (thx avij)
-rw-r--r--src/buffer.c15
-rw-r--r--src/buffer.h1
-rw-r--r--src/chunk.c3
-rw-r--r--src/mod_dirlisting.c6
-rw-r--r--src/mod_userdir.c12
-rw-r--r--src/mod_webdav.c42
-rw-r--r--src/response.c6
-rw-r--r--src/t/test_buffer.c34
8 files changed, 73 insertions, 46 deletions
diff --git a/src/buffer.c b/src/buffer.c
index 77d76a8e..f958e17f 100644
--- a/src/buffer.c
+++ b/src/buffer.c
@@ -198,6 +198,21 @@ void buffer_append_string_len(buffer *b, const char *s, size_t s_len) {
b->used += s_len;
}
+void buffer_append_path_len(buffer *b, const char *a, size_t alen) {
+ size_t blen = buffer_string_length(b);
+ int aslash = (alen && a[0] == '/');
+ buffer_string_prepare_append(b, alen+2); /*(+ '/' and + '\0' if 0 == blen)*/
+ if (blen && b->ptr[blen-1] == '/') {
+ if (aslash) --b->used;
+ }
+ else {
+ if (!b->used) ++b->used;
+ if (!aslash) b->ptr[++b->used - 2] = '/';
+ }
+ memcpy(b->ptr+b->used-1, a, alen);
+ b->ptr[(b->used += alen)-1] = '\0';
+}
+
void buffer_append_uint_hex_lc(buffer *b, uintmax_t value) {
char *buf;
unsigned int shift = 0;
diff --git a/src/buffer.h b/src/buffer.h
index 733cb43a..df461e1a 100644
--- a/src/buffer.h
+++ b/src/buffer.h
@@ -170,6 +170,7 @@ static inline int light_isalnum(int c) {
static inline size_t buffer_string_length(const buffer *b); /* buffer string length without terminating 0 */
static inline size_t buffer_string_space(const buffer *b); /* maximum length of string that can be stored without reallocating */
static inline void buffer_append_slash(buffer *b); /* append '/' no non-empty strings not ending in '/' */
+void buffer_append_path_len(buffer *b, const char *a, size_t alen); /* join strings with '/', if '/' not present */
#define BUFFER_APPEND_STRING_CONST(x, y) \
buffer_append_string_len(x, y, sizeof(y) - 1)
diff --git a/src/chunk.c b/src/chunk.c
index 4489a854..8f32d643 100644
--- a/src/chunk.c
+++ b/src/chunk.c
@@ -509,8 +509,7 @@ static chunk *chunkqueue_get_append_tempfile(server *srv, chunkqueue *cq) {
data_string *ds = (data_string *)cq->tempdirs->data[cq->tempdir_idx];
buffer_copy_buffer(template, ds->value);
- buffer_append_slash(template);
- buffer_append_string_len(template, CONST_STR_LEN("lighttpd-upload-XXXXXX"));
+ buffer_append_path_len(template, CONST_STR_LEN("lighttpd-upload-XXXXXX"));
#ifdef __COVERITY__
/* POSIX-2008 requires mkstemp create file with 0600 perms */
diff --git a/src/mod_dirlisting.c b/src/mod_dirlisting.c
index 5c492a95..2f746740 100644
--- a/src/mod_dirlisting.c
+++ b/src/mod_dirlisting.c
@@ -807,8 +807,7 @@ static void http_list_directory_header(server *srv, connection *con, plugin_data
buffer *hb = p->conf.show_header;
if (hb->ptr[0] != '/') {
buffer_copy_buffer(p->tmp_buf, con->physical.path);
- buffer_append_slash(p->tmp_buf);
- buffer_append_string_buffer(p->tmp_buf, p->conf.show_header);
+ buffer_append_path_len(p->tmp_buf, CONST_BUF_LEN(p->conf.show_header));
hb = p->tmp_buf;
}
@@ -858,8 +857,7 @@ static void http_list_directory_footer(server *srv, connection *con, plugin_data
buffer *rb = p->conf.show_readme;
if (rb->ptr[0] != '/') {
buffer_copy_buffer(p->tmp_buf, con->physical.path);
- buffer_append_slash(p->tmp_buf);
- buffer_append_string_buffer(p->tmp_buf, p->conf.show_readme);
+ buffer_append_path_len(p->tmp_buf, CONST_BUF_LEN(p->conf.show_readme));
rb = p->tmp_buf;
}
diff --git a/src/mod_userdir.c b/src/mod_userdir.c
index cf99cc03..6389d9fa 100644
--- a/src/mod_userdir.c
+++ b/src/mod_userdir.c
@@ -262,6 +262,7 @@ URIHANDLER_FUNC(mod_userdir_docroot_handler) {
}
/* we build the physical path */
+ buffer_clear(p->temp_path);
if (buffer_string_is_empty(p->conf.basepath)) {
#ifdef HAVE_PWD_H
@@ -287,16 +288,13 @@ URIHANDLER_FUNC(mod_userdir_docroot_handler) {
}
buffer_copy_buffer(p->temp_path, p->conf.basepath);
- buffer_append_slash(p->temp_path);
if (p->conf.letterhomes) {
if (p->username->ptr[0] == '.') return HANDLER_GO_ON;
- buffer_append_string_len(p->temp_path, p->username->ptr, 1);
- buffer_append_slash(p->temp_path);
+ buffer_append_path_len(p->temp_path, p->username->ptr, 1);
}
- buffer_append_string_buffer(p->temp_path, p->username);
+ buffer_append_path_len(p->temp_path, CONST_BUF_LEN(p->username));
}
- buffer_append_slash(p->temp_path);
- buffer_append_string_buffer(p->temp_path, p->conf.path);
+ buffer_append_path_len(p->temp_path, CONST_BUF_LEN(p->conf.path));
if (buffer_string_is_empty(p->conf.basepath)) {
struct stat st;
@@ -330,8 +328,6 @@ URIHANDLER_FUNC(mod_userdir_docroot_handler) {
}
buffer_copy_buffer(con->physical.path, p->temp_path);
- buffer_clear(p->temp_path);
-
return HANDLER_GO_ON;
}
diff --git a/src/mod_webdav.c b/src/mod_webdav.c
index 1fde022e..8087779c 100644
--- a/src/mod_webdav.c
+++ b/src/mod_webdav.c
@@ -590,6 +590,7 @@ static int webdav_delete_dir(server *srv, connection *con, handler_ctx *hctx, ph
while(NULL != (de = readdir(dir))) {
struct stat st;
+ size_t nlen;
if ((de->d_name[0] == '.' && de->d_name[1] == '\0') ||
(de->d_name[0] == '.' && de->d_name[1] == '.' && de->d_name[2] == '\0')) {
@@ -597,13 +598,12 @@ static int webdav_delete_dir(server *srv, connection *con, handler_ctx *hctx, ph
/* ignore the parent dir */
}
+ nlen = strlen(de->d_name);
buffer_copy_buffer(d.path, dst->path);
- buffer_append_slash(d.path);
- buffer_append_string(d.path, de->d_name);
+ buffer_append_path_len(d.path, de->d_name, nlen);
buffer_copy_buffer(d.rel_path, dst->rel_path);
- buffer_append_slash(d.rel_path);
- buffer_append_string(d.rel_path, de->d_name);
+ buffer_append_path_len(d.rel_path, de->d_name, nlen);
/* stat and unlink afterwards */
if (-1 == stat(d.path->ptr, &st)) {
@@ -770,27 +770,25 @@ static int webdav_copy_dir(server *srv, connection *con, handler_ctx *hctx, phys
while (NULL != (de = readdir(srcdir))) {
struct stat st;
+ size_t nlen;
if ((de->d_name[0] == '.' && de->d_name[1] == '\0')
|| (de->d_name[0] == '.' && de->d_name[1] == '.' && de->d_name[2] == '\0')) {
continue;
}
+ nlen = strlen(de->d_name);
buffer_copy_buffer(s.path, src->path);
- buffer_append_slash(s.path);
- buffer_append_string(s.path, de->d_name);
+ buffer_append_path_len(s.path, de->d_name, nlen);
buffer_copy_buffer(d.path, dst->path);
- buffer_append_slash(d.path);
- buffer_append_string(d.path, de->d_name);
+ buffer_append_path_len(d.path, de->d_name, nlen);
buffer_copy_buffer(s.rel_path, src->rel_path);
- buffer_append_slash(s.rel_path);
- buffer_append_string(s.rel_path, de->d_name);
+ buffer_append_path_len(s.rel_path, de->d_name, nlen);
buffer_copy_buffer(d.rel_path, dst->rel_path);
- buffer_append_slash(d.rel_path);
- buffer_append_string(d.rel_path, de->d_name);
+ buffer_append_path_len(d.rel_path, de->d_name, nlen);
if (-1 == stat(s.path->ptr, &st)) {
/* why ? */
@@ -1500,19 +1498,18 @@ static handler_t mod_webdav_propfind(server *srv, connection *con, plugin_data *
d.rel_path = buffer_init();
while(NULL != (de = readdir(dir))) {
+ size_t nlen;
if (de->d_name[0] == '.' && (de->d_name[1] == '\0' || (de->d_name[1] == '.' && de->d_name[2] == '\0'))) {
continue;
/* ignore the parent and target dir */
}
+ nlen = strlen(de->d_name);
buffer_copy_buffer(d.path, dst->path);
- buffer_append_slash(d.path);
+ buffer_append_path_len(d.path, de->d_name, nlen);
buffer_copy_buffer(d.rel_path, dst->rel_path);
- buffer_append_slash(d.rel_path);
-
- buffer_append_string(d.path, de->d_name);
- buffer_append_string(d.rel_path, de->d_name);
+ buffer_append_path_len(d.rel_path, de->d_name, nlen);
buffer_clear(prop_200);
buffer_clear(prop_404);
@@ -2064,16 +2061,7 @@ static handler_t mod_webdav_copymove(server *srv, connection *con, plugin_data *
buffer_copy_buffer(p->physical.path, p->physical.doc_root);
buffer_append_slash(p->physical.path);
buffer_copy_buffer(p->physical.basedir, p->physical.path);
-
- /* don't add a second / */
- if (p->physical.rel_path->ptr[0] == '/') {
- #ifdef __COVERITY__
- if (buffer_string_length(p->physical.rel_path) < 1) return HANDLER_ERROR;
- #endif
- buffer_append_string_len(p->physical.path, p->physical.rel_path->ptr + 1, buffer_string_length(p->physical.rel_path) - 1);
- } else {
- buffer_append_string_buffer(p->physical.path, p->physical.rel_path);
- }
+ buffer_append_path_len(p->physical.path, CONST_BUF_LEN(p->physical.rel_path));
}
}
diff --git a/src/response.c b/src/response.c
index 7df36691..f6d910dd 100644
--- a/src/response.c
+++ b/src/response.c
@@ -615,11 +615,7 @@ handler_t http_response_prepare(server *srv, connection *con) {
buffer_copy_buffer(con->physical.basedir, con->physical.doc_root);
buffer_copy_buffer(con->physical.path, con->physical.doc_root);
- if (buffer_string_is_empty(con->physical.rel_path)
- || con->physical.rel_path->ptr[0] != '/') {
- buffer_append_slash(con->physical.path);
- }
- buffer_append_string_buffer(con->physical.path, con->physical.rel_path);
+ buffer_append_path_len(con->physical.path, CONST_BUF_LEN(con->physical.rel_path));
if (con->conf.log_request_handling) {
log_error_write(srv, __FILE__, __LINE__, "s", "-- after doc_root");
diff --git a/src/t/test_buffer.c b/src/t/test_buffer.c
index 3e6eb4df..1dae0b41 100644
--- a/src/t/test_buffer.c
+++ b/src/t/test_buffer.c
@@ -114,10 +114,44 @@ static void test_buffer_string_space(void) {
buffer_free(b);
}
+static void test_buffer_append_path_len(void) {
+ buffer *b = buffer_init();
+
+ buffer_append_path_len(b, CONST_STR_LEN("a"));
+ assert(buffer_is_equal_string(b, CONST_STR_LEN("/a")));
+ buffer_clear(b);
+ buffer_append_path_len(b, CONST_STR_LEN("a"));
+ assert(buffer_is_equal_string(b, CONST_STR_LEN("/a")));
+ buffer_clear(b);
+ buffer_append_path_len(b, CONST_STR_LEN("/a"));
+ assert(buffer_is_equal_string(b, CONST_STR_LEN("/a")));
+ buffer_copy_string_len(b, CONST_STR_LEN("/"));
+ buffer_append_path_len(b, CONST_STR_LEN("a"));
+ assert(buffer_is_equal_string(b, CONST_STR_LEN("/a")));
+ buffer_copy_string_len(b, CONST_STR_LEN("/"));
+ buffer_append_path_len(b, CONST_STR_LEN("/a"));
+ assert(buffer_is_equal_string(b, CONST_STR_LEN("/a")));
+ buffer_copy_string_len(b, CONST_STR_LEN("a"));
+ buffer_append_path_len(b, CONST_STR_LEN("a"));
+ assert(buffer_is_equal_string(b, CONST_STR_LEN("a/a")));
+ buffer_copy_string_len(b, CONST_STR_LEN("a/"));
+ buffer_append_path_len(b, CONST_STR_LEN("a"));
+ assert(buffer_is_equal_string(b, CONST_STR_LEN("a/a")));
+ buffer_copy_string_len(b, CONST_STR_LEN("a/"));
+ buffer_append_path_len(b, CONST_STR_LEN("/a"));
+ assert(buffer_is_equal_string(b, CONST_STR_LEN("a/a")));
+ buffer_copy_string_len(b, CONST_STR_LEN("/a/"));
+ buffer_append_path_len(b, CONST_STR_LEN("/a"));
+ assert(buffer_is_equal_string(b, CONST_STR_LEN("/a/a")));
+
+ buffer_free(b);
+}
+
int main() {
test_buffer_path_simplify();
test_buffer_to_lower_upper();
test_buffer_string_space();
+ test_buffer_append_path_len();
return 0;
}