Swatantra-66 opened a new pull request, #21548:
URL: https://github.com/apache/nuttx/pull/21548
## Summary
Add POSIX-mandated `[EINVAL]` validation to `preadv()` and `pwritev()` for
`iovcnt` bounds, `offset` sign, and `iov_len` overflow, as required by
POSIX.1-2024 (IEEE Std 1003.1-2024). In addition, fix a bug in `preadv()` where
partial read progress was lost on a subsequent read error.
## Problem
`preadv()` and `pwritev()` in `libs/libc/uio/lib_preadv.c` and
`libs/libc/uio/lib_pwritev.c` omitted standard POSIX boundary and overflow
validation:
1. **`iovcnt <= 0 || iovcnt > IOV_MAX`**: When `iovcnt <= 0`, both functions
returned `0` without modifying `errno` instead of returning `-1` with `errno =
EINVAL`.
2. **`iov == NULL`**: Dereferenced without validation.
3. **`offset < 0`**: Not validated upfront before invoking `pread()` /
`pwrite()`.
4. **`sum(iov_len) > SSIZE_MAX`**: Neither function checked for accumulation
overflow into `ssize_t ntotal`.
5. **Partial read data loss in `preadv()`**: In `lib_preadv.c`, if a
subsequent `pread()` failed after reading earlier buffers (`ntotal > 0`), it
returned `nread` (`-1`) directly. The caller had no way of knowing how many
bytes were already read from the file. In contrast, `lib_pwritev.c` correctly
preserved partial writes via `ntotal ? ntotal : ERROR`.
6. **Missing header**: `lib_preadv.c` did not include `<errno.h>`.
## Changes
- `libs/libc/uio/lib_preadv.c`:
- Include `<errno.h>` and `<limits.h>`.
- Validate `iovcnt <= 0 || iovcnt > IOV_MAX` returning `ERROR` with `errno
= EINVAL`.
- Validate `iov == NULL` returning `ERROR` with `errno = EFAULT`.
- Validate `offset < 0` returning `ERROR` with `errno = EINVAL`.
- Validate `SSIZE_MAX - len < iov[i].iov_len` returning `ERROR` with
`errno = EINVAL`.
- Validate non-NULL `iov_base` for non-zero `iov_len` entries returning
`ERROR` with `errno = EFAULT`.
- Return `ntotal > 0 ? ntotal : ERROR` on read failure to preserve partial
read progress, matching `pwritev()`.
- `libs/libc/uio/lib_pwritev.c`:
- Include `<limits.h>`.
- Apply the same upfront POSIX parameter and vector validation.
- Keep `ntotal > 0 ? ntotal : ERROR` partial write error handling.
## Behavior Comparison
| Condition | Before | After | POSIX Requirement |
|---|---|---|---|
| `iovcnt == 0` | Returns `0` | Returns `-1`, `errno = EINVAL` | `-1`,
`[EINVAL]` |
| `iovcnt < 0` | Returns `0` | Returns `-1`, `errno = EINVAL` | `-1`,
`[EINVAL]` |
| `iovcnt > IOV_MAX` | No check | Returns `-1`, `errno = EINVAL` | `-1`,
`[EINVAL]` |
| `iov == NULL` | Crash / undefined | Returns `-1`, `errno = EFAULT` | `-1`,
`[EFAULT]` |
| `offset < 0` | Passed to pread/pwrite | Returns `-1`, `errno = EINVAL` |
`-1`, `[EINVAL]` |
| Sum of `iov_len` > `SSIZE_MAX` | Overflow in `ntotal` | Returns `-1`,
`errno = EINVAL` | `-1`, `[EINVAL]` |
| Partial error in `preadv()` | Returns `-1` (loses `ntotal`) | Returns
bytes read (`ntotal`) | Partial read count |
## Impact
- Brings NuttX `preadv()` and `pwritev()` into full compliance with
POSIX.1-2024.
- Zero behavioral change for valid calls.
## Testing
I confirm that changes are verified on local setup and works as intended:
* Build Host(s): Linux (Ubuntu 24.04 on WSL2, x86_64), gcc 15.2.0
* Target(s): sim:nsh (x86_64)
### Style Verification (nxstyle in Docker)
```
$ nxstyle -v 1 libs/libc/uio/lib_preadv.c
/work/libs/libc/uio/lib_preadv.c: PASSED nxstyle check
$ nxstyle -v 1 libs/libc/uio/lib_pwritev.c
/work/libs/libc/uio/lib_pwritev.c: PASSED nxstyle check
```
### Build Log
```
$ ./tools/configure.sh -l sim:nsh
$ make -j$(nproc)
...
CC: uio/lib_preadv.c
CC: uio/lib_pwritev.c
...
LD: nuttx
Pac SIM with dynamic libs..
SIM elf with dynamic libs archive in nuttx.tgz
```
### Runtime Verification Log (Docker ubuntu:24.04)
```
$ ./nuttx
nsh> help
help usage: help [-v] [<cmd>]
. dirname free mount set umount
[ date help mv kill unset
? df hexdump pidof pkill uptime
alias dmesg losetup poweroff sleep watch
unalias echo ln quit usleep xd
basename env ls printf source wait
break exec du ps test
cat exit mkdir pwd time
cd expr mkfatfs readlink true
cp false mkfifo rm truncate
cmp fdinfo mkrd rmdir uname
Builtin Apps:
dd gcov hello nsh sh
dumpstack gpio init ostest
nsh> exit
```
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]