diff options
author | vda <vda@69ca8d6d-28ef-0310-b511-8ec308f3f277> | 2007-05-31 15:56:10 +0000 |
---|---|---|
committer | vda <vda@69ca8d6d-28ef-0310-b511-8ec308f3f277> | 2007-05-31 15:56:10 +0000 |
commit | 5a0772ad0b877d851856a7954de650d1db92eb5d (patch) | |
tree | cba198adefc5030fee5c04009a2591b05e0e6b59 | |
parent | deb78c496edb448ad8c879ad4185e4e7373c7ab9 (diff) | |
download | busybox-w32-5a0772ad0b877d851856a7954de650d1db92eb5d.tar.gz busybox-w32-5a0772ad0b877d851856a7954de650d1db92eb5d.tar.bz2 busybox-w32-5a0772ad0b877d851856a7954de650d1db92eb5d.zip |
less: fix very obscure memory corruption bug
git-svn-id: svn://busybox.net/trunk/busybox@18714 69ca8d6d-28ef-0310-b511-8ec308f3f277
-rw-r--r-- | miscutils/less.c | 45 |
1 files changed, 38 insertions, 7 deletions
diff --git a/miscutils/less.c b/miscutils/less.c index d6b71b9f2..58c1ec217 100644 --- a/miscutils/less.c +++ b/miscutils/less.c | |||
@@ -204,7 +204,27 @@ static void fill_match_lines(unsigned pos); | |||
204 | #define fill_match_lines(pos) ((void)0) | 204 | #define fill_match_lines(pos) ((void)0) |
205 | #endif | 205 | #endif |
206 | 206 | ||
207 | 207 | /* Devilishly complex routine. | |
208 | * | ||
209 | * Has to deal with EOF and EPIPE on input, | ||
210 | * with line wrapping, with last line not ending in '\n' | ||
211 | * (possibly not ending YET!), with backspace and tabs. | ||
212 | * | ||
213 | * Variables used: | ||
214 | * flines[] - array of lines already read. Linewrap may cause | ||
215 | * one source file line to occupy several flines[n]. | ||
216 | * flines[max_fline] - last line, possibly incomplete. | ||
217 | * terminated - 1 if flines[max_fline] is 'terminated' | ||
218 | * (if there was '\n' [which isn't stored itself, we just remember | ||
219 | * that it was seen]) | ||
220 | * max_lineno - last line's number, this one doesn't increment | ||
221 | * on line wrap, only on "real" new lines. | ||
222 | * readbuf[0..readeof-1] - small preliminary buffer. | ||
223 | * readbuf[readpos] - next character to add to current line. | ||
224 | * linepos - screen line position of next char to be read | ||
225 | * (takes into account tabs and backspaces) | ||
226 | * eof_error - < 0 error, == 0 EOF, > 0 not EOF/error | ||
227 | */ | ||
208 | static void read_lines(void) | 228 | static void read_lines(void) |
209 | { | 229 | { |
210 | #define readbuf bb_common_bufsiz1 | 230 | #define readbuf bb_common_bufsiz1 |
@@ -225,6 +245,7 @@ static void read_lines(void) | |||
225 | cp += 8; | 245 | cp += 8; |
226 | strcpy(current_line, cp); | 246 | strcpy(current_line, cp); |
227 | p += strlen(current_line); | 247 | p += strlen(current_line); |
248 | /* linepos is still valid from previous read_lines() */ | ||
228 | } else { | 249 | } else { |
229 | linepos = 0; | 250 | linepos = 0; |
230 | } | 251 | } |
@@ -275,17 +296,27 @@ static void read_lines(void) | |||
275 | if (c == '\x8' && linepos && p[-1] != '\t') { | 296 | if (c == '\x8' && linepos && p[-1] != '\t') { |
276 | readpos++; /* eat it */ | 297 | readpos++; /* eat it */ |
277 | linepos--; | 298 | linepos--; |
299 | /* was buggy (p could end up <= current_line)... */ | ||
278 | *--p = '\0'; | 300 | *--p = '\0'; |
279 | continue; | 301 | continue; |
280 | } | 302 | } |
281 | if (c == '\t') | 303 | { |
282 | linepos += (linepos^7) & 7; | 304 | size_t new_linepos = linepos + 1; |
283 | linepos++; | 305 | if (c == '\t') { |
284 | if (linepos >= w) | 306 | new_linepos += 7; |
285 | break; | 307 | new_linepos &= (~7); |
308 | } | ||
309 | if (new_linepos >= w) | ||
310 | break; | ||
311 | linepos = new_linepos; | ||
312 | } | ||
286 | /* ok, we will eat this char */ | 313 | /* ok, we will eat this char */ |
287 | readpos++; | 314 | readpos++; |
288 | if (c == '\n') { terminated = 1; break; } | 315 | if (c == '\n') { |
316 | terminated = 1; | ||
317 | linepos = 0; | ||
318 | break; | ||
319 | } | ||
289 | /* NUL is substituted by '\n'! */ | 320 | /* NUL is substituted by '\n'! */ |
290 | if (c == '\0') c = '\n'; | 321 | if (c == '\0') c = '\n'; |
291 | *p++ = c; | 322 | *p++ = c; |