nanoMODBUS icon indicating copy to clipboard operation
nanoMODBUS copied to clipboard

send_exception_msg() implicit signed conversion

Open mrnoise-ko opened this issue 6 months ago • 3 comments

The send_exception_msg() will take an uint8_t exception argument but is used throughout the code with the nmbs_error enum. The enum is signed because values <=0 are library errors. So there is a implicit signed conversion happening.

I know that only values >0 should be send via send_exception_msg() because these values are known modbus error codes but I think it is bad design because it will break if someone changes the code without being aware of that.

I would change the function(untestet):


static uint8_t clamp_exception_msg(nmbs_error exception) {
    const int8_t except = (int8_t) exception;
    if (except < 0)
        return 0;
    return (uint8_t) except;
}

static nmbs_error send_exception_msg(nmbs_t* nmbs, nmbs_error exception) {
    nmbs->msg.fc += 0x80;
    put_msg_header(nmbs, 1);
    put_1(nmbs, clamp_exception_msg(exception));

    NMBS_DEBUG_PRINT("%d NMBS res -> address_rtu %d\texception %d", nmbs->address_rtu, nmbs->address_rtu, exception);

    return send_msg(nmbs);
}
´´´´

mrnoise-ko avatar Jul 01 '25 14:07 mrnoise-ko

Yes, i think that preventing an (unlikely) implicit conversion is a good idea. However, clamping it to 0 will basically give the same result: the value will be altered unbeknownst to the user. I think a better approach would be printing a big giant error and then, maybe, stopping the program. The priority is letting the user know that she is sending a negative exception number.

debevv avatar Jul 02 '25 18:07 debevv

Yeah you are right! Maybe an assert() is the right way to handle this?

mrnoise-ko avatar Jul 03 '25 06:07 mrnoise-ko

I think returning an NMBS_ERROR_INVALID_ARGUMENT could suffice, since you should check the return value anyway to be sure that the exception was actually sent.

debevv avatar Sep 22 '25 12:09 debevv