Skip to content

feat(serial): board fingerprints + fbuild serial probe CLI (#686)#700

Merged
zackees merged 1 commit into
mainfrom
feat/686-board-fingerprints
Jun 20, 2026
Merged

feat(serial): board fingerprints + fbuild serial probe CLI (#686)#700
zackees merged 1 commit into
mainfrom
feat/686-board-fingerprints

Conversation

@zackees

@zackees zackees commented Jun 20, 2026

Copy link
Copy Markdown
Member

Summary

#686 mirrors two artifacts that landed on the FastLED side in FastLED/FastLED#3339: a vendored (vid, pid) → human hint table and a port-probe CLI that opens with the correct DTR/RTS for the inferred board family. Both close gaps the closed #684 surfaced — with the rename to esp_hard_reset_blocking and the new cdc_vcom_safe_assert on the library side, the next missing piece was the data + tooling.

What this PR ships

crates/fbuild-serial/src/boards.rs

  • BOARD_FINGERPRINTS — vendored VID:PID → human hint table covering NXP (LPC8xx CMSIS-DAP + LPC11U35), Espressif native USB + USB JTAG/serial, Silicon Labs CP210x, WCH CH340/CH9102, FTDI FT232R/FT231X, Arduino official, RP2040/Pico.
  • ENVIRONMENT_TO_VCOM — env-name → VCOM (vid, pid) for boards where the data port is NOT the primary USB endpoint (LPC845-BRK, LPC804, LPCXpresso845-MAX/804 → LPC11U35).
  • board_hint(vid, pid), vcom_for_env(env), family_for_vid_pid(vid, pid) lookup APIs.
  • BoardFamily { Esp32NativeUsbCdc | Esp32ExternalUart | CdcAcmBridge | Arduino } with idle_dtr_rts(&self) -> (bool, bool). Minimal scope — polymorphic ResetMethod dispatch is the scope of fbuild-serial: BoardFamily enum + polymorphic ResetMethod dispatch registry #687.

crates/fbuild-cli/src/cli/serial_probe.rs + dispatch wiring

$ fbuild serial probe list
COM25      303A:1001  ser=80:F1:B2:D1:DF:B1  USB Serial Device  [Espressif native USB CDC (ESP32-S3/C3/C6/H2/P4)]
COM20      16C0:0483  ser=15821020          USB Serial Device  [LPC11U35 VCOM bridge (LPC845-BRK USART0) OR PJRC Teensy USB-Serial]
COM10      1FC9:0132  ser=0B03400A          USB Serial Device  [NXP CMSIS-DAP debug (LPC845-BRK / LPC11U35)]
…

$ fbuild serial probe find --env lpc845brk
COM20                                                 # → the VCOM bridge, NOT the CMSIS-DAP probe

$ fbuild serial probe read COM20 --seconds 4 --send '{"jsonrpc":"2.0","id":1,"method":"echo"}\n'
# opens COM20 with DTR=true / RTS=true (CDC-ACM idle), sends, dumps bytes for 4s

The read path picks DTR/RTS via family_for_vid_pid(...).idle_dtr_rts() — so CDC-ACM bridges see "host ready" instead of the ESP-default "host not ready" that silently drops every byte the target transmits (the FastLED/FastLED#3300 failure).

Tests

  • 9 boards-module tests — every public API + a regression test pinning family_for_vid_pid(0x16C0, 0x0483).idle_dtr_rts() == (true, true). The LPC11U35 VCOM bridge MUST end at host-ready, or the [BLOCKER] LPC845-BRK AutoResearch bring-up echo returns empty RX (suspected HardFault) — blocks #3102 FastLED#3300 silent-byte-drop bug reappears.
  • 6 CLI testsparse_vid_pid (colon + comma forms, malformed rejection) and unescape_send (common escapes, hex bytes, unknown escape pass-through, trailing backslash edge case).
  • No tests for the hardware-touching paths (list, find, read) — those need a board attached. Manually smoke-verified locally against a multi-board host: find --env lpc845brkCOM20 (the VCOM bridge), NOT COM10 (the CMSIS-DAP debug probe) — the disambiguation step that FastLED's port_utils.py had to add post-#3300.
running 9 tests          # fbuild-serial::boards
test result: ok. 9 passed; 0 failed; ...

running 6 tests          # fbuild-cli::cli::serial_probe
test result: ok. 6 passed; 0 failed; ...

cargo clippy -p fbuild-serial -p fbuild-cli --all-targets -- -D warnings clean. cargo fmt --all --check clean.

Out of scope (deferred to #686's siblings)

Test plan

  • cargo test -p fbuild-serial --lib boards:: (9/9)
  • cargo test -p fbuild-cli --bin fbuild cli::serial_probe:: (6/6)
  • cargo clippy -p fbuild-serial -p fbuild-cli --all-targets -- -D warnings clean
  • cargo fmt --all --check clean
  • Manual smoke test: serial probe list on a multi-board host
  • Manual smoke test: serial probe find --env lpc845brk returns COM20
  • Full workspace CI green

Closes #686.

Summary by CodeRabbit

Release Notes

  • New Features
    • Added fbuild serial debugging command with port enumeration, lookup, and reading capabilities
    • serial list displays available USB serial ports with board identification hints
    • serial find locates ports by VID/PID or environment mapping
    • serial read opens and reads from serial ports with configurable baud rate and signal control

#686 mirrors two artifacts that landed on the FastLED
side in FastLED/FastLED#3339: a vendored `(vid, pid) → human hint`
table and a port-probe CLI that opens with the correct DTR/RTS for the
inferred board family. Both close gaps the closed #684 surfaced: with
the rename to `esp_hard_reset_blocking` and the new `cdc_vcom_safe_assert`
on the library side, the next missing piece was data + tooling.

## What this PR ships

### `crates/fbuild-serial/src/boards.rs`

- `BOARD_FINGERPRINTS: &[(u16, u16, &str)]` — vendored from FastLED's
  `ci/util/serial_probe.py`. Covers NXP (LPC8xx CMSIS-DAP + LPC11U35),
  Espressif native USB + USB JTAG/serial, Silicon Labs CP210x,
  WCH CH340/CH9102, FTDI FT232R/FT231X, Arduino official, RP2040/Pico.
- `ENVIRONMENT_TO_VCOM: &[(&str, u16, u16)]` — env-name → VCOM (vid, pid)
  for boards where the data port is NOT the primary USB endpoint
  (LPC845-BRK, LPC804, LPCXpresso845-MAX, LPCXpresso804 → LPC11U35).
- `pub fn board_hint(vid, pid) -> Option<&'static str>` — exact-match
  lookup.
- `pub fn vcom_for_env(env) -> Option<(u16, u16)>` — env-keyed lookup.
- `pub fn family_for_vid_pid(vid, pid) -> Option<BoardFamily>` —
  classifier that returns the right `BoardFamily` so probe / monitor
  open paths can pick the right DTR/RTS via `idle_dtr_rts()` instead of
  the ESP-default that drops bytes on CDC-ACM bridges.
- `pub enum BoardFamily { Esp32NativeUsbCdc, Esp32ExternalUart,
  CdcAcmBridge, Arduino }` with `idle_dtr_rts(&self) -> (bool, bool)`.
  Minimal scope per the #687 follow-up that owns the polymorphic
  `ResetMethod` registry.

### `crates/fbuild-cli/src/cli/serial_probe.rs`

New `fbuild serial probe …` subcommand tree:

* `fbuild serial probe list` — enumerate every visible serial port with
  VID:PID + board hint. Verified locally — output matches FastLED's
  `serial_probe.py list` shape exactly:

  ```
  COM25      303A:1001  ser=…  USB Serial Device (COM25)  [Espressif native USB CDC …]
  COM20      16C0:0483  ser=…  USB Serial Device (COM20)  [LPC11U35 VCOM bridge …]
  COM10      1FC9:0132  ser=…  USB Serial Device (COM10)  [NXP CMSIS-DAP debug …]
  ```

* `fbuild serial probe find --vid-pid V:P | --env <name>` — return one
  port path on stdout (exit 0) or exit 1 when no match. Verified
  locally: `--env lpc845brk` → `COM20` (the VCOM bridge), NOT `COM10`
  (the CMSIS-DAP debug probe) — the disambiguation step that
  FastLED's `port_utils.py` had to add post-#3300.

* `fbuild serial probe read PORT [--baud N] [--seconds N] [--send STR]`
  — open with `family_for_vid_pid(...).idle_dtr_rts()` so CDC-ACM
  bridges see DTR=true / RTS=true instead of the ESP-default that
  silently drops every byte the target MCU transmits. Supports a
  small set of `\n`/`\r`/`\t`/`\0`/`\xHH` escapes in the `--send`
  payload so scripted probes don't need shell-quoting gymnastics.

### Tests

* 9 boards-module tests — every public API + a regression test
  pinning that `family_for_vid_pid(0x16C0, 0x0483).idle_dtr_rts()` ==
  `(true, true)` (the LPC11U35 VCOM bridge MUST end at host-ready, or
  we reintroduce the FastLED/FastLED#3300 silent-byte-drop bug).
* 6 CLI tests covering `parse_vid_pid` (colon + comma forms, malformed
  rejection) and `unescape_send` (common escapes, hex bytes, unknown
  escape pass-through, trailing backslash edge case).
* No new tests for the hardware-touching paths (`list`, `find`, `read`)
  — those need a board attached. Manually smoke-verified locally
  against a multi-board host (LPC845-BRK on COM20, three ESP32-S3 on
  COM9 / COM22 / COM25, LPC CMSIS-DAP on COM10) and the disambiguation
  works.

`cargo clippy -p fbuild-serial -p fbuild-cli --all-targets -- -D warnings`
clean. `cargo fmt --all --check` clean.

## Out of scope (deferred to siblings of #686)

- Cross-repo sync (acceptance criterion 3) — the data table is now in
  fbuild and the FastLED side could load it directly in a follow-up
  PR (option a from #686), OR a CI diff check could compare the two
  tables (option b). Neither is in this PR; both options remain open.
- Polymorphic `ResetMethod` / `BootModeClassifier` dispatch registry —
  scope of #687, #688 respectively. `BoardFamily` here is the minimum
  needed by #686 criterion 4; the polymorphic dispatch comes next.

Closes #686.
@coderabbitai

coderabbitai Bot commented Jun 20, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

Adds a board fingerprint registry crate module (fbuild-serial/boards.rs) with USB VID/PID lookup tables, a BoardFamily enum, and idle_dtr_rts() for per-family DTR/RTS conventions. Builds a new fbuild serial probe CLI in fbuild-cli with list, find, and read subcommands that use those tables for DTR/RTS-correct port access.

Changes

Serial Probe CLI and Board Registry

Layer / File(s) Summary
Board fingerprint registry
crates/fbuild-serial/src/lib.rs, crates/fbuild-serial/src/boards.rs
Adds pub mod boards exposing BOARD_FINGERPRINTS and ENVIRONMENT_TO_VCOM static tables, the BoardFamily enum with idle_dtr_rts() returning per-family (dtr, rts) idle states, and three lookup helpers: board_hint, vcom_for_env, and family_for_vid_pid. Includes unit tests for all lookup paths and idle_dtr_rts mappings.
Serial probe CLI: command model, wiring, and dispatch
crates/fbuild-cli/Cargo.toml, crates/fbuild-cli/src/cli/mod.rs, crates/fbuild-cli/src/cli/args.rs, crates/fbuild-cli/src/cli/dispatch.rs, crates/fbuild-cli/src/cli/serial_probe.rs
Adds fbuild-serial and serialport deps; declares Commands::Serial with nested SerialAction/ProbeAction Clap types; wires run_serial(action) in the dispatcher. Implements list_ports (VID/PID annotation via board_hint), find_port (resolves target by --vid-pid or --env, exits with code 1 on miss), parse_vid_pid (hex VID:PID parser), read_port (opens port with board-family-aware DTR/RTS, optional escaped payload write, timed byte drain to stdout), infer_family_for_port (VID/PID → BoardFamily with CDC fallback), and unescape_send (backslash-escape decoder). Includes unit tests for parsing and unescaping.

Sequence Diagram(s)

sequenceDiagram
  participant Agent as Agent / Human
  participant fbuild as fbuild CLI
  participant SerialProbe as serial_probe.rs
  participant Boards as fbuild-serial::boards
  participant Port as serialport

  Agent->>fbuild: fbuild serial probe read /dev/ttyUSB0 --baud 115200 --send '{"id":1}'
  fbuild->>SerialProbe: run_serial(SerialAction::Probe { action: Read { ... } })
  SerialProbe->>Port: available_ports()
  Port-->>SerialProbe: port list with USB info
  SerialProbe->>Boards: family_for_vid_pid(vid, pid)
  Boards-->>SerialProbe: BoardFamily::CdcAcmBridge
  SerialProbe->>Boards: idle_dtr_rts() → (true, true)
  SerialProbe->>Port: open(port, baud)
  SerialProbe->>Port: write_data_terminal_ready(true), write_request_to_send(true)
  SerialProbe->>SerialProbe: unescape_send(payload)
  SerialProbe->>Port: write(escaped_bytes)
  loop until deadline
    SerialProbe->>Port: read(buf)
    Port-->>SerialProbe: bytes (or timeout)
    SerialProbe->>Agent: stdout.write(bytes)
  end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related issues

  • #684 — This PR directly implements the BoardFamily enum with idle_dtr_rts() and the ENVIRONMENT_TO_VCOM table that issue #684 explicitly proposed as an acceptance criterion; read_port applies the resulting DTR/RTS convention rather than defaulting to ESP-style (false, false).
  • #686 — This PR satisfies the core acceptance criteria of #686: board_hint/vcom_for_env APIs backed by a shared data table, and a fbuild serial probe CLI with list, find, and read modes using BoardFamily::idle_dtr_rts() for per-family DTR/RTS selection.
  • #687 — The BoardFamily enum and family_for_vid_pid helper introduced here are the foundational data layer #687 identifies as a prerequisite for its polymorphic reset-dispatch registry.
  • #688 — The BoardFamily enum landed in boards.rs is the exact type #688 proposes as the parameter to its Registry::for_family(family: BoardFamily) boot-mode classifier.
  • #691 — The BoardFamily enum added here is the direct target for the HandoffTiming/handoff_timing() extension #691 proposes adding to that enum.
  • #693 — The BOARD_FINGERPRINTS table and board_hint/family_for_vid_pid functions satisfy the USB VID:PID classification layer #693 identifies as prerequisite for bootloader re-enumeration detection.
  • #697 — The serial_probe subcommand and BoardFamily infrastructure introduced here are listed explicitly in #697 as prerequisite dependencies for the fbuild bringup orchestrator.
  • #699 — This PR implements the serial-probe CLI and board fingerprinting work that #699 tracks as a structural follow-up in its META checklist.

Poem

🐇 A bunny hopped through ports one day,
Found VID and PID along the way.
With DTR true and RTS set,
No byte was lost, no board was fret.
fbuild serial probe now knows the lore —
No silent boards shall fool us more! ✨

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed Title accurately describes the main changes: board fingerprints and fbuild serial probe CLI functionality.
Linked Issues check ✅ Passed All linked issue requirements are met: BoardFamily enum with idle_dtr_rts() API, board_hint/vcom_for_env lookups, and fbuild serial probe CLI with list/find/read subcommands all implemented.
Out of Scope Changes check ✅ Passed All changes are directly aligned with issue #684 and #686 objectives; no unrelated modifications detected outside scope.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/686-board-fingerprints

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@crates/fbuild-cli/src/cli/serial_probe.rs`:
- Around line 112-125: The `list_ports()` function currently violates the
thin-client architecture by directly calling `serialport::available_ports()` to
enumerate serial ports in the CLI process. Replace this direct serial port
enumeration with an HTTP request to the daemon that returns the list of
available ports. The daemon should be responsible for all serial port operations
and device access. Apply this same refactoring pattern to the other serial probe
functions mentioned (in the 156-190 and 216-285 ranges) that also perform direct
device access operations like opening, reading, and writing to serial ports.
- Around line 246-247: The `seconds` parameter passed to
`Duration::from_secs_f64(seconds)` on line 246 is user-controlled CLI input that
lacks validation, which can cause panics if the value is negative, non-finite
(NaN/infinity), or exceeds Duration's maximum capacity. Before calling
`Duration::from_secs_f64(seconds)`, add validation to check that `seconds` is a
valid non-negative finite number within acceptable bounds, and return an
appropriate error to the user if validation fails instead of allowing the method
to panic.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 6fbf72b1-9b9f-40e7-a5a1-0ccbef872d51

📥 Commits

Reviewing files that changed from the base of the PR and between 6243618 and 040aaf5.

⛔ Files ignored due to path filters (1)
  • Cargo.lock is excluded by !**/*.lock
📒 Files selected for processing (7)
  • crates/fbuild-cli/Cargo.toml
  • crates/fbuild-cli/src/cli/args.rs
  • crates/fbuild-cli/src/cli/dispatch.rs
  • crates/fbuild-cli/src/cli/mod.rs
  • crates/fbuild-cli/src/cli/serial_probe.rs
  • crates/fbuild-serial/src/boards.rs
  • crates/fbuild-serial/src/lib.rs

Comment on lines +112 to +125
fn list_ports() -> Result<()> {
let ports = serialport::available_ports()
.map_err(|e| FbuildError::SerialError(format!("serial port enumeration failed: {e}")))?;

if ports.is_empty() {
eprintln!("no serial ports visible");
return Ok(());
}

for port in &ports {
print_port_summary(port);
}
Ok(())
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | 🏗️ Heavy lift

Route serial probe I/O through daemon instead of direct device access in CLI.

fbuild-cli now directly enumerates and opens serial ports (available_ports, open, read, write) in-process. That breaks the thin-client boundary and creates an additional hardware-access path outside daemon coordination.

As per coding guidelines, "fbuild-cli is a thin HTTP client to daemon ... that send JSON requests to the daemon."

Also applies to: 156-190, 216-285

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@crates/fbuild-cli/src/cli/serial_probe.rs` around lines 112 - 125, The
`list_ports()` function currently violates the thin-client architecture by
directly calling `serialport::available_ports()` to enumerate serial ports in
the CLI process. Replace this direct serial port enumeration with an HTTP
request to the daemon that returns the list of available ports. The daemon
should be responsible for all serial port operations and device access. Apply
this same refactoring pattern to the other serial probe functions mentioned (in
the 156-190 and 216-285 ranges) that also perform direct device access
operations like opening, reading, and writing to serial ports.

Source: Coding guidelines

Comment on lines +246 to +247
let deadline = Instant::now() + Duration::from_secs_f64(seconds);
let mut buf = [0u8; 1024];

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Verify the panic-prone callsite and absence/presence of input guards.
rg -n -C4 'fn read_port|from_secs_f64\(seconds\)|is_finite|checked_add' crates/fbuild-cli/src/cli/serial_probe.rs

Repository: FastLED/fbuild

Length of output: 1094


🏁 Script executed:

# Get the full function to see if there's any validation we missed
sed -n '216,350p' crates/fbuild-cli/src/cli/serial_probe.rs

Repository: FastLED/fbuild

Length of output: 5176


🏁 Script executed:

# Find all callers of read_port to understand where seconds comes from
rg -n 'read_port\(' crates/fbuild-cli/src/cli/serial_probe.rs

Repository: FastLED/fbuild

Length of output: 220


🏁 Script executed:

# Check what CLI argument parsing looks like for --seconds
rg -n -B5 -A5 '--seconds|seconds:' crates/fbuild-cli/src/cli/serial_probe.rs

Repository: FastLED/fbuild

Length of output: 479


🏁 Script executed:

# Check the context around line 107 where read_port is called
sed -n '90,125p' crates/fbuild-cli/src/cli/serial_probe.rs

Repository: FastLED/fbuild

Length of output: 1056


🏁 Script executed:

# Search for where seconds argument is defined in the CLI structure
rg -n 'seconds' crates/fbuild-cli/src/cli/serial_probe.rs | head -30

Repository: FastLED/fbuild

Length of output: 503


🌐 Web query:

Rust Duration::from_secs_f64 panic behavior with negative non-finite values

💡 Result:

In Rust, the Duration::from_secs_f64 method will panic if the provided f64 value is negative, is non-finite (e.g., NaN or infinity), or exceeds the maximum capacity of a Duration [1][2][3]. The method is implemented to explicitly check these conditions by calling Duration::try_from_secs_f64 internally; if the checked conversion returns an error, the method panics with the error message [2][3]. To perform this conversion without panicking, you should use the stable method Duration::try_from_secs_f64, which returns a Result<Duration, TryFromFloatSecsError> instead [4][3]. This allows you to handle negative, non-finite, or overflowing input values gracefully as part of your program's error-handling logic [4].

Citations:


Validate --seconds before Duration::from_secs_f64 to prevent process panic.

seconds is user-controlled CLI input currently passed directly to Duration::from_secs_f64(seconds) without validation. The method panics if the value is negative, non-finite (NaN/infinity), or exceeds the maximum capacity of a Duration. This will crash the CLI.

Proposed fix
 fn read_port(port_name: &str, baud: u32, seconds: f64, send: Option<&str>) -> Result<()> {
+    if !seconds.is_finite() || seconds < 0.0 || seconds > (u64::MAX as f64) {
+        return Err(FbuildError::SerialError(format!(
+            "invalid `--seconds` value `{seconds}`; expected a finite non-negative number"
+        )));
+    }
+
     // Resolve the family by looking up the connected port's VID:PID,
@@
-    let deadline = Instant::now() + Duration::from_secs_f64(seconds);
+    let read_window = Duration::from_secs_f64(seconds);
+    let deadline = Instant::now()
+        .checked_add(read_window)
+        .ok_or_else(|| FbuildError::SerialError("`--seconds` is too large".to_string()))?;
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
let deadline = Instant::now() + Duration::from_secs_f64(seconds);
let mut buf = [0u8; 1024];
fn read_port(port_name: &str, baud: u32, seconds: f64, send: Option<&str>) -> Result<()> {
if !seconds.is_finite() || seconds < 0.0 || seconds > (u64::MAX as f64) {
return Err(FbuildError::SerialError(format!(
"invalid `--seconds` value `{seconds}`; expected a finite non-negative number"
)));
}
// Resolve the family by looking up the connected port's VID:PID,
let read_window = Duration::from_secs_f64(seconds);
let deadline = Instant::now()
.checked_add(read_window)
.ok_or_else(|| FbuildError::SerialError("`--seconds` is too large".to_string()))?;
let mut buf = [0u8; 1024];
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@crates/fbuild-cli/src/cli/serial_probe.rs` around lines 246 - 247, The
`seconds` parameter passed to `Duration::from_secs_f64(seconds)` on line 246 is
user-controlled CLI input that lacks validation, which can cause panics if the
value is negative, non-finite (NaN/infinity), or exceeds Duration's maximum
capacity. Before calling `Duration::from_secs_f64(seconds)`, add validation to
check that `seconds` is a valid non-negative finite number within acceptable
bounds, and return an appropriate error to the user if validation fails instead
of allowing the method to panic.

@zackees
zackees merged commit 0af0583 into main Jun 20, 2026
85 of 91 checks passed
@zackees
zackees deleted the feat/686-board-fingerprints branch June 20, 2026 18:52
@fastled-project-sync fastled-project-sync Bot moved this to Triage in FastLED Tracker Jun 21, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Triage

1 participant