On Friday 20 June 2008 17:42, walter harms wrote:
> Hello Denys,
> can you please look at "vi.c coredump" mail ?
> 
> I found that that stupid_insert() can return NULL (what is never checked)
> and therefore can crash vi. it is not a security issue but very annoying.
> unfortunately is that a core function and i feel not good to add simple
> checks without understand what they may cause.

You are assuming that I know busybox vi.c :)
I don't. Nobody knows it :)

Okay.

static char *stupid_insert(char * p, char c) // stupidly insert the char c at 
'p'
{
        p = text_hole_make(p, 1);
        if (p != 0) {
                *p = c;
                file_modified++;        // has the file been modified
                p++;
        }
        return p;
}

Neat function, yes. it will silently fail to insert char if p == NULL.
How nice. I bet callers don't expect that!

//  open a hole in text[]
static char *text_hole_make(char * p, int size) // at "p", make a 'size' byte 
hole
{
        char *src, *dest;
        int cnt;

        if (size <= 0)
                goto thm0;
        src = p;
        dest = p + size;
        cnt = end - src;        // the rest of buffer
        if ( ((end + size) >= (text + text_size)) // TODO: realloc here
                        || memmove(dest, src, cnt) != dest) {
                status_line_bold("can't create room for new characters");
                p = NULL;
                goto thm0;
        }
        memset(p, ' ', size);   // clear new hole
        end += size;            // adjust the new END
        file_modified++;        // has the file been modified
 thm0:
        return p;
}

More coolness. "if memmove(dest, src, cnt) != dest ..." - what?!
Since when memmove can return something else than dest?

Wait. Look closely. src, dest, cnt are all NEVER USED!  8]

Superfluous file_modified++ in stupid_insert()...

Oh well.

Try this patch please.
--
vda
diff -d -urpN busybox.8/editors/vi.c busybox.9/editors/vi.c
--- busybox.8/editors/vi.c	2008-06-17 17:53:29.000000000 +0200
+++ busybox.9/editors/vi.c	2008-06-20 21:12:14.000000000 +0200
@@ -451,9 +451,7 @@ static int init_text_buffer(char *fn)
 
 	/* allocate/reallocate text buffer */
 	free(text);
-	text_size = size * 2;
-	if (text_size < 10240)
-		text_size = 10240;	// have a minimum size for new files
+	text_size = size + 10240;
 	screenbegin = dot = end = text = xzalloc(text_size);
 
 	if (fn != current_filename) {
@@ -970,7 +968,7 @@ static void colon(char *buf)
 			// if the insert is before "dot" then we need to update
 			if (q <= dot)
 				dot += ch;
-			file_modified++;
+			file_modified = 1;
 		}
 	} else if (strncasecmp(cmd, "rewind", i) == 0) {	// rewind cmd line args
 		if (file_modified && !useforce) {
@@ -1611,7 +1609,7 @@ static char *char_insert(char * p, char 
 		c = get_one_char();
 		*p = c;
 		p++;
-		file_modified++;	// has the file been modified
+		file_modified = 1;	// has the file been modified
 	} else if (c == 27) {	// Is this an ESC?
 		cmd_mode = 0;
 		cmdcnt = 0;
@@ -1654,12 +1652,9 @@ static char *char_insert(char * p, char 
 static char *stupid_insert(char * p, char c) // stupidly insert the char c at 'p'
 {
 	p = text_hole_make(p, 1);
-	if (p != 0) {
-		*p = c;
-		file_modified++;	// has the file been modified
-		p++;
-	}
-	return p;
+	*p = c;
+	//file_modified = 1; - done by text_hole_make()
+	return p + 1;
 }
 
 static int find_range(char ** start, char ** stop, char c)
@@ -1842,24 +1837,21 @@ static void showmatching(char *p)
 //  open a hole in text[]
 static char *text_hole_make(char * p, int size)	// at "p", make a 'size' byte hole
 {
-	char *src, *dest;
-	int cnt;
-
 	if (size <= 0)
-		goto thm0;
-	src = p;
-	dest = p + size;
-	cnt = end - src;	// the rest of buffer
-	if ( ((end + size) >= (text + text_size)) // TODO: realloc here
-			|| memmove(dest, src, cnt) != dest) {
-		status_line_bold("can't create room for new characters");
-		p = NULL;
-		goto thm0;
+		return p;
+	end += size;		// adjust the new END
+	if (end >= (text + text_size)) {
+		char *new_text;
+		text_size += end - (text + text_size) + 10240;
+		new_text = xrealloc(text, text_size);
+		screenbegin = new_text + (screenbegin - text);
+		dot         = new_text + (dot         - text);
+		end         = new_text + (end         - text);
+		p           = new_text + (p           - text);
+		text = new_text;
 	}
 	memset(p, ' ', size);	// clear new hole
-	end += size;		// adjust the new END
-	file_modified++;	// has the file been modified
- thm0:
+	file_modified = 1;
 	return p;
 }
 
@@ -1885,16 +1877,14 @@ static char *text_hole_delete(char * p, 
 		goto thd0;
 	if (src >= end)
 		goto thd_atend;	// just delete the end of the buffer
-	if (memmove(dest, src, cnt) != dest) {
-		status_line_bold("can't delete the character");
-	}
+	memmove(dest, src, cnt);
  thd_atend:
 	end = end - hole_size;	// adjust the new END
 	if (dest >= end)
 		dest = end - 1;	// make sure dest in below end-1
 	if (end <= text)
 		dest = end = text;	// keep pointers valid
-	file_modified++;	// has the file been modified
+	file_modified = 1;	// has the file been modified
  thd0:
 	return dest;
 }
@@ -2412,7 +2402,7 @@ static int file_insert(const char * fn, 
 		status_line_bold("cannot read all of file \"%s\"", fn);
 	}
 	if (cnt >= size)
-		file_modified++;
+		file_modified = 1;
 	close(fd);
  fi0:
 #if ENABLE_FEATURE_VI_READONLY
@@ -3547,7 +3537,7 @@ static void do_cmd(char c)
 		dot_end();		// move to NL
 		if (dot < end - 1) {	// make sure not last char in text[]
 			*dot++ = ' ';	// replace NL with space
-			file_modified++;
+			file_modified = 1;
 			while (isblank(*dot)) {	// delete leading WS
 				dot_delete();
 			}
@@ -3750,7 +3740,7 @@ static void do_cmd(char c)
 		c1 = get_one_char();	// get the replacement char
 		if (*dot != '\n') {
 			*dot = c1;
-			file_modified++;	// has the file been modified
+			file_modified = 1;	// has the file been modified
 		}
 		end_cmd_q();	// stop adding to q
 		break;
@@ -3795,10 +3785,10 @@ static void do_cmd(char c)
 		}				// repeat cnt
 		if (islower(*dot)) {
 			*dot = toupper(*dot);
-			file_modified++;	// has the file been modified
+			file_modified = 1;	// has the file been modified
 		} else if (isupper(*dot)) {
 			*dot = tolower(*dot);
-			file_modified++;	// has the file been modified
+			file_modified = 1;	// has the file been modified
 		}
 		dot_right();
 		end_cmd_q();	// stop adding to q
_______________________________________________
busybox mailing list
[email protected]
http://busybox.net/cgi-bin/mailman/listinfo/busybox

Reply via email to