[PATCH] tabled: fix key corruption

Jeff Garzik <[email protected]>
Newsgroups org.kernel.vger.hail-devel
Message-ID <[email protected]>
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 */
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.