From 5298861c63eb9d879a957e30ef3afc3445b7591f Mon Sep 17 00:00:00 2001 From: Klaus Crusius Date: Wed, 27 Sep 2017 11:46:35 +0200 Subject: [PATCH 1/3] fixed issue #23880 --- base/printf.jl | 15 ++++++++------- test/printf.jl | 12 ++++++++++++ 2 files changed, 20 insertions(+), 7 deletions(-) diff --git a/base/printf.jl b/base/printf.jl index 2f8347f6f8a95..a76e06cf6eaf1 100644 --- a/base/printf.jl +++ b/base/printf.jl @@ -36,23 +36,24 @@ end ### printf format string parsing ### function parse(s::AbstractString) - # parse format string in to stings and format tuples + # parse format string into strings and format tuples list = [] i = j = start(s) + j1 = 0 # invariant: j1 == prevind(s, j-1) while !done(s,j) c, k = next(s,j) if c == '%' - isempty(s[i:j-1]) || push!(list, s[i:j-1]) + i > j1 || push!(list, s[i:j1]) flags, width, precision, conversion, k = parse1(s,k) '\'' in flags && error("printf format flag ' not yet supported") conversion == 'n' && error("printf feature %n not supported") push!(list, conversion == '%' ? "%" : (flags,width,precision,conversion)) - i = j = k - else - j = k + i = k end + j1 = j + j = k end - isempty(s[i:end]) || push!(list, s[i:end]) + i > endof(s) || push!(list, s[i:end]) # coalesce adjacent strings i = 1 while i < length(list) @@ -98,7 +99,7 @@ function parse1(s::AbstractString, k::Integer) while c in "#0- + '" c, k = next_or_die(s,k) end - flags = String(s[j:k-2]) + flags = String(s[j:k-2]) # exploiting that all specifier characters are one-byte. # parse width while '0' <= c <= '9' width = 10*width + c-'0' diff --git a/test/printf.jl b/test/printf.jl index 90c0e10769621..f086d9a4ba80c 100644 --- a/test/printf.jl +++ b/test/printf.jl @@ -272,3 +272,15 @@ end # Check bug with trailing nul printing BigFloat @test (@sprintf("%.330f", BigFloat(1)))[end] != '\0' + +# Check utf8 strings #23880 +@test (@sprintf("X%d", 2)) == "X2" +@test (@sprintf("\u00d0%d", 2)) == "\u00d02" +@test (@sprintf("\u0f00%d", 2)) == "\u0f002" +@test (@sprintf("\U0001ffff%d", 2)) == "\U0001ffff2" +@test (@sprintf("%dX%d", 1, 2)) == "1X2" +@test (@sprintf("%d\u00d0%d", 1, 2)) == "1\u00d02" +@test (@sprintf("%d\u0f00%d", 1, 2)) == "1\u0f002" +@test (@sprintf("%d\U0001ffff%d", 1, 2)) == "1\U0001ffff2" +@test (@sprintf("%d\u2203%d\u0203", 1, 2)) == "1\u22032\u0203" + From 2c8c7f839ec146be86dd88df89ca1de22e9fe304 Mon Sep 17 00:00:00 2001 From: Klaus Crusius Date: Wed, 27 Sep 2017 17:33:14 +0200 Subject: [PATCH 2/3] error in comment --- base/printf.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/base/printf.jl b/base/printf.jl index a76e06cf6eaf1..b66c976170e94 100644 --- a/base/printf.jl +++ b/base/printf.jl @@ -39,7 +39,7 @@ function parse(s::AbstractString) # parse format string into strings and format tuples list = [] i = j = start(s) - j1 = 0 # invariant: j1 == prevind(s, j-1) + j1 = 0 # invariant: j1 == prevind(s, j) while !done(s,j) c, k = next(s,j) if c == '%' From c685e8fc4a06891f41e5f388cc8afe2c98e44207 Mon Sep 17 00:00:00 2001 From: Klaus Crusius Date: Thu, 28 Sep 2017 18:39:46 +0200 Subject: [PATCH 3/3] throw ArgumentError if non-ascii character after flags --- base/printf.jl | 2 +- test/printf.jl | 5 ++++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/base/printf.jl b/base/printf.jl index b66c976170e94..c6e121405f02f 100644 --- a/base/printf.jl +++ b/base/printf.jl @@ -99,7 +99,7 @@ function parse1(s::AbstractString, k::Integer) while c in "#0- + '" c, k = next_or_die(s,k) end - flags = String(s[j:k-2]) # exploiting that all specifier characters are one-byte. + flags = String(s[j:prevind(s,k)-1]) # exploiting that all flags are one-byte. # parse width while '0' <= c <= '9' width = 10*width + c-'0' diff --git a/test/printf.jl b/test/printf.jl index f086d9a4ba80c..0674d172d66d1 100644 --- a/test/printf.jl +++ b/test/printf.jl @@ -283,4 +283,7 @@ end @test (@sprintf("%d\u0f00%d", 1, 2)) == "1\u0f002" @test (@sprintf("%d\U0001ffff%d", 1, 2)) == "1\U0001ffff2" @test (@sprintf("%d\u2203%d\u0203", 1, 2)) == "1\u22032\u0203" - +@test_throws ArgumentError @macroexpand(@sprintf("%y%d", 1, 2)) +@test_throws ArgumentError @macroexpand(@sprintf("%\u00d0%d", 1, 2)) +@test_throws ArgumentError @macroexpand(@sprintf("%\u0f00%d", 1, 2)) +@test_throws ArgumentError @macroexpand(@sprintf("%\U0001ffff%d", 1, 2))