From 5d81681461b349c4d89e757af577309cedb07502 Mon Sep 17 00:00:00 2001 From: Jonas Isensee Date: Mon, 14 Jul 2025 16:44:11 +0200 Subject: [PATCH 1/3] Use aligned_sizeof instead of sizeof --- stdlib/Mmap/src/Mmap.jl | 8 ++++---- stdlib/Mmap/test/runtests.jl | 12 ++++++++++++ 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/stdlib/Mmap/src/Mmap.jl b/stdlib/Mmap/src/Mmap.jl index 7d57bf053940d..c527123d51bb8 100644 --- a/stdlib/Mmap/src/Mmap.jl +++ b/stdlib/Mmap/src/Mmap.jl @@ -187,16 +187,16 @@ like HDF5 (which can be used with memory-mapping). """ function mmap(io::IO, ::Type{Array{T,N}}=Vector{UInt8}, - dims::NTuple{N,Integer}=(div(filesize(io)-position(io),sizeof(T)),), + dims::NTuple{N,Integer}=(div(filesize(io)-position(io),Base.aligned_sizeof(T)),), offset::Integer=position(io); grow::Bool=true, shared::Bool=true) where {T,N} # check inputs isopen(io) || throw(ArgumentError("$io must be open to mmap")) isbitstype(T) || throw(ArgumentError("unable to mmap $T; must satisfy isbitstype(T) == true")) - len = sizeof(T) + len = Base.aligned_sizeof(T) for l in dims len, overflow = Base.Checked.mul_with_overflow(promote(len, l)...) - overflow && throw(ArgumentError("requested size prod($((sizeof(T), dims...))) too large, would overflow typeof(size(T)) == $(typeof(len))")) + overflow && throw(ArgumentError("requested size prod($((len, dims...))) too large, would overflow typeof(size(T)) == $(typeof(len))")) end len >= 0 || throw(ArgumentError("requested size must be ≥ 0, got $len")) len == 0 && return Array{T}(undef, ntuple(x->0,Val(N))) @@ -267,7 +267,7 @@ end mmap(file::AbstractString, ::Type{T}=Vector{UInt8}, - dims::NTuple{N,Integer}=(div(filesize(file),sizeof(eltype(T))),), + dims::NTuple{N,Integer}=(div(filesize(file),Base.aligned_sizeof(eltype(T))),), offset::Integer=Int64(0); grow::Bool=true, shared::Bool=true) where {T<:Array,N} = open(io->mmap(io, T, dims, offset; grow=grow, shared=shared), file, isfile(file) ? "r" : "w+")::Array{eltype(T),N} diff --git a/stdlib/Mmap/test/runtests.jl b/stdlib/Mmap/test/runtests.jl index f4b6abb147fb7..61ed432f90c4f 100644 --- a/stdlib/Mmap/test/runtests.jl +++ b/stdlib/Mmap/test/runtests.jl @@ -343,6 +343,18 @@ end GC.gc() rm(file) +# test for #58982 +file = tempname() +primitive type PrimType9Bytes 9*8 end +arr = Vector{PrimType9Bytes}(undef, 2) +write(file, arr) +m = mmap(file, Vector{PrimType9Bytes}) +@test length(m) == 2 +@test m[1] == arr[1] +@test m[2] == arr[2] +finalize(m); m = nothing; GC.gc() +rm(file) + @testset "Docstrings" begin @test isempty(Docs.undocumented_names(Mmap)) end From 3f88efa56779185c39ddb7b0c3003e80744cc54e Mon Sep 17 00:00:00 2001 From: Jonas Isensee Date: Mon, 14 Jul 2025 22:53:19 +0200 Subject: [PATCH 2/3] non isbits now (correctly) throws an ArgumentError --- stdlib/Mmap/test/runtests.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stdlib/Mmap/test/runtests.jl b/stdlib/Mmap/test/runtests.jl index 61ed432f90c4f..7875dc45a1e19 100644 --- a/stdlib/Mmap/test/runtests.jl +++ b/stdlib/Mmap/test/runtests.jl @@ -44,7 +44,7 @@ s = open(file) @test length(@inferred mmap(s, Vector{Int8}, 12, 0; grow=false)) == 12 @test length(@inferred mmap(s, Vector{Int8}, 12, 0; shared=false)) == 12 close(s) -@test_throws ErrorException mmap(file, Vector{Ref}) # must be bit-type +@test_throws ArgumentError mmap(file, Vector{Ref}) # must be bit-type GC.gc(); GC.gc() file = tempname() # new name to reduce chance of issues due slow windows fs From 9b4ba24a0b002021240c620d6b88c67f2b5d2a3a Mon Sep 17 00:00:00 2001 From: Jonas Isensee Date: Thu, 17 Jul 2025 15:56:26 +0200 Subject: [PATCH 3/3] wrap new test into testset --- stdlib/Mmap/test/runtests.jl | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/stdlib/Mmap/test/runtests.jl b/stdlib/Mmap/test/runtests.jl index 7875dc45a1e19..064217a24e3be 100644 --- a/stdlib/Mmap/test/runtests.jl +++ b/stdlib/Mmap/test/runtests.jl @@ -343,17 +343,18 @@ end GC.gc() rm(file) -# test for #58982 -file = tempname() -primitive type PrimType9Bytes 9*8 end -arr = Vector{PrimType9Bytes}(undef, 2) -write(file, arr) -m = mmap(file, Vector{PrimType9Bytes}) -@test length(m) == 2 -@test m[1] == arr[1] -@test m[2] == arr[2] -finalize(m); m = nothing; GC.gc() -rm(file) +@testset "test for #58982 - mmap with primitive types" begin + file = tempname() + primitive type PrimType9Bytes 9*8 end + arr = Vector{PrimType9Bytes}(undef, 2) + write(file, arr) + m = mmap(file, Vector{PrimType9Bytes}) + @test length(m) == 2 + @test m[1] == arr[1] + @test m[2] == arr[2] + finalize(m); m = nothing; GC.gc() + rm(file) +end @testset "Docstrings" begin @test isempty(Docs.undocumented_names(Mmap))