commit a58d541cf4357ab0aa7ae5e21765de35f65c6177
Author: Jeff Garzik <[email protected]>
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 <[email protected]>
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 [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html