commit a58d541cf4357ab0aa7ae5e21765de35f65c6177 Author: Jeff Garzik <jeff@xxxxxxxxxx> Date: Sat Mar 6 17:44:51 2010 -0500 tabled: fix key corruption due to string overrun When obtaining the path (and thus, the object key) from the URI, it went unnoticed that the URI-based strings are not null terminated, but instead length-delimited via a separate variable. This resulted in incorrect keys being associated with each object, if the key contained spaces or other unusual chars. Signed-off-by: Jeff Garzik <jgarzik@xxxxxxxxxx> diff --git a/server/bucket.c b/server/bucket.c index 300a8a6..0acf987 100644 --- a/server/bucket.c +++ b/server/bucket.c @@ -376,34 +376,49 @@ static int bucket_find(DB_TXN *txn, const char *bucket, char *owner, * Parse the uri_path and return bucket and path, strndup-ed. * Returns true iff succeeded. Else, bucket and path are unchanged. */ -bool bucket_base(const char *uri_path, char **pbucket, char **ppath) +bool bucket_base(const char *uri_path, size_t uri_path_len, + char **pbucket, char **ppath) { const char *p; char *bucket, *path; - if (*uri_path != '/') + if (!uri_path_len || *uri_path != '/') return false; + uri_path++; + uri_path_len--; - if (uri_path[0] == '\0') { + /* just a slash; no bucket, path == / */ + if (uri_path_len == 0) { bucket = NULL; if ((path = strdup("/")) == NULL) return false; - } else if ((p = strchr(uri_path, '/')) == NULL) { - if ((bucket = strdup(uri_path)) == NULL) + } + + /* no slash; just a bucket, no path, force path to / */ + else if ((p = memchr(uri_path, '/', uri_path_len)) == NULL) { + if ((bucket = g_strndup(uri_path, uri_path_len)) == NULL) return false; if ((path = strdup("/")) == NULL) { /* fake slash */ free(bucket); return false; } - } else { - if ((bucket = g_strndup(uri_path, p - uri_path)) == NULL) + } + + /* otherwise, bucket precedes first slash; path follows */ + else { + size_t bucket_len = p - uri_path; + + if ((bucket = g_strndup(uri_path, bucket_len)) == NULL) return false; - if ((path = strdup(p)) == NULL) { /* include slash */ + + /* include slash */ + if ((path = g_strndup(p, uri_path_len - bucket_len)) == NULL) { free(bucket); return false; } } + *pbucket = bucket; *ppath = path; return true; diff --git a/server/server.c b/server/server.c index e5d356e..e0d785c 100644 --- a/server/server.c +++ b/server/server.c @@ -846,17 +846,19 @@ static bool cli_evt_http_req(struct client *cli, unsigned int events) /* attempt to obtain bucket name from URI path */ if (!bucket) - buck_in_path = bucket_base(req->uri.path, &bucket, &path); + buck_in_path = bucket_base(req->uri.path, req->uri.path_len, + &bucket, &path); else - path = strdup(req->uri.path); + path = g_strndup(req->uri.path, req->uri.path_len); if (!path) path = strdup("/"); key = pathtokey(path); if (debugging) - applog(LOG_INFO, "%s: method %s, path '%s', bucket '%s'", - cli->addr_host, method, path, bucket); + applog(LOG_INFO, + "%s: method %s, path '%s', key '%s', bucket '%s'", + cli->addr_host, method, path, key, bucket); if (auth) { err = authcheck(&cli->req, buck_in_path? NULL: bucket, auth, diff --git a/server/tabled.h b/server/tabled.h index 91cccae..72bf20d 100644 --- a/server/tabled.h +++ b/server/tabled.h @@ -272,7 +272,8 @@ extern bool bucket_del(struct client *cli, const char *user, const char *bucket) extern bool bucket_add(struct client *cli, const char *user, const char *bucket); extern bool bucket_valid(const char *bucket); extern char *bucket_host(const char *host, const char *ourhost); -extern bool bucket_base(const char *uri_path, char **pbucket, char **ppath); +extern bool bucket_base(const char *uri_path, size_t uri_path_len, + char **pbucket, char **ppath); extern bool service_list(struct client *cli, const char *user); /* object.c */ -- To unsubscribe from this list: send the line "unsubscribe hail-devel" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html