[git commit] base32/64: decode in-place

Denys Vlasenko vda.linux at googlemail.com
Fri Nov 27 14:39:23 UTC 2020


commit: https://git.busybox.net/busybox/commit/?id=cdab3c4fac76bcf941e55e309b061ac97925f9b0
branch: https://git.busybox.net/busybox/commit/?id=refs/heads/master

Signed-off-by: Denys Vlasenko <vda.linux at googlemail.com>
---
 coreutils/uudecode.c | 17 ++++++++++++-----
 1 file changed, 12 insertions(+), 5 deletions(-)

diff --git a/coreutils/uudecode.c b/coreutils/uudecode.c
index 751976a87..10e5a55de 100644
--- a/coreutils/uudecode.c
+++ b/coreutils/uudecode.c
@@ -286,13 +286,19 @@ int baseNUM_main(int argc UNUSED_PARAM, char **argv)
 	} else {
 		enum {
 			SRC_BUF_SIZE = 3 * 5 * 32, /* this *MUST* be a multiple of 3 and 5 */
-			DST_BUF_SIZE = 4 * ((SRC_BUF_SIZE + 2) / 3),
+			DST_BUF_SIZE = 8 * ((SRC_BUF_SIZE + 4) / 5), /* max growth on decode (base32 case) */
 		};
-		char src_buf[SRC_BUF_SIZE];
-		char dst_buf[DST_BUF_SIZE + 1];
-		int src_fd = fileno(src_stream);
-		int rem = 0;
+		/* Use one buffer for both input and output:
+		 * decoding reads input "left-to-right",
+		 * it's safe to place source at the end of the buffer and
+		 * overwrite it while decoding, just be careful to have a gap.
+		 */
+		char dst_buf[((DST_BUF_SIZE + /*gap:*/ 16) /*round up to 16:*/ | 0xf) + 1];
+#define src_buf (dst_buf + sizeof(dst_buf) - SRC_BUF_SIZE)
+		int src_fd, rem;
 
+		src_fd = fileno(src_stream);
+		rem = 0;
 		while (1) {
 			size_t size = full_read(src_fd, src_buf, SRC_BUF_SIZE);
 			if ((ssize_t)size < 0)
@@ -331,6 +337,7 @@ int baseNUM_main(int argc UNUSED_PARAM, char **argv)
 				}
 			}
 		}
+#undef src_buf
 	}
 
 	fflush_stdout_and_exit(EXIT_SUCCESS);


More information about the busybox-cvs mailing list