From 6e9251ae570796ff4f1fe237010d95107ab845da Mon Sep 17 00:00:00 2001 From: Jerry Ling Date: Tue, 29 Mar 2022 10:01:32 -0400 Subject: [PATCH] fix `===` when encountering null pointer (#44749) (cherry picked from commit 1a7355b3866fecfebdcb1923cfd691b48fe5a762) --- src/builtins.c | 21 +++++++++++++-------- test/core.jl | 15 +++++++++++++++ 2 files changed, 28 insertions(+), 8 deletions(-) diff --git a/src/builtins.c b/src/builtins.c index 913d6d70dba4b..54d3989878bbd 100644 --- a/src/builtins.c +++ b/src/builtins.c @@ -96,20 +96,25 @@ static int NOINLINE compare_fields(jl_value_t *a, jl_value_t *b, jl_datatype_t * else { jl_datatype_t *ft = (jl_datatype_t*)jl_field_type_concrete(dt, f); if (jl_is_uniontype(ft)) { - uint8_t asel = ((uint8_t*)ao)[jl_field_size(dt, f) - 1]; - uint8_t bsel = ((uint8_t*)bo)[jl_field_size(dt, f) - 1]; + size_t idx = jl_field_size(dt, f) - 1; + uint8_t asel = ((uint8_t*)ao)[idx]; + uint8_t bsel = ((uint8_t*)bo)[idx]; if (asel != bsel) return 0; ft = (jl_datatype_t*)jl_nth_union_component((jl_value_t*)ft, asel); } else if (ft->layout->first_ptr >= 0) { - // If the field is a inline immutable that can be can be undef - // we need to check to check for undef first since undef struct + // If the field is a inline immutable that can be undef + // we need to check for undef first since undef struct // may have fields that are different but should still be treated as equal. - jl_value_t *ptra = ((jl_value_t**)ao)[ft->layout->first_ptr]; - jl_value_t *ptrb = ((jl_value_t**)bo)[ft->layout->first_ptr]; - if (ptra == NULL && ptrb == NULL) { - return 1; + int32_t idx = ft->layout->first_ptr; + jl_value_t *ptra = ((jl_value_t**)ao)[idx]; + jl_value_t *ptrb = ((jl_value_t**)bo)[idx]; + if ((ptra == NULL) != (ptrb == NULL)) { + return 0; + } + else if (ptra == NULL) { // implies ptrb == NULL + continue; // skip this field (it is #undef) } } if (!ft->layout->haspadding) { diff --git a/test/core.jl b/test/core.jl index 4d5590d7642dc..bc5eb37b7aab9 100644 --- a/test/core.jl +++ b/test/core.jl @@ -9,6 +9,21 @@ const Bottom = Union{} # For curmod_* include("testenv.jl") +# test `===` handling null pointer in struct #44712 +struct N44712 + a::Some{Any} + b::Int + N44712() = new() +end +let a = Int[0, 1], b = Int[0, 2] + GC.@preserve a b begin + @test unsafe_load(Ptr{N44712}(pointer(a))) !== unsafe_load(Ptr{N44712}(pointer(b))) + end +end + +# another possible issue in #44712 +@test (("", 0),) !== (("", 1),) + f47(x::Vector{Vector{T}}) where {T} = 0 @test_throws MethodError f47(Vector{Vector}()) @test f47(Vector{Vector{Int}}()) == 0