[PATCH] grep: fix infinite loop in -o

Denys Vlasenko vda.linux at googlemail.com
Tue Aug 24 03:59:31 UTC 2010


On Monday 23 August 2010 11:39, Colin Watson wrote:
> > > +						if (gl->matched_range.rm_so == gl->matched_range.rm_eo) {
> > > +							end++;
> > 
> > Why do you think end++ does not run off the end of the line?
> 
> Fair point, thanks.  Updated version follows.
...

>  					} else while (1) {
>  						unsigned end = gl->matched_range.rm_eo;
>  						char old = line[end];
> -						line[end] = '\0';
> -						print_line(line + gl->matched_range.rm_so,
> -								end - gl->matched_range.rm_so,
> -								linenum, ':');
> -						if (old == '\0')
> -							break;
> -						line[end] = old;
> +						if (gl->matched_range.rm_so == gl->matched_range.rm_eo) {
> +							/* Already at end of line? */
> +							if (line[end] == '\0')
> +								break;
> +							/* Otherwise make sure we make some progress. */
> +							if (line[++end] == '\0')
> +								break;
> +						} else {
> +							line[end] = '\0';
> +							print_line(line + gl->matched_range.rm_so,
> +									end - gl->matched_range.rm_so,
> +									linenum, ':');
> +							if (old == '\0')
> +								break;
> +							line[end] = old;
> +						}

Still not good. It may be not buggy now, but, for one, why do
you still save  char old = line[end]  when you don't use it?

Here's how I did it:


+                                               unsigned start = gl->matched_range.rm_so;
                                                unsigned end = gl->matched_range.rm_eo;
+                                               unsigned len = end - start;
                                                char old = line[end];
                                                line[end] = '\0';
-                                               print_line(line + gl->matched_range.rm_so,
-                                                               end - gl->matched_range.rm_so,
-                                                               linenum, ':');
+                                               /* Empty match is not printed: try "echo test | grep -o ''" */
+                                               if (len != 0)
+                                                       print_line(line + start, len, linenum, ':');
                                                if (old == '\0')
                                                        break;
                                                line[end] = old;
+                                               if (len == 0)
+                                                       end++;



Please try current git, it should have this bug fixed.

-- 
vda


More information about the busybox mailing list