Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: HonestLocksmith/Arduino
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: master
Choose a base ref
...
head repository: esp8266/Arduino
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: master
Choose a head ref
Checking mergeability… Don’t worry, you can still create the pull request.
  • 1 commit
  • 1 file changed
  • 1 contributor

Commits on Mar 23, 2026

  1. Mock - clean up in UdpContext destructor (esp8266#9312)

    * Fix possible crash in UdpContext host mocking.
    
    I saw this crash in UdpContext.h happen after some hours of regular NTP requests....
    
    ```
    [17:38:51] ADE:  voltage spike: phase A, factor=0.81, cycles=1
    (mock) ClientContext::connect: ::connect(): Connection refused
    (mock) ClientContext::connect: ::connect(): Connection refused
    (mock) ClientContext::connect: ::connect(): Connection refused
    (mock) ClientContext::connect: ::connect(): Connection refused
    [17:41:14] ADE:  voltage spike: phase A, factor=0.86, cycles=2
    (mock) ClientContext::connect: ::connect(): Connection refused
    (mock) ClientContext::connect: ::connect(): Connection refused
    (mock) ClientContext::connect: ::connect(): Connection refused
    (mock) ClientContext::connect: ::connect(): Connection refused
    [17:43:49] ADE:  voltage spike: phase B, factor=1.12, cycles=3
    (mock) ClientContext::connect: ::connect(): Connection refused
    (mock) =====> UdpServer port: 2390 <=====
    [17:44:31] NTP:  waiting for response from '81.169.233.252' timed out
    
    Program received signal SIGSEGV, Segmentation fault.
    0x000055555556848c in std::_Function_base::_M_empty() const ()
    (gdb) where
    #0  0x000055555556848c in std::_Function_base::_M_empty() const ()
    esp8266#1  0x00005555555685be in std::function<void ()>::operator bool() const ()
    esp8266#2  0x00005555555684b8 in UdpContext::mock_cb() ()
    esp8266#3  0x00005555555683af in check_incoming_udp() ()
    esp8266#4  0x0000555555567fa6 in main ()
    ```
    
    I tracked it down to UdpContext::mock_cb() which is calling a std::function callback that's been destroyed thus used-after-free. I believe  what happens is:
      1. UdpContext::unref() calls delete this when refcount hits 0 (line 56)
      2. The destructor (~UdpContext(), line 47) is empty — it never calls register_udp(_sock, nullptr) to remove itself from the global udps map
      3. check_incoming_udp() iterates udps, finds the dangling pointer, calls mock_cb() on freed memory
      4. _on_rx (a destroyed std::function) → segfault in _M_empty()
    
    The disconnect() method already does the right thing (lines 78-84: closes socket + unregisters), but it's never called before the object is destroyed via  unref().
    
    The fix is to make the destructor clean up properly.
    
    I tested intensely, no crashes since.
    
    * Format destructor for UdpContext for clarity
    
    Fixes code-style CI.
    everslick authored Mar 23, 2026
    Configuration menu
    Copy the full SHA
    f946290 View commit details
    Browse the repository at this point in the history
Loading