aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenis Vlasenko <vda.linux@googlemail.com>2008-11-19 13:25:14 +0000
committerDenis Vlasenko <vda.linux@googlemail.com>2008-11-19 13:25:14 +0000
commit4ae1e13d3f4716a35acf6186f5485e53da39829d (patch)
tree6a6b72300774220f9c7d914a3ca371af89aa3bc9
parent58a88916b926ffac657bb3c063b9906f324d4d79 (diff)
downloadbusybox-w32-4ae1e13d3f4716a35acf6186f5485e53da39829d.tar.gz
busybox-w32-4ae1e13d3f4716a35acf6186f5485e53da39829d.tar.bz2
busybox-w32-4ae1e13d3f4716a35acf6186f5485e53da39829d.zip
vi: fix several instances of major goof: when text grows, text[]
might get reallocated! We were keeping around pointers to old place... function old new delta colon 3017 3037 +20 char_insert 336 354 +18 stupid_insert 18 24 +6 string_insert 89 94 +5 do_cmd 4461 4465 +4 file_insert 328 329 +1 text_hole_make 134 120 -14 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 6/1 up/down: 54/-14) Total: 40 bytes
-rw-r--r--editors/vi.c123
1 files changed, 78 insertions, 45 deletions
diff --git a/editors/vi.c b/editors/vi.c
index 92c069de0..7f1d27fdf 100644
--- a/editors/vi.c
+++ b/editors/vi.c
@@ -300,13 +300,17 @@ static void dot_delete(void); // delete the char at 'dot'
300static char *bound_dot(char *); // make sure text[0] <= P < "end" 300static char *bound_dot(char *); // make sure text[0] <= P < "end"
301static char *new_screen(int, int); // malloc virtual screen memory 301static char *new_screen(int, int); // malloc virtual screen memory
302static char *char_insert(char *, char); // insert the char c at 'p' 302static char *char_insert(char *, char); // insert the char c at 'p'
303static char *stupid_insert(char *, char); // stupidly insert the char c at 'p' 303// might reallocate text[]! use p += stupid_insert(p, ...),
304// and be careful to not use pointers into potentially freed text[]!
305static uintptr_t stupid_insert(char *, char); // stupidly insert the char c at 'p'
304static int find_range(char **, char **, char); // return pointers for an object 306static int find_range(char **, char **, char); // return pointers for an object
305static int st_test(char *, int, int, char *); // helper for skip_thing() 307static int st_test(char *, int, int, char *); // helper for skip_thing()
306static char *skip_thing(char *, int, int, int); // skip some object 308static char *skip_thing(char *, int, int, int); // skip some object
307static char *find_pair(char *, char); // find matching pair () [] {} 309static char *find_pair(char *, char); // find matching pair () [] {}
308static char *text_hole_delete(char *, char *); // at "p", delete a 'size' byte hole 310static char *text_hole_delete(char *, char *); // at "p", delete a 'size' byte hole
309static char *text_hole_make(char *, int); // at "p", make a 'size' byte hole 311// might reallocate text[]! use p += text_hole_make(p, ...),
312// and be careful to not use pointers into potentially freed text[]!
313static uintptr_t text_hole_make(char *, int); // at "p", make a 'size' byte hole
310static char *yank_delete(char *, char *, int, int); // yank text[] into register then delete 314static char *yank_delete(char *, char *, int, int); // yank text[] into register then delete
311static void show_help(void); // display some help info 315static void show_help(void); // display some help info
312static void rawmode(void); // set "raw" mode on tty 316static void rawmode(void); // set "raw" mode on tty
@@ -316,11 +320,11 @@ static int mysleep(int);
316static int readit(void); // read (maybe cursor) key from stdin 320static int readit(void); // read (maybe cursor) key from stdin
317static int get_one_char(void); // read 1 char from stdin 321static int get_one_char(void); // read 1 char from stdin
318static int file_size(const char *); // what is the byte size of "fn" 322static int file_size(const char *); // what is the byte size of "fn"
319#if ENABLE_FEATURE_VI_READONLY 323#if !ENABLE_FEATURE_VI_READONLY
320static int file_insert(const char *, char *, int); 324#define file_insert(fn, p, update_ro_status) file_insert(fn, p)
321#else
322static int file_insert(const char *, char *);
323#endif 325#endif
326// file_insert might reallocate text[]!
327static int file_insert(const char *, char *, int);
324static int file_write(char *, char *, char *); 328static int file_write(char *, char *, char *);
325#if !ENABLE_FEATURE_VI_OPTIMIZE_CURSOR 329#if !ENABLE_FEATURE_VI_OPTIMIZE_CURSOR
326#define place_cursor(a, b, optimize) place_cursor(a, b) 330#define place_cursor(a, b, optimize) place_cursor(a, b)
@@ -370,7 +374,9 @@ static void end_cmd_q(void); // stop saving input chars
370static void showmatching(char *); // show the matching pair () [] {} 374static void showmatching(char *); // show the matching pair () [] {}
371#endif 375#endif
372#if ENABLE_FEATURE_VI_YANKMARK || (ENABLE_FEATURE_VI_COLON && ENABLE_FEATURE_VI_SEARCH) || ENABLE_FEATURE_VI_CRASHME 376#if ENABLE_FEATURE_VI_YANKMARK || (ENABLE_FEATURE_VI_COLON && ENABLE_FEATURE_VI_SEARCH) || ENABLE_FEATURE_VI_CRASHME
373static char *string_insert(char *, char *); // insert the string at 'p' 377// might reallocate text[]! use p += string_insert(p, ...),
378// and be careful to not use pointers into potentially freed text[]!
379static uintptr_t string_insert(char *, const char *); // insert the string at 'p'
374#endif 380#endif
375#if ENABLE_FEATURE_VI_YANKMARK 381#if ENABLE_FEATURE_VI_YANKMARK
376static char *text_yank(char *, char *, int); // save copy of "p" into a register 382static char *text_yank(char *, char *, int); // save copy of "p" into a register
@@ -486,8 +492,7 @@ static int init_text_buffer(char *fn)
486 char_insert(text, '\n'); 492 char_insert(text, '\n');
487 rc = 0; 493 rc = 0;
488 } else { 494 } else {
489 rc = file_insert(fn, text 495 rc = file_insert(fn, text, 1);
490 USE_FEATURE_VI_READONLY(, 1));
491 } 496 }
492 file_modified = 0; 497 file_modified = 0;
493 last_file_modified = -1; 498 last_file_modified = -1;
@@ -584,7 +589,8 @@ static void edit_file(char *fn)
584 crash_dummy(); // generate a random command 589 crash_dummy(); // generate a random command
585 } else { 590 } else {
586 crashme = 0; 591 crashme = 0;
587 dot = string_insert(text, "\n\n##### Ran out of text to work on. #####\n\n"); // insert the string 592 string_insert(text, "\n\n##### Ran out of text to work on. #####\n\n"); // insert the string
593 dot = text;
588 refresh(FALSE); 594 refresh(FALSE);
589 } 595 }
590 } 596 }
@@ -976,7 +982,11 @@ static void colon(char *buf)
976 // read after current line- unless user said ":0r foo" 982 // read after current line- unless user said ":0r foo"
977 if (b != 0) 983 if (b != 0)
978 q = next_line(q); 984 q = next_line(q);
979 ch = file_insert(fn, q USE_FEATURE_VI_READONLY(, 0)); 985 { // dance around potentially-reallocated text[]
986 uintptr_t ofs = q - text;
987 ch = file_insert(fn, q, 0);
988 q = text + ofs;
989 }
980 if (ch < 0) 990 if (ch < 0)
981 goto vc1; // nothing was inserted 991 goto vc1; // nothing was inserted
982 // how many lines in text[]? 992 // how many lines in text[]?
@@ -990,7 +1000,7 @@ static void colon(char *buf)
990 // if the insert is before "dot" then we need to update 1000 // if the insert is before "dot" then we need to update
991 if (q <= dot) 1001 if (q <= dot)
992 dot += ch; 1002 dot += ch;
993 file_modified++; 1003 /*file_modified++; - done by file_insert */
994 } 1004 }
995 } else if (strncasecmp(cmd, "rewind", i) == 0) { // rewind cmd line args 1005 } else if (strncasecmp(cmd, "rewind", i) == 0) { // rewind cmd line args
996 if (file_modified && !useforce) { 1006 if (file_modified && !useforce) {
@@ -1063,10 +1073,12 @@ static void colon(char *buf)
1063 c = orig_buf[1]; // what is the delimiter 1073 c = orig_buf[1]; // what is the delimiter
1064 F = orig_buf + 2; // start of "find" 1074 F = orig_buf + 2; // start of "find"
1065 R = strchr(F, c); // middle delimiter 1075 R = strchr(F, c); // middle delimiter
1066 if (!R) goto colon_s_fail; 1076 if (!R)
1077 goto colon_s_fail;
1067 *R++ = '\0'; // terminate "find" 1078 *R++ = '\0'; // terminate "find"
1068 buf1 = strchr(R, c); 1079 buf1 = strchr(R, c);
1069 if (!buf1) goto colon_s_fail; 1080 if (!buf1)
1081 goto colon_s_fail;
1070 *buf1++ = '\0'; // terminate "replace" 1082 *buf1++ = '\0'; // terminate "replace"
1071 if (*buf1 == 'g') { // :s/foo/bar/g 1083 if (*buf1 == 'g') { // :s/foo/bar/g
1072 buf1++; 1084 buf1++;
@@ -1084,10 +1096,14 @@ static void colon(char *buf)
1084 vc4: 1096 vc4:
1085 buf1 = char_search(q, F, FORWARD, LIMITED); // search cur line only for "find" 1097 buf1 = char_search(q, F, FORWARD, LIMITED); // search cur line only for "find"
1086 if (buf1) { 1098 if (buf1) {
1099 uintptr_t bias;
1087 // we found the "find" pattern - delete it 1100 // we found the "find" pattern - delete it
1088 text_hole_delete(buf1, buf1 + strlen(F) - 1); 1101 text_hole_delete(buf1, buf1 + strlen(F) - 1);
1089 // inset the "replace" patern 1102 // inset the "replace" patern
1090 string_insert(buf1, R); // insert the string 1103 bias = string_insert(buf1, R); // insert the string
1104 buf1 += bias;
1105 ls += bias;
1106 /*q += bias; - recalculated anyway */
1091 // check for "global" :s/foo/bar/g 1107 // check for "global" :s/foo/bar/g
1092 if (gflag == 1) { 1108 if (gflag == 1) {
1093 if ((buf1 + strlen(R)) < end_line(ls)) { 1109 if ((buf1 + strlen(R)) < end_line(ls)) {
@@ -1623,8 +1639,7 @@ static char *char_search(char *p, const char *pat, int dir, int range)
1623static char *char_insert(char *p, char c) // insert the char c at 'p' 1639static char *char_insert(char *p, char c) // insert the char c at 'p'
1624{ 1640{
1625 if (c == 22) { // Is this an ctrl-V? 1641 if (c == 22) { // Is this an ctrl-V?
1626 p = stupid_insert(p, '^'); // use ^ to indicate literal next 1642 p += stupid_insert(p, '^'); // use ^ to indicate literal next
1627 p--; // backup onto ^
1628 refresh(FALSE); // show the ^ 1643 refresh(FALSE); // show the ^
1629 c = get_one_char(); 1644 c = get_one_char();
1630 *p = c; 1645 *p = c;
@@ -1651,7 +1666,7 @@ static char *char_insert(char *p, char c) // insert the char c at 'p'
1651 if (c == 13) 1666 if (c == 13)
1652 c = '\n'; // translate \r to \n 1667 c = '\n'; // translate \r to \n
1653 sp = p; // remember addr of insert 1668 sp = p; // remember addr of insert
1654 p = stupid_insert(p, c); // insert the char 1669 p += 1 + stupid_insert(p, c); // insert the char
1655#if ENABLE_FEATURE_VI_SETOPTS 1670#if ENABLE_FEATURE_VI_SETOPTS
1656 if (showmatch && strchr(")]}", *sp) != NULL) { 1671 if (showmatch && strchr(")]}", *sp) != NULL) {
1657 showmatching(sp); 1672 showmatching(sp);
@@ -1659,9 +1674,11 @@ static char *char_insert(char *p, char c) // insert the char c at 'p'
1659 if (autoindent && c == '\n') { // auto indent the new line 1674 if (autoindent && c == '\n') { // auto indent the new line
1660 char *q; 1675 char *q;
1661 1676
1662 q = prev_line(p); // use prev line as templet 1677 q = prev_line(p); // use prev line as template
1663 for (; isblank(*q); q++) { 1678 for (; isblank(*q); q++) {
1664 p = stupid_insert(p, *q); // insert the char 1679 uintptr_t bias = stupid_insert(p, *q); // insert the char
1680 p += bias + 1;
1681 q += bias;
1665 } 1682 }
1666 } 1683 }
1667#endif 1684#endif
@@ -1669,12 +1686,16 @@ static char *char_insert(char *p, char c) // insert the char c at 'p'
1669 return p; 1686 return p;
1670} 1687}
1671 1688
1672static char *stupid_insert(char *p, char c) // stupidly insert the char c at 'p' 1689// might reallocate text[]! use p += stupid_insert(p, ...),
1690// and be careful to not use pointers into potentially freed text[]!
1691static uintptr_t stupid_insert(char *p, char c) // stupidly insert the char c at 'p'
1673{ 1692{
1674 p = text_hole_make(p, 1); 1693 uintptr_t bias;
1694 bias = text_hole_make(p, 1);
1695 p += bias;
1675 *p = c; 1696 *p = c;
1676 //file_modified++; - done by text_hole_make() 1697 //file_modified++; - done by text_hole_make()
1677 return p + 1; 1698 return bias;
1678} 1699}
1679 1700
1680static int find_range(char **start, char **stop, char c) 1701static int find_range(char **start, char **stop, char c)
@@ -1854,26 +1875,31 @@ static void showmatching(char *p)
1854} 1875}
1855#endif /* FEATURE_VI_SETOPTS */ 1876#endif /* FEATURE_VI_SETOPTS */
1856 1877
1857// open a hole in text[] 1878// open a hole in text[]
1858static char *text_hole_make(char *p, int size) // at "p", make a 'size' byte hole 1879// might reallocate text[]! use p += text_hole_make(p, ...),
1880// and be careful to not use pointers into potentially freed text[]!
1881static uintptr_t text_hole_make(char *p, int size) // at "p", make a 'size' byte hole
1859{ 1882{
1883 uintptr_t bias = 0;
1884
1860 if (size <= 0) 1885 if (size <= 0)
1861 return p; 1886 return bias;
1862 end += size; // adjust the new END 1887 end += size; // adjust the new END
1863 if (end >= (text + text_size)) { 1888 if (end >= (text + text_size)) {
1864 char *new_text; 1889 char *new_text;
1865 text_size += end - (text + text_size) + 10240; 1890 text_size += end - (text + text_size) + 10240;
1866 new_text = xrealloc(text, text_size); 1891 new_text = xrealloc(text, text_size);
1867 screenbegin = new_text + (screenbegin - text); 1892 bias = (new_text - text);
1868 dot = new_text + (dot - text); 1893 screenbegin += bias;
1869 end = new_text + (end - text); 1894 dot += bias;
1870 p = new_text + (p - text); 1895 end += bias;
1896 p += bias;
1871 text = new_text; 1897 text = new_text;
1872 } 1898 }
1873 memmove(p + size, p, end - size - p); 1899 memmove(p + size, p, end - size - p);
1874 memset(p, ' ', size); // clear new hole 1900 memset(p, ' ', size); // clear new hole
1875 file_modified++; 1901 file_modified++;
1876 return p; 1902 return bias;
1877} 1903}
1878 1904
1879// close a hole in text[] 1905// close a hole in text[]
@@ -2006,21 +2032,28 @@ static void end_cmd_q(void)
2006#if ENABLE_FEATURE_VI_YANKMARK \ 2032#if ENABLE_FEATURE_VI_YANKMARK \
2007 || (ENABLE_FEATURE_VI_COLON && ENABLE_FEATURE_VI_SEARCH) \ 2033 || (ENABLE_FEATURE_VI_COLON && ENABLE_FEATURE_VI_SEARCH) \
2008 || ENABLE_FEATURE_VI_CRASHME 2034 || ENABLE_FEATURE_VI_CRASHME
2009static char *string_insert(char *p, char *s) // insert the string at 'p' 2035// might reallocate text[]! use p += string_insert(p, ...),
2036// and be careful to not use pointers into potentially freed text[]!
2037static uintptr_t string_insert(char *p, const char *s) // insert the string at 'p'
2010{ 2038{
2011 int cnt, i; 2039 uintptr_t bias;
2040 int i;
2012 2041
2013 i = strlen(s); 2042 i = strlen(s);
2014 text_hole_make(p, i); 2043 bias = text_hole_make(p, i);
2044 p += bias;
2015 strncpy(p, s, i); 2045 strncpy(p, s, i);
2016 for (cnt = 0; *s != '\0'; s++) {
2017 if (*s == '\n')
2018 cnt++;
2019 }
2020#if ENABLE_FEATURE_VI_YANKMARK 2046#if ENABLE_FEATURE_VI_YANKMARK
2021 status_line("Put %d lines (%d chars) from [%c]", cnt, i, what_reg()); 2047 {
2048 int cnt;
2049 for (cnt = 0; *s != '\0'; s++) {
2050 if (*s == '\n')
2051 cnt++;
2052 }
2053 status_line("Put %d lines (%d chars) from [%c]", cnt, i, what_reg());
2054 }
2022#endif 2055#endif
2023 return p; 2056 return bias;
2024} 2057}
2025#endif 2058#endif
2026 2059
@@ -2273,8 +2306,8 @@ static int file_size(const char *fn) // what is the byte size of "fn"
2273 return cnt; 2306 return cnt;
2274} 2307}
2275 2308
2276static int file_insert(const char *fn, char *p 2309// might reallocate text[]!
2277 USE_FEATURE_VI_READONLY(, int update_ro_status)) 2310static int file_insert(const char *fn, char *p, int update_ro_status)
2278{ 2311{
2279 int cnt = -1; 2312 int cnt = -1;
2280 int fd, size; 2313 int fd, size;
@@ -2302,7 +2335,7 @@ static int file_insert(const char *fn, char *p
2302 goto fi0; 2335 goto fi0;
2303 } 2336 }
2304 size = statbuf.st_size; 2337 size = statbuf.st_size;
2305 p = text_hole_make(p, size); 2338 p += text_hole_make(p, size);
2306 cnt = safe_read(fd, p, size); 2339 cnt = safe_read(fd, p, size);
2307 if (cnt < 0) { 2340 if (cnt < 0) {
2308 status_line_bold("\"%s\" %s", fn, strerror(errno)); 2341 status_line_bold("\"%s\" %s", fn, strerror(errno));
@@ -3103,7 +3136,7 @@ static void do_cmd(int c)
3103 if (c == 'p') 3136 if (c == 'p')
3104 dot_right(); // move to right, can move to NL 3137 dot_right(); // move to right, can move to NL
3105 } 3138 }
3106 dot = string_insert(dot, p); // insert the string 3139 string_insert(dot, p); // insert the string
3107 end_cmd_q(); // stop adding to q 3140 end_cmd_q(); // stop adding to q
3108 break; 3141 break;
3109 case 'U': // U- Undo; replace current line with original version 3142 case 'U': // U- Undo; replace current line with original version
@@ -3111,7 +3144,7 @@ static void do_cmd(int c)
3111 p = begin_line(dot); 3144 p = begin_line(dot);
3112 q = end_line(dot); 3145 q = end_line(dot);
3113 p = text_hole_delete(p, q); // delete cur line 3146 p = text_hole_delete(p, q); // delete cur line
3114 p = string_insert(p, reg[Ureg]); // insert orig line 3147 p += string_insert(p, reg[Ureg]); // insert orig line
3115 dot = p; 3148 dot = p;
3116 dot_skip_over_ws(); 3149 dot_skip_over_ws();
3117 } 3150 }