diff mbox series

[v3,3/3] libselinux: simplify string formatting

Message ID 20241126102621.20253-3-cgoettsche@seltendoof.de (mailing list archive)
State New
Delegated to: Petr Lautrbach
Headers show
Series [v3,1/3] libselinux: avoid memory allocation in common file label lookup | expand

Commit Message

Christian Göttsche Nov. 26, 2024, 10:26 a.m. UTC
From: Christian Göttsche <cgzones@googlemail.com>

Instead of using asprintf(3) and heavy string formatting just manually
concatenate the substitution string.

Signed-off-by: Christian Göttsche <cgzones@googlemail.com>
---
v2: add patch
---
 libselinux/src/label_file.c | 38 +++++++++++++++++++++++++------------
 libselinux/src/label_file.h |  1 +
 2 files changed, 27 insertions(+), 12 deletions(-)
diff mbox series

Patch

diff --git a/libselinux/src/label_file.c b/libselinux/src/label_file.c
index 8050ef1a..ef308309 100644
--- a/libselinux/src/label_file.c
+++ b/libselinux/src/label_file.c
@@ -1130,9 +1130,9 @@  static void selabel_subs_fini(struct selabel_sub *subs, uint32_t num)
 	free(subs);
 }
 
-static char *selabel_apply_subs(const struct selabel_sub *subs, uint32_t num, const char *src)
+static char *selabel_apply_subs(const struct selabel_sub *subs, uint32_t num, const char *src, size_t slen)
 {
-	char *dst;
+	char *dst, *tmp;
 	uint32_t len;
 
 	for (uint32_t i = 0; i < num; i++) {
@@ -1146,8 +1146,14 @@  static char *selabel_apply_subs(const struct selabel_sub *subs, uint32_t num, co
 					len = ptr->slen + 1;
 				else
 					len = ptr->slen;
-				if (asprintf(&dst, "%s%s", ptr->dst, &src[len]) < 0)
+
+				dst = malloc(ptr->dlen + slen - len + 1);
+				if (!dst)
 					return NULL;
+
+				tmp = mempcpy(dst, ptr->dst, ptr->dlen);
+				tmp = mempcpy(tmp, &src[len], slen - len);
+				*tmp = '\0';
 				return dst;
 			}
 		}
@@ -1183,7 +1189,7 @@  static int selabel_subs_init(const char *path, struct selabel_digest *digest,
 		char *ptr;
 		char *src = buf;
 		char *dst;
-		size_t len;
+		size_t slen, dlen;
 
 		while (*src && isspace((unsigned char)*src))
 			src++;
@@ -1204,8 +1210,14 @@  static int selabel_subs_init(const char *path, struct selabel_digest *digest,
 		if (! *dst)
 			continue;
 
-		len = strlen(src);
-		if (len >= UINT32_MAX) {
+		slen = strlen(src);
+		if (slen >= UINT32_MAX) {
+			errno = EINVAL;
+			goto err;
+		}
+
+		dlen = strlen(dst);
+		if (dlen >= UINT32_MAX) {
 			errno = EINVAL;
 			goto err;
 		}
@@ -1224,8 +1236,9 @@  static int selabel_subs_init(const char *path, struct selabel_digest *digest,
 
 		tmp[tmp_num++] = (struct selabel_sub) {
 			.src = src_cpy,
-			.slen = len,
+			.slen = slen,
 			.dst = dst_cpy,
+			.dlen = dlen,
 		};
 		src_cpy = NULL;
 		dst_cpy = NULL;
@@ -1259,19 +1272,19 @@  err:
 }
 #endif
 
-static char *selabel_sub_key(const struct saved_data *data, const char *key)
+static char *selabel_sub_key(const struct saved_data *data, const char *key, size_t key_len)
 {
 	char *ptr, *dptr;
 
-	ptr = selabel_apply_subs(data->subs, data->subs_num, key);
+	ptr = selabel_apply_subs(data->subs, data->subs_num, key, key_len);
 	if (ptr) {
-		dptr = selabel_apply_subs(data->dist_subs, data->dist_subs_num, ptr);
+		dptr = selabel_apply_subs(data->dist_subs, data->dist_subs_num, ptr, strlen(ptr));
 		if (dptr) {
 			free(ptr);
 			ptr = dptr;
 		}
 	} else {
-		ptr = selabel_apply_subs(data->dist_subs, data->dist_subs_num, key);
+		ptr = selabel_apply_subs(data->dist_subs, data->dist_subs_num, key, key_len);
 	}
 
 	return ptr;
@@ -1787,9 +1800,10 @@  FUZZ_EXTERN struct lookup_result *lookup_all(struct selabel_handle *rec,
 
 		clean_key[len - 1] = '\0';
 		key = clean_key;
+		len--;
 	}
 
-	sub = selabel_sub_key(data, key);
+	sub = selabel_sub_key(data, key, len);
 	if (sub)
 		key = sub;
 
diff --git a/libselinux/src/label_file.h b/libselinux/src/label_file.h
index 436982bf..122894a2 100644
--- a/libselinux/src/label_file.h
+++ b/libselinux/src/label_file.h
@@ -72,6 +72,7 @@  struct selabel_sub {
 	char *src;				/* source path prefix */
 	char *dst;				/* substituted path prefix */
 	uint32_t slen;				/* length of source path prefix */
+	uint32_t dlen;				/* length of substituted path prefix */
 };
 
 /* A regular expression file security context specification */