develooper Front page | perl.perl5.porters | Postings from March 2019

[perl #133913] Assertion failure in Perl_sv_vcatpvfn_flags(sv.c:13127)

Thread Next
From:
Tony Cook via RT
Date:
March 20, 2019 06:01
Subject:
[perl #133913] Assertion failure in Perl_sv_vcatpvfn_flags(sv.c:13127)
Message ID:
rt-4.0.24-2975-1553061668-309.133913-15-0@perl.org
On Fri, 08 Mar 2019 15:36:30 -0800, randir wrote:
> While fuzzing perl v5.29.8-21-gde59f38ed9 built with afl and run
> under libdislocator, I found the following program
> 
> printf q)%7000000000E)=>
> 
> to cause an assertion failure
> 
> perl: sv.c:13127: Perl_sv_vcatpvfn_flags: Assertion `elen >= width'
> failed.
> 
> GDB stack trace is following:
> 
> #0  __GI_raise (sig=sig@entry=6) at
> ../sysdeps/unix/sysv/linux/raise.c:50
> #1  0x00007ffff7c25535 in __GI_abort () at abort.c:79
> #2  0x00007ffff7c2540f in __assert_fail_base (fmt=0x7ffff7d87ee0
> "%s%s%s:%u: %s%sAssertion `%s' failed.\n%n", assertion=0x555555aa0f0e
> "elen >= width",
>     file=0x555555a8ff60 "sv.c", line=13189, function=<optimized out>)
> at assert.c:92
> #3  0x00007ffff7c330f2 in __GI___assert_fail (assertion=0x555555aa0f0e
> "elen >= width", file=0x555555a8ff60 "sv.c", line=13189,
>     function=0x555555aa33b0 <__PRETTY_FUNCTION__.23320>
> "Perl_sv_vcatpvfn_flags") at assert.c:101
> #4  0x00005555557c2b6b in Perl_sv_vcatpvfn_flags (sv=0x555555b2d740,
> pat=0x555555b54950 "%7000000000E", patlen=12, args=0x0,
> svargs=0x555555b2fdb0,
>     sv_count=0, maybe_tainted=0x7fffffffddd7, flags=0) at sv.c:13189
> #5  0x00005555557bb9a8 in Perl_sv_vsetpvfn (sv=0x555555b2d740,
> pat=0x555555b54950 "%7000000000E", patlen=12, args=0x0,
> svargs=0x555555b2fdb0, sv_count=0,
>     maybe_tainted=0x7fffffffddd7) at sv.c:10977
> #6  0x000055555586a67c in Perl_do_sprintf (sv=0x555555b2d740, len=1,
> sarg=0x555555b2fda8) at doop.c:734
> #7  0x00005555558485c3 in Perl_pp_prtf () at pp_sys.c:1628
> #8  0x00005555556f6ff4 in Perl_runops_debug () at dump.c:2537
> #9  0x00005555555da157 in S_run_body (oldscope=1) at perl.c:2692
> #10 0x00005555555d96d5 in perl_run (my_perl=0x555555b2b260) at
> perl.c:2615
> #11 0x000055555558e14e in main (argc=2, argv=0x7fffffffe1e8,
> env=0x7fffffffe200) at perlmain.c:127
> 
> This is a regression between 5.26 and 5.28, bisect points to
> 
> commit 5860c1eebae0e97105f7ef5ebcb86d1c72654c51
> Author: David Mitchell <davem@iabyn.com>
> Date:   Mon May 29 09:59:16 2017 +0100
> 
> S_expect_number(): return STRLEN not I32
> 
> This static function is used by Perl_sv_vcatpvfn_flags() to read in
> a width or explicit argument number. It currently returns an I32
> result
> (and croaks if the number exceeds the maximum possible I32 value).
> 
> Change it to return STRLEN, and to croak on the value being greater
> than
> max(STRLEN) / 4.

The bug causing this is this code:

		if (width) {
		    base = width;
		    do { *--ptr = '0' + (base % 10); } while (base /= 10);
		}

since base is an int, the very large 7000000000 becomes a largish negative
number breaking the formatting of the width.

But fixing that reveals a different issue.

The return type of v?snprintf() is int, so such a large result can't be reported
by v?snprintf() anyway.

So fail earlier than this by checking the expected width fits in an int.

Tony

---
via perlbug:  queue: perl5 status: new
https://rt.perl.org/Ticket/Display.html?id=133913

Thread Next


nntp.perl.org: Perl Programming lists via nntp and http.
Comments to Ask Bjørn Hansen at ask@perl.org | Group listing | About