Bugfixes 2 #208

Merged
andrey merged 10 commits from bugfixes2 into master 2026-08-05 23:26:37 +03:00
10 Commits
Author SHA1 Message Date
andrey 1ddec15b87 threadsafe fixes 2026-08-05 19:48:01 +03:00
andrey 3f293ebd65 fix(PIFileTransfer): validate file id before array access
processFile() accessed files_[id - 1] without validating id.
When id == 0 (from a crafted network packet), id - 1 = -1 caused
out-of-bounds access. Added bounds check: id must be in range
[1, files_.size()]. Stops receive and logs error on invalid id.
2026-08-05 17:39:38 +03:00
andrey 27a9f05d65 fix(PIProcess): handle fork() failure (return value -1)
fork() can return -1 on error (too many processes, out of memory).
The old code treated pid_ == -1 as a successful fork, entering the
parent branch and calling waitpid(-1, ...) which waits for ANY
child process. Added explicit check: close pipes, free memory,
and return on fork failure.
2026-08-05 17:39:38 +03:00
andrey 13a9a75f79 fix(PISerial): break infinite loop when readDevice returns <= 0
In the blocking read path (timeout_ms <= 0), the while loop had no
exit condition for readDevice() returning 0 (EOF) or -1 (error).
This caused an infinite busy-loop at 100% CPU. Added 'else break'
to exit the loop on read failure, matching the timeout branch
which already handles this case.
2026-08-05 17:39:37 +03:00
andrey b2e637ee2b fix(PIIOByteArray): advance pos by actual bytes read, not requested size
readDevice() did pos += size instead of pos += ret. The clamping
on the next line (pos = min(pos, data_->size_s())) masked the
issue in practice, but the semantics were wrong. Aligns with
writeDevice() which correctly uses pos += rs.size_s().
2026-08-05 17:39:37 +03:00
andrey 9cd56ab66c fix(PIEthernet): check open() return value with >= 0 instead of != 0
open() returns -1 on error. The check fd != 0 treated -1 as a
valid fd (since -1 != 0 is true), causing devctl(-1, ...) and
close(-1) on QNX. Fixed to fd >= 0.
2026-08-05 17:39:36 +03:00
andrey e05abf16b5 fix(PIWaitEvent): use -1 as pipe_fd sentinel instead of 0
File descriptor 0 is stdin (a valid fd). Using 0 as the 'not-open'
sentinel caused isCreate() to return false and destroy() to skip
close() when pipe() happened to allocate fds {0, 1} (e.g. in daemons
with closed stdio). POSIX convention: -1 = invalid fd.
2026-08-05 17:39:36 +03:00
andrey 6c5c4b73e0 fix(PIClientServer): delete PIEthernet when client_factory returns nullptr
When the custom client_factory() returned nullptr, the incoming
PIEthernet pointer was leaked. Matches existing pattern used in the
max_clients overflow branch.
2026-08-05 17:39:35 +03:00
andrey e89ae88f3a fix(PICAN): align socket handling with PIEthernet patterns
- Sentinel: sock = 0 → sock = -1 (0 is stdin, valid fd)
- openDevice(): close socket on ioctl/bind failure (resource leak)
- openDevice(): set O_NONBLOCK via fcntl after socket()
- openDevice(): check setsockopt() return value
- closeDevice(): call shutdown() before close(), reset sock to -1
- readDevice() / writeDevice(): guard against sock == -1
- Add missing #include <fcntl.h>
2026-08-05 17:39:35 +03:00
andrey 216109b8ed fix(PIString): initialize toChar() return value and fix operator+= OOB
- toChar(): char v was uninitialized, causing UB when
  sscanf fails to match (empty string). Initialize to 0.

- operator+=(PIConstChars): loop iterated l < d.size() instead of
  l < str.size(), reading past the end of str after d.enlarge().
  This is a heap buffer overread with undefined behavior.
2026-08-05 17:39:34 +03:00