JuliaParallel / JuliaParallel/rodinia
[CUDA][srad_v2] Out-of-bounds neighbor reads occur before boundary correction
- Dominant language
- C
- Stars
- 56
- Forks
- 42
- PR merge metrics
- No merged PRs in 30d
Description
The `srad_v2` CUDA implementation in this repository contains global-memory out-of-bounds reads in `srad_cuda_1` and `srad_cuda_2`.
The kernels compute neighbor indices and immediately use them to load data from global memory. For boundary blocks, some of these indices fall outside the underlying allocation. The code only replaces the corresponding shared-memory values with valid boundary values after the
loads have already occurred.
I detected these invalid reads during memory-safety testing and subsequently confirmed the issue from the source-level index calculations.
## Affected Code
File: `cuda/srad_v2/srad_kernel.cu`
In `srad_cuda_1`, neighbor values are loaded before the boundary condition is handled:
```cpp
north[ty][tx] = J_cuda[index_n];
south[ty][tx] = J_cuda[index_s];
if (by == 0) {
north[ty][tx] = J_cuda[BLOCK_SIZE * bx + tx];
} else if (by == gridDim.y - 1) {
south[ty][tx] =
J_cuda[cols * BLOCK_SIZE * (gridDim.y - 1)
+ BLOCK_SIZE * bx
+ cols * (BLOCK_SIZE - 1) + tx];
}
```
A similar pattern occurs in srad_cuda_2:
```
south_c[ty][tx] = C_cuda[index_s];
if (by == gridDim.y - 1) {
south_c[ty][tx] =
C_cuda[cols * BLOCK_SIZE * (gridDim.y - 1)
+ BLOCK_SIZE * bx
+ cols * (BLOCK_SIZE - 1) + tx];
}
```
## Root Cause
The device arrays contain exactly:
`rows * cols`
elements, so the valid index range is:
`0 ... rows * cols - 1`
For the top block row (`by == 0`), `index_n` is negative, causing a read before the beginning of `J_cuda`.
For the bottom block row (`by == gridDim.y - 1`), the south-neighbor index satisfies:
`index_s >= rows * cols`
and therefore accesses memory beyond the end of the allocation.
For example, with:
`rows = 128`
`cols = 128`
the allocation contains:
`128 * 128 = 16384`
floating-point elements, corresponding to:
`16384 * sizeof(float) = 65536 bytes`
The first invalid south-neighbor access can therefore occur at:
`base + 65536`
which is exactly the first address beyond the allocation.
The later boundary correction only overwrites the value stored in shared memory. It cannot undo the out-of-bounds global-memory read
that has already occurred.
The same issue also affects the corresponding neighbor accesses in `srad_cuda_2`.
Contributor guide
No contributing guide indexed for this repository
Research direction
Start in cuda/srad_v2/srad_kernel.cu at srad_cuda_1 and srad_cuda_2, tracing index_n and index_s through the boundary branches. Verify that no neighbor load can access outside the rows * cols allocation before correction, then validate the result with the repository's memory-safety testing.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- c
- Domain
- hpc
- Issue type
- Bug
- Difficulty
- 2/5
- Estimated time
- 1-3 hours
- Activity status
- Active
- Clarity
- Clearly specified
- Newbie friendliness
- 76/100