Created
April 19, 2025 16:49
-
-
Save schkovich/e6554deb8675ff9e2ada2aa27509f5fe to your computer and use it in GitHub Desktop.
async_context_threadsafe_background: race in handle_sync_func_call() causes use‑after‑free on multicore
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <Arduino.h> | |
#include <array> | |
#include <memory> | |
#include "pico/async_context_threadsafe_background.h" | |
bool core1_separate_stack = true; | |
volatile bool operational = false; | |
static constexpr int BLUE_LED = D7; | |
static constexpr int RED_LED = D8; | |
static constexpr int YELLOW_LED = D9; | |
static constexpr int GREEN_LED = D10; | |
static async_context_threadsafe_background_t asyncCtx; | |
uint32_t doSomeWork(void* param) { | |
digitalWrite(YELLOW_LED, HIGH); | |
auto* ptr = static_cast<uint32_t*>(param); | |
(*ptr) += 1; // Simple operation to demonstrate synchronous call | |
digitalWrite(YELLOW_LED, LOW); | |
return *ptr; | |
} | |
uint32_t sync_call(uint32_t& myNumber) { | |
return async_context_execute_sync(&asyncCtx.core, doSomeWork, &myNumber); | |
} | |
uint32_t green_call(uint32_t& myNumber) { | |
static constexpr size_t BIGNUMBER = 4096; | |
std::array<uint8_t, BIGNUMBER> arr; | |
const uint32_t rc = sync_call(myNumber); | |
std::uninitialized_fill_n(arr.begin(), BIGNUMBER, 1); | |
return rc; | |
} | |
void setup() { | |
Serial.begin(115200); | |
while (!Serial) { | |
delay(10); | |
} | |
delay(5000); | |
Serial.printf("C0: Left leader standing by...\n"); | |
RP2040::enableDoubleResetBootloader(); | |
pinMode(BLUE_LED, OUTPUT); | |
pinMode(RED_LED, OUTPUT); | |
pinMode(YELLOW_LED, OUTPUT); | |
pinMode(GREEN_LED, OUTPUT); | |
pinMode(LED_BUILTIN, OUTPUT); | |
async_context_threadsafe_background_config_t cfg = async_context_threadsafe_background_default_config(); | |
operational = async_context_threadsafe_background_init(&asyncCtx, &cfg); | |
assert(operational); | |
Serial.printf("C0 ready...\n"); | |
} | |
void setup1() { | |
while (!operational) { | |
delay(10); | |
} | |
Serial.printf("C1 ready...\n"); | |
} | |
void loop() { | |
delay(1); | |
static unsigned long c0_counter = 0; | |
digitalWrite(BLUE_LED, HIGH); | |
c0_counter++; | |
if (c0_counter % 1000 == 0) { | |
digitalWrite(LED_BUILTIN, HIGH); | |
delay(5); | |
digitalWrite(LED_BUILTIN, LOW); | |
} else if (c0_counter % 7070 == 0) { | |
Serial.printf("Core %d: Free stack %d bytes\n", get_core_num(), rp2040.getFreeStack()); | |
} | |
digitalWrite(BLUE_LED, LOW); | |
delay(1); | |
} | |
void loop1() { | |
delay(2); | |
digitalWrite(GREEN_LED, HIGH); | |
static unsigned long c1_counter = 0; | |
static uint32_t myNumber = 0; | |
c1_counter++; | |
if ((c1_counter % 100) == 0) { | |
digitalWrite(RED_LED, HIGH); | |
delay(5); | |
digitalWrite(RED_LED, LOW); | |
} else if (c1_counter % 333 == 0) { | |
const auto rc = green_call(myNumber); | |
Serial.printf("Core 1: doSomeWork() returned %d\n", rc); | |
} else if (c1_counter % 5050 == 0) { | |
Serial.printf("Core %d: Free stack %d bytes\n", get_core_num(), rp2040.getFreeStack()); | |
} else if (c1_counter % 9090 == 0) { | |
Serial.printf("Free heap: %d bytes\n", rp2040.getFreeHeap()); | |
} | |
digitalWrite(GREEN_LED, LOW); | |
delay(2); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment