JuliaParallel / JuliaParallel/PETSc.jl
PetscBool output refs are uninitialised, so 3.25's one-byte write leaves the top three bytes undefined
- Dominant language
- Julia
- Stars
- 182
- Forks
- 46
- Avg merge
- 15h
- Merged PRs (30d)
- 18
Description
0.4.13 allows `PETSc_jll = "~3.25"`, but `PetscBool` stopped being a 4-byte enum in 3.24 (`typedef bool`, `changes/324.md`), and the wrappers still declare it 32 bits and pass an uninitialised `Ref{PetscBool}()` for every output, 446 of them. `Bool(x)` is true when any of the 32 bits is set (`typedefs_wrappers.jl:29`), so on 3.25 a false result reads as true whenever the top three bytes of that slot happen to be non-zero.
A raw ccall into 3.25.4, passing a slot with bits preset, shows only the low byte coming back:
```
PetscFinalized in 0x7f000000 -> out 0x7f000000
PetscFinalized in 0xdeadbe01 -> out 0xdeadbe00
PetscInitialized in 0x7f000000 -> out 0x7f000001
```
The same probe on 3.22.2 gives `0x00000000` and `0x00000001`, all four bytes written.
I haven't seen this go wrong through the wrappers themselves. In 200k calls a freshly allocated ref was always zero, even after filling the heap with non-zero `UInt32` refs first, so it's undefined behaviour rather than an observed wrong answer.
Zeroing the output ref makes the read correct against either library on little-endian, since 3.22 writes all four bytes and 3.25 writes the low one. Declaring `PetscBool` as 8 bits instead would break 3.22, which writes four bytes into the slot, and 0.4.x binds both releases.
Probe, on macOS arm64 with PETSc 0.4.13 in a fresh environment:
```julia
using PETSc, Libdl
lib = PETSc.getlib(PetscScalar = Float64)
PETSc.initialize(lib)
h = Libdl.dlopen(lib.petsc_library)
for name in (:PetscInitialized, :PetscFinalized)
f = Libdl.dlsym(h, name)
for init in (0x7f000000, 0xdeadbe01)
r = Ref{UInt32}(init)
ccall(f, Cint, (Ptr{UInt32},), r)
println(rpad(string(name), 17), " in 0x", string(init; base = 16, pad = 8),
" -> out 0x", string(r[]; base = 16, pad = 8))
end
end
```
Contributor guide
No contributing guide indexed for this repository
Research direction
Start in typedefs_wrappers.jl:29 and trace how the 446 PetscBool output Refs are declared and initialized. Use the provided raw ccall probe against PETSc 3.22.2 and 3.25.4 to verify the behavior, then confirm that the wrappers no longer depend on unwritten bytes while remaining compatible with both releases.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- c, julia
- Domain
- backend-api-design
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 52/100