http://www.perlmonks.org?node_id=1015527


in reply to Re: regex on gigabyte string
in thread regex on gigabyte string

Worse than that, I've seen tools explicitly dump something like (...)*? in a regex as something very close to (...){0,32766}?, because repetition only supported 15 bits, not 32, at least in some cases (but maybe that isn't true of modern versions of Perl). But it also seemed like those tools didn't always do such. So I'm not sure how often that limitation applies.

But it is easy to find the breaking point for this particular regex:

$ perl -del DB<1> x 0+( () = join('','<c>','x'x(1<<30),'</c>') =~ m{<c.*?/c>}g ) 0 1 DB<2> x 0+( () = join('','<c>','x'x(1<<31),'</c>') =~ m{<c.*?/c>}g ) 0 0 DB<3> x 0+( () = join('','<c>','x'x((1<<31)-8),'</c>') =~ m{<c.*?/c> +}g ) 0 1 DB<4> x 0+( () = join('','<c>','x'x((1<<31)-7),'</c>') =~ m{<c.*?/c> +}g ) 0 0

So (my version of) Perl can't deal with a capture string of more than 2**31-1 characters. And:

$ perl -del DB<2> x 0+( () = join('',('<c>','x'x((1<<30)-10),'</c>')x2) =~ m{<c. +*?/c>}g ) 0 2 DB<1> x 0+( () = join('',('<c>','x'x((1<<30)-10),'</c>')x3) =~ m{<c. +*?/c>}g ) 0 0

Surprisingly, it fails to even find the first match if there is a match beyond the 2**31-1 character position? Even trying to iterate to that point doesn't really help (perhaps .*? backtracks?):

$ perl -del DB<1> $x = join('',('<c>','x'x((1<<30)-10),'</c>')x2); while( $x =~ +m{<c.*?/c>}g ) { print pos($x), $/ } 1073741821 2147483642 DB<1> $x = join('',('<c>','x'x((1<<30)-10),'</c>')x3); while( $x =~ +m{<c.*?/c>}g ) { print pos($x), $/ } DB<2>

So one needs to deal with the string in reasonably-sized chunks. Which makes me wonder which XML-parsing modules manage to get that right. Their test suites should include a tag with a 4GB attribute value (with an escaped character at the end). :)

- tye