From 408b03d0b9aea32ae1742b9bc9205da87ef49b66 Mon Sep 17 00:00:00 2001 From: Simeon Schaub Date: Thu, 28 May 2020 15:55:03 +0200 Subject: [PATCH] fix #36031: Printf bug for BigInt (#36033) * fix #36031 * Apply suggestions from code review Co-authored-by: Simon Byrne --- stdlib/Printf/src/Printf.jl | 23 ++++++++++++++--------- stdlib/Printf/test/runtests.jl | 5 ++--- 2 files changed, 16 insertions(+), 12 deletions(-) diff --git a/stdlib/Printf/src/Printf.jl b/stdlib/Printf/src/Printf.jl index ee40edd32c8b84..ac4d3d4e7dff38 100644 --- a/stdlib/Printf/src/Printf.jl +++ b/stdlib/Printf/src/Printf.jl @@ -942,10 +942,12 @@ function decode_0ct(x::BigInt, digits) pt = Base.ndigits0z(x, 8) + 1 length(digits) < pt+1 && resize!(digits, pt+1) neg && (x.size = -x.size) - p = convert(Ptr{UInt8}, digits) + 1 - GMP.MPZ.get_str!(p, 8, x) + GC.@preserve digits begin + p = pointer(digits,2) + GMP.MPZ.get_str!(p, 8, x) + end neg && (x.size = -x.size) - return neg, Int32(pt), Int32(pt) + return Int32(pt), Int32(pt), neg end ### decoding functions directly used by printf generated code ### @@ -1059,13 +1061,16 @@ function ini_dec(x::BigInt, n::Int, digits) end d = Base.ndigits0z(x) if d <= n - info = decode_dec(x) - d == n && return info - p = convert(Ptr{Cvoid}, digits) + info[2] - ccall(:memset, Ptr{Cvoid}, (Ptr{Cvoid}, Cint, Csize_t), p, '0', n - info[2]) - return info + len,pt,neg = decode_dec(x, digits) + d == n && return (len,pt,neg) + + GC.@preserve digits begin + ccall(:memset, Ptr{Cvoid}, (Ptr{Cvoid}, Cint, Csize_t), pointer(digits, pt+1), '0', n - pt) + end + return (len,pt,neg) end - return (n, d, decode_dec(round(BigInt,x/big(10)^(d-n)))[3]) + _, _, neg = decode_dec(round(BigInt,x/big(10)^(d-n)), digits) + return (n, d, neg) end diff --git a/stdlib/Printf/test/runtests.jl b/stdlib/Printf/test/runtests.jl index e2b1e9ff4962d2..562d478ef4676c 100644 --- a/stdlib/Printf/test/runtests.jl +++ b/stdlib/Printf/test/runtests.jl @@ -39,11 +39,10 @@ for (fmt, val) in (("%i", "42"), ("%20a"," 0x2.ap+4"), ("%-20a","0x2.ap+4 "), ("%f", "42.000000"), - ("%g", "42")), + ("%g", "42"), + ("%e", "4.200000e+01")), num in (UInt16(42), UInt32(42), UInt64(42), UInt128(42), Int16(42), Int32(42), Int64(42), Int128(42), big"42") - #big"42" causes stack overflow on %a ; gh #14409 - num isa BigInt && fmt in ["%a", "%#o", "%g"] && continue @test @eval(@sprintf($fmt, $num) == $val) end