Skip to content

Potential integer overflow in the usleep implementation of ESP IDF (IDFGH-13493) #14390

Closed
@ivmarkov

Description

@ivmarkov

Answers checklist.

  • I have read the documentation ESP-IDF Programming Guide and the issue is not addressed there.
  • I have updated my IDF branch (master or release) to the latest version and checked that the issue is present there.
  • I have searched the issue tracker for a similar issue and not found a similar issue.

IDF version.

master and any earlier

Espressif SoC revision.

all

Operating System used.

Linux

How did you build your project?

Command line with Make

If you are using Windows, please specify command line type.

None

Development Kit.

all

Power Supply used.

USB

What is the expected behavior?

Passing 0xFFFFFFFF to the current ESP IDF usleep implementation should make the system sleep for 0xFFFFFFFF microseconds, OR return EINVAL to indicate that values larger than 1_000_000 are not supported (as per the usleep syscall spec).

What is the actual behavior?

Passing 0xFFFFFFFF to the current ESP IDF usleep implementation will overflow and sleep for a smaller amount of time.

Steps to reproduce.

  1. Generate an ESP-IDF template with cargo generate https://github.com/esp-rs/esp-idf-template and accept all defaults
  2. Replace the main.rs of the generated template with
use std::time::Instant;

use esp_idf_svc::sys::usleep;

fn main() {
    // It is necessary to call this function once. Otherwise some patches to the runtime
    // implemented by esp-idf-sys might not link properly. See https://github.com/esp-rs/esp-idf-template/issues/71
    esp_idf_svc::sys::link_patches();

    // Bind the log crate to the ESP Logging facilities
    esp_idf_svc::log::EspLogger::initialize_default();

    for sleep_us in [
        1_000_000, // Works
        0xffff_ffffu32, // Will not work due to a silent integer overflow in `usleep`
        0xffff_ffffu32 - 10 /*ms - the default tick-rate*/ * 1000 - 1 // Works as we avoid the integer overflow
    ] {
        log::info!("About to sleep for ~{sleep_us}us");

        let start_sleep = Instant::now();

        let error_code = unsafe {
            usleep(sleep_us)
        };

        log::info!("Actual sleep: ~{}us, error_code: {error_code}", start_sleep.elapsed().as_micros());
    }
}

... or translate to C.

Build, flash and run.

Debug Logs.

No response

More Information.

Related to ivmarkov/rust@1faccba#diff-2b173511d53f2c01a70eac2f753b998948ca6cbe3d013b6119fbe4631770ec60R279 which fixes rust-lang/rust#129212 (comment)

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions