Skip Menu |

This queue is for tickets about the Net-IDN-Encode CPAN distribution.

Report information
The Basics
Id: 118924
Status: resolved
Worked: 10 min
Priority: 0/
Queue: Net-IDN-Encode

People
Owner: CFAERBER [...] cpan.org
Requestors: alexander.bluhm [...] gmx.net
Cc:
AdminCc:

Bug Information
Severity: Critical
Broken in:
  • 2.300
  • 2.301
Fixed in: 2.399_20161227



Subject: encode_punycode heap overflow
When running the tests of Net-IDN-Encode-2.300 on OpenBSD with additional malloc(3) checks, Perl crashes. This happens during test t/uts46_to_ascii-trans.t: t/uts46_encode_utf8.t ..... ok perl(92732) in free(): chunk canary corrupted 0x17858bb94100 0x65@0x65 t/uts46_to_ascii-trans.t .. Failed 3600/3770 subtests (2 TODO tests unexpectedly succeeded) t/uts46_to_ascii.t ........ ok Subtest 171 seems to trigger the heap overflow: ok 170 - to_ascii('xn--53h') [data/IdnaTest.txt:275] perl(4839) in free(): chunk canary corrupted 0x1d2e5083ce80 0x65@0x65 Abort trap Here is the man page snippet that describes what is going on: ``chunk canary corrupted address offset@length'' A byte after the requested size has been overwritten, indicating a heap overflow. The offset at which corruption was detected is printed before the @, and the requested length of the allocation after the @. I have looked at the XS code and only the length of the input string is checked. The size of the output string is increased from time to time, but not always when the output pointer is moved forward. So I have put the realloc in a function grow_string() and call it every time before a value is written to *re_p. This patch fixes the test. --- lib/Net/IDN/Punycode.xs.orig Fri Jul 17 21:10:51 2015 +++ lib/Net/IDN/Punycode.xs Tue Nov 22 14:34:09 2016 @@ -49,6 +49,20 @@ static int adapt(int delta, int numpoints, int first) return k + (((BASE-TMIN+1) * delta) / (delta+SKEW)); }; +static void +grow_string(SV *const sv, char **start, char **current, char **end, STRLEN add) +{ + STRLEN len; + + if(*current + add <= *end) + return; + + len = (*current - *start + add + 15) & ~15; + *start = SvGROW(sv, len); + *current = *start + len; + *end = *start + SvLEN(sv); +} + MODULE = Net::IDN::Punycode PACKAGE = Net::IDN::Punycode SV* @@ -81,15 +95,20 @@ encode_punycode(input) /* copy basic code points */ while(in_p < in_e) { - if( isBASE(*in_p) ) + if( isBASE(*in_p) ) { + grow_string(RETVAL, &re_s, &re_p, &re_e, 1); *re_p++ = *in_p; + } in_p++; } h = re_p - re_s; /* add DELIM if needed */ - if(h) *re_p++ = DELIM; + if(h) { + grow_string(RETVAL, &re_s, &re_p, &re_e, 1); + *re_p++ = DELIM; + } for(;;) { /* find smallest code point not yet handled */ @@ -138,20 +157,14 @@ encode_punycode(input) q = delta; for(k = BASE;; k += BASE) { - if(re_p >= re_e) { - length_guess = re_e - re_s + 16; - re_e = SvGROW(RETVAL, length_guess); - re_p = re_e + (re_p - re_s); - re_s = re_e; - re_e = re_s + SvLEN(RETVAL); - } - t = TMIN_MAX(k - bias); if(q < t) break; + grow_string(RETVAL, &re_s, &re_p, &re_e, 1); *re_p++ = enc_digit[t + ((q-t) % (BASE-t))]; q = (q-t) / (BASE-t); } if(q > BASE) croak("input exceeds punycode limit"); + grow_string(RETVAL, &re_s, &re_p, &re_e, 1); *re_p++ = enc_digit[q]; bias = adapt(delta, h+1, first); delta = first = 0; @@ -162,6 +175,7 @@ encode_punycode(input) ++delta; ++n; } + grow_string(RETVAL, &re_s, &re_p, &re_e, 1); *re_p = 0; SvCUR_set(RETVAL, re_p - re_s); ST(0) = RETVAL; @@ -201,6 +215,7 @@ decode_punycode(input) c = *in_p; /* we don't care whether it's UTF-8 */ if(!isBASE(c)) croak("non-base character in input for decode_punycode"); if(c == DELIM) skip_p = in_p; + grow_string(RETVAL, &re_s, &re_p, &re_e, 1); *re_p++ = c; /* copy it */ } @@ -236,18 +251,11 @@ decode_punycode(input) u8 = UNISKIP(n); /* how many bytes we need */ - if(re_p + u8 >= re_e) { - length_guess = re_e - re_p + u8 + 16; - re_e = SvGROW(RETVAL, length_guess); - re_p = re_e + (re_p - re_s); - re_s = re_e; - re_e = re_s + SvLEN(RETVAL); - } - j = i; for(skip_p = re_s; j > 0; j--) /* find position in UTF-8 */ skip_p+=UTF8SKIP(skip_p); + grow_string(RETVAL, &re_s, &re_p, &re_e, u8); if(skip_p < re_p) /* move succeeding chars */ Move(skip_p, skip_p + u8, re_p - skip_p, char); re_p += u8; @@ -255,6 +263,7 @@ decode_punycode(input) } if(!first) SvUTF8_on(RETVAL); /* UTF-8 chars have been inserted */ + grow_string(RETVAL, &re_s, &re_p, &re_e, 1); *re_p = 0; SvCUR_set(RETVAL, re_p - re_s); ST(0) = RETVAL;
Thank you for reporting this. It's interesting that this bug has not been noticed so far. I'll release a new version shortly.
From: paul [...] city-fan.org
On Sat Dec 03 06:47:36 2016, CFAERBER wrote: Show quoted text
> Thank you for reporting this. It's interesting that this bug has not > been noticed so far. I'll release a new version shortly.
I'm now seeing crashes on x86_32 builds on some perls: $ ./Build test t/00use.t ................. ok t/10pod.t ................. ok t/11pod_cover.t ........... ok t/domain_to_ascii.t ....... ok t/domain_to_unicode.t ..... ok t/encode_bytes.t .......... ok t/encode_utf8.t ........... ok t/punycode_vec-pp.t ....... ok t/punycode_vec-xs.t ....... ok t/uts46_api_call.t ........ ok t/uts46_encode_bytes.t .... ok t/uts46_encode_utf8.t ..... ok *** glibc detected *** /usr/bin/perl: free(): invalid next size (normal): 0x08d2d420 *** ======= Backtrace: ========= /lib/libc.so.6[0xf73903a4] /lib/libc.so.6[0xf7393e46] /lib/libc.so.6(realloc+0x106)[0xf7394c86] /usr/lib/perl5/5.10.0/i386-linux-thread-multi/CORE/libperl.so(Perl_safesysrealloc+0x8a)[0xf75fb7aa] /usr/lib/perl5/5.10.0/i386-linux-thread-multi/CORE/libperl.so(Perl_sv_grow+0x7d)[0xf76527fd] /builddir/build/BUILD/Net-IDN-Encode-2.301/blib/arch/auto/Net/IDN/Punycode/Punycode.so[0xf709c34e] /builddir/build/BUILD/Net-IDN-Encode-2.301/blib/arch/auto/Net/IDN/Punycode/Punycode.so[0xf709d075] /usr/lib/perl5/5.10.0/i386-linux-thread-multi/CORE/libperl.so(Perl_pp_entersub+0xb29)[0xf76267b9] /usr/lib/perl5/5.10.0/i386-linux-thread-multi/CORE/libperl.so(Perl_runops_debug+0x153)[0xf75e7f53] /usr/lib/perl5/5.10.0/i386-linux-thread-multi/CORE/libperl.so(perl_run+0x274)[0xf7620904] /usr/bin/perl(main+0x10e)[0x8048a2e] /lib/libc.so.6(__libc_start_main+0xe5)[0xf73376e5] /usr/bin/perl[0x8048881] ======= Memory map: ======== 08048000-08049000 r-xp 00000000 00:2a 126137650 /usr/bin/perl 08049000-0804a000 rw-p 00000000 00:2a 126137650 /usr/bin/perl 089cf000-09428000 rw-p 00000000 00:00 0 [heap] f6e00000-f6e21000 rw-p 00000000 00:00 0 f6e21000-f6f00000 ---p 00000000 00:00 0 f6fcf000-f6fdc000 r-xp 00000000 00:2a 126138418 /lib/libgcc_s-4.3.2-20081105.so.1 f6fdc000-f6fdd000 rw-p 0000c000 00:2a 126138418 /lib/libgcc_s-4.3.2-20081105.so.1 f6fdd000-f709b000 rw-p 00000000 00:00 0 f709b000-f70a0000 r-xp 00000000 00:2a 126136495 /builddir/build/BUILD/Net-IDN-Encode-2.301/blib/arch/auto/Net/IDN/Punycode/Punycode.so f70a0000-f70a1000 rw-p 00004000 00:2a 126136495 /builddir/build/BUILD/Net-IDN-Encode-2.301/blib/arch/auto/Net/IDN/Punycode/Punycode.so f70a1000-f70cb000 r-xp 00000000 00:2a 126142185 /usr/lib/perl5/5.10.0/i386-linux-thread-multi/auto/Unicode/Normalize/Normalize.so f70cb000-f70ec000 rw-p 00029000 00:2a 126142185 /usr/lib/perl5/5.10.0/i386-linux-thread-multi/auto/Unicode/Normalize/Normalize.so f70ec000-f7109000 r-xp 00000000 00:2a 126142221 /usr/lib/perl5/5.10.0/i386-linux-thread-multi/auto/Storable/Storable.so f7109000-f710a000 rw-p 0001d000 00:2a 126142221 /usr/lib/perl5/5.10.0/i386-linux-thread-multi/auto/Storable/Storable.so f710a000-f710d000 r-xp 00000000 00:2a 126142444 /usr/lib/perl5/5.10.0/i386-linux-thread-multi/auto/Fcntl/Fcntl.so f710d000-f710e000 rw-p 00003000 00:2a 126142444 /usr/lib/perl5/5.10.0/i386-linux-thread-multi/auto/Fcntl/Fcntl.so f710e000-f7113000 r-xp 00000000 00:2a 126142424 /usr/lib/perl5/5.10.0/i386-linux-thread-multi/auto/IO/IO.so f7113000-f7114000 rw-p 00005000 00:2a 126142424 /usr/lib/perl5/5.10.0/i386-linux-thread-multi/auto/IO/IO.so f7114000-f711f000 r-xp 00000000 00:2a 126142419 /usr/lib/perl5/5.10.0/i386-linux-thread-multi/auto/List/Util/Util.so f711f000-f7120000 rw-p 0000a000 00:2a 126142419 /usr/lib/perl5/5.10.0/i386-linux-thread-multi/auto/List/Util/Util.so f7120000-f7320000 r--p 00000000 00:2a 126143014 /usr/lib/locale/locale-archive f7320000-f7321000 rw-p 00000000 00:00 0 f7321000-f748f000 r-xp 00000000 00:2a 126138410 /lib/libc-2.9.so f748f000-f7491000 r--p 0016e000 00:2a 126138410 /lib/libc-2.9.so f7491000-f7492000 rw-p 00170000 00:2a 126138410 /lib/libc-2.9.so f7492000-f7495000 rw-p 00000000 00:00 0 f7495000-f74ab000 r-xp 00000000 00:2a 126138386 /lib/libpthread-2.9.so f74ab000-f74ac000 r--p 00015000 00:2a 126138386 /lib/libpthread-2.9.so f74ac000-f74ad000 rw-p 00016000 00:2a 126138386 /lib/libpthread-2.9.so f74ad000-f74af000 rw-p 00000000 00:00 0 f74af000-f74b1000 r-xp 00000000 00:2a 126138378 /lib/libutil-2.9.so f74b1000-f74b2000 r--p 00001000 00:2a 126138378 /lib/libutil-2.9.so f74b2000-f74b3000 rw-p 00002000 00:2a 126138378 /lib/libutil-2.9.so f74b3000-f74b4000 rw-p 00000000 00:00 0 f74b4000-f74be000 r-xp 00000000 00:2a 126138406 /lib/libcrypt-2.9.so f74be000-f74bf000 r--p 00009000 00:2a 126138406 /lib/libcrypt-2.9.so f74bf000-f74c0000 rw-p 0000a000 00:2a 126138406 /lib/libcrypt-2.9.so f74c0000-f74e7000 rw-p 00000000 00:00 0 f74e7000-f750e000 r-xp 00000000 00:2a 126138402 /lib/libm-2.9.so f750e000-f750f000 r--p 00026000 00:2a 126138402 /lib/libm-2.9.so f750f000-f7510000 rw-p 00027000 00:2a 126138402 /lib/libm-2.9.so f7510000-f7513000 r-xp 00000000 00:2a 126138404 /lib/libdl-2.9.so f7513000-f7514000 r--p 00002000 00:2a 126138404 /lib/libdl-2.9.so f7514000-f7515000 rw-p 00003000 00:2a 126138404 /lib/libdl-2.9.so f7515000-f752b000 r-xp 00000000 00:2a 126138400 /lib/libnsl-2.9.so f752b000-f752c000 r--p 00016000 00:2a 126138400 /lib/libnsl-2.9.so f752c000-f752d000 rw-p 00017000 00:2a 126138400 /lib/libnsl-2.9.so f752d000-f752f000 rw-p 00000000 00:00 0 f752f000-f7542000 r-xp 00000000 00:2a 126138384 /lib/libresolv-2.9.so f7542000-f7543000 r--p 00012000 00:2a 126138384 /lib/libresolv-2.9.so f7543000-f7544000 rw-p 00013000 00:2a 126138384 /lib/libresolv-2.9.so f7544000-f7546000 rw-p 00000000 00:00 0 f7549000-f77b2000 r-xp 00000000 00:2a 126142629 /usr/lib/perl5/5.10.0/i386-linux-thread-multi/CORE/libperl.so f77b2000-f77b7000 rw-p 00269000 00:2a 126142629 /usr/lib/perl5/5.10.0/i386-linux-thread-multi/CORE/libperl.so f77b7000-f77d7000 r-xp 00000000 00:2a 126103465 /lib/ld-2.9.so f77d7000-f77d8000 rw-p 00000000 00:00 0 f77d8000-f77d9000 r--p 00020000 00:2a 126103465 /lib/ld-2.9.so f77d9000-f77da000 rw-p 00021000 00:2a 126103465 /lib/ld-2.9.so ff7cf000-ff9de000 rw-p 00000000 00:00 0 [stack] t/uts46_to_ascii-trans.t .. Failed 3600/3770 subtests (less 2 skipped subtests: 168 okay) t/uts46_to_ascii.t ........ ok t/uts46_to_unicode.t ...... ok t/xtra_pp.t ............... ok Test Summary Report ------------------- t/uts46_to_ascii-trans.t (Wstat: 134 Tests: 170 Failed: 0) Non-zero wait status: 134 Parse errors: Bad plan. You planned 3770 tests but ran 170. t/uts46_to_ascii.t (Wstat: 0 Tests: 3770 Failed: 0) TODO passed: 765, 1124, 1197, 1215, 1581, 1631, 1733-1734 1938-1941, 1984-1991, 2474-2475, 2501-2502 2614, 2771-2772, 2946, 3226, 3334-3338 3561, 3563-3564, 3716 t/uts46_to_unicode.t (Wstat: 0 Tests: 5026 Failed: 0) TODO passed: 955-956, 1430, 1535-1536, 1564, 2069-2070 2134-2135, 2264-2265, 2543-2546, 2600-2607 3242-3243, 3282-3283, 3434, 3663-3664, 3891 4264, 4416-4420, 4736, 4738-4739, 4953 Files=16, Tests=9181, 3 wallclock secs ( 0.63 usr 0.03 sys + 2.65 cusr 0.07 csys = 3.38 CPU) Result: FAIL Failed 1/16 test programs. 0/9181 subtests failed. I'm not sure what's wrong with the current code that causes this, but looking at the previous version (which did not result in crashes for me), it seems to me that the return value of SvGROW was being treated as an end pointer rather than a start pointer, which might possibly account for the reporter's heap overflow?
From: paul [...] city-fan.org
On Sun Dec 04 07:06:36 2016, paul@city-fan.org wrote: Show quoted text
> On Sat Dec 03 06:47:36 2016, CFAERBER wrote:
> > Thank you for reporting this. It's interesting that this bug has not > > been noticed so far. I'll release a new version shortly.
> > I'm now seeing crashes on x86_32 builds on some perls: > > $ ./Build test > t/00use.t ................. ok > t/10pod.t ................. ok > t/11pod_cover.t ........... ok > t/domain_to_ascii.t ....... ok > t/domain_to_unicode.t ..... ok > t/encode_bytes.t .......... ok > t/encode_utf8.t ........... ok > t/punycode_vec-pp.t ....... ok > t/punycode_vec-xs.t ....... ok > t/uts46_api_call.t ........ ok > t/uts46_encode_bytes.t .... ok > t/uts46_encode_utf8.t ..... ok > *** glibc detected *** /usr/bin/perl: free(): invalid next size > (normal): 0x08d2d420 *** > ======= Backtrace: ========= > /lib/libc.so.6[0xf73903a4] > /lib/libc.so.6[0xf7393e46] > /lib/libc.so.6(realloc+0x106)[0xf7394c86] > /usr/lib/perl5/5.10.0/i386-linux-thread- > multi/CORE/libperl.so(Perl_safesysrealloc+0x8a)[0xf75fb7aa] > /usr/lib/perl5/5.10.0/i386-linux-thread- > multi/CORE/libperl.so(Perl_sv_grow+0x7d)[0xf76527fd] > /builddir/build/BUILD/Net-IDN-Encode- > 2.301/blib/arch/auto/Net/IDN/Punycode/Punycode.so[0xf709c34e] > /builddir/build/BUILD/Net-IDN-Encode- > 2.301/blib/arch/auto/Net/IDN/Punycode/Punycode.so[0xf709d075] > /usr/lib/perl5/5.10.0/i386-linux-thread- > multi/CORE/libperl.so(Perl_pp_entersub+0xb29)[0xf76267b9] > /usr/lib/perl5/5.10.0/i386-linux-thread- > multi/CORE/libperl.so(Perl_runops_debug+0x153)[0xf75e7f53] > /usr/lib/perl5/5.10.0/i386-linux-thread- > multi/CORE/libperl.so(perl_run+0x274)[0xf7620904] > /usr/bin/perl(main+0x10e)[0x8048a2e] > /lib/libc.so.6(__libc_start_main+0xe5)[0xf73376e5] > /usr/bin/perl[0x8048881] > ======= Memory map: ======== > 08048000-08049000 r-xp 00000000 00:2a 126137650 > /usr/bin/perl > 08049000-0804a000 rw-p 00000000 00:2a 126137650 > /usr/bin/perl > 089cf000-09428000 rw-p 00000000 00:00 0 > [heap] > f6e00000-f6e21000 rw-p 00000000 00:00 0 > f6e21000-f6f00000 ---p 00000000 00:00 0 > f6fcf000-f6fdc000 r-xp 00000000 00:2a 126138418 > /lib/libgcc_s-4.3.2-20081105.so.1 > f6fdc000-f6fdd000 rw-p 0000c000 00:2a 126138418 > /lib/libgcc_s-4.3.2-20081105.so.1 > f6fdd000-f709b000 rw-p 00000000 00:00 0 > f709b000-f70a0000 r-xp 00000000 00:2a 126136495 > /builddir/build/BUILD/Net-IDN-Encode- > 2.301/blib/arch/auto/Net/IDN/Punycode/Punycode.so > f70a0000-f70a1000 rw-p 00004000 00:2a 126136495 > /builddir/build/BUILD/Net-IDN-Encode- > 2.301/blib/arch/auto/Net/IDN/Punycode/Punycode.so > f70a1000-f70cb000 r-xp 00000000 00:2a 126142185 > /usr/lib/perl5/5.10.0/i386-linux-thread- > multi/auto/Unicode/Normalize/Normalize.so > f70cb000-f70ec000 rw-p 00029000 00:2a 126142185 > /usr/lib/perl5/5.10.0/i386-linux-thread- > multi/auto/Unicode/Normalize/Normalize.so > f70ec000-f7109000 r-xp 00000000 00:2a 126142221 > /usr/lib/perl5/5.10.0/i386-linux-thread- > multi/auto/Storable/Storable.so > f7109000-f710a000 rw-p 0001d000 00:2a 126142221 > /usr/lib/perl5/5.10.0/i386-linux-thread- > multi/auto/Storable/Storable.so > f710a000-f710d000 r-xp 00000000 00:2a 126142444 > /usr/lib/perl5/5.10.0/i386-linux-thread-multi/auto/Fcntl/Fcntl.so > f710d000-f710e000 rw-p 00003000 00:2a 126142444 > /usr/lib/perl5/5.10.0/i386-linux-thread-multi/auto/Fcntl/Fcntl.so > f710e000-f7113000 r-xp 00000000 00:2a 126142424 > /usr/lib/perl5/5.10.0/i386-linux-thread-multi/auto/IO/IO.so > f7113000-f7114000 rw-p 00005000 00:2a 126142424 > /usr/lib/perl5/5.10.0/i386-linux-thread-multi/auto/IO/IO.so > f7114000-f711f000 r-xp 00000000 00:2a 126142419 > /usr/lib/perl5/5.10.0/i386-linux-thread-multi/auto/List/Util/Util.so > f711f000-f7120000 rw-p 0000a000 00:2a 126142419 > /usr/lib/perl5/5.10.0/i386-linux-thread-multi/auto/List/Util/Util.so > f7120000-f7320000 r--p 00000000 00:2a 126143014 > /usr/lib/locale/locale-archive > f7320000-f7321000 rw-p 00000000 00:00 0 > f7321000-f748f000 r-xp 00000000 00:2a 126138410 > /lib/libc-2.9.so > f748f000-f7491000 r--p 0016e000 00:2a 126138410 > /lib/libc-2.9.so > f7491000-f7492000 rw-p 00170000 00:2a 126138410 > /lib/libc-2.9.so > f7492000-f7495000 rw-p 00000000 00:00 0 > f7495000-f74ab000 r-xp 00000000 00:2a 126138386 > /lib/libpthread-2.9.so > f74ab000-f74ac000 r--p 00015000 00:2a 126138386 > /lib/libpthread-2.9.so > f74ac000-f74ad000 rw-p 00016000 00:2a 126138386 > /lib/libpthread-2.9.so > f74ad000-f74af000 rw-p 00000000 00:00 0 > f74af000-f74b1000 r-xp 00000000 00:2a 126138378 > /lib/libutil-2.9.so > f74b1000-f74b2000 r--p 00001000 00:2a 126138378 > /lib/libutil-2.9.so > f74b2000-f74b3000 rw-p 00002000 00:2a 126138378 > /lib/libutil-2.9.so > f74b3000-f74b4000 rw-p 00000000 00:00 0 > f74b4000-f74be000 r-xp 00000000 00:2a 126138406 > /lib/libcrypt-2.9.so > f74be000-f74bf000 r--p 00009000 00:2a 126138406 > /lib/libcrypt-2.9.so > f74bf000-f74c0000 rw-p 0000a000 00:2a 126138406 > /lib/libcrypt-2.9.so > f74c0000-f74e7000 rw-p 00000000 00:00 0 > f74e7000-f750e000 r-xp 00000000 00:2a 126138402 > /lib/libm-2.9.so > f750e000-f750f000 r--p 00026000 00:2a 126138402 > /lib/libm-2.9.so > f750f000-f7510000 rw-p 00027000 00:2a 126138402 > /lib/libm-2.9.so > f7510000-f7513000 r-xp 00000000 00:2a 126138404 > /lib/libdl-2.9.so > f7513000-f7514000 r--p 00002000 00:2a 126138404 > /lib/libdl-2.9.so > f7514000-f7515000 rw-p 00003000 00:2a 126138404 > /lib/libdl-2.9.so > f7515000-f752b000 r-xp 00000000 00:2a 126138400 > /lib/libnsl-2.9.so > f752b000-f752c000 r--p 00016000 00:2a 126138400 > /lib/libnsl-2.9.so > f752c000-f752d000 rw-p 00017000 00:2a 126138400 > /lib/libnsl-2.9.so > f752d000-f752f000 rw-p 00000000 00:00 0 > f752f000-f7542000 r-xp 00000000 00:2a 126138384 > /lib/libresolv-2.9.so > f7542000-f7543000 r--p 00012000 00:2a 126138384 > /lib/libresolv-2.9.so > f7543000-f7544000 rw-p 00013000 00:2a 126138384 > /lib/libresolv-2.9.so > f7544000-f7546000 rw-p 00000000 00:00 0 > f7549000-f77b2000 r-xp 00000000 00:2a 126142629 > /usr/lib/perl5/5.10.0/i386-linux-thread-multi/CORE/libperl.so > f77b2000-f77b7000 rw-p 00269000 00:2a 126142629 > /usr/lib/perl5/5.10.0/i386-linux-thread-multi/CORE/libperl.so > f77b7000-f77d7000 r-xp 00000000 00:2a 126103465 > /lib/ld-2.9.so > f77d7000-f77d8000 rw-p 00000000 00:00 0 > f77d8000-f77d9000 r--p 00020000 00:2a 126103465 > /lib/ld-2.9.so > f77d9000-f77da000 rw-p 00021000 00:2a 126103465 > /lib/ld-2.9.so > ff7cf000-ff9de000 rw-p 00000000 00:00 0 > [stack] > t/uts46_to_ascii-trans.t .. > Failed 3600/3770 subtests > (less 2 skipped subtests: 168 okay) > t/uts46_to_ascii.t ........ ok > t/uts46_to_unicode.t ...... ok > t/xtra_pp.t ............... ok > Test Summary Report > ------------------- > t/uts46_to_ascii-trans.t (Wstat: 134 Tests: 170 Failed: 0) > Non-zero wait status: 134 > Parse errors: Bad plan. You planned 3770 tests but ran 170. > t/uts46_to_ascii.t (Wstat: 0 Tests: 3770 Failed: 0) > TODO passed: 765, 1124, 1197, 1215, 1581, 1631, 1733-1734 > 1938-1941, 1984-1991, 2474-2475, 2501-2502 > 2614, 2771-2772, 2946, 3226, 3334-3338 > 3561, 3563-3564, 3716 > t/uts46_to_unicode.t (Wstat: 0 Tests: 5026 Failed: 0) > TODO passed: 955-956, 1430, 1535-1536, 1564, 2069-2070 > 2134-2135, 2264-2265, 2543-2546, 2600-2607 > 3242-3243, 3282-3283, 3434, 3663-3664, 3891 > 4264, 4416-4420, 4736, 4738-4739, 4953 > Files=16, Tests=9181, 3 wallclock secs ( 0.63 usr 0.03 sys + 2.65 > cusr 0.07 csys = 3.38 CPU) > Result: FAIL > Failed 1/16 test programs. 0/9181 subtests failed. > > I'm not sure what's wrong with the current code that causes this, but > looking at the previous version (which did not result in crashes for > me), it seems to me that the return value of SvGROW was being treated > as an end pointer rather than a start pointer, which might possibly > account for the reporter's heap overflow?
Never mind that last comment, I see what you were doing now. I'm still getting crashes with 2.301 though.
Is it possible that these systems have sizeof(char) > 1?
Show quoted text
> Is it possible that these systems have sizeof(char) > 1?
Disregard this, it guaranteed to be 1 in C. I'm wondering whether it's easier to start from scratch than trying to find the bug.
From: paul [...] city-fan.org
On Sun Dec 04 17:55:37 2016, CFAERBER wrote: Show quoted text
> > Is it possible that these systems have sizeof(char) > 1?
> Disregard this, it guaranteed to be 1 in C. > > I'm wondering whether it's easier to start from scratch than trying to > find the bug.
Got it. grow_string was not updating the "current" pointer correctly. This change fixes it: --- lib/Net/IDN/Punycode.xs +++ lib/Net/IDN/Punycode.xs @@ -53,14 +53,16 @@ static void grow_string(SV *const sv, char **start, char **current, char **end, STRLEN add) { STRLEN len; + char *new_start; if(*current + add <= *end) return; len = (*current - *start + add + 15) & ~15; - *start = SvGROW(sv, len); - *current = *start + len; - *end = *start + SvLEN(sv); + new_start = SvGROW(sv, len); + *current = new_start + (*current - *start); + *start = new_start; + *end = new_start + SvLEN(sv); } MODULE = Net::IDN::Punycode PACKAGE = Net::IDN::Punycode
From: alexander.bluhm [...] gmx.net
On Wed Dec 07 09:52:49 2016, paul@city-fan.org wrote: Show quoted text
> On Sun Dec 04 17:55:37 2016, CFAERBER wrote: > Got it. grow_string was not updating the "current" pointer correctly.
Oh yes, how could I miss this? All my tests pass with this fix.
From: alexander.bluhm [...] gmx.net
This patch would also work. It is shorter and closer to my intension what I wanted to do with the len variable. --- lib/Net/IDN/Punycode.xs.orig Sat Dec 3 13:00:06 2016 +++ lib/Net/IDN/Punycode.xs Wed Dec 7 16:39:07 2016 @@ -57,8 +57,8 @@ grow_string(SV *const sv, char **start, char **current if(*current + add <= *end) return; - len = (*current - *start + add + 15) & ~15; - *start = SvGROW(sv, len); + len = (*current - *start); + *start = SvGROW(sv, (len + add + 15) & ~15); *current = *start + len; *end = *start + SvLEN(sv); }
Thanks! I did not see this bug, either, and was just about rewriting the entire memory management. I've just uploaded version 2.302, which includes this fix.
From: alexander.bluhm [...] gmx.net
On Wed Dec 07 12:57:43 2016, CFAERBER wrote: Show quoted text
> I've just uploaded version 2.302, which includes this fix.
Thanks. All my tests pass with this version. There is an unused variable char* new_start left in the code, but that is not an issue.
From: paul [...] city-fan.org
On Wed Dec 07 13:34:43 2016, bluhm wrote: Show quoted text
> On Wed Dec 07 12:57:43 2016, CFAERBER wrote:
> > I've just uploaded version 2.302, which includes this fix.
> > Thanks. All my tests pass with this version. There is an unused > variable char* new_start left in the code, but that is not an issue.
There's a double-dereference introduced by the new macro for utf8_to_uvchr_buf on older perls. It's also casting in_p to U8* both in the macro definition and when calling the macro. Attached patch fixes these and also removes the unused new_start variable.
Subject: Net-IDN-Encode-2.302-fix.patch
--- lib/Net/IDN/Punycode.xs +++ lib/Net/IDN/Punycode.xs @@ -21,7 +21,7 @@ #define TMIN_MAX(t) (((t) < TMIN) ? (TMIN) : ((t) > TMAX) ? (TMAX) : (t)) #ifndef utf8_to_uvchr_buf -#define utf8_to_uvchr_buf(in_p,in_e,u8) utf8_to_uvchr((U8*)in_p, &u8); +#define utf8_to_uvchr_buf(in_p,in_e,u8) utf8_to_uvchr(in_p,u8); #endif static char enc_digit[BASE] = { @@ -57,7 +57,6 @@ static void grow_string(SV *const sv, char **start, char **current, char **end, STRLEN add) { STRLEN len; - char* new_start; if(*current + add <= *end) return;
From: paul [...] city-fan.org
On Thu Dec 08 05:48:02 2016, paul@city-fan.org wrote: Show quoted text
> On Wed Dec 07 13:34:43 2016, bluhm wrote:
> > On Wed Dec 07 12:57:43 2016, CFAERBER wrote:
> > > I've just uploaded version 2.302, which includes this fix.
> > > > Thanks. All my tests pass with this version. There is an unused > > variable char* new_start left in the code, but that is not an issue.
> > There's a double-dereference introduced by the new macro for > utf8_to_uvchr_buf on older perls. It's also casting in_p to U8* both > in the macro definition and when calling the macro. Attached patch > fixes these and also removes the unused new_start variable.
Looks good in 2.303 now, thanks.