Skip to content

Release v1.5.3: Security hardening, refactoring, and community fixes#102

Merged
epsilonrt merged 30 commits intoepsilonrt:masterfrom
zknpr:release-v1.5.3
Feb 8, 2026
Merged

Release v1.5.3: Security hardening, refactoring, and community fixes#102
epsilonrt merged 30 commits intoepsilonrt:masterfrom
zknpr:release-v1.5.3

Conversation

@zknpr
Copy link
Copy Markdown
Contributor

@zknpr zknpr commented Feb 7, 2026

Overview

This release introduces significant security hardening, code modernization, and performance improvements over the original repository.

Security Enhancements

  • Integer Overflow Fix: Resolved a potential integer overflow in iGetIntList.
  • Memory Safety: Fixed strict aliasing violations in lSwapLong and fSwapFloat.
  • Signal Handling: Refactored signal handling to use volatile sig_atomic_t for improved safety.
  • Hardening: Enabled additional compiler security flags and improved CI/CD pipelines.

Performance & Features

  • Request Batching: Optimized Modbus reads by batching contiguous requests.
  • Optimization: Improved slave address setting in the ModBus polling loop.
  • Bug Fix: Removed suspicious sleep(-1) call in mb_delay.

Refactoring & Architecture

  • Modularization:
    • Separated ChipIO logic into a dedicated module (src/chipio.c).
    • Extracted utility functions (like endianness swapping) into src/utils.c.
    • Refactored main by extracting argument parsing logic.
  • Cleanup: Removed unused declarations and improved code organization.

Testing & Build

  • Unit Tests: Added comprehensive tests for serial module and utility functions.
  • Build System: Enabled test_utils in CMake and fixed various compilation issues.

Release v1.5.3 includes all changes from the security-fixes-and-community-prs branch.

zknpr and others added 30 commits February 6, 2026 20:28
## Security Fixes
- Fix memory leak: piStartRef was not freed in cleanup paths
- Add NULL checks after all malloc/calloc calls to prevent crashes
- Add compiler security flags: -fstack-protector-strong, -D_FORTIFY_SOURCE=2, -Wformat-security

## Code Modernization
- Modernize CMakeLists.txt with proper Release/Debug build separation
- Use target-based CMake properties instead of global definitions
- Add -Wpedantic flag (with exception for 3rdparty getopt code)
- Update copyright years to 2015-2025
- Update libmodbus minimum version to 3.1.7
- Translate all French comments to English

## Community PR Integration
- Implement PR epsilonrt#87: Check modbus_set_slave() return value to prevent crashes with invalid slave addresses (credit: @r00t-)
- Implement PR epsilonrt#90: Add -x option to print register addresses in hexadecimal format (credit: @ciakval)
- Implement PR epsilonrt#99: Add -Q and -X options for libmodbus quirks (MAX_SLAVE and REPLY_TO_BROADCAST) (credit: @JesseRiemens)

## New Features
- `-x` Print address (reference) in hexadecimal format
- `-Q` Enable MAX_SLAVE quirk (accept slave id 0-255)
- `-X` Enable REPLY_TO_BROADCAST quirk (send reply to broadcast)

## CI/CD
- Add GitHub Actions workflow for automated builds on Linux, macOS, and Windows

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Bump CMake minimum to 3.13 (required for target_link_directories)
- Move find_package(PkgConfig) to Unix-only block (Windows uses bundled libmodbus)
- Fix printf format UB: cast iAddr to unsigned int for %X specifier
- Allow RTU slave address 0 when -Q quirk is enabled
- Apply consistent quirk logic to TCP mode for symmetry

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Added bounds checking to prevent iCount from overflowing when parsing
large ranges, which could lead to heap buffer overflow via insufficient
calloc allocation.

Changes:
- Check range size with long long arithmetic before adding to iCount
- Check iCount bounds before incrementing
- Fix signed/unsigned comparison warning in mb_delay

Cherry-picked from Jules: 8f639d0
Reviewed by: Gemini Code Assist

Co-Authored-By: google-labs-jules[bot] <161369871+google-labs-jules[bot]@users.noreply.github.com>
Replace unsafe pointer casting (which violates C strict aliasing rules)
with memcpy and bitwise operations to safely swap 16-bit halves of
32-bit values.

This ensures correct behavior across different optimization levels
and compilers, avoiding undefined behavior.

Cherry-picked from Jules: a6472ec
Reviewed by: Gemini Code Assist

