EttusResearch / uhd

The USRP™ Hardware Driver Repository
http://uhd.ettus.com
Other
946 stars 646 forks source link

Y2038 bug in sensor gps_time and utility program query_gpsdo_sensors #659

Open cosmos72 opened 1 year ago

cosmos72 commented 1 year ago

Issue Description

Reading the example https://github.com/EttusResearch/uhd/blob/master/host/utils/query_gpsdo_sensors.cpp#L215 I noticed that sensor value "gps_time" is converted to signed:

    uhd::sensor_value_t gps_time   = usrp->get_mboard_sensor("gps_time");
    // we only care about the full seconds
    signed gps_seconds    = gps_time.to_int();

which will overflow on 19 January 2038 - it's an instance of the Y2038 bug, see for example https://en.wikipedia.org/wiki/Year_2038_problem

I tracked down where the sensor value for "gps_time" is created by uhd library, and it has an analogous problem: https://github.com/EttusResearch/uhd/blob/master/host/lib/usrp/gps_ctrl.cpp#L274

    } else if (key == "gps_time") {
            return sensor_value_t("GPS epoch time", int(get_epoch_time()), "seconds");

while get_epoch_time() returns an int64_t, truncating it to int will again overflow on 19 January 2038.

Setup Details

To reproduce this bug, one would have to wait for 19 January 2038, and execute the utility program query_gpsdo_sensors on a radio with GPSDO chip and external GPS antenna.

Alternatively, a get_epoch_time() > 2^31-1 may be injected by modifying uhd sources.

Expected Behavior

query_gpsdo_sensors continues to work also after 19 January 2038.

Actual Behaviour

query_gpsdo_sensors will not be able to synchronize radio's clock to GPS time after 19 January 2038.

Steps to reproduce the problem

Wait for 19 January 2038, and execute the utility program query_gpsdo_sensors on a radio with GPSDO chip and external GPS antenna.

Alternatively, inject a get_epoch_time() > 2^31-1 by modifying uhd sources.

Additional Information

As a possible solution, host/lib/usrp/gps_ctrl.cpp could create the sensor value "gps_time" as follows:

    } else if (key == "gps_time") {
            return sensor_value_t("GPS epoch time", std::to_string(get_epoch_time()), "seconds");

with the (hopefully acceptable) side effect that sensor_value_t type changes from INT to STRING.

Also host/utils/query_gpsdo_sensors.cpp could read the sensor value as follows:

    uhd::sensor_value_t gps_time   = usrp->get_mboard_sensor("gps_time");
    // we only care about the full seconds
    long long gps_seconds    = std::stoll(gps_time.value);