Function call causing a delayed hard crash

When I run this test program, it crashes just before leaving the decipherReceived function. Sometimes It will crash in the middle of printing the last Serial.print line in decipherReceived. But the crash is initiated in the jsonParseValue function somewhere. If I change the if condition from jsonParseValue() to true, it doesn’t crash.

The only way to recover is to remove the power completely and plug it in again, a simple press of the reset button doesn’t work. What am I missing?

bool serial4Ready = true;           // ready to write data into wifiData array
char recData[255] = "{\"id\":\"env101\",\"type\":\"env\",\"name\":\"Hub temp sensor\",\"firmware\":\"v.1.0\",\"values\":{\"t\": 78.08,\"h\":49.60}}";


/*************************** setup ******************************************************************************************************/
void setup() {
    Serial.begin(9600);
    delay(50);
}


void loop() {
    if (serial4Ready) {
        readSerial();
    }
}


void readSerial()
{
    serial4Ready = false;
    decipherReceived(recData);
}


void decipherReceived(char * data) {
    // find sensor id and acknowledge data receipt
    char sensorId[7];
    // check for valid json string
    if (strchr(data, '{') != NULL) {
        Serial.printf("From sub-hub %d bytes: %s\n\n", strlen(data), data);
        
        if (findJsonValue(data, "id", sensorId) != NULL) { //*** this function call causes a delayed crash
            publishSensorData(data);
        }
    }
    Serial.println("data has been published");
}





void publishSensorData(char * data) {
    // publish data
    Serial.printf("To cloud (%d bytes): \n%s\n\n", strlen(data), &data[0]);
        publishResponse("not published", "development mode");
}



void publishResponse(const char *event, const char *data) {
    Serial.printf("From cloud: %s, %s\n", event, data);
}


/* json parser library */
char * findJsonValue(char * jsonStr, const char * jsonKey, char * valueChar) {
  if (jsonStr == NULL) {return NULL;}

  char * res;
  res = strstr(jsonStr, jsonKey);
  if (res == NULL) {
    *valueChar = '\0';
    return NULL;
  } else {
    boolean exitLoop = false;
    
    res = strchr(res, ':');
    while (!exitLoop) {
      res++;
      if ((strchr("\"", *res)) != NULL) { 
        exitLoop = true;
        parseJsonString(res, valueChar);
      }
    }
  }
  if (*valueChar == '\0') {
    return NULL;
  } else {
    Serial.printf("returning %s\n", valueChar);
    return valueChar;
  }
}

char * parseJsonString(char * jsonStr, char * result) {
  strcpy(result, jsonStr+1);

  // find the next " character (end of string)
  char * resEnd = strchr(result, '\"');
  if (resEnd != NULL) {
    *resEnd = '\0';
  } else {
    *result = {};
    result = NULL;
    Serial.println("JSON parse error");
  }
  return result;
}

The output I receive from running this on an Electron is:

C:\Users\mpete\Downloads>particle serial monitor
Opening serial monitor for com port: "COM3"
Serial monitor opened successfully:
From sub-hub 104 bytes: {"id":"env101","type":"env","name":"Hub temp sensor","firmware":"v.1.0","values":{"t": 78.08,"h":49.60}}

returning env101
To cloud (104 bytes):
{"id":"env101","type":"env","name":"Hub temp sensor","firmware":"v.1.0","values":{"t": 78.08,"h":49.60}}

From cloud: not published, deSerial connection closed.
Caught Interrupt.  Cleaning up.

C:\Users\mpete\Downloads>

One rule of thumb when passing arrays via a pointer is to always also pass the length of the array and check the bounds of your manipulations inside the functions against that length.

2 Likes

Thanks for pointing me in the right direction. I was doing a strcpy and overflowing the result string length.

I solved it by moving the strcpy to later in the function and using strncpy to make sure I only copied what was needed and it would fit into the result string.

2 Likes