Skip to content

Use, abuse or erroneous implementation of overlapping hal_float_t/hal_u32_t #4130

@BsAtHome

Description

@BsAtHome

While doing the HAL getter/setter changes...

@pcw-mesa In hal/drivers/mesa-hostmot2/abs_encoder.c lines 617-624 we find this little gem:

617:    case HM2_GTAG_FABS:
618:        if (chan->params->timer_num > 4) chan->params->timer_num = 4;
619:        if (chan->params->u32_param > 15) chan->params->u32_param = 15;
620:        buff3 = chan->num_read_bits << 24
621:                | (rtapi_u32)(8.0e-6 * hm2->absenc.clock_frequency) << 14;
622:        buff2 = chan->params->u32_param << 28
623:                | ((rtapi_u32)(0x100000 * (chan->params->float_param * 1000
624:                / hm2->absenc.clock_frequency)));
...

The addressed variables are part of a union in hm2_sserial_params_t defined in sserial.h:

  • chan->params->u32_param - a parameter typed hal_u32_t
  • chan->params->float_param - a parameter typed hal_float_t

Please note, these are addressing a HAL parameter, so they are visible from userland and can be changed and inspected by, f.ex, halcmd.

Both variables share the same underlying memory and the 32-bit unsigned is addressing some of the mantissa bits of the 64-bit floating point.

The code first uses the unsigned value in line 619 and rewrites it to be 15 when larger than 15, isolating 4 lower bits of the 32-bit value. Then, in line 622 it reads the value and takes the lower 4 bits to the top (the ones limited in line 619). However, the next line, 623, reads the same memory as a floating point value. This assumes that there is valid data in the higher 32 bits of the 64-bit memory read for the floating point value, which is doubtful, and uses the read value as is.

This is obviously either a bad hack or an error. What is the purpose of this code? How is this in any way predictable what will happen? If the parameter is created as a HAL_U32, then the upper 32-bit are undefined. If the parameter is created as HAL_FLOAT, then the lower 4 bits are for all practical purposes and intends not controllable.

Was this code written before the HAL_FLOAT became a double? If so, then there would have been a full variable size overlap. But then this code was never run or tested again after the change. Even so, I still don't get it because using a float is a potentially unstable (especially after division).

The question is now how to fix it. Insights what is actually required and suggestions are welcome.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions