Repository navigation
Fix exception function code wraparound when function >= 0x80 - #873
Closed
afonsojanu wants to merge 1 commit into
Closed
afonsojanu wants to merge 1 commit into
afonsojanu wants to merge 1 commit into
Conversation
response_exception() builds the exception function byte with plain integer addition (function + 0x80). modbus_reply()'s default case routes any unrecognized function code there, including raw bytes from 0x80 to 0xFF, so the addition can carry past 0xFF. Once that gets truncated to a single byte for the wire in build_response_basis, the result wraps back below 0x80 and the response looks like an ordinary function code instead of an exception. Switch to a bitwise OR, which matches the Modbus spec (set the top bit) and gives the same result as the addition whenever the top bit was already clear. Adds a client-side regression test alongside the existing invalid function code test, using a request byte that already has the top bit set.
|
We require contributors to sign our Contributor License Agreement. In order for us to review and merge your code, please fill https://forms.gle/5635zjphDo5JEJQSA to get added. Your document will be manually checked by the maintainer. Be patient... |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
response_exception()builds the exception function byte with plain integer addition:modbus_reply()routes any function code its switch doesn't recognize through the default case into this function, and that includes raw bytes from 0x80 to 0xFF (a client can send those directly withmodbus_send_raw_request, or they show up as garbage/unsupported function codes on the wire). Whensft->functionis already >= 0x80, the addition carries past 0xFF.sft->functionis anint, so the overflow itself is harmless, but the value then gets written into the response buffer as a single byte inbuild_response_basis(rsp[7] = sft->function;for TCP, similarly for RTU), which truncates it back into range. For a function byte like0xFF,0xFF + 0x80 = 0x17F, which truncates to0x7F, a value with the top bit clear. The client then sees what looks like an ordinary function code instead of an exception.This is the same class of bug as #845, which covers
modbus_reply_exception()(already has an open PR, #869). This report is about the separate code path insidemodbus_reply()itself, used both for the "unrecognized function code" case and the "truncated request" case, which #869 doesn't touch.Fix: use bitwise OR instead of addition, matching the actual Modbus rule (set the top bit of the function code). For any function code below 0x80 this produces exactly the same byte as before; for one at or above 0x80 it now stays correct instead of wrapping.
Verified with a small standalone repro that opens a
modbus_reply()call through a socketpair and inspects the raw response bytes: with a request function byte of0xFF, the reply's function byte came back as0x7Fbefore this change and0xFFafter.Also adds a client-side test next to the existing "invalid function code" test in
unit-test-client.c, using a function byte that already has its top bit set (0xFF), which fails before the fix and passes after.