Skip to content

Invalid memory access in all callback examples #42

@martincizek

Description

@martincizek

According to the code, SerialTransfer requires the passed callback array to stay allocated for its whole lifetime.

  1. This is not documented.
  2. All the callback-related examples are actually accessing reusable stack memory.

Steps to reproduce: A modified uart_rx_with_callbacks.ino example is attached below - using LED blinking, as I have just one serial. I was able to reproduce it also by printing the memory addresses.

Expected behavior:

  1. This should be documented.
  2. Examples should have the callback config defined outside of any functions.
  3. I actually noticed that a solution is already part of the "polishing" effort, where a dynamic linked list is used instead. So not filing a PR for now.

Example of invalid memory access:

#include <Arduino.h>
#include "SerialTransfer.h"

SerialTransfer myTransfer;

// A callback passed to SerialTransfer
void hi() {
  digitalWrite(LED_BUILTIN, HIGH);
  delay(500);
  digitalWrite(LED_BUILTIN, LOW);
  delay(500);
}

// My very private function
void hey() {
  for (int i = 0; i < 10; i++) {
    digitalWrite(LED_BUILTIN, HIGH);
    delay(50);
    digitalWrite(LED_BUILTIN, LOW);
    delay(50);
  }
}

// Prevent compiler from optimizing unused stack variables.
// Serial1.println(foo) would work too if you had Serial1 :-)
volatile uint16_t variableInUse1 = 0;
volatile uint16_t variableInUse2 = 0;

void setup() {
  Serial.begin(115200);
  pinMode(LED_BUILTIN, OUTPUT);
  functionPtr callbackArr[] = { hi };
  variableInUse1 = (uint16_t) &callbackArr[0];
  ///////////////////////////////////////////////////////////////// Config Parameters
  configST myConfig;
  myConfig.debug        = true;
  myConfig.callbacks    = callbackArr;
  myConfig.callbacksLen = sizeof(callbackArr) / sizeof(functionPtr);
  /////////////////////////////////////////////////////////////////
  myTransfer.begin(Serial, myConfig);

  // Dispatch a few messages with the setup() stack
  while (millis() < 10000LU) {
    myTransfer.tick(); // hi() is called
  }
}


void loop() {
  functionPtr myVeryPrivateArray[] = { hey };
  variableInUse2 = (uint16_t) &myVeryPrivateArray[0];

  // Dispatch messages within the loop() stack
  myTransfer.tick(); // oh my - hey() is called!
}

Metadata

Metadata

Assignees

Labels

No labels
No labels

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions