Skip to content

ThingerConsole::parse_command: static lambdas with reference captures cause use-after-scope crash on second and subsequent commands #55

Description

@alex-reusables

ThingerConsole::parse_command declares its two helpers as static lambdas that capture by reference. Because a function-local static is constructed exactly once (on the first call) the captures in add_token and move_left bind permanently to the stack frame of that first invocation. Every subsequent call to parse_command re-uses those bindings, so command, size, argc, argv, current_arg and max_args all refer to a frame that no longer exists. The first console command after boot parses correctly; every one after that is undefined behaviour, reading and writing through dangling references.

In practice this shows up as an intermittent crash some number of commands into a session, which is easy to misattribute to whatever the device happened to be doing at the time. On an ESP32-S3 (thinger.io 2.41.0, Arduino framework) we hit Guru Meditation Error: Core 1 panic'ed (StoreProhibited) with EXCVADDR 0x00000005, store through a stale command pointer, with frame #0 inside the add_token lambda at ThingerConsole.h:332 and frame #1 in parse_command at ThingerConsole.h:373. Removing static from both lambdas resolves it; they are cheap to construct per call and the surrounding code already assumes ordinary locals. We're currently applying that as a build-time patch to the installed header.

src/ThingerConsole.h, lines 325–346 (v2.41.0):

    int parse_command(char* command, size_t size, char *argv[], size_t max_args){
        int argc = 0;
        char* current_arg = nullptr;
        bool open_quote = false;
        bool scape_next = false;

        static auto add_token = [&](size_t i){
            command[i] = 0;
            if(argc<max_args){
                argv[argc++] = current_arg;
            }
            current_arg = nullptr;
        };

        static auto move_left = [&](int& i){
            for(auto j=i; j<size-1; j++){
                command[j] = command[j+1];
            }
            command[--size] = 0;
            i--;
        };

Fix:

-        static auto add_token = [&](size_t i){
+        auto add_token = [&](size_t i){
-        static auto move_left = [&](int& i){
+        auto move_left = [&](int& i){

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

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