Skip to content

InvalidAddr warning reported and non-working advertisements with empty scan_data and recent rustc #283

Open
@peter9477

Description

@peter9477

We'd been pinned to rust v1.75 (nightly 2023-08-08) with code that worked fine when passing in scan_data: &[] when it built a ConnectableAdvertisement::ScannableUndirected advertisement. We used only the adv_data portion, and didn't want any scan data.

Once we tried going to rust versions starting around 2024, including with the recent rust v1.85 (nightly-2024-12-01), this code still compiled but led to the advertise_connectable() call logging a warning, and no advertisements showing up.

220.121 WARN : nrf_softdevice::ble::peripheral || sd_ble_gap_adv_set_configure err InvalidAddr
220.121 WARN : nrf_softdevice::ble::peripheral || sd_ble_gap_adv_stop: InvalidState

After experimentation we found a viable workaround, apparently without negative side-effects, by passing in scan_data: &[0u8] instead.

I don't understand the cause yet. It appears consistent with the SoftDevice applying an unnecessary check that any non-NULL pointer must have non-zero length data. The nrf-softdevice code provides no way to ensure that an actual NULL pointer is passed into the sd_ble_gap_adv_set_configure() routine, however, as we can't directly supply a RawAdvertisement with None for the scan_data field, but only the ScannableUndirected which requires a valid slice.

I get the impression using .as_ptr() to get an address for an empty slice may produce bogus values that are never meant to be used, such as 0x1, or really anything other than a NULL. It seems possible that the SoftDevice is applying some checks to those addresses before noticing that the length is zero. Possibly it insists that it be a valid RAM or flash address, or above its own region of memory. In any case, it seems that it may be a latent bug if we ever supply an address to the SoftDevice produced by as_ptr() on an empty slice, so I would suggest possibly the map_data() closure in start_adv() should check the length first, and always supply ptr::null_mut() as the address if the length is zero. Does that make any sense?

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions