develooper Front page | perl.perl5.porters | Postings from October 2016

[ #76824] [perl #112608] panic: sv_setpvn called withnegative strlen -1

Thread Previous
Karl Williamson via RT
October 18, 2016 19:45
[ #76824] [perl #112608] panic: sv_setpvn called withnegative strlen -1
Message ID:
<URL: >

On Sat Oct 08 06:33:55 2016, PALI wrote:
> Problem is still there also with blead perl. No crash or sv_setpvn
> panic anymore but valgrind show this error message:
> ==17627== Conditional jump or move depends on uninitialised value(s)
> ==17627==    at 0x51E0AA: Perl_utf8n_to_uvchr (utf8.c:858)
> ==17627==    by 0x663CA14: encode_method (Encode.xs:193)
> ==17627==    by 0x663CCF9: XS_Encode__XS_encode (Encode.xs:785)
> Problem is again in this code from Encode.xs:
> STRLEN clen;
> UV ch =
>     utf8n_to_uvuni(s+slen, (SvCUR(src)-slen),
>            &clen, UTF8_ALLOW_ANY|UTF8_CHECK_ONLY);
> I suspect that (SvCUR(src)-slen) is really incorrect and something
> like (tlen-sdone-slen) should be passed.
> IIRC s is pointer to first C char which is not yet processed in dst,
> slen is number of characters processed by last do_encode() call (in
> case of problems it can be just one or zero) and SvCUR(src) is length
> of original input string. (tlen-sdone) should be number of remaining
> characters in src, not processed in dst.
> With change (SvCUR(src)-slen) to (tlen-sdone-slen) valgrind does not
> show error message anymore...
> CCing khw, can you recheck this?

The current code is wrong.  

The 2nd parameter to utf8n_to_uvuni() is the upper limit of how far it is permissible to look beyond the first byte of the string pointed to by the first parameter.  The typical way that the core code uses to handle this type of thing is to save s as s0 upon entrance to the function, and then it's easy to get it right.  In this case, one could set s0 after s is adjusted for *offset. 

s0 = s;

before the loop.  tlen has been calculated to be the number of bytes available in s0, it should be used instead of SvCUR.

Because at the time of the function call, s is slen bytes behind the sequence you want to convert, adjustments have to be made.  You could write.

utf8n_to_uvuni(s+slen, tlen - (s + slen - s0), ...

I think this is the most foolproof and maintainable method. 

Note that

slen = tlen - sdone

so pali's solution


can be rewritten as

tlen - sdone - (tlen -sdone) == 0

which is wrong.  Another option would be to calculate and use sleft

Thread Previous Perl Programming lists via nntp and http.
Comments to Ask Bjørn Hansen at | Group listing | About