On Sunday 21 September 2008 14:27, poly-p man wrote:
> I'm using a (somewhat) recent svn build...
> 
> Found a pretty nasty bug... I'll help hunt down the code shortly..
> 
> Steps to reproduce:
> Type many spaces into the command-line, hit enter
> hit up (previous command before the spaces appears).
> hit down
> 
> What appears seems to be pointer overflow junk - one time it gave me "/root", 
> another time it gave me random data and let me backspace into the prompt.
> 
> Alone this doesn't seem like much, but could it be part of a larger bug?

Try this patch.
--
vda
diff -d -urpN busybox.3/libbb/lineedit.c busybox.4/libbb/lineedit.c
--- busybox.3/libbb/lineedit.c	2008-09-11 21:23:19.000000000 +0200
+++ busybox.4/libbb/lineedit.c	2008-09-22 00:22:46.000000000 +0200
@@ -956,24 +956,33 @@ static void input_tab(smallint *lastWasT
 
 #if MAX_HISTORY > 0
 
+static void save_command_ps_at_cur_history(void)
+{
+	if (command_ps[0] != '\0') {
+		int cur = state->cur_history;
+		free(state->history[cur]);
+		state->history[cur] = xstrdup(command_ps);
+	}
+}
+
 /* state->flags is already checked to be nonzero */
-static void get_previous_history(void)
+static int get_previous_history(void)
 {
-	if (command_ps[0] != '\0' || state->history[state->cur_history] == NULL) {
-		free(state->history[state->cur_history]);
-		state->history[state->cur_history] = xstrdup(command_ps);
+	if ((state->flags & DO_HISTORY) && state->cur_history) {
+		save_command_ps_at_cur_history();
+		state->cur_history--;
+		return 1;
 	}
-	state->cur_history--;
+	beep();
+	return 0;
 }
 
 static int get_next_history(void)
 {
 	if (state->flags & DO_HISTORY) {
-		int ch = state->cur_history;
-		if (ch < state->cnt_history) {
-			get_previous_history(); /* save the current history line */
-			state->cur_history = ch + 1;
-			return state->cur_history;
+		if (state->cur_history < state->cnt_history) {
+			save_command_ps_at_cur_history(); /* save the current history line */
+			return ++state->cur_history;
 		}
 	}
 	beep();
@@ -995,6 +1004,7 @@ static void load_history(const char *fro
 		for (hi = state->cnt_history; hi > 0;) {
 			hi--;
 			free(state->history[hi]);
+			state->history[hi] = NULL;
 		}
 
 		for (hi = 0; hi < MAX_HISTORY;) {
@@ -1006,7 +1016,7 @@ static void load_history(const char *fro
 			l = strlen(hl);
 			if (l >= MAX_LINELEN)
 				hl[MAX_LINELEN-1] = '\0';
-			if (l == 0 || hl[0] == ' ') {
+			if (l == 0) {
 				free(hl);
 				continue;
 			}
@@ -1043,19 +1053,27 @@ static void remember_in_history(const ch
 
 	if (!(state->flags & DO_HISTORY))
 		return;
-
+	if (str[0] == '\0')
+		return;
 	i = state->cnt_history;
-	free(state->history[MAX_HISTORY]);
-	state->history[MAX_HISTORY] = NULL;
-	/* After max history, remove the oldest command */
+	/* Don't save dupes */
+	if (i && strcmp(state->history[i-1], str) == 0)
+		return;
+
+	free(state->history[MAX_HISTORY]); /* redundant, paranoia */
+	state->history[MAX_HISTORY] = NULL; /* redundant, paranoia */
+
+	/* If history[] is full, remove the oldest command */
+	/* we need to keep history[MAX_HISTORY] empty, hence >=, not > */
 	if (i >= MAX_HISTORY) {
 		free(state->history[0]);
 		for (i = 0; i < MAX_HISTORY-1; i++)
 			state->history[i] = state->history[i+1];
+		/* i == MAX_HISTORY-1 */
 	}
-// Maybe "if (!i || strcmp(history[i-1], command) != 0) ..."
-// (i.e. do not save dups?)
+	/* i <= MAX_HISTORY-1 */
 	state->history[i++] = xstrdup(str);
+	/* i <= MAX_HISTORY */
 	state->cur_history = i;
 	state->cnt_history = i;
 #if ENABLE_FEATURE_EDITING_SAVEHISTORY
@@ -1432,6 +1450,13 @@ int FAST_FUNC read_line_input(const char
 		}
 	}
 #endif
+
+#if 0
+	for (ic = 0; ic <= MAX_HISTORY; ic++)
+		bb_error_msg("history[%d]:'%s'", ic, state->history[ic]);
+	bb_error_msg("cur_history:%d cnt_history:%d", state->cur_history, state->cnt_history);
+#endif
+
 	/* Print out the command prompt */
 	parse_and_put_prompt(prompt);
 
@@ -1540,11 +1565,8 @@ int FAST_FUNC read_line_input(const char
 		vi_case(CTRL('P')|vbit:)
 		vi_case('k'|vbit:)
 			/* Control-p -- Get previous command from history */
-			if ((state->flags & DO_HISTORY) && state->cur_history > 0) {
-				get_previous_history();
+			if (get_previous_history())
 				goto rewrite_line;
-			}
-			beep();
 			break;
 #endif
 
@@ -1733,10 +1755,8 @@ int FAST_FUNC read_line_input(const char
 #if MAX_HISTORY > 0
 			case 'A':
 				/* Up Arrow -- Get previous command from history */
-				if ((state->flags & DO_HISTORY) && state->cur_history > 0) {
-					get_previous_history();
+				if (get_previous_history())
 					goto rewrite_line;
-				}
 				beep();
 				break;
 			case 'B':
@@ -1746,7 +1766,7 @@ int FAST_FUNC read_line_input(const char
  rewrite_line:
 				/* Rewrite the line with the selected history item */
 				/* change command */
-				command_len = strlen(strcpy(command, state->history[state->cur_history]));
+				command_len = strlen(strcpy(command, state->history[state->cur_history] ? : ""));
 				/* redraw and go to eol (bol, in vi */
 				redraw(cmdedit_y, (state->flags & VI_MODE) ? 9999 : 0);
 				break;
_______________________________________________
busybox mailing list
[email protected]
http://busybox.net/cgi-bin/mailman/listinfo/busybox
  • bug in ash? poly-p man
    • Re: bug in ash? Denys Vlasenko

Reply via email to