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]

Reply via email to