Co-Authored-By: google-labs-jules[bot] <161369871+google-labs-jules[bot]@users.noreply.github.com>
The mb_delay function contained a dead code path that called sleep(-1)
when d == ULONG_MAX. This is problematic because:
- sleep() takes unsigned int, causing UINT_MAX seconds (~136 years) sleep
- The input d is derived from iPollRate (>= 100) or constant 20, never -1

Changes:
- Remove the dead code path entirely
- Use nanosleep unconditionally on Unix-like systems
- Mark mb_delay as static (internal linkage)

Cherry-picked from Jules: 1c4863c
Reviewed by: Gemini Code Assist

Co-Authored-By: google-labs-jules[bot] <161369871+google-labs-jules[bot]@users.noreply.github.com>
Avoid redundant modbus_set_slave() calls by checking if the current
slave address matches the target before setting it. This reduces
unnecessary I/O overhead when polling a single slave repeatedly.

Cherry-picked from Jules: b37345e
Reviewed by: Gemini Code Assist

Co-Authored-By: google-labs-jules[bot] <161369871+google-labs-jules[bot]@users.noreply.github.com>
Replace direct exit/cleanup in signal handler with a volatile flag that
is checked in the main loop. This follows best practices for async-signal
safety:

- Add g_bExitSignal volatile sig_atomic_t flag
- Check flag at loop entry and inner loops
- Suppress spurious error messages when interrupted by signal
- Signal handler now only sets the flag

This prevents undefined behavior from calling non-async-signal-safe
functions (like modbus_close, free, printf) in signal handlers.

Cherry-picked from Jules: fd2744a
Reviewed by: Gemini Code Assist

Co-Authored-By: google-labs-jules[bot] <161369871+google-labs-jules[bot]@users.noreply.github.com>
Add typedef to prevent ISO C warning about empty translation unit
when MBPOLL_GPIO_RTS is not defined (file becomes effectively empty).

Partial cherry-pick from Jules: a7109f0
(mb_delay cast fix superseded by sleep refactor in bd7c742)

Co-Authored-By: google-labs-jules[bot] <161369871+google-labs-jules[bot]@users.noreply.github.com>
The function was declared but never implemented or used in the codebase.
Removing dead code improves maintainability.

Cherry-picked from Jules: 82d3e16 (PR #2)
Reviewed by: Gemini Code Assist

Co-Authored-By: google-labs-jules[bot] <161369871+google-labs-jules[bot]@users.noreply.github.com>
Add comprehensive test suite for serial port configuration functions:
- sSerialFlowToStr: flow control type conversion
- sSerialDataBitsToStr: data bits conversion
- sSerialStopBitsToStr: stop bits conversion
- sSerialParityToStr: parity conversion

Test infrastructure:
- tests/test_serial.c: All serial function tests
- tests/CMakeLists.txt: CTest integration
- BUILD_TESTING option in main CMakeLists.txt

Based on Jules AI contributions from PRs #10, #11, #14, #15
Reviewed by: Gemini Code Assist

Co-Authored-By: google-labs-jules[bot] <161369871+google-labs-jules[bot]@users.noreply.github.com>
Replaces the N+1 read pattern with batched Modbus requests for contiguous addresses.
Supports up to 125 registers or 2000 bits per request, significantly reducing transaction overhead.
Ensures alignment by using a `uint16_t` buffer.
Verified with `unit-test-server` for correctness and performance.
Rebased on origin/master to incorporate latest changes.

Co-authored-by: zknpr <96851588+zknpr@users.noreply.github.com>
Replaces the N+1 read pattern with batched Modbus requests for contiguous addresses.
Supports up to 125 registers or 2000 bits per request, significantly reducing transaction overhead.
Ensures alignment by using a `uint16_t` buffer.
Verified with `unit-test-server` for correctness and performance.
Rebased on origin/master to incorporate latest changes and resolved conflicts.

Co-authored-by: zknpr <96851588+zknpr@users.noreply.github.com>
Replaces the N+1 read pattern with batched Modbus requests for contiguous addresses.
Supports up to 125 registers or 2000 bits per request, significantly reducing transaction overhead.
Ensures alignment by using a `uint16_t` buffer.
Verified with `unit-test-server` for correctness and performance.
Rebased on v1.5.3 as requested.

Co-authored-by: zknpr <96851588+zknpr@users.noreply.github.com>
Replaces the N+1 read pattern with batched Modbus requests for contiguous addresses.
Supports up to 125 registers or 2000 bits per request, significantly reducing transaction overhead.
Ensures alignment by using a `uint16_t` buffer.
Respects recent signal handling improvements (`g_bExitSignal`).
Verified with `unit-test-server` for correctness and performance.
Rebased on v1.5.3 (bbc029b).

Co-authored-by: zknpr <96851588+zknpr@users.noreply.github.com>
Optimizes Modbus polling with batched reads for contiguous addresses:
- Batches up to 125 registers or 2000 bits per request
- Uses uint16_t buffer for proper alignment
- Reduces transaction overhead significantly
- Preserves all v1.5.3 improvements (signal handler, security fixes)

Includes benchmark.sh for performance testing.

Merged from: origin/batch-reads-optimization-14003233585538614312
Original PR: #22 by google-labs-jules[bot]

Co-Authored-By: google-labs-jules[bot] <161369871+google-labs-jules[bot]@users.noreply.github.com>
- Moved `xMbPollContext` and enums to `src/mbpoll.h`.
- Created `src/chipio.h` and `src/chipio.c` for ChipIO specific logic.
- Defined `xChipIoContext` to encapsulate ChipIO state.
- Updated `src/mbpoll.c` to use the new module.
- Exposed necessary helper functions from `mbpoll.c` in `mbpoll.h`.
- Updated `CMakeLists.txt` to include `src/chipio.c`.
- Fixed `-Wsign-compare` warning in `mb_delay`.
- Cleaned up duplicate `_GNU_SOURCE` definitions.

This change addresses the TODO to separate the ChipIO part, improving maintainability and reducing the size of `mbpoll.c`. Re-based on v1.5.3.

Co-authored-by: zknpr <96851588+zknpr@users.noreply.github.com>
Verified compatibility with v1.5.3 base branch. The `iGetIntList` refactor and tests function correctly. Minor cleanup in `CMakeLists.txt` to avoid duplicate test inclusion.

Co-authored-by: zknpr <96851588+zknpr@users.noreply.github.com>
- Remove duplicate enum definitions in mbpoll.c (already in mbpoll.h)
- Fix variable redeclaration in parse_args
- Add src/utils.c and src/chipio.c to CMakeLists.txt
- Update mbpoll.h to include utils.h
- Add modbus_get_slave mock to tests/include/modbus.h

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Extracted lSwapLong and fSwapFloat from src/mbpoll.c to src/utils.c.
- Updated functions to accept endianness flag instead of relying on global state.
- Implemented swapping using memcpy to avoid strict aliasing violations.
- Added src/utils.h header.
- Added tests/test_utils.c with unit tests covering identity, swap, and negative scenarios.
- Updated CMakeLists.txt to include new sources, enable testing, and make libmodbus optional (allowing tests to run without it).

Co-authored-by: zknpr <96851588+zknpr@users.noreply.github.com>
- Resolved merge conflicts in mbpoll.c
- Updated lSwapLong/fSwapFloat calls to use explicit endianness
- Added _GNU_SOURCE to chipio.c for strcasestr
- Added overflow check for integer list allocation in utils.c
- Add integer overflow protection in batch buffer calculations
- Add overflow checks in vAllocate for size calculations
- Add strtol/strtod range validation (errno + bounds checks)
- Add NULL check for modbus context in vCleanup
- Add weak vFailureExit implementation in utils.c for standalone compilation
- Enable unit tests in CI for Linux, macOS, and Windows
- Fix .gitignore to allow .github directory

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Added `release-*` to push trigger branches.
- Added `v*.*.*` tags to push trigger.

This ensures CI runs for release branches and tagged releases, addressing the issue where tests existed but weren't automatically validated on pushes to these refs.
- src/chipio.c: Use standard <string.h> instead of <strings.h> for Windows compatibility. Map strcasecmp to _stricmp on Windows. Wrap _GNU_SOURCE definition.
- src/mbpoll.c: Wrap _GNU_SOURCE definition to avoid redefinition warnings.
- src/utils.c: Conditionally exclude vFailureExit when SKIP_FAILURE_EXIT is defined to avoid linker errors with test mocks.
- tests/CMakeLists.txt: Define SKIP_FAILURE_EXIT for test_utils target to prevent multiple definition errors.
MSVC does not support -Wno-pedantic, which caused a build error. This flag is now applied only when NOT MSVC.
- Define SKIP_FAILURE_EXIT for mbpoll target to prevent src/utils.c from defining vFailureExit.
- This resolves LNK2005 error as mbpoll.c already provides the definition.
@epsilonrt epsilonrt merged commit 022fc70 into epsilonrt:master Feb 8, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants