[git commit] bc: shrink zdc_lex_string()

Denys Vlasenko vda.linux at googlemail.com
Tue Dec 18 12:48:37 UTC 2018


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

This actually fixes a rather obscure bug. This was failing to find
end of the string:

	$ echo -n '[foo]' | dc
	dc: string end could not be found

function                                             old     new   delta
zbc_lex_next                                        2230    2141     -89
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 0/1 up/down: 0/-89)             Total: -89 bytes
   text	   data	    bss	    dec	    hex	filename
 981461	    485	   7296	 989242	  f183a	busybox_old
 981372	    485	   7296	 989153	  f17e1	busybox_unstripped

Signed-off-by: Denys Vlasenko <vda.linux at googlemail.com>
---
 miscutils/bc.c | 32 +++++++++++++++++++-------------
 1 file changed, 19 insertions(+), 13 deletions(-)

diff --git a/miscutils/bc.c b/miscutils/bc.c
index 37c9012f9..5d969c9d0 100644
--- a/miscutils/bc.c
+++ b/miscutils/bc.c
@@ -3272,25 +3272,31 @@ static BC_STATUS zdc_lex_register(BcLex *l)
 
 static BC_STATUS zdc_lex_string(BcLex *l)
 {
-	size_t depth = 1, nls = 0, i = l->i;
-	char c;
+	size_t depth, nls, i;
 
 	l->t.t = BC_LEX_STR;
 	bc_vec_pop_all(&l->t.v);
 
-	for (c = l->buf[i]; c != 0 && depth; c = l->buf[++i]) {
-
-		depth += (c == '[' && (i == l->i || l->buf[i - 1] != '\\'));
-		depth -= (c == ']' && (i == l->i || l->buf[i - 1] != '\\'));
+	nls = 0;
+	depth = 1;
+	i = l->i;
+	for (;;) {
+		char c = l->buf[i];
+		if (c == '\0') {
+			l->i = i;
+			RETURN_STATUS(bc_error("string end could not be found"));
+		}
 		nls += (c == '\n');
-
-		if (depth) bc_vec_push(&l->t.v, &c);
-	}
-
-	if (c == '\0') {
-		l->i = i;
-		RETURN_STATUS(bc_error("string end could not be found"));
+		if (i == l->i || l->buf[i - 1] != '\\') {
+			if (c == '[') depth++;
+			if (c == ']')
+				if (--depth == 0)
+					break;
+		}
+		bc_vec_push(&l->t.v, &l->buf[i]);
+		i++;
 	}
+	i++;
 
 	bc_vec_pushZeroByte(&l->t.v);
 	// This check makes sense only if size_t is (much) larger than BC_MAX_STRING.


More information about the busybox-cvs mailing